Update to m13
[ooovba.git] / applied_patches / 0857-calc-perf-flat-segment-tree.diff
blob97c7e4e65138338e9b432e12c7f39258c29f41a9
1 diff --git sc/inc/mdds/flatsegmenttree.hxx sc/inc/mdds/flatsegmenttree.hxx
2 new file mode 100644
3 index 0000000..59d1e0c
4 --- /dev/null
5 +++ sc/inc/mdds/flatsegmenttree.hxx
6 @@ -0,0 +1,509 @@
7 +/*************************************************************************
8 + *
9 + * Copyright (c) 2008-2009 Kohei Yoshida
10 + *
11 + * Permission is hereby granted, free of charge, to any person
12 + * obtaining a copy of this software and associated documentation
13 + * files (the "Software"), to deal in the Software without
14 + * restriction, including without limitation the rights to use,
15 + * copy, modify, merge, publish, distribute, sublicense, and/or sell
16 + * copies of the Software, and to permit persons to whom the
17 + * Software is furnished to do so, subject to the following
18 + * conditions:
19 + *
20 + * The above copyright notice and this permission notice shall be
21 + * included in all copies or substantial portions of the Software.
22 + *
23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25 + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 + * OTHER DEALINGS IN THE SOFTWARE.
31 + *
32 + ************************************************************************/
34 +#ifndef __MDDS_FLATSEGMENTTREE_HXX__
35 +#define __MDDS_FLATSEGMENTTREE_HXX__
37 +#include <iostream>
38 +#include <cassert>
40 +#include "node.hxx"
42 +namespace mdds {
44 +template<typename _Key, typename _Value>
45 +class flat_segment_tree
47 +public:
48 + typedef _Key key_type;
49 + typedef _Value value_type;
51 + struct nonleaf_value_type
52 + {
53 + key_type low; /// low range value (inclusive)
54 + key_type high; /// high range value (non-inclusive)
55 + };
57 + struct leaf_value_type
58 + {
59 + key_type key;
60 + value_type value;
61 + };
63 + struct node : public node_base
64 + {
65 + union {
66 + nonleaf_value_type value_nonleaf;
67 + leaf_value_type value_leaf;
68 + };
70 + node(bool _is_leaf) :
71 + node_base(_is_leaf)
72 + {
73 + }
75 + virtual ~node()
76 + {
77 + }
79 + virtual void fill_nonleaf_value(const node_base_ptr& left_node, const node_base_ptr& right_node)
80 + {
81 + // Parent node should carry the range of all of its child nodes.
82 + if (left_node)
83 + value_nonleaf.low = left_node->is_leaf ? get_node(left_node)->value_leaf.key : get_node(left_node)->value_nonleaf.low;
84 + else
85 + // Having a left node is prerequisite.
86 + return;
88 + if (right_node)
89 + {
90 + if (right_node->is_leaf)
91 + {
92 + // When the child nodes are leaf nodes, the upper bound
93 + // must be the value of the node that comes after the
94 + // right leaf node (if such node exists).
96 + if (right_node->right)
97 + value_nonleaf.high = get_node(right_node->right)->value_leaf.key;
98 + else
99 + value_nonleaf.high = get_node(right_node)->value_leaf.key;
101 + else
103 + value_nonleaf.high = get_node(right_node)->value_nonleaf.high;
106 + else
107 + value_nonleaf.high = left_node->is_leaf ? get_node(left_node)->value_leaf.key : get_node(left_node)->value_nonleaf.high;
110 + virtual void dump_value() const
112 + using ::std::cout;
113 + if (is_leaf)
115 + cout << "(" << value_leaf.key << ")";
117 + else
119 + cout << "(" << value_nonleaf.low << "-" << value_nonleaf.high << ")";
121 + cout << " ";
124 + virtual node_base* create_new(bool leaf) const
126 + return new node(leaf);
128 + };
130 + /**
131 + * Get a pointer of concrete node type from the base pointer.
133 + * @param base_node base node pointer (ref-counted)
134 + *
135 + * @return raw pointer of concrete node type
136 + */
137 + static node* get_node(const node_base_ptr& base_node)
139 + return static_cast<node*>(base_node.get());
142 + flat_segment_tree(key_type min_val, key_type max_val, value_type init_val) :
143 + m_root_node(static_cast<node*>(NULL)),
144 + m_left_leaf(new node(true)),
145 + m_right_leaf(new node(true)),
146 + m_valid_tree(false)
148 + // we need to create two end nodes during initialization.
149 + get_node(m_left_leaf)->value_leaf.key = min_val;
150 + get_node(m_left_leaf)->value_leaf.value = init_val;
151 + m_left_leaf->right = m_right_leaf;
153 + get_node(m_right_leaf)->value_leaf.key = max_val;
154 + m_right_leaf->left = m_left_leaf;
157 + ~flat_segment_tree()
159 + // Go through all leaf nodes, and disconnect their links.
160 + node_base* cur_node = m_left_leaf.get();
161 + do
163 + node_base* next_node = cur_node->right.get();
164 + disconnect_node(cur_node);
165 + cur_node = next_node;
167 + while (cur_node != m_right_leaf.get());
169 + disconnect_node(m_right_leaf.get());
170 + clear_tree(m_root_node);
171 + disconnect_node(m_root_node.get());
174 + /**
175 + * Insert a new segment into the tree.
177 + * @param start start value of the segment being inserted. The value is
178 + * inclusive.
179 + * @param end end value of the segment being inserted. The value is not
180 + * inclusive.
181 + * @param val value associated with this segment.
182 + */
183 + void insert_segment(key_type start, key_type end, value_type val)
185 + if (end < get_node(m_left_leaf)->value_leaf.key || start > get_node(m_right_leaf)->value_leaf.key)
186 + // The new segment does not overlap the current interval.
187 + return;
189 + if (start < get_node(m_left_leaf)->value_leaf.key)
190 + // The start value should not be smaller than the current minimum.
191 + start = get_node(m_left_leaf)->value_leaf.key;
193 + if (end > get_node(m_right_leaf)->value_leaf.key)
194 + // The end value should not be larger than the current maximum.
195 + end = get_node(m_right_leaf)->value_leaf.key;
197 + if (start >= end)
198 + return;
200 + // Find the node with value that either equals or is greater than the
201 + // start value.
203 + node_base_ptr start_pos = get_insertion_pos_leaf(start, m_left_leaf);
204 + if (!start_pos)
205 + // Insertion position not found. Bail out.
206 + return;
208 + node_base_ptr end_pos = get_insertion_pos_leaf(end, start_pos);
209 + if (!end_pos)
210 + end_pos = m_right_leaf;
212 + node_base_ptr new_start_node;
213 + value_type old_value;
215 + // Set the start node.
217 + if (get_node(start_pos)->value_leaf.key == start)
219 + // Re-use the existing node, but save the old value for later.
221 + if (start_pos->left && get_node(start_pos->left)->value_leaf.value == val)
223 + // Extend the existing segment.
224 + old_value = get_node(start_pos)->value_leaf.value;
225 + new_start_node = start_pos->left;
227 + else
229 + // Update the value of the existing node.
230 + old_value = get_node(start_pos)->value_leaf.value;
231 + get_node(start_pos)->value_leaf.value = val;
232 + new_start_node = start_pos;
235 + else if (get_node(start_pos->left)->value_leaf.value == val)
237 + // Extend the existing segment.
238 + old_value = get_node(start_pos->left)->value_leaf.value;
239 + new_start_node = start_pos->left;
241 + else
243 + // Insert a new node before the insertion position node.
244 + node_base_ptr new_node(new node(true));
245 + get_node(new_node)->value_leaf.key = start;
246 + get_node(new_node)->value_leaf.value = val;
247 + new_start_node = new_node;
249 + node_base_ptr left_node = start_pos->left;
250 + old_value = get_node(left_node)->value_leaf.value;
252 + // Link to the left node.
253 + link_nodes(left_node, new_node);
255 + // Link to the right node.
256 + link_nodes(new_node, start_pos);
259 + node_base_ptr cur_node = new_start_node->right;
260 + while (cur_node != end_pos)
262 + // Disconnect the link between the current node and the previous node.
263 + cur_node->left->right.reset();
264 + cur_node->left.reset();
265 + old_value = get_node(cur_node)->value_leaf.value;
267 + cur_node = cur_node->right;
270 + // Set the end node.
272 + if (get_node(end_pos)->value_leaf.key == end)
274 + // The new segment ends exactly at the end node position.
276 + if (end_pos->right && get_node(end_pos)->value_leaf.value == val)
278 + // Remove this node, and connect the new start node with the
279 + // node that comes after this node.
280 + new_start_node->right = end_pos->right;
281 + if (end_pos->right)
282 + end_pos->right->left = new_start_node;
283 + disconnect_node(end_pos.get());
285 + else
287 + // Just link the new segment to this node.
288 + new_start_node->right = end_pos;
289 + end_pos->left = new_start_node;
292 + else if (old_value == val)
294 + link_nodes(new_start_node, end_pos);
296 + else
298 + // Insert a new node before the insertion position node.
299 + node_base_ptr new_node(new node(true));
300 + get_node(new_node)->value_leaf.key = end;
301 + get_node(new_node)->value_leaf.value = old_value;
303 + // Link to the left node.
304 + link_nodes(new_start_node, new_node);
306 + // Link to the right node.
307 + link_nodes(new_node, end_pos);
310 + m_valid_tree = false;
313 + bool search(key_type key, value_type& value, key_type* start = NULL, key_type* end = NULL) const
315 + if (key < get_node(m_left_leaf)->value_leaf.key || get_node(m_right_leaf)->value_leaf.key <= key)
316 + // key value is out-of-bound.
317 + return false;
319 + const node* pos = get_insertion_pos_leaf(key, get_node(m_left_leaf));
320 + if (pos->value_leaf.key == key)
322 + value = pos->value_leaf.value;
323 + if (start)
324 + *start = pos->value_leaf.key;
325 + if (end && pos->right)
326 + *end = get_node(pos->right)->value_leaf.key;
327 + return true;
329 + else if (pos->left && get_node(pos->left)->value_leaf.key < key)
331 + value = get_node(pos->left)->value_leaf.value;
332 + if (start)
333 + *start = get_node(pos->left)->value_leaf.key;
334 + if (end)
335 + *end = pos->value_leaf.key;
336 + return true;
339 + return false;
342 + bool search_tree(key_type key, value_type& value, key_type* start = NULL, key_type* end = NULL) const
344 + if (!m_root_node || !m_valid_tree)
345 + {
346 + // either tree has not been built, or is in an invalid state.
347 + return false;
350 + if (key < get_node(m_left_leaf)->value_leaf.key || get_node(m_right_leaf)->value_leaf.key <= key)
351 + {
352 + // key value is out-of-bound.
353 + return false;
356 + // Descend down the tree through the last non-leaf layer.
358 + node* cur_node = get_node(m_root_node);
359 + while (true)
361 + if (cur_node->left)
363 + if (cur_node->left->is_leaf)
364 + break;
366 + const nonleaf_value_type& v = get_node(cur_node->left)->value_nonleaf;
367 + if (v.low <= key && key < v.high)
368 + {
369 + cur_node = get_node(cur_node->left);
370 + continue;
373 + else
374 + {
375 + // left child node can't be missing !
376 + return false;
379 + if (cur_node->right)
381 + const nonleaf_value_type& v = get_node(cur_node->right)->value_nonleaf;
382 + if (v.low <= key && key < v.high)
383 + {
384 + cur_node = get_node(cur_node->right);
385 + continue;
388 + return false;
391 + assert(cur_node->left->is_leaf && cur_node->right->is_leaf);
393 + key_type key1 = get_node(cur_node->left)->value_leaf.key;
394 + key_type key2 = get_node(cur_node->right)->value_leaf.key;
396 + if (key1 <= key && key < key2)
398 + cur_node = get_node(cur_node->left);
400 + else if (key2 <= key && key < cur_node->value_nonleaf.high)
402 + cur_node = get_node(cur_node->right);
404 + else
405 + cur_node = NULL;
407 + if (!cur_node)
408 + {
409 + return false;
412 + value = cur_node->value_leaf.value;
413 + if (start)
414 + *start = cur_node->value_leaf.key;
416 + if (end)
418 + assert(cur_node->right);
419 + if (cur_node->right)
420 + *end = get_node(cur_node->right)->value_leaf.key;
421 + else
422 + // This should never happen, but just in case....
423 + *end = get_node(m_right_leaf)->value_leaf.key;
426 + return true;
429 + void build_tree()
431 + if (!m_left_leaf)
432 + return;
434 + clear_tree(m_root_node);
435 + m_root_node = ::mdds::build_tree(m_left_leaf);
436 + m_valid_tree = true;
439 + bool is_tree_valid() const
441 + return m_valid_tree;
444 + void dump_tree() const
446 + using ::std::cout;
447 + using ::std::endl;
449 + ::mdds::dump_tree(m_root_node);
451 + cout << endl << " node instance count = " << node_base::get_instance_count() << endl;
454 + void dump_leaf_nodes() const
456 + using ::std::cout;
457 + using ::std::endl;
459 + cout << "------------------------------------------" << endl;
461 + node_base_ptr cur_node = m_left_leaf;
462 + long node_id = 0;
463 + while (cur_node)
465 + cout << " node " << node_id++ << ": key = " << get_node(cur_node)->value_leaf.key
466 + << "; value = " << get_node(cur_node)->value_leaf.value
467 + << endl;
468 + cur_node = cur_node->right;
470 + cout << endl << " node instance count = " << node_base::get_instance_count() << endl;
473 +private:
474 + flat_segment_tree();
476 + node_base_ptr get_insertion_pos_leaf(key_type key, const node_base_ptr& start_pos) const
478 + node_base_ptr cur_node = start_pos;
479 + while (cur_node)
481 + if (key <= get_node(cur_node)->value_leaf.key)
483 + // Found the insertion position.
484 + return cur_node;
486 + cur_node = cur_node->right;
488 + return node_base_ptr();
491 + const node* get_insertion_pos_leaf(key_type key, const node* start_pos) const
493 + const node* cur_node = start_pos;
494 + while (cur_node)
496 + if (key <= cur_node->value_leaf.key)
498 + // Found the insertion position.
499 + return cur_node;
501 + cur_node = get_node(cur_node->right);
503 + return NULL;
506 +private:
507 + node_base_ptr m_root_node;
508 + node_base_ptr m_left_leaf;
509 + node_base_ptr m_right_leaf;
510 + bool m_valid_tree;
515 +#endif
516 diff --git sc/inc/mdds/node.hxx sc/inc/mdds/node.hxx
517 new file mode 100644
518 index 0000000..8975c86
519 --- /dev/null
520 +++ sc/inc/mdds/node.hxx
521 @@ -0,0 +1,301 @@
522 +/*************************************************************************
524 + * Copyright (c) 2008-2009 Kohei Yoshida
525 + *
526 + * Permission is hereby granted, free of charge, to any person
527 + * obtaining a copy of this software and associated documentation
528 + * files (the "Software"), to deal in the Software without
529 + * restriction, including without limitation the rights to use,
530 + * copy, modify, merge, publish, distribute, sublicense, and/or sell
531 + * copies of the Software, and to permit persons to whom the
532 + * Software is furnished to do so, subject to the following
533 + * conditions:
534 + *
535 + * The above copyright notice and this permission notice shall be
536 + * included in all copies or substantial portions of the Software.
537 + *
538 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
539 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
540 + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
541 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
542 + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
543 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
544 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
545 + * OTHER DEALINGS IN THE SOFTWARE.
547 + ************************************************************************/
549 +#ifndef __MDDS_NODE_HXX__
550 +#define __MDDS_NODE_HXX__
552 +#include <iostream>
553 +#include <list>
554 +#include <cassert>
556 +//#define DEBUG_NODE_BASE 1
558 +#define USE_INTRUSIVE_PTR 0
560 +#if USE_INTRUSIVE_PTR
561 +#include <boost/intrusive_ptr.hpp>
562 +#else
563 +#include <boost/shared_ptr.hpp>
564 +#endif
566 +namespace mdds {
568 +struct intrusive_ref_base
570 +#if USE_INTRUSIVE_PTR
571 + size_t _refcount;
573 + intrusive_ref_base() :
574 + _refcount(0) {}
575 +#endif
576 + virtual ~intrusive_ref_base() {}
579 +#if USE_INTRUSIVE_PTR
580 +inline void intrusive_ptr_add_ref(intrusive_ref_base* p)
582 + ++p->_refcount;
585 +inline void intrusive_ptr_release(intrusive_ref_base* p)
587 + --p->_refcount;
588 + if (!p->_refcount)
589 + delete p;
591 +#endif
593 +#ifdef DEBUG_NODE_BASE
594 +size_t node_instance_count = 0;
595 +#endif
597 +struct node_base;
598 +#if USE_INTRUSIVE_PTR
599 +typedef ::boost::intrusive_ptr<node_base> node_base_ptr;
600 +#else
601 +typedef ::boost::shared_ptr<node_base> node_base_ptr;
602 +#endif
604 +struct node_base : public intrusive_ref_base
606 + static size_t get_instance_count()
608 +#ifdef DEBUG_NODE_BASE
609 + return node_instance_count;
610 +#else
611 + return 0;
612 +#endif
614 + node_base_ptr parent; /// parent node
615 + node_base_ptr left; /// left child node or previous sibling if it's a leaf node.
616 + node_base_ptr right; /// right child node or next sibling if it's aleaf node.
617 + bool is_leaf;
619 + node_base(bool _is_leaf) :
620 + intrusive_ref_base(),
621 + parent(static_cast<node_base*>(NULL)),
622 + left(static_cast<node_base*>(NULL)),
623 + right(static_cast<node_base*>(NULL)),
624 + is_leaf(_is_leaf)
626 +#ifdef DEBUG_NODE_BASE
627 + ++node_instance_count;
628 +#endif
631 + virtual ~node_base()
633 +#ifdef DEBUG_NODE_BASE
634 + --node_instance_count;
635 +#endif
638 + // These methods are specific to concrete class implementation.
640 + virtual void fill_nonleaf_value(const node_base_ptr& left_node, const node_base_ptr& right_node) = 0;
641 + virtual void dump_value() const = 0;
642 + virtual node_base* create_new(bool leaf) const = 0;
645 +template<typename _NodePtr>
646 +void disconnect_node(_NodePtr p)
648 + if (!p)
649 + return;
651 + p->left.reset();
652 + p->right.reset();
653 + p->parent.reset();
656 +template<typename _NodePtr>
657 +void link_nodes(_NodePtr& left, _NodePtr& right)
659 + left->right = right;
660 + right->left = left;
663 +/**
664 + * Disconnect all non-leaf nodes so that their ref-counted instances will
665 + * all get destroyed afterwards.
666 + */
667 +template<typename _NodePtr>
668 +void clear_tree(const _NodePtr& node)
670 + if (!node)
671 + // Nothing to do.
672 + return;
674 + if (node->is_leaf)
676 + node->parent.reset();
677 + return;
680 + clear_tree(node->left);
681 + clear_tree(node->right);
682 + disconnect_node(node.get());
685 +template<typename _NodePtr>
686 +_NodePtr make_parent_node(const _NodePtr& node1, const _NodePtr& node2)
688 + _NodePtr parent_node(node1->create_new(false));
689 + node1->parent = parent_node;
690 + parent_node->left = node1;
691 + if (node2)
693 + node2->parent = parent_node;
694 + parent_node->right = node2;
697 + parent_node->fill_nonleaf_value(node1, node2);
698 + return parent_node;
701 +template<typename _NodePtr>
702 +_NodePtr build_tree(const _NodePtr& left_leaf_node)
704 + if (!left_leaf_node)
705 + // The left leaf node is empty. Nothing to build.
706 + return _NodePtr();
708 + _NodePtr node1, node2;
709 + node1 = left_leaf_node;
711 + ::std::list<_NodePtr> node_list;
712 + while (true)
714 + node2 = node1->right;
715 + _NodePtr parent_node = make_parent_node(node1, node2);
716 + node_list.push_back(parent_node);
718 + if (!node2 || !node2->right)
719 + // no more nodes. Break out of the loop.
720 + break;
722 + node1 = node2->right;
725 + return build_tree_non_leaf(node_list);
728 +template<typename _NodePtr>
729 +_NodePtr build_tree_non_leaf(const ::std::list<_NodePtr>& node_list)
731 + size_t node_count = node_list.size();
732 + if (node_count == 1)
734 + return node_list.front();
736 + else if (node_count == 0)
737 + return _NodePtr();
739 + ::std::list<_NodePtr> new_node_list;
740 + _NodePtr node_pair[2];
741 + typename ::std::list<_NodePtr>::const_iterator itr = node_list.begin();
742 + typename ::std::list<_NodePtr>::const_iterator itrEnd = node_list.end();
743 + for (bool even_itr = false; itr != itrEnd; ++itr, even_itr = !even_itr)
745 + node_pair[even_itr] = *itr;
746 + if (even_itr)
748 + _NodePtr parent_node = make_parent_node(node_pair[0], node_pair[1]);
749 + node_pair[0].reset();
750 + node_pair[1].reset();
751 + new_node_list.push_back(parent_node);
755 + if (node_pair[0])
757 + // Un-paired node still needs a parent...
758 + _NodePtr parent_node = make_parent_node(node_pair[0], _NodePtr());
759 + node_pair[0].reset();
760 + node_pair[1].reset();
761 + new_node_list.push_back(parent_node);
764 + // Move up one level, and do the same procedure until the root node is reached.
765 + return build_tree_non_leaf(new_node_list);
768 +template<typename _NodePtr>
769 +void dump_tree_layer(const ::std::list<_NodePtr>& node_list, unsigned int level)
771 + using ::std::cout;
772 + using ::std::endl;
774 + if (node_list.empty())
775 + return;
777 + bool isLeaf = node_list.front()->is_leaf;
778 + cout << "level " << level << " (" << (isLeaf?"leaf":"non-leaf") << ")" << endl;
780 + ::std::list<_NodePtr> newList;
781 + typename ::std::list<_NodePtr>::const_iterator itr = node_list.begin(), itrEnd = node_list.end();
782 + for (; itr != itrEnd; ++itr)
784 + const _NodePtr& p = *itr;
785 + if (!p)
787 + cout << "(x) ";
788 + continue;
791 + p->dump_value();
793 + if (p->is_leaf)
794 + continue;
796 + if (p->left)
798 + newList.push_back(p->left);
799 + if (p->right)
800 + newList.push_back(p->right);
803 + cout << endl;
805 + if (!newList.empty())
806 + dump_tree_layer(newList, level+1);
809 +template<typename _NodePtr>
810 +void dump_tree(const _NodePtr& root_node)
812 + if (!root_node)
813 + return;
815 + ::std::list<_NodePtr> node_list;
816 + node_list.push_back(root_node);
817 + dump_tree_layer(node_list, 0);
822 +#endif
823 diff --git sc/inc/segmenttree.hxx sc/inc/segmenttree.hxx
824 new file mode 100644
825 index 0000000..f414002
826 --- /dev/null
827 +++ sc/inc/segmenttree.hxx
828 @@ -0,0 +1,85 @@
829 +/*************************************************************************
831 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
832 + *
833 + * Copyright 2008 by Sun Microsystems, Inc.
835 + * OpenOffice.org - a multi-platform office productivity suite
837 + * $RCSfile: compressedarray.hxx,v $
838 + * $Revision: 1.7.32.2 $
840 + * This file is part of OpenOffice.org.
842 + * OpenOffice.org is free software: you can redistribute it and/or modify
843 + * it under the terms of the GNU Lesser General Public License version 3
844 + * only, as published by the Free Software Foundation.
846 + * OpenOffice.org is distributed in the hope that it will be useful,
847 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
848 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
849 + * GNU Lesser General Public License version 3 for more details
850 + * (a copy is included in the LICENSE file that accompanied this code).
852 + * You should have received a copy of the GNU Lesser General Public License
853 + * version 3 along with OpenOffice.org. If not, see
854 + * <http://www.openoffice.org/license.html>
855 + * for a copy of the LGPLv3 License.
857 + ************************************************************************/
859 +#ifndef SC_SEGMENTTREE_HXX
860 +#define SC_SEGMENTTREE_HXX
862 +#include "address.hxx"
864 +#include <memory>
866 +class ScFlatBoolSegmentsImpl;
868 +class ScFlatBoolRowSegments
870 +public:
871 + struct RangeData
873 + SCROW mnRow1;
874 + SCROW mnRow2;
875 + bool mbValue;
876 + };
877 + ScFlatBoolRowSegments();
878 + ~ScFlatBoolRowSegments();
880 + void setTrue(SCROW nRow1, SCROW nRow2);
881 + void setFalse(SCROW nRow1, SCROW nRow2);
882 + bool getValue(SCROW nRow);
883 + bool getRangeData(SCROW nRow, RangeData& rData);
885 +private:
886 + ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl;
889 +// ============================================================================
891 +class ScFlatBoolColSegments
893 +public:
894 + struct RangeData
896 + SCCOL mnCol1;
897 + SCCOL mnCol2;
898 + bool mbValue;
899 + };
900 + ScFlatBoolColSegments();
901 + ~ScFlatBoolColSegments();
903 + void setTrue(SCCOL nCol1, SCCOL nCol2);
904 + void setFalse(SCCOL nCol1, SCCOL nCol2);
905 + bool getValue(SCCOL nCol);
906 + bool getRangeData(SCCOL nCol, RangeData& rData);
908 +private:
909 + ::std::auto_ptr<ScFlatBoolSegmentsImpl> mpImpl;
913 +#endif
914 diff --git sc/source/core/data/makefile.mk sc/source/core/data/makefile.mk
915 index c631bb4..5fbec41 100644
916 --- sc/source/core/data/makefile.mk
917 +++ sc/source/core/data/makefile.mk
918 @@ -102,6 +102,7 @@ SLOFILES = \
919 $(SLO)$/phonetic.obj \
920 $(SLO)$/poolhelp.obj \
921 $(SLO)$/scimpexpmsg.obj \
922 + $(SLO)$/segmenttree.obj \
923 $(SLO)$/sortparam.obj \
924 $(SLO)$/stlpool.obj \
925 $(SLO)$/stlsheet.obj \
926 @@ -147,7 +148,8 @@ EXCEPTIONSFILES= \
927 $(SLO)$/dbdocutl.obj \
928 $(SLO)$/dptabsrc.obj \
929 $(SLO)$/drwlayer.obj \
930 - $(SLO)$/globalx.obj
931 + $(SLO)$/globalx.obj \
932 + $(SLO)$/segmenttree.obj
934 .IF "$(OS)$(COM)$(CPUNAME)"=="LINUXGCCSPARC"
935 NOOPTFILES= \
936 diff --git sc/source/core/data/segmenttree.cxx sc/source/core/data/segmenttree.cxx
937 new file mode 100644
938 index 0000000..b534de1
939 --- /dev/null
940 +++ sc/source/core/data/segmenttree.cxx
941 @@ -0,0 +1,193 @@
942 +/*************************************************************************
944 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
945 + *
946 + * Copyright 2008 by Sun Microsystems, Inc.
948 + * OpenOffice.org - a multi-platform office productivity suite
950 + * $RCSfile: compressedarray.hxx,v $
951 + * $Revision: 1.7.32.2 $
953 + * This file is part of OpenOffice.org.
955 + * OpenOffice.org is free software: you can redistribute it and/or modify
956 + * it under the terms of the GNU Lesser General Public License version 3
957 + * only, as published by the Free Software Foundation.
959 + * OpenOffice.org is distributed in the hope that it will be useful,
960 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
961 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
962 + * GNU Lesser General Public License version 3 for more details
963 + * (a copy is included in the LICENSE file that accompanied this code).
965 + * You should have received a copy of the GNU Lesser General Public License
966 + * version 3 along with OpenOffice.org. If not, see
967 + * <http://www.openoffice.org/license.html>
968 + * for a copy of the LGPLv3 License.
970 + ************************************************************************/
972 +// MARKER(update_precomp.py): autogen include statement, do not remove
973 +#include "precompiled_sc.hxx"
975 +#include "segmenttree.hxx"
976 +#include "mdds/flatsegmenttree.hxx"
978 +#define USE_TREE_SEARCH 1
980 +class ScFlatBoolSegmentsImpl
982 +public:
983 + struct RangeData
985 + SCCOLROW mnPos1;
986 + SCCOLROW mnPos2;
987 + bool mbValue;
988 + };
989 + ScFlatBoolSegmentsImpl(SCCOLROW nMax);
990 + ~ScFlatBoolSegmentsImpl();
992 + void setTrue(SCCOLROW nPos1, SCCOLROW nPos2);
993 + void setFalse(SCCOLROW nPos1, SCCOLROW nPos2);
994 + bool getValue(SCCOLROW nPos);
995 + bool getRangeData(SCCOLROW nPos, RangeData& rData);
997 +private:
998 + ScFlatBoolSegmentsImpl();
999 + ScFlatBoolSegmentsImpl(const ScFlatBoolSegmentsImpl&);
1001 + ::mdds::flat_segment_tree<SCCOLROW, bool> maSegments;
1004 +ScFlatBoolSegmentsImpl::ScFlatBoolSegmentsImpl(SCCOLROW nMax) :
1005 + maSegments(0, nMax+1, false)
1009 +ScFlatBoolSegmentsImpl::~ScFlatBoolSegmentsImpl()
1013 +void ScFlatBoolSegmentsImpl::setTrue(SCCOLROW nPos1, SCCOLROW nPos2)
1015 + maSegments.insert_segment(nPos1, nPos2+1, true);
1018 +void ScFlatBoolSegmentsImpl::setFalse(SCCOLROW nPos1, SCCOLROW nPos2)
1020 + maSegments.insert_segment(nPos1, nPos2+1, false);
1023 +bool ScFlatBoolSegmentsImpl::getValue(SCCOLROW nPos)
1025 + bool bValue = false;
1026 +#if USE_TREE_SEARCH
1027 + if (!maSegments.is_tree_valid())
1028 + maSegments.build_tree();
1030 + maSegments.search_tree(nPos, bValue);
1031 +#else
1032 + maSegments.search(nPos, bValue);
1033 +#endif
1034 + return bValue;
1037 +bool ScFlatBoolSegmentsImpl::getRangeData(SCCOLROW nPos, RangeData& rData)
1039 +#if USE_TREE_SEARCH
1040 + if (!maSegments.is_tree_valid())
1041 + maSegments.build_tree();
1042 +#endif
1044 + bool bValue;
1045 + SCCOLROW nPos1, nPos2;
1046 +#if USE_TREE_SEARCH
1047 + if (!maSegments.search_tree(nPos, bValue, &nPos1, &nPos2))
1048 + return false;
1049 +#else
1050 + if (!maSegments.search(nPos, bValue, &nPos1, &nPos2))
1051 + return false;
1052 +#endif
1054 + rData.mnPos1 = nPos1;
1055 + rData.mnPos2 = nPos2-1; // end point is not inclusive.
1056 + rData.mbValue = bValue;
1057 + return true;
1060 +// ============================================================================
1062 +ScFlatBoolRowSegments::ScFlatBoolRowSegments() :
1063 + mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXROW)))
1067 +ScFlatBoolRowSegments::~ScFlatBoolRowSegments()
1071 +void ScFlatBoolRowSegments::setTrue(SCROW nRow1, SCROW nRow2)
1073 + mpImpl->setTrue(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2));
1076 +void ScFlatBoolRowSegments::setFalse(SCROW nRow1, SCROW nRow2)
1078 + mpImpl->setFalse(static_cast<SCCOLROW>(nRow1), static_cast<SCCOLROW>(nRow2));
1081 +bool ScFlatBoolRowSegments::getValue(SCROW nRow)
1083 + return mpImpl->getValue(static_cast<SCCOLROW>(nRow));
1086 +bool ScFlatBoolRowSegments::getRangeData(SCROW nRow, RangeData& rData)
1088 + ScFlatBoolSegmentsImpl::RangeData aData;
1089 + if (!mpImpl->getRangeData(static_cast<SCCOLROW>(nRow), aData))
1090 + return false;
1092 + rData.mbValue = aData.mbValue;
1093 + rData.mnRow1 = static_cast<SCROW>(aData.mnPos1);
1094 + rData.mnRow2 = static_cast<SCROW>(aData.mnPos2);
1095 + return true;
1098 +// ============================================================================
1100 +ScFlatBoolColSegments::ScFlatBoolColSegments() :
1101 + mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW>(MAXCOL)))
1105 +ScFlatBoolColSegments::~ScFlatBoolColSegments()
1109 +void ScFlatBoolColSegments::setTrue(SCCOL nCol1, SCCOL nCol2)
1111 + mpImpl->setTrue(static_cast<SCCOLROW>(nCol1), static_cast<SCCOLROW>(nCol2));
1114 +void ScFlatBoolColSegments::setFalse(SCCOL nCol1, SCCOL nCol2)
1116 + mpImpl->setFalse(static_cast<SCCOLROW>(nCol1), static_cast<SCCOLROW>(nCol2));
1119 +bool ScFlatBoolColSegments::getValue(SCCOL nCol)
1121 + return mpImpl->getValue(static_cast<SCCOLROW>(nCol));
1124 +bool ScFlatBoolColSegments::getRangeData(SCCOL nCol, RangeData& rData)
1126 + ScFlatBoolSegmentsImpl::RangeData aData;
1127 + if (!mpImpl->getRangeData(static_cast<SCCOLROW>(nCol), aData))
1128 + return false;
1130 + rData.mbValue = aData.mbValue;
1131 + rData.mnCol1 = static_cast<SCCOL>(aData.mnPos1);
1132 + rData.mnCol2 = static_cast<SCCOL>(aData.mnPos2);
1133 + return true;