Actual source code: Filter.hh
1: #ifndef included_ALE_Predicate_hh
2: #define included_ALE_Predicate_hh
4: #ifndef included_ALE_hh
5: #include <ALE.hh>
6: #endif
8: #include <boost/multi_index/mem_fun.hpp>
10: namespace ALE {
12: //
13: // Various Filter concepts and definitions
14: //
15: namespace FilterDef {
16: //
17: // PredicateTraits encapsulates Predicate types encoding object subsets with a given Predicate value or within a value range.
18: template<typename Predicate_>
19: struct PredicateTraits {};
20: // Traits of different predicate types are defined via specialization of PredicateTraits.
21: // We require that the predicate type act like a signed int.
22: template<>
23: struct PredicateTraits<int> {
24: typedef int predicate_type;
25: typedef int printable_type;
26: //
27: static const predicate_type third;
28: static const predicate_type max;
29: static const predicate_type min;
30: };
31: const PredicateTraits<int>::predicate_type PredicateTraits<int>::max = INT_MAX;
32: const PredicateTraits<int>::predicate_type PredicateTraits<int>::min = INT_MIN;
33: const PredicateTraits<int>::predicate_type PredicateTraits<int>::third = (abs(INT_MIN)<abs(INT_MAX))?abs(INT_MIN)/3:abs(INT_MAX)/3;
34: //
35: template<>
36: struct PredicateTraits<short> {
37: typedef short predicate_type;
38: typedef short printable_type;
39: //
40: static const predicate_type third;
41: static const predicate_type max;
42: static const predicate_type min;
43: };
44: const PredicateTraits<short>::predicate_type PredicateTraits<short>::max = SHRT_MAX;
45: const PredicateTraits<short>::predicate_type PredicateTraits<short>::min = SHRT_MIN;
46: const PredicateTraits<short>::predicate_type PredicateTraits<short>::third = (abs(SHRT_MIN)<abs(SHRT_MAX))?abs(SHRT_MIN)/3:abs(SHRT_MAX)/3;;
47: //
48: template<>
49: struct PredicateTraits<char> {
50: typedef char predicate_type;
51: typedef short printable_type;
52: //
53: static const predicate_type third;
54: static const predicate_type max;
55: static const predicate_type min;
56: };
57: const PredicateTraits<char>::predicate_type PredicateTraits<char>::max = CHAR_MAX;
58: const PredicateTraits<char>::predicate_type PredicateTraits<char>::min = CHAR_MIN;
59: const PredicateTraits<char>::predicate_type PredicateTraits<char>::third = (abs(CHAR_MIN)<abs(CHAR_MAX))?abs(CHAR_MIN)/3:abs(CHAR_MAX)/3;
60: //
61: template <typename Predicate_, typename PredicateTraits_ = PredicateTraits<Predicate_> >
62: struct PredicateRec {
63: typedef PredicateRec<Predicate_, PredicateTraits_> predicate_rec_type;
64: typedef Predicate_ predicate_type;
65: typedef PredicateTraits_ predicate_traits;
66: //
67: predicate_type predicate;
68: struct PredicateAdjuster {
69: PredicateAdjuster(const predicate_type& newPredicate = 0) :
70: _newPredicate(newPredicate) {};
71: void operator()(predicate_rec_type& r) {r.predicate = this->_newPredicate;};
72: private:
73: predicate_type _newPredicate; // assume predicate is cheap to copy,no more expensive than a pointer -- else ref would be used
74: };
75: //
76: // Basic interface
77: PredicateRec(const predicate_type& p = 0) : predicate(p) {};
78: PredicateRec(const PredicateRec& r) : predicate(r.p) {};
79: ~PredicateRec() {};
80: };
82: class FilterError : public ALE::Exception {
83: public:
84: explicit FilterError(const string& msg) : ALE::Exception(msg){}
85: explicit FilterError(const ostringstream& txt) : ALE::Exception(txt){};
86: ~FilterError(){};
87: };
89: template <typename PredicateSet_>
90: class DummyPredicateSetClearer {
91: public:
92: typedef PredicateSet_ predicate_set_type;
93: typedef typename predicate_set_type::value_type predicate_rec_type;
94: typedef typename predicate_rec_type::predicate_type predicate_type;
95: typedef typename predicate_rec_type::predicate_traits predicate_traits;
96: //
97: void clear(predicate_set_type& set, const predicate_type& low, const predicate_type& high){};
98: };
100: template <typename PredicateSet_, typename PredicateSetClearer_ = DummyPredicateSetClearer<PredicateSet_> >
101: struct FilterContainer {
102: public:
103: //
104: // Encapsulated types
105: typedef FilterContainer filter_container_type;
106: typedef PredicateSet_ predicate_set_type;
107: typedef typename predicate_set_type::value_type predicate_rec_type;
108: typedef typename predicate_rec_type::predicate_type predicate_type;
109: typedef typename predicate_rec_type::predicate_traits predicate_traits;
110: //
111: typedef PredicateSetClearer_ clearer_type;
112: //
113: class Filter : public std::pair<predicate_type, predicate_type> {
114: protected:
115: filter_container_type& _container;
116: public:
117: Filter(filter_container_type& container) : std::pair<predicate_type, predicate_type>(0,0), _container(container) {};
118: Filter(filter_container_type& container, const predicate_type& left, const predicate_type& right) :
119: std::pair<predicate_type, predicate_type>(left, right), _container(container) {};
120: Filter(const Filter& f) : std::pair<predicate_type, predicate_type>(f.left(), f.right()),_container(f._container) {};
121: ~Filter(){if((this->left()!=0)||(this->right()!=0)){this->_container.returnFilter(*this);}};
122: //
123: predicate_type left() const {return this->first;};
124: predicate_type right() const {return this->second;};
125: filter_container_type container() const {return this->_container;};
126: void extend(const predicate_type& width) {this->_container.extendFilter(*this, width);};
127: void contract(const predicate_type& width) {this->_container.contractFilter(*this, width);};
128: template <typename Stream_>
129: friend Stream_& operator<<(Stream_& os, const Filter& f) {
130: os << "[";
131: os << ((typename predicate_traits::printable_type)(f.left())) << ",";
132: os << ((typename predicate_traits::printable_type)(f.right()));
133: os << "]";
134: return os;
135: };
136: template <typename Stream_>
137: friend Stream_& operator<<(Stream_& os, const Obj<Filter>& f) {
138: os << "[";
139: os << ((typename predicate_traits::printable_type)(f->left())) << ",";
140: os << ((typename predicate_traits::printable_type)(f->right()));
141: os << "]";
142: return os;
143: };
144: };
145: typedef Filter filter_type;
146: typedef Obj<Filter> filter_object_type;
147:
148: //
149: //
150: // FilterSequence extends IndexSequence:
151: // 0) elements are 'PredicateRec's
152: // 1) holds the parent FilterContainer and an Obj<Filter>
153: // 2) elements' predicates can be modified through the index iterator
154: // 3) intent: in subclasses iterator construction (begin(), end()) and other queries should depend on the Filter(Object).
155: template <typename FilterContainer_, typename Index_, typename ValueExtractor_>
156: class FilterSequence : public IndexSequence<Index_, ValueExtractor_> { // class FilterSequence
157: public:
158: typedef FilterContainer_ container_type;
159: typedef IndexSequence<Index_, ValueExtractor_> index_sequence_type;
160: typedef typename index_sequence_type::index_type index_type;
161: typedef typename index_sequence_type::extractor_type extractor_type;
162: typedef typename container_type::filter_type filter_type;
163: typedef typename container_type::filter_object_type filter_object_type;
164: //
165: // Basic iterator over records with predicates
166: template <typename Sequence_ = FilterSequence>
167: class iterator : public index_sequence_type::template iterator<Sequence_> { // class iterator
168: public:
169: typedef typename index_sequence_type::template iterator<Sequence_> index_sequence_iterator;
170: typedef typename index_sequence_iterator::sequence_type sequence_type;
171: public:
172: iterator(sequence_type& sequence, typename index_type::iterator& itor) : index_sequence_iterator(sequence, itor) {};
173: iterator(const iterator& iter) : index_sequence_iterator(iter) {};
174: //
175: predicate_type predicate() const {return this->_itor->predicate;};
176: bool markOut(const predicate_type& p) {
177: // We only allow predicate to increase or decrease so as to leave the filter.
178: // In either case the iterator is advanced
179: filter_object_type f = this->_sequence.filter();
180: predicate_type left = 0;
181: predicate_type right = 0;
182: bool result = false;
183: if(!f.isNull()) {
184: left = f->left();
185: right = f->right();
186: }
187: if((p < left) || (p > right)){
188: // We keep a copy of the inderlying _itor of the location following *this prior to the mark up.
189: // This becomes the new value of *this at the end, since the marked up *this will be out of the filter.
190: iterator it(*this); ++it;
191: // We have to deal with the following "corner case":
192: // ++it points to this->_sequence.end(), but after having been marked Up *this becomes the new this->_sequence.end().
193: // There are two ways to deal with the situation:
194: // (1) the situation arises only if *this <= it, hence we can check for this using the ordering of this->_sequence --
195: // the ordering of the underlying index;
196: // (2) the situation arises only if until the markUp ++it == this->_sequence.end(), so we can check for this
197: // and at the end of the markUp enforce *this == this->_sequence.end() regardless of the actual relationship
198: // between ++it and *this;
199: // We choose option (2).
200: bool atEnd = (it == this->_sequence.end());
201: this->_sequence.mark(this->_itor, p);
202: // now we advance this->_itor relative to ++it, not to the new marked up *this
203: // can't use 'iterator' assignments because of the reference member _sequence
204: if(atEnd) {
205: this->_itor = this->_sequence.end()._itor;
206: }
207: else {
208: this->_itor = it._itor;
209: }
210: result = true;
211: }// if((p < left) || (p > right))
212: else {
213: ++(*this);
214: }
215: return result; // return true if markUp successful
216: };// markOut()
217: };// class iterator
218: protected:
219: container_type& _container;
220: filter_object_type _filter;
221: public:
222: //
223: // Basic interface
224: FilterSequence(const FilterSequence& seq) : index_sequence_type(seq),_container(seq._container), _filter(seq._filter) {};
225: FilterSequence(container_type& container, index_type& index, const filter_object_type& filter = filter_object_type()) :
226: index_sequence_type(index), _container(container), _filter(filter) {};
227: ~FilterSequence(){};
228: //
229: // Extended interface
230: filter_object_type filter() {return _filter;};
231: void mark(typename index_type::iterator itor, const predicate_type& p) {
232: this->_index.modify(itor, typename predicate_rec_type::PredicateAdjuster(p));
233: };
234: }; // class FilterSequence
235: protected:
236: predicate_set_type _set;
237: predicate_type _top;
238: predicate_type _bottom;
239: predicate_type _poccupancy[3];
240: predicate_type _noccupancy[3];
241: clearer_type _clearer;
242: void __clear(const predicate_type& low, const predicate_type& high) {this->_clearer.clear(this->_set,low,high);};
243: //
244: void __validateFilter(const filter_type& f) {
245: // Check filter validity
246: bool negative = (f.left() < 0);
247: // Produce correct filter limits and figure out which occupancy array to use
248: predicate_type left;
249: predicate_type right;
250: if(negative) {
251: left = -f.right(); right = -f.left();
252: }
253: else {
254: left = f.left(); right = f.right();
255: }
256: predicate_type width = right - left + 1;
257: if(((f.left() > 0)&&(f.right() < 0)) || ((f.left() < 0)&&(f.right() > 0))) {
258: throw FilterError("inverted");
259: }
260: if((f.left()==0) || (f.right()==0)) {
261: throw FilterError("zero extremum");
262: }
263: if(width > predicate_traits::third) {
264: ostringstream txt;
265: txt << "width too large: " << (typename predicate_traits::printable_type)width;;
266: txt << " (limit is " << (typename predicate_traits::printable_type)predicate_traits::third << ")";
267: throw FilterError(txt);
268: }
269: };// __validateFilter()
270: public:
271: //
272: // Basic interface
273: FilterContainer() : _top(1), _bottom(1) {
274: this->_poccupancy[0] = 0; this->_poccupancy[1] = 0; this->_poccupancy[2] = 0;
275: this->_noccupancy[0] = 0; this->_noccupancy[1] = 0; this->_noccupancy[2] = 0;
276: };
277: ~FilterContainer() {};
278: //
279: // Extended interface
280: predicate_type top() const {return this->_top;};
281: predicate_type bottom() const {return this->_bottom;};
282: predicate_type pOccupancy(const int& i) const {
283: if((i < 0) || (i > 2)){throw FilterError("Invalid interval index");}
284: return this->_poccupancy[i];
285: };
286: predicate_type nOccupancy(const int& i) const {
287: if((i < 0) || (i > 2)){throw FilterError("Invalid interval index");}
288: return this->_noccupancy[i];
289: };
290: public:
291: //
292: filter_object_type newFilter(predicate_type width) {
293: // This routine will allocate a new filter prescribed by a (left,right) predicate pair.
294: // Depending on the sign of width, left & right are both positive or negative; here we describe the positive case.
295: // Filter endpoints are chosen from three different intervals of size predicate_traits::third ('third' here) each:
296: // 'left' is picked from [1,third] or [third+1,2*third],
297: // while 'right' is picked from [1,third],[third+1,2*third],[2*third+1,3*third].
298: // The container keeps track of the number of filters intersecting each interval as well as the 'top' of the allocated
299: // predicate range: 'top' is the next available predicate -- the next 'left'. Here are the rules for picking 'left' and 'right':
300: // (1) 'left' = 'top', 'right' = 'left' + width - 1, and allocation of 'width' = 'right' - 'left' + 1 >= 'third' fails.
301: // Hence, if 'left' is from [1,third] then 'right' can be from [1,third] or [third+1,2*third]
302: // (depending on 'left' & 'width').
303: // Likewise, if 'left' is from [third+1,2*third] then 'right' can be from [third+1,2*third] or [2*third+1,3*third].
304: // (2) When 'top' ends up in [2*third+1, 3*third] it is shifted to 1 upon a subsequent allocation request so that it is
305: // served from [1,third] thereby completing the 'circle'.
306: // (3) Any time a filter crosses into a new interval, that interval is required to have no intersections with previously
307: // allocated filters, or allocation fails.
308: // The rules can be intuitively summed up by imagining a cycle of intervals such that all old filters are deallocated from
309: // an interval before new filters move in there again. The working assumption is that the life span of filters is short enough
310: // relative to the rate of new filter creation. Rule (2) ensures that the interval endpoints always satisfy left <= right:
311: // [2*third+1, 3*third] forms an 'overlflow buffer' for [third+1,2*third] and is little used.
312: //
313: if(width == 0) {
314: ostringstream txt; txt << "Invalid filter requested: width = " << width << " (" << *this << ")";
315: throw FilterError(txt);
316: }
317: // Select the correct 'top' & 'occupancy' indicators and make 'width' positive, if necessary
318: bool negative = (width < 0);
319: predicate_type* occupancy;
320: predicate_type* top;
321: if(negative) {
322: width = -width;
323: occupancy = this->_noccupancy;
324: top = &(this->_bottom);
325:
326: }
327: else {
328: occupancy = this->_poccupancy;
329: top = &(this->_top);
330: }
331: if(width > predicate_traits::third){
332: ostringstream txt; txt << "Too big a filter requested: width = " << (typename predicate_traits::printable_type)width;
333: txt << " (" << *this << ")";
334: throw FilterError(txt);
335: }
336: // First, we set 'top' to 1 if it is greater than 2*third (i.e. within [2*third+1, 3*third]).
337: if(*top > 2*predicate_traits::third) {
338: *top = 1;
339: }
340: predicate_type lastRight = *top-1; // 'right' of the preceeding interval
341: predicate_type left = *top;
342: predicate_type right = *top+width-1;
343: // Before we return the new filter, internal bookkeeping and checks must be done to enforce the rules above.
344: for(int i = 0; i < 2; i++) {
345: // Check if crossing from the (i-1)-st interval [(i-1)*third+1,i*third] to the i-th interval [i*third+1,i*third] has occured.
346: if((lastRight <= i*predicate_traits::third) && (right > i*predicate_traits::third)) {
347: // Line from [(i-1)*third+1,i*third] to [i*third+1,(i+1)*third] has been crossed
348: // Check if [i*third+1,(i+1)*third] has been fully vacated
349: if(occupancy[i] > 0){
350: ostringstream txt;
351: if(negative) {
352: txt << "Negative ";
353: }
354: else {
355: txt << "Positive ";
356: }
357: txt << "interval " << i << " not fully vacated when new filter requested: width = ";
358: txt << (typename predicate_traits::printable_type)width;
359: txt << " (" << *this << ")";
360: throw FilterError(txt);
361: }
362: // Clear out the interval [i*third+1,(i+1)*third]
363: this->__clear(i*predicate_traits::third+1, (i+1)*predicate_traits::third);
364: break;
365: }
366: }// for(int i = 0; i < 2; i++) {
367: // Adjust occupancy of intervals
368: // Find the interval that 'left' lies in: 'left' is only allowed in the first two intervals
369: for(int i = 0; i < 2; i++) {
370: if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
371: ++(occupancy[i]);
372: // Now check whether the interval spans two intervals (i.e., 'right' lies in the following interval)
373: if(right > (i+1)*predicate_traits::third) {
374: ++(occupancy[i+1]);
375: }
376: }
377: }// for(int i = 0; i < 2; i++)
378: // Finally, we advance 'top'
379: *top = right+1;
380: //
381: filter_object_type f;
382: f.create(filter_type(*this));
383: if(negative) {
384: f->first = -right;
385: f->second = -left;
386: }
387: else {
388: f->first = left;
389: f->second = right;
390: }
391: return f;
392: }; // newFilter()
393: //
394: void extendFilter(filter_type& f, const predicate_type& w) {
395: try {
396: __validateFilter(f);
397: }
398: catch(const FilterError& e) {
399: ostringstream txt;
400: txt << "Cannot extend invalid filter " << f << " in container " << f.container() << ": " << e.msg();
401: throw FilterError(txt);
402: }
403: // Positive or negative filter?
404: bool negative = (f.left() < 0);
405: predicate_type width = f.right()-f.left()+1;
406: predicate_type *top;
407: predicate_type *occupancy;
408: predicate_type left, right;
409: if(negative) {
410: width = -width;
411: top = &this->_bottom;
412: occupancy = this->_noccupancy;
413: left = -f.right();
414: right = -f.left();
415: }
416: else {
417: top = &this->_top;
418: occupancy = this->_poccupancy;
419: left = f.left();
420: right = f.right();
421: }
422: // Only top filters can be extended
423: if(right + 1 != *top){
424: ostringstream txt;
425: txt << "Only top/bottom filters can be extended: filter " << f << " in container " << *this;
426: }
427: if((width + w) > predicate_traits::third) {
428: ostringstream txt;
429: txt << "Extesion of ";
430: if(negative) {
431: txt << "negative ";
432: }
433: else {
434: txt << "positive ";
435: }
436: txt << "filter " << f << " by " << w;
437: txt << " width would exceed width limit of " << predicate_traits::third << " in container " << *this;
438: }
439: // newRight is right + w. Is newRight > 3*third? How do we check without an overflow?
440: // newRight = left + width - 1 + w, so newRight > 3*third <==> width + w = newRight - left + 1 > third - left + 1.
441: if(w+width > (3*predicate_traits::third-left+1)) {
442: ostringstream txt;
443: txt << "Extesion of ";
444: if(negative) {
445: txt << "negative ";
446: }
447: else {
448: txt << "positive ";
449: }
450: txt << "filter " << f << " by " << w;
451: txt << " width would exceed the upper limit limit of " << 3*predicate_traits::third << " in container " << *this;
452: }
453: predicate_type newRight = right + w;
454: // CONTINUE: this is sorta messed up
455: // Locate the 'right' footprint
456: for(int i = 0; i < 2; i++) {
457: if((i*predicate_traits::third < right) && (right <= (i+1)*predicate_traits::third)) {
458: if(newRight > (i+1)*predicate_traits::third){ // crossing occured
459: // Extension leads to a new interval crossing into the (i+1)-st interval
460: // We check if the interval is occupied or not
461: if(occupancy[i+1] > 0){
462: ostringstream txt;
463: if(negative) {
464: txt << "Negative ";
465: }
466: else {
467: txt << "Positive ";
468: }
469: txt << "interval " << i+1 << " not fully vacated when attempting extension of filter " << f << "by width = " << w;
470: txt << (typename predicate_traits::printable_type)w;
471: txt << " (container " << *this << ")";
472: throw FilterError(txt);
473: }
474: // Clear out the interval [i*third+1,(i+1)*third]
475: this->__clear((i+1)*predicate_traits::third+1, (i+2)*predicate_traits::third);
476: // We record the new crossing in the occupancy array
477: ++(occupancy[i+1]);
478: break;
479: }// if(newRight > (i+1)*predicate_traits::third): crossing occured
480: }// if((i*predicate_traits::third < right) && (right <= (i+1)*predicate_traits::third))
481: }// for(int i = 0; i < 2; i++)
482: // Update 'top'
483: *top = newRight+1;
484: // Update filter limits
485: if(negative) {
486: f.first = -newRight;
487: }
488: else {
489: f.second = newRight;
490: }
491: };// extendFilter()
492: //
493: void contractFilter(filter_type& f, const predicate_type& w) {
494: try{
495: __validateFilter(f);
496: }
497: catch(const FilterError& e) {
498: ostringstream txt;
499: txt << "Cannot contract invalid filter " << f << " in container " << f.container() << ": " << e.msg();
500: throw FilterError(txt);
501: }
502: // Positive or negative filter?
503: bool negative = (f.left() < 0);
504: predicate_type width = f.right()-f.left()+1;
505: predicate_type *top;
506: predicate_type *occupancy;
507: predicate_type left, right;
508: if(negative) {
509: width = -width;
510: top = &this->_bottom;
511: occupancy = this->_noccupancy;
512: left = -f.right();
513: right = -f.left();
514: }
515: else {
516: top = &this->_top;
517: occupancy = this->_poccupancy;
518: left = f.left();
519: right = f.right();
520: }
521: if((width - w) <= 0) {
522: ostringstream txt;
523: txt << "Contraction of ";
524: if(negative) {
525: txt << "negative ";
526: }
527: else {
528: txt << "positive ";
529: }
530: txt << "filter " << f << " by " << w;
531: txt << " would result in non-positive filter width " << width - w << " in container " << *this;
532: }
533: predicate_type newLeft = left + w;
534: // Locate the 'left' footprint
535: for(int i = 0; i < 2; i++) {
536: if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
537: if(newLeft > (i+1)*predicate_traits::third){
538: // Extension leads to a new interval crossing eliminated, which we record in the occupancy array
539: --occupancy[i];
540: }
541: }
542: }
543: // Update filter limits
544: if(negative) {
545: f.second = -newLeft;
546: }
547: else {
548: f.first = newLeft;
549: }
550: };// contractFilter()
551: //
552: void returnFilter(const filter_type& f) {
553: try {
554: __validateFilter(f);
555: }
556: catch(const FilterError& e) {
557: ostringstream txt;
558: txt << "Cannot return invalid filter " << f << " in container " << f.container() << ": " << e.msg();
559: throw FilterError(txt);
560: }
561: // Compute the sign of the filter
562: bool negative = (f.left() < 0);
563: // Produce correct filter limits and figure out which occupancy array to use
564: predicate_type left;
565: predicate_type right;
566: predicate_type* occupancy;
567: if(negative) {
568: left = -f.right(); right = -f.left();
569: occupancy = this->_noccupancy;
570: }
571: else {
572: left = f.left(); right = f.right();
573: occupancy = this->_poccupancy;
574: }
575: // Find the interval that 'left' lies in: 'left' only allowed in the first two intervals
576: for(int i = 0; i < 2; i++) {
577: if((i*predicate_traits::third < left) && (left <= (i+1)*predicate_traits::third)) {
578: if(occupancy[i] == 0) {
579: ostringstream txt;
580: if(negative) {
581: txt << "Negative ";
582: }
583: else {
584: txt << "Positive ";
585: }
586: txt << "occupancy of interval " << i << " will be negative upon closing of filter " << f;
587: txt << " (container: " << *this << ")";
588: throw FilterError(txt);
589: }
590: --(occupancy[i]);
591: // Now check whether the interval spans two intervals (i.e., 'right' lies in the following interval)
592: if(right > (i+1)*predicate_traits::third) {
593: if(occupancy[i+1] == 0) {
594: ostringstream txt;
595: if(negative) {
596: txt << "Negative ";
597: }
598: else {
599: txt << "Positive ";
600: }
601: txt << "occupancy of interval " << i+1 << " will be negative upon closing of filter " << f;
602: txt << " (container: " << *this << ")";
603: throw FilterError(txt);
604: }
605: --(occupancy[i+1]);
606: }
607: }
608: }// for(int i = 0; i < 2; i++)
609: }; // returnFilter()
610: //
611: // Printing
612: template <typename Stream_>
613: friend Stream_& operator<<(Stream_& os, const FilterContainer& fc) {
614: os << "top = " << (typename predicate_traits::printable_type)(fc.top()) << ", pOccupancy = [";
615: os << (typename predicate_traits::printable_type)(fc.pOccupancy(0)) << ",";
616: os << (typename predicate_traits::printable_type)(fc.pOccupancy(1)) << ",";
617: os << (typename predicate_traits::printable_type)(fc.pOccupancy(2));
618: os << "]; ";
619: os << "bottom = " << (typename predicate_traits::printable_type)(fc.bottom()) << ", nOccupancy = [";
620: os << (typename predicate_traits::printable_type)(fc.nOccupancy(0)) << ",";
621: os << (typename predicate_traits::printable_type)(fc.nOccupancy(1)) << ",";
622: os << (typename predicate_traits::printable_type)(fc.nOccupancy(2));
623: os << "]; ";
624: return os;
625: };
626: };// class FilterContainer
627: }// namespace FilterDef
629: namespace X {
630: using namespace ALE::FilterDef;
631: namespace SifterDef { // namespace SifterDef
632: //
633: // Various ArrowContainer definitionsg
634: //
636: // Index tags
637: struct PredicateTag{};
638: struct ConeTag{};
640: // Arrow record 'concept' -- conceptual structure names the fields expected in such an ArrowRec
641: template <typename Predicate_, typename Arrow_>
642: struct ArrowRec : public PredicateRec<Predicate_> {
643: typedef PredicateRec<Predicate_> predicate_rec_type;
644: typedef typename predicate_rec_type::predicate_type predicate_type;
645: typedef typename predicate_rec_type::predicate_traits predicate_traits;
646: //
647: typedef Arrow_ arrow_type;
648: typedef typename arrow_type::source_type source_type;
649: typedef typename arrow_type::target_type target_type;
650: typedef typename arrow_type::color_type color_type;
651: public:
652: //
653: arrow_type arrow;
654: public:
655: //
656: // Basic interface
657: ArrowRec(const source_type& s, const target_type& t, const color_type& c, const predicate_type& p = predicate_type()) :
658: predicate_rec_type(p), arrow(s,t,c) {};
659: ArrowRec(const ArrowRec& r) :
660: predicate_rec_type(r.predicate), arrow(r.arrow.source, r.arrow.target, r.arrow.color) {};
661: ~ArrowRec(){};
662: //
663: // Extended interface
664: const predicate_type& getPredicate() const {return this->predicate;};
665: const arrow_type& getArrow() const {return this->arrow;};
666: const source_type& getSource() const {return this->arrow.source;};
667: const target_type& getTarget() const {return this->arrow.target;};
668: const color_type& getColor() const {return this->arrow.color;};
669: template <typename Stream_>
670: friend Stream_& operator<<(Stream_& os, const ArrowRec& r) {
671: os << r.getArrow() << " <" << (typename predicate_traits::printable_type)(r.getPredicate()) << "> ";
672: return os;
673: };
674: };// class ArrowRec
675:
676: template<typename ArrowRecSet_, typename FilterTag_>
677: struct ArrowContainer : public FilterContainer<ArrowRecSet_, FilterTag_> { // class ArrowContainer
678: public:
679: //
680: // Encapsulated types
681: typedef FilterContainer<ArrowRecSet_, FilterTag_> filter_container_type;
682: typedef typename filter_container_type::filter_type filter_type;
683: typedef typename filter_container_type::filter_object_type filter_object_type;
684: //
685: typedef ArrowRecSet_ arrow_rec_set_type; //must have correct tags
686: typedef typename arrow_rec_set_type::value_type arrow_rec_type; // must (conceptually) extend ArrowContainerDef::ArrowRec
687: typedef typename arrow_rec_type::arrow_type arrow_type; // arrow_type must have 'source','target','color' fields
688: typedef typename arrow_rec_type::predicate_type predicate_type;
689: typedef typename arrow_rec_type::predicate_traits predicate_traits;
690: //
691: typedef typename arrow_type::source_type source_type;
692: typedef typename arrow_type::target_type target_type;
693: typedef typename arrow_type::color_type color_type;
694: //
695: //
696: template <typename ArrowContainer_, typename Index_, typename ValueExtractor_>
697: class NoKeyArrowSequence : public filter_container_type::template FilterSequence<ArrowContainer_, Index_, ValueExtractor_>
698: { // class NoKeyArrowSequence
699: public:
700: //
701: // Encapsulated types
702: typedef typename filter_container_type::template FilterSequence<ArrowContainer_,Index_,ValueExtractor_> filter_sequence_type;
703: typedef typename filter_sequence_type::container_type container_type;
704: typedef typename filter_sequence_type::index_sequence_type index_sequence_type;
705: typedef typename filter_sequence_type::index_type index_type;
706: typedef typename filter_sequence_type::extractor_type extractor_type;
707: typedef typename filter_sequence_type::filter_type filter_type;
708: typedef typename filter_sequence_type::filter_object_type filter_object_type;
709: // Need to extend the inherited iterator to be able to extract arrow attributes
710: template <typename Sequence_ = NoKeyArrowSequence>
711: class iterator : public filter_sequence_type::template iterator<Sequence_> {
712: public:
713: typedef typename filter_sequence_type::template iterator<Sequence_> filter_sequence_iterator;
714: typedef typename filter_sequence_iterator::sequence_type sequence_type;
715: typedef typename sequence_type::index_type index_type;
716: //
717: iterator(sequence_type& sequence, typename index_type::iterator itor) : filter_sequence_iterator(sequence, itor) {};
718: virtual const source_type& source() const {return this->_itor->arrow.source;};
719: virtual const color_type& color () const {return this->_itor->arrow.color;};
720: virtual const target_type& target() const {return this->_itor->arrow.target;};
721: virtual const arrow_type& arrow () const {return this->_itor->arrow;};
722: };// class iterator
723: public:
724: //
725: // Basic interface
726: NoKeyArrowSequence(const NoKeyArrowSequence& seq) : filter_sequence_type(seq) {};
727: NoKeyArrowSequence(container_type& container, index_type& index, filter_object_type filter=filter_object_type()) : filter_sequence_type(container, index, filter) {};
728: ~NoKeyArrowSequence() {};
729: //
730: // Extended interface
731: virtual typename index_type::size_type size() {
732: typename index_type::size_type sz = 0;
733: predicate_type low = 0;
734: predicate_type high = 0;
735: if(!(this->_filter.isNull())) {
736: low = this->_filter->left();
737: high = this->_filter->right();
738: }
739: for(predicate_type p = low; p != high; p++) {
740: sz += this->_index.count(p);
741: }
742: return sz;
743: };
744: virtual iterator<> begin() {
745: predicate_type low = 0;
746: if(!(this->_filter.isNull())) {
747: low = this->_filter->left();
748: }
749: return iterator<>(*this, this->_index.lower_bound(low));
750: };
751: virtual iterator<> end() {
752: predicate_type high = 0;
753: if(!(this->_filter.isNull())) {
754: high = this->_filter->right();
755: }
756: return iterator<>(*this, this->_index.upper_bound(high));
757: };
758: template<typename ostream_type>
759: void view(ostream_type& os, const char* label = NULL){
760: os << "Viewing";
761: if(label != NULL) {
762: os << " " << label;
763: }
764: if(!this->_filter.isNull()) {
765: os << " filtered";
766: }
767: os << " sequence";
768: if(!this->_filter.isNull()) {
769: os << ", filter " << this->_filter;
770: }
771: os << ":" << std::endl;
772: os << "[";
773: for(iterator<> i = this->begin(); i != this->end(); i++) {
774: if(i != this->begin()) {
775: os << ", " << i.arrow();
776: }
777: else {
778: os << i.arrow();
779: }
780: os << " <" << (typename predicate_traits::printable_type)(i.predicate()) << ">";
781: };
782: os << "]" << std::endl;
783: };// view()
784: };// class NoKeyArrowSequence
785: //
786: template <typename ArrowContainer_, typename Index_, typename Key_, typename ValueExtractor_>
787: class UniKeyArrowSequence : public filter_container_type::template FilterSequence<ArrowContainer_, Index_, ValueExtractor_>
788: { // class TopFilterArrowSequence
789: public:
790: //
791: // Encapsulated types
792: typedef typename filter_container_type::template FilterSequence<ArrowContainer_,Index_,ValueExtractor_> filter_sequence_type;
793: typedef typename filter_sequence_type::container_type container_type;
794: typedef typename filter_sequence_type::index_sequence_type index_sequence_type;
795: typedef typename filter_sequence_type::index_type index_type;
796: typedef typename filter_sequence_type::extractor_type extractor_type;
797: typedef typename filter_sequence_type::filter_type filter_type;
798: typedef typename filter_sequence_type::filter_object_type filter_object_type;
799: typedef Key_ key_type;
800: // Need to extend the inherited iterator to be able to extract arrow attributes
801: template <typename Sequence_ = UniKeyArrowSequence>
802: class iterator : public filter_sequence_type::template iterator<Sequence_> {
803: public:
804: typedef typename filter_sequence_type::template iterator<Sequence_> filter_sequence_iterator;
805: typedef typename filter_sequence_iterator::sequence_type sequence_type;
806: typedef typename sequence_type::index_type index_type;
807: //
808: iterator(sequence_type& sequence, typename index_type::iterator itor) : filter_sequence_iterator(sequence, itor) {};
809: virtual const source_type& source() const {return this->_itor->arrow.source;};
810: virtual const color_type& color () const {return this->_itor->arrow.color;};
811: virtual const target_type& target() const {return this->_itor->arrow.target;};
812: virtual const arrow_type& arrow () const {return this->_itor->arrow;};
813: };// class iterator
814: protected:
815: const key_type _key;
816: public:
817: //
818: // Basic interface
819: UniKeyArrowSequence(const UniKeyArrowSequence& seq) : filter_sequence_type(seq), _key(seq._key) {};
820: UniKeyArrowSequence(container_type& container, index_type& index,const key_type& key, filter_object_type filter=filter_object_type()) : filter_sequence_type(container, index, filter), _key(key) {};
821: ~UniKeyArrowSequence() {};
822: //
823: // Extended interface
824: virtual typename index_type::size_type size() {
825: typename index_type::size_type sz = 0;
826: predicate_type low = 0;
827: predicate_type high = 0;
828: if(!(this->_filter.isNull())) {
829: low = this->_filter->left();
830: high = this->_filter->right();
831: }
832: for(predicate_type p = low; p != high; p++) {
833: sz += this->_index.count(::boost::make_tuple(this->_key,p));
834: }
835: return sz;
836: };
837: virtual iterator<> begin() {
838: predicate_type low = 0;
839: if(!(this->_filter.isNull())) {
840: low = this->_filter->left();
841: }
842: return iterator<>(*this, this->_index.lower_bound(::boost::make_tuple(this->_key,low)));
843: };
844: virtual iterator<> end() {
845: predicate_type high = 0;
846: if(!(this->_filter.isNull())) {
847: high = this->_filter->right();
848: }
849: return iterator<>(*this, this->_index.upper_bound(::boost::make_tuple(this->_key,high)));
850: };
851: virtual iterator<> beginAll() {
852: return iterator<>(*this, this->_index.lower_bound(::boost::make_tuple(this->_key)));
853: };
854: virtual iterator<> endAll() {
855: return iterator<>(*this, this->_index.upper_bound(::boost::make_tuple(this->_key)));
856: };
857: template<typename ostream_type>
858: void view(ostream_type& os, const char* label = NULL){
859: os << "Viewing";
860: if(label != NULL) {
861: os << " " << label;
862: }
863: if(!this->_filter.isNull()) {
864: os << " filtered";
865: }
866: os << " sequence";
867: if(!this->_filter.isNull()) {
868: os << ", filter " << this->_filter;
869: }
870: os << ":" << std::endl;
871: os << "[";
872: for(iterator<> i = this->begin(); i != this->end(); i++) {
873: if(i != this->begin()) {
874: os << ", " << i.arrow();
875: }
876: else {
877: os << i.arrow();
878: }
879: os << " <" << (typename predicate_traits::printable_type)(i.predicate()) << ">";
880: };
881: os << "]" << std::endl;
882: };// view()
883: };// class UniKeyArrowSequence
884: public:
885: //
886: // Basic interface
887: ArrowContainer() {};
888: ArrowContainer(const ArrowContainer& container) : filter_container_type(container) {};
889: ~ArrowContainer(){};
890: //
891: // Extended interface
892: void addArrow(const source_type& s, const target_type& t, const color_type& c) {
893: this->_set.insert(arrow_rec_type(s,t,c));
894: };
895: //
896: typedef UniKeyArrowSequence<ArrowContainer,
897: typename ::boost::multi_index::index<arrow_rec_set_type,ConeTag>::type,
898: target_type,
899: typename ::boost::multi_index::const_mem_fun<arrow_rec_type, const source_type&, &arrow_rec_type::getSource> >
900: ConeSequence;
901: ConeSequence cone(const target_type& t, typename ConeSequence::filter_object_type f = filter_object_type()) {
902: return ConeSequence(*this, ::boost::multi_index::get<ConeTag>(this->_set), t, f);
903: };
904: };// class ArrowContainer
906: //
907: // Various PointContainer definitions
908: //
910: // Index tags
911: struct PointTag{};
913: // Point record 'concept' -- conceptual structure names the fields expected in such an PointRec
914: template <typename Predicate_, typename Point_>
915: struct PointRec : public PredicateRec<Predicate_> {
916: typedef PredicateRec<Predicate_> predicate_rec_type;
917: typedef typename predicate_rec_type::predicate_type predicate_type;
918: typedef typename predicate_rec_type::predicate_traits predicate_traits;
919: //
920: typedef Point_ point_type;
921: public:
922: //
923: point_type point;
924: public:
925: //
926: // Basic interface
927: PointRec(const point_type& q, const predicate_type& p = predicate_type()) : predicate_rec_type(p), point(q) {};
928: PointRec(const PointRec& r) : predicate_rec_type(r.predicate), point(r.point) {};
929: ~PointRec(){};
930: //
931: // Extended interface
932: const predicate_type& getPredicate() const {return this->predicate;};
933: const point_type& getPoint() const {return this->point;};
934: template <typename Stream_>
935: friend Stream_& operator<<(Stream_& os, const PointRec& r) {
936: os << r.getPoint() << " <" << (typename predicate_traits::printable_type)(r.getPredicate()) << "> ";
937: return os;
938: };
939: };// class PointRec
941: };// namespace SifterDef
943: typedef SifterDef::ArrowRec<char, ALE::Arrow<int, int, int> > MyArrowRec;
944: typedef SifterDef::PointRec<char, ALE::Point> MySourceRec;
945: typedef SifterDef::PointRec<char, ALE::Point> MyTargetRec;
947: // multi-index set type -- arrow set
948: typedef ::boost::multi_index::multi_index_container<
949: MyArrowRec,
950: ::boost::multi_index::indexed_by<
951: ::boost::multi_index::ordered_non_unique<
952: ::boost::multi_index::tag<SifterDef::ConeTag>,
953: ::boost::multi_index::composite_key<
954: MyArrowRec,
955: ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::target_type&, &MyArrowRec::getTarget>,
956: ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::predicate_type&, &MyArrowRec::getPredicate>,
957: ::boost::multi_index::const_mem_fun<MyArrowRec, const MyArrowRec::color_type&, &MyArrowRec::getColor>
958: >
959: >
960: >,
961: ALE_ALLOCATOR<MyArrowRec>
962: > UniColorArrowSet;
963: }; // namespace X
964: }; // namespace ALE
966: #endif