SheafSystem  0.0.0.0
interval_set.cc
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
20 
21 #include "SheafSystem/interval_set.h"
22 #include "SheafSystem/assert_contract.h"
23 #include "SheafSystem/deep_size.h"
24 #include "SheafSystem/interval_set_iterator.h"
25 
26 using namespace std;
27 
28 // =============================================================
29 // INTERVAL_SET FACET
30 // =============================================================
31 
32 // PUBLIC MEMBER FUNCTIONS
33 
36 {
37  // Preconditions:
38 
39  // Body:
40 
41  // Postconditions:
42 
43  ensure(invariant());
44 
45  // Exit:
46 
47  return;
48 }
49 
51 interval_set(const interval_set& xother)
52 {
53  // Preconditions:
54 
55  // Body:
56 
57  *this = xother;
58 
59  // Postconditions:
60 
61  ensure(*this == xother);
62 
63  // Exit:
64 
65  return;
66 }
67 
70 {
71  // Preconditions:
72 
73  // Body:
74 
75  // nothing to do.
76 
77  // Postconditions:
78 
79  // Exit:
80 
81  return;
82 }
83 
84 bool
86 operator==(const interval_set& xother) const
87 {
88  bool result;
89 
90  // Preconditions:
91 
92  // Body:
93 
94  result = (_interval_map == xother._interval_map);
95 
96  // Postconditions:
97 
98  // Exit:
99 
100  return result;
101 }
102 
103 void
106 {
107  // Preconditions:
108 
109  // Body:
110 
111  put_interval(xbegin, xend, true);
112 
113  // Postconditions:
114 
115  ensure(invariant());
116  ensure(interval_is_full(xbegin, xend));
117 
118  // Exit:
119 
120  return;
121 }
122 
123 void
126 {
127  // Preconditions:
128 
129  // Body:
130 
131  put_interval(xmbr, xmbr, true);
132 
133  // Preconditions:
134 
135  ensure(invariant());
136  ensure(contains_member(xmbr));
137 
138  // Exit:
139 
140  return;
141 }
142 
143 void
146 {
147  // Preconditions:
148 
149  // Body:
150 
151  put_interval(xbegin, xend, false);
152 
153  // Postconditions:
154 
155  ensure(invariant());
156  ensure(interval_is_empty(xbegin, xend));
157 
158  // Exit:
159 
160  return;
161 }
162 
163 void
166 {
167  // Preconditions:
168 
169  // Body:
170 
171  put_interval(xmbr, xmbr, false);
172 
173  // Preconditions:
174 
175  ensure(invariant());
176  ensure(!contains_member(xmbr));
177 
178  // Exit:
179 
180  return;
181 }
182 
183 bool
186 {
187  bool result;
188 
189  // Preconditions:
190 
191  // Body:
192 
193  map_type::const_iterator litr = _interval_map.lower_bound(xmbr);
194 
195  result = (litr != _interval_map.end());
196  if(result)
197  result = litr->second;
198 
199  // Postconditions:
200 
201  // Exit:
202 
203  return result;
204 }
205 
208 member_ct(pod_type xbegin, pod_type xend) const
209 {
210  // Preconditions:
211 
212  // Body:
213 
214  size_type result = 0;
215 
216  // Postconditions:
217 
218  map_type::const_iterator litr = _interval_map.lower_bound(xbegin);
219 
220  pod_type lbegin = xbegin;
221 
222  while((litr != _interval_map.end()) && (lbegin <= xend))
223  {
224  pod_type lend = litr->first;
225 
226  if(litr->second)
227  {
228  // The interval is full, add members.
229 
230  if(xend <= lend)
231  {
232  // Only part of the interval is greater than the input interval,
233  // add the part and exit the loop.
234 
235  result += (xend - lbegin) + 1;
236  break;
237  }
238  else
239  {
240  // The entire interval is in the input interval, add it and continue.
241 
242  result += (lend - lbegin) + 1;
243  }
244  }
245 
246  // Set the begin of the next interval and increment the iterator.
247 
248  lbegin = lend+1;
249  litr++;
250  }
251 
252  // Exit:
253 
254  return result;
255 }
256 
257 bool
260 {
261  bool result;
262 
263  // Preconditions:
264 
265  // Body:
266 
267  map_type::const_iterator litr = _interval_map.lower_bound(xbegin);
268 
269  result =
270  (litr == _interval_map.end()) ||
271  (!litr->second && (litr->first >= xend));
272 
273  // Postcondtions:
274 
275  // Exit:
276 
277  return result;
278 }
279 
280 bool
282 interval_is_full(pod_type xbegin, pod_type xend) const
283 {
284  bool result;
285 
286  // Preconditions:
287 
288  // Body:
289 
290  map_type::const_iterator litr = _interval_map.lower_bound(xbegin);
291 
292  result =
293  (litr != _interval_map.end()) &&
294  litr->second && (litr->first >= xend);
295 
296  // Postcondtions:
297 
298  // Exit:
299 
300  return result;
301 }
302 
305 begin() const
306 {
307  // Preconditions:
308 
309  // Body:
310 
311  pod_type result;
312 
313  if(is_empty())
314  {
315  result = invalid_pod_index();
316  }
317  else
318  {
319  result = _interval_map.begin()->first+1;
320  }
321 
322  // Postconditions:
323 
324  ensure(is_empty() ? !is_valid(result) : true);
325 
326  // Exit:
327 
328  return result;
329 }
330 
333 end() const
334 {
335  // Preconditions:
336 
337  // Body:
338 
339  pod_type result;
340 
341  if(is_empty())
342  {
343  result = invalid_pod_index();
344  }
345  else
346  {
347  map_iterator_type litr = _interval_map.end();
348  --litr;
349 
350  result = litr->first;
351  }
352 
353  // Postconditions:
354 
355  ensure(is_empty() ? !is_valid(result) : true);
356 
357  // Exit:
358 
359  return result;
360 }
361 
362 void
365 {
366  // Preconditions:
367 
368  // Body:
369 
370  _interval_map.clear();
371 
372  // Postconditions:
373 
374  ensure(invariant());
375  ensure(is_empty());
376 
377  // Exit:
378 
379  return;
380 }
381 
382 bool
384 is_empty() const
385 {
386  bool result;
387 
388  // Preconditions:
389 
390  // Body:
391 
392  result = _interval_map.empty();
393 
394  // Postconditions:
395 
396  ensure(is_basic_query);
397 
398  // Exit:
399 
400  return result;
401 }
402 
405 iterator(bool xis_full_iterator) const
406 {
407  interval_set_iterator* result;
408 
409  // Preconditions:
410 
411  // Body:
412 
413  result = new interval_set_iterator(*this, xis_full_iterator);
414 
415  // Postconditions:
416 
417  // Exit:
418 
419  return result;
420 }
421 
422 // PROTECTED MEMBER FUNCTIONS
423 
424 // PRIVATE MEMBER FUNCTIONS
425 
426 void
427 sheaf::interval_set::
428 put_interval(pod_type xbegin, pod_type xend, bool xvalue)
429 {
430  // Preconditions:
431 
432  // Body:
433 
434  // The map contains n entries {e(i) = (end, value), 0 <= i < n}
435  // and two implicit entries e(-1) = (before_end, false) and
436  // e(n) = (max_pod_index, false).
437  // These entries partition the src id space into n+1 intervals:
438  //
439  // r(-1) = [min_pod_index, e(-1)],
440  // r(0) = [e(-1)+1, e(0)],
441  // ... ,
442  // r(i) = [r(i-1)+1, e(i)],
443  // ... ,
444  // r(n) = [e(n-1)+1, e(n)].
445  //
446  // The value of the map at an index p is equal to lower_bound(p).mapped_value.
447  //
448  // The interval defined by [xbegin, xend] we will refer to as
449  // the "new interval". The interval r(l) = [e(l-1), e(l)) that satisfies
450  // e(l-1) < xbegin <= e(l) will be referred to as the "left interval".
451  // Similarly, the interval r(r) = [e(r-1), e(r)) that satisfies e(r-1) <
452  // xend <= e(r) will be referred to as the "right interval".
453  //
454  // The policy is that the new interval takes precedence over any existing
455  // intervals, so typically the left interval is truncated on the right
456  // by inserting a new entry (xbegin-1, old contains_member(xbegin)) and the
457  // right interval is truncated on the left inserting a new entry
458  // (xend, xvalue). Any existing entries that lie completely with the new
459  // interval are erased.
460  //
461  // Two special conditions complicate this typical case:
462  // (1) either xbegin or xend fall on an existing entry, and/or
463  // (2) the new interval extends an existing interval.
464  // Condition (1) requires dealing with the existing record and
465  // changes how to detect condition (2). Condition (2) requires merging
466  // intervals by either not inserting records or erasing them.
467  //
468  // If xbegin != e(i).key+1 for any i, then the new interval "right extends"
469  // the left interval if xvalue == old contains_member(xbegin) and we don't
470  // want to insert an entry for xbegin because it doesn't terminate
471  // the left interval or begin the new interval.
472  //
473  // If xbegin == e(i).key+1 for some i, then the new interval right extends the
474  // left interval if xvalue == e(i).value. Not only do we not want to insert
475  // a new entry, we want to erase the existing record because it no longer
476  // terminates the left interval or begins a new interval..
477  //
478  // Simlarly, if xend != e(i).key for any i, the new interval "left extends"
479  // the right interval if xvalue == e(r).value and we don't want
480  // to insert an entry for xend because it doesn't terminate the new
481  // interval or begin the right interval.
482  //
483  // If xend == e(i) for some i, then the new interval left extends the
484  // right interval if xvalue != e(i).value. Not only do we not want to
485  // insert a new entry, we want to erase the existing record because it
486  // no longer begins the right interval or terminates a new interval.
487 
488  // Put the beginning of the interval.
489 
490  map_type::iterator litr = _interval_map.find(xbegin-1);
491  if(litr != _interval_map.end())
492  {
493  // Begin == end of left interval.
494 
495  bool lold_begin = litr->second;
496  if(lold_begin == xvalue)
497  {
498  // New interval right extends left interval;
499  // remove the end of the existing interval.
500 
501  _interval_map.erase(litr);
502  }
503  else
504  {
505  // New interval terminates the left interval,
506  // but it's already terminated properly;
507  // do nothing.
508  }
509  }
510  else
511  {
512  // Begin is not the end of an existing interval.
513 
514  bool lold_begin = contains_member(xbegin);
515  if(lold_begin == xvalue)
516  {
517  // New interval right extends left interval;
518  // do nothing.
519  }
520  else
521  {
522  // New interval right truncates left interval.
523 
524  _interval_map[xbegin-1] = lold_begin;
525  }
526  }
527 
528  // Put the end of the interval.
529 
530  bool lold_end = contains_member(xend);
531 
532  litr = _interval_map.find(xend);
533  if(litr != _interval_map.end())
534  {
535  // End == begin of right interval.
536 
537  if(lold_end == xvalue)
538  {
539  // Make entry to terminate new interval;
540  // nothing to do.
541  }
542  else
543  {
544  // New interval left extends right interval;
545  // remove the begin of the existing interval.
546 
547  _interval_map.erase(litr);
548  }
549  }
550  else
551  {
552  // End is not beginning of right interval.
553 
554  if(lold_end == xvalue)
555  {
556  // New interval left extends right interval;
557  // do nothing.
558  }
559  else
560  {
561  // Make entry to terminate new interval;
562  // truncates right interval.
563 
564  _interval_map[xend] = xvalue;
565  }
566  }
567 
568  // Clear any existing entries within the interval.
569 
570  litr = _interval_map.lower_bound(xbegin);
571  while(litr != _interval_map.end() && litr->first < xend)
572  {
573  _interval_map.erase(litr);
574  litr = _interval_map.lower_bound(xbegin);
575  }
576 
577  // Postconditions:
578 
579  ensure(invariant());
580 
581  // Exit:
582 
583  return;
584 }
585 
586 
587 // =============================================================
588 // INTERVAL MAP FACET
589 // =============================================================
590 
591 // PUBLIC MEMBER FUNCTIONS
592 
596 {
597  return _interval_map;
598 }
599 
600 bool
603 {
604  // Preconditions:
605 
606  require(!is_empty());
607 
608  // Body:
609 
610  bool result = _interval_map.begin()->second;
611 
612  // Postconditions:
613 
614  // Exit:
615 
616  return result;
617 }
618 
619 bool
622 {
623  // Preconditions:
624 
625  require(!is_empty());
626 
627  // Body:
628 
629  bool result = (--_interval_map.end())->second;
630 
631  // Postconditions:
632 
633  // Exit:
634 
635  return result;
636 }
637 
638 // PROTECTED MEMBER FUNCTIONS
639 
640 // PRIVATE MEMBER FUNCTIONS
641 
642 
643 // =============================================================
644 // ANY FACET
645 // =============================================================
646 
647 // PUBLIC MEMBER FUNCTIONS
648 
649 bool
651 is_ancestor_of(const any* other) const
652 {
653  // Preconditions:
654 
655  require(other != 0);
656 
657  // Body:
658 
659  // True if other conforms to this
660 
661  bool result = dynamic_cast<const interval_set*>(other) != 0;
662 
663  // Postconditions:
664 
665  return result;
666 }
667 
670 clone() const
671 {
672  // Preconditions:
673 
674  // Body:
675 
676  interval_set* result = new interval_set();
677 
678  // Postconditions:
679 
680  ensure(result != 0);
681  ensure(result->is_empty());
682 
683  // Exit:
684 
685  return result;
686 }
687 
690 operator=(const interval_set& xother)
691 {
692  // Preconditions:
693 
694  // Body:
695 
696  _interval_map = xother._interval_map;
697 
698  // Postconditions:
699 
700  ensure(*this == xother);
701 
702  // Exit:
703 
704  return *this;
705 }
706 
707 bool
709 invariant() const
710 {
711  bool result = true;
712 
713  if(invariant_check())
714  {
715  // Must satisfy base class invariant
716 
717  invariance(any::invariant());
718 
719  // Prevent recursive calls to invariant
720 
721  disable_invariant_check();
722 
723  // Invariances for this class:
724 
725  invariance(is_empty() || !first_map_entry());
726  invariance_for_range(map_iterator_type itr = interval_map().begin(); pod_type i=0,
727  itr != interval_map().end(), ++itr; ++i,
728  itr->second == (i%2 == 1));
729  invariance(is_empty() || last_map_entry());
730 
731  // Finished, turn invariant checking back on.
732 
733  enable_invariant_check();
734  }
735 
736  // Exit
737 
738  return result;
739 }
740 
741 // PROTECTED MEMBER FUNCTIONS
742 
743 // PRIVATE MEMBER FUNCTIONS
744 
745 
746 // ===========================================================
747 // NON-MEMBER FUNCTIONS
748 // ===========================================================
749 
750 std::ostream&
751 sheaf::operator << (std::ostream& xos, const interval_set& xset)
752 {
753  // Preconditions:
754 
755  // Body:
756 
757  xos << endl << "begin: " << xset.begin()
758  << endl << "end: " << xset.end() << endl;
759 
760  xos << endl << "members:" << endl;
761  interval_set_iterator* litr = xset.iterator(true);
762  while(!litr->is_done())
763  {
764  interval_set::pod_type litem = litr->item();
765  xos << litem << " ";
766 
767  litr->next();
768  }
769  delete litr;
770 
771  xos << endl << endl << "non-members:" << endl;
772  litr = xset.iterator(false);
773  while(!litr->is_done())
774  {
775  interval_set::pod_type litem = litr->item();
776  xos << litem << " ";
777 
778  litr->next();
779  }
780  delete litr;
781 
782  xos << endl;
783 
784  // Postconditions:
785 
786  // Exit:
787 
788  return xos;
789 }
790 
791 size_t
792 sheaf::deep_size(const interval_set& xset, bool xinclude_shallow)
793 {
794  size_t result;
795 
796  // Preconditions:
797 
798  // Body:
799 
800  result = xinclude_shallow ? sizeof(xset) : 0;
801 
802  // Add the member allocated in member _interval_map.
803 
804  typedef interval_set::pod_type pod_type;
805  typedef no_deep_size_policy<map<pod_type, bool> > map_policy_type;
806  result += deep_size<pod_type, bool, map_policy_type>(xset._interval_map, false);
807 
808  // Preconditions:
809 
810  // Exit:
811 
812  return result;
813 }
An iterator over the integers in an interval_set.
bool is_empty() const
True, if this set is empty.
bool contains_member(pod_type xmbr) const
True, if the integer xmbr is in this set.
const map_type & interval_map() const
Map that defines the intervals of this set.
Set of integers optimized for when the integers are concentrated in closed intervals.
Definition: interval_set.h:70
bool last_map_entry() const
Value of the last map entry.
pod_index_type pod_type
The "plain old data" index type for this set.
Definition: interval_set.h:86
STL namespace.
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
bool interval_is_empty(pod_type xbegin, pod_type xend) const
True, if there are no members in this set for the interval [xbegin, xend].
std::map< pod_type, bool > map_type
The type of the interval map.
Definition: interval_set.h:198
Abstract base class with useful features for all objects.
Definition: any.h:39
bool operator==(const interval_set &xother) const
True if this is equivalent to xother.
Definition: interval_set.cc:86
Do not call deep_size on either the key or value.
Definition: deep_size.h:54
pod_type begin() const
The first member in this set.
SHEAF_DLL_SPEC size_t deep_size(const dof_descriptor_array &xp, bool xinclude_shallow=true)
The deep size of the referenced object of type dof_descriptor_array.
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
bool interval_is_full(pod_type xbegin, pod_type xend) const
True, if there is a continuous interval of members [xbegin, xend] in this set.
interval_set()
Default constructor.
Definition: interval_set.cc:35
pod_type item() const
The current integer of the iteration.
virtual bool invariant() const
Class invariant.
void next()
Makes item() the next integer in the iteration.
size_type member_ct(pod_type xbegin, pod_type xend) const
The number of members in the interval [xbegin, xend].
pod_type end() const
The last member in this set.
interval_set_iterator * iterator(bool xis_full_iterator) const
Iterator for this set. If xis_full_iterator, iterate over the members in the set. Otherwise...
void insert_interval(pod_type xbegin, pod_type xend)
Insert an interval of members [xbegin, xend] into this set.
virtual interval_set * clone() const
Virtual constructor, makes a new instance of the same type as this.
SHEAF_DLL_SPEC std::ostream & operator<<(std::ostream &os, const dof_descriptor_array &p)
Insert dof_descriptor_array& p into ostream& os.
~interval_set()
Destructor.
Definition: interval_set.cc:69
interval_set & operator=(const interval_set &xother)
Assignment operator.
void clear()
Clear this set.
SHEAF_DLL_SPEC bool is_valid(pod_index_type xpod_index)
True if an only if xpod_index is valid.
Definition: pod_types.cc:37
void remove_interval(pod_type xbegin, pod_type xend)
Remove an interval of members [xbegin, xend] from this set.
SHEAF_DLL_SPEC pod_index_type invalid_pod_index()
The invalid pod index value.
Definition: pod_types.cc:31
bool is_done() const
True if iteration is finished.
void insert_member(pod_type xmbr)
Insert xmbr into this set.
map_type::const_iterator map_iterator_type
The type of the interval map iterator.
Definition: interval_set.h:203
void remove_member(pod_type xmbr)
Remove xmbr from this set.
bool first_map_entry() const
Value of the first map entry.