Actual source code: XSieve.hh
1: #ifndef included_ALE_XSieve_hh
2: #define included_ALE_XSieve_hh
4: #include <X.hh>
6: namespace ALE {
7:
8: namespace XSieveDef {
10: //
11: // Rec compares
12: //
13: // RecKeyOrder compares records by comparing keys of type Key_ extracted from arrows using a KeyExtractor_.
14: // In addition, a record can be compared to a single Key_ or another CompatibleKey_.
15: #undef __CLASS__
17: template<typename Rec_, typename KeyExtractor_, typename KeyOrder_ = std::less<typename KeyExtractor_::result_type> >
18: struct RecKeyOrder {
19: typedef Rec_ rec_type;
20: typedef KeyExtractor_ key_extractor_type;
21: typedef typename key_extractor_type::result_type key_type;
22: typedef KeyOrder_ key_order_type;
23: protected:
24: key_order_type _key_order;
25: key_extractor_type _kex;
26: public:
27: key_order_type& keyCompare(){return this->_key_order;};
28: //
29: bool operator()(const rec_type& rec1, const rec_type& rec2) const {
30: return this->_key_order(this->_kex(rec1), this->_kex(rec2));
31: };
32: //
33: // bool operator()(const key_type& key1, const key_type& key2) const {
34: // return this->_key_order(key1, key2);
35: // };
36: //
37: #undef __FUNCT__
39: #undef __ALE_XDEBUG__
41: template <typename CompatibleKey_>
42: bool operator()(const rec_type& rec, const CompatibleKey_ key) const {
43: static bool res;
44: res = this->_key_order(this->_kex(rec), key);
45: #ifdef ALE_USE_DEBUGGING
46: if(ALE_XDEBUG) {
47: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
48: if(res) {
49: std::cout << rec << " < " << key << "\n";
50: }
51: else {
52: std::cout << rec << " >= " << key << "\n";
53: }
54: };
55: #endif
56: return res;
57: };
58: //
59: #undef __FUNCT__
61: #undef __ALE_XDEBUG__
63: template <typename CompatibleKey_>
64: bool operator()(const CompatibleKey_ key, const rec_type rec) const {
65: static bool res;
66: res = this->_key_order(key,this->_kex(rec));
67: #ifdef ALE_USE_DEBUGGING
68: if(ALE_XDEBUG) {
69: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
70: if(res) {
71: std::cout << key << " < " << rec << "\n";
72: }
73: else {
74: std::cout << key << " >= " << rec << "\n";
75: }
76: };
77: #endif
78: return res;
79: };
80: //
81: #undef __FUNCT__
83: #undef __ALE_XDEBUG__
85: template <typename CompatibleKey_>
86: bool operator()(const CompatibleKey_ key, const rec_type& rec) const {
87: static bool res;
88: res = this->_key_order(key, this->_kex(rec));
89: #ifdef ALE_USE_DEBUGGING
90: if(ALE_XDEBUG) {
91: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
92: if(res) {
93: std::cout << rec << " < " << key << "\n";
94: }
95: else {
96: std::cout << rec << " >= " << key << "\n";
97: }
98: };
99: #endif
100: return res;
101: };
102: };// RecKeyOrder
104: //
105: // Composite Rec ordering operators (e.g., used to generate cone and support indices for Arrows).
106: // An RecKeyXXXOrder first orders on a single key using KeyOrder (e.g., Target or Source for cone and support respectively),
107: // and then on the whole Rec, using an additional predicate XXXOrder.
108: // These are then specialized (with Rec = Arrow) to SupportCompare & ConeCompare, using the order operators supplied by the user:
109: // SupportOrder = (SourceOrder, SupportXXXOrder),
110: // ConeOrder = (TargetOrder, ConeXXXOrder), etc
111: #undef __CLASS__
113: template <typename Rec_, typename KeyExtractor_, typename KeyOrder_, typename XXXOrder_>
114: struct RecKeyXXXOrder {
115: typedef Rec_ rec_type;
116: typedef KeyExtractor_ key_extractor_type;
117: typedef KeyOrder_ key_order_type;
118: typedef typename key_extractor_type::result_type key_type;
119: typedef XXXOrder_ xxx_order_type;
120: //
121: typedef RecKeyXXXOrder pre_compare_type;
122: typedef xxx_order_type pos_compare_type;
123: typedef key_extractor_type pre_extractor_type;
124: typedef typename xxx_order_type::key_extractor_type pos_extractor_type;
125: private:
126: key_order_type _compare_keys;
127: xxx_order_type _compare_xxx;
128: key_extractor_type _kex;
129: public:
130: inline const pre_compare_type& preCompare() const {return *this;};
131: inline const pos_compare_type& posCompare() const {return this->_compare_xxx;};
132: //
133: #undef __FUNCT__
135: #undef __ALE_XDEBUG__
137: inline bool operator()(const rec_type& rec1, const rec_type& rec2) const {
138: static bool res;
139: if(this->_compare_keys(this->_kex(rec1), this->_kex(rec2))) {
140: res = true;
141: }
142: else if(this->_compare_keys(this->_kex(rec2), this->_kex(rec1))) {
143: res = false;
144: }
145: else if(this->_compare_xxx(rec1,rec2)){
146: res = true;
147: }
148: else {
149: res = false;
150: }
151: #ifdef ALE_USE_DEBUGGING
152: if(ALE_XDEBUG) {
153: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
154: if(res) {
155: std::cout << rec1 << " < " << rec2 << "\n";
156: }
157: else {
158: std::cout << rec2 << " >= " << rec1 << "\n";
159: }
160: };
161: #endif
162: return res;
163: };
164: //
165: // Comparisons with individual keys; XXX-part is ignored
166: #undef __FUNCT__
168: #undef __ALE_XDEBUG__
170: template <typename CompatibleKey_>
171: inline bool operator()(const rec_type& rec, const CompatibleKey_ key) const {
172: static bool res;
173: res = this->_compare_keys(this->_kex(rec), key);
174: #ifdef ALE_USE_DEBUGGING
175: if(ALE_XDEBUG) {
176: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
177: if(res) {
178: std::cout << rec << " < " << key << "\n";
179: }
180: else {
181: std::cout << rec << " >= " << key << "\n";
182: }
183: };
184: #endif
185: return res;
186: };
187: //
188: #undef __FUNCT__
190: #undef __ALE_XDEBUG__
192: template <typename CompatibleKey_>
193: inline bool operator()(const CompatibleKey_ key, const rec_type& rec) const {
194: static bool res;
195: res = this->_compare_keys(key, this->_kex(rec));
196: #ifdef ALE_USE_DEBUGGING
197: if(ALE_XDEBUG) {
198: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
199: if(res) {
200: std::cout << key << " < " << rec << "\n";
201: }
202: else {
203: std::cout << key << " >= " << rec << "\n";
204: }
205: };
206: #endif
207: return res;
208: };
209: //
210: // Comparisons with key pairs; XXX-part is compared against the second key of the pair
211: #undef __FUNCT__
213: #undef __ALE_XDEBUG__
215: template <typename CompatibleKey_, typename CompatibleSubKey_>
216: inline bool operator()(const rec_type& rec, const ::ALE::pair<CompatibleKey_, CompatibleSubKey_>& keypair) const {
217: static bool res;
218: if(this->_compare_keys(this->_kex(rec), keypair.first)) {
219: res = true;
220: }
221: else if(this->_compare_keys(keypair.first, this->_kex(rec))) {
222: res = false;
223: }
224: else if(this->_compare_xxx(rec,keypair.second)){
225: res = true;
226: }
227: else {
228: res = false;
229: }
230: #ifdef ALE_USE_DEBUGGING
231: if(ALE_XDEBUG) {
232: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
233: if(res) {
234: std::cout << rec << " < " << keypair << "\n";
235: }
236: else {
237: std::cout << keypair << " >= " << rec << "\n";
238: }
239: };
240: #endif
241: return res;
242: };
243: //
244: #undef __FUNCT__
246: #undef __ALE_XDEBUG__
248: template <typename CompatibleKey_, typename CompatibleSubKey_>
249: inline bool operator()(const ::ALE::pair<CompatibleKey_, CompatibleSubKey_>& keypair, const rec_type& rec) const {
250: static bool res;
251: if(this->_compare_keys(keypair.first, this->_kex(rec))) {
252: res = true;
253: }
254: else if(this->_compare_keys(this->_kex(rec), keypair.first)) {
255: res = false;
256: }
257: else if(this->_compare_xxx(keypair.second, rec)){
258: res = true;
259: }
260: else {
261: res = false;
262: }
263: #ifdef ALE_USE_DEBUGGING
264: if(ALE_XDEBUG) {
265: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
266: if(res) {
267: std::cout << keypair << " >= " << rec << "\n";
268: }
269: else {
270: std::cout << rec << " < " << keypair << "\n";
271: }
272: };
273: #endif
274: return res;
275: };
276: //
277: };// class RecKeyXXXOrder
280: // Bounder.
281: // Here we define auxiliary classes that can be derived from comparion operators.
282: // These convert a compare into a bounder (lower or upper).
283: //
284: template <typename Compare_, typename Bound_>
285: class LowerBounder {
286: public:
287: typedef Compare_ compare_type;
288: typedef Bound_ bound_type;
289: protected:
290: compare_type _compare;
291: bound_type _bound;
292: public:
293: // Basic
294: LowerBounder(){};
295: LowerBounder(const bound_type& bound) : _bound(bound) {};
296: inline void reset(const bound_type& bound) {this->_bound = bound;};
297: // Extended
298: inline const compare_type& compare(){return this->_compare;};
299: inline const bound_type& bound(){return this->_bound;};
300: // Main
301: template <typename Key_>
302: inline bool operator()(const Key_& key){return !this->compare()(key, this->bound());};
303: };// class LowerBounder
304: //
305: template <typename Compare_, typename Bound_>
306: class UpperBounder {
307: public:
308: typedef Compare_ compare_type;
309: typedef Bound_ bound_type;
310: protected:
311: compare_type _compare;
312: bound_type _bound;
313: public:
314: // Basic
315: UpperBounder(){};
316: UpperBounder(const bound_type& bound) : _bound(bound) {};
317: inline void reset(const bound_type& bound) {this->_bound = bound;};
318: // Extended
319: const compare_type& compare(){return this->_compare;};
320: const bound_type& bound(){return this->_bound;};
321: // Main
322: template <typename Key_>
323: bool operator()(const Key_& key){return !this->compare()(this->bound(),key);};
324: };// class UpperBounder
326: //
327: // Arrow definition: a concrete arrow; other Arrow definitions are possible, since orders above are templated on it
328: // To be an Arrow a struct must contain the relevant member functions: source, target, tail and head.
329: // This one also has color :-)
330: //
331: template<typename Source_, typename Target_, typename Color_>
332: struct Arrow {
333: typedef Arrow arrow_type;
334: typedef Source_ source_type;
335: typedef Target_ target_type;
336: typedef Color_ color_type;
337: source_type _source;
338: target_type _target;
339: color_type _color;
340: //
341: const arrow_type& arrow() const {return *this;};
342: const source_type& source() const {return this->_source;};
343: const target_type& target() const {return this->_target;};
344: const color_type& color() const {return this->_color;};
345: // Basic
346: Arrow(const source_type& s, const target_type& t, const color_type& c) : _source(s), _target(t), _color(c) {};
347: // Rebinding
348: template <typename OtherSource_, typename OtherTarget_, typename OtherColor_>
349: struct rebind {
350: typedef Arrow<OtherSource_, OtherTarget_, OtherColor_> type;
351: };
352: // Flipping
353: struct flip {
354: typedef Arrow<target_type, source_type, color_type> type;
355: type arrow(const arrow_type& a) { return type(a.target, a.source, a.color);};
356: };
357: // Printing
358: friend std::ostream& operator<<(std::ostream& os, const Arrow& a) {
359: os << "<" << a._source << "--(" << a._color << ")-->" << a._target << ">";
360: return os;
361: }
362: // Modifying
363: struct sourceChanger {
364: sourceChanger(const source_type& newSource) : _newSource(newSource) {};
365: void operator()(arrow_type& a) {a._source = this->_newSource;}
366: private:
367: source_type _newSource;
368: };
369: //
370: struct targetChanger {
371: targetChanger(const target_type& newTarget) : _newTarget(newTarget) {};
372: void operator()(arrow_type& a) { a._target = this->_newTarget;}
373: private:
374: const target_type _newTarget;
375: };
376: //
377: struct colorChanger {
378: colorChanger(const color_type& newColor) : _newColor(newColor) {};
379: void operator()(arrow_type& a) { a._color = this->_newColor;}
380: private:
381: const color_type _newColor;
382: };
383: };// struct Arrow
386: //
387: // Arrow Sequence type
388: //
389: #undef __CLASS__
391: template <typename XSieve_, typename Index_, typename KeyExtractor_, typename ValueExtractor_>
392: class ArrowSequence {
393: public:
394: typedef ArrowSequence arrow_sequence_type;
395: typedef XSieve_ xsieve_type;
396: typedef Index_ index_type;
397: typedef KeyExtractor_ key_extractor_type;
398: typedef ValueExtractor_ value_extractor_type;
399: //
400: typedef typename key_extractor_type::result_type key_type;
401: typedef typename value_extractor_type::result_type value_type;
402: //
403: typedef typename xsieve_type::rec_type rec_type;
404: typedef typename xsieve_type::arrow_type arrow_type;
405: typedef typename arrow_type::source_type source_type;
406: typedef typename arrow_type::target_type target_type;
407: //
408: typedef typename index_type::key_compare index_compare_type;
409: typedef typename index_type::iterator itor_type;
410: typedef typename index_type::const_iterator const_itor_type;
411: //
412: // cookie_type
413: //
414: struct cookie_type {
415: itor_type segment_end;
416: cookie_type() : segment_end(NULL) {};
417: // Printing
418: friend std::ostream& operator<<(std::ostream& os, const cookie_type& cookie) {
419: os << "[...," << *(cookie.segment_end) << "]";
420: return os;
421: }
422: };
423: //
424: // iterator_type
425: //
426: friend class iterator;
427: class iterator {
428: public:
429: // Parent sequence type
430: friend class ArrowSequence;
431: typedef ArrowSequence sequence_type;
432: typedef typename sequence_type::itor_type itor_type;
433: typedef typename sequence_type::cookie_type cookie_type;
434: // Value types
435: typedef typename sequence_type::value_extractor_type value_extractor_type;
436: typedef typename value_extractor_type::result_type value_type;
437: // Standard iterator typedefs
438: typedef std::input_iterator_tag iterator_category;
439: typedef int difference_type;
440: typedef value_type* pointer;
441: typedef value_type& reference;
442: protected:
443: // Parent sequence
444: sequence_type *_sequence;
445: // Underlying iterator
446: itor_type _itor;
447: cookie_type _cookie;
448: //cookie_type& cookie() {return _cookie;};
449: public:
450: iterator() : _sequence(NULL) {};
451: iterator(sequence_type* sequence, const itor_type& itor, const cookie_type& cookie) :
452: _sequence(sequence), _itor(itor), _cookie(cookie) {};
453: iterator(const iterator& iter) : _sequence(iter._sequence), _itor(iter._itor), _cookie(iter._cookie) {};
454: ~iterator() {};
455: //
456: itor_type& itor(){return this->_itor;};
457: //
458: inline const source_type& source() const {return this->_itor->source();};
459: inline const target_type& target() const {return this->_itor->target();};
460: inline const arrow_type& arrow() const {return *(this->_itor);};
461: inline const rec_type& rec() const {return *(this->_itor);};
462: //
463: inline bool operator==(const iterator& iter) const {return this->_itor == iter._itor;};
464: inline bool operator!=(const iterator& iter) const {return this->_itor != iter._itor;};
465: //
466: // FIX: operator*() should return a const reference, but it won't compile that way, because _ex() returns const value_type
467: inline const value_type operator*() const {return this->_sequence->value(this->_itor);};
468: //
469: #undef __FUNCT__
471: #undef __ALE_XDEBUG__
473: inline iterator operator++() { // comparison ignores cookies; only increment uses cookies
474: #ifdef ALE_USE_DEBUGGING
475: if(ALE_XDEBUG) {
476: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << std::endl;
477: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
478: std::cout << "*itor: " << *(this->_itor) << ", cookie: " << (this->_cookie);
479: std::cout << std::endl;
480: }
481: #endif
482: this->_sequence->next(this->_itor, this->_cookie);
483: #ifdef ALE_USE_DEBUGGING
484: if(ALE_XDEBUG) {
485: std::cout << "itor: " << *(this->_itor) << ", cookie: " << (this->_cookie) << "\n";
486: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << std::endl;
487: }
488: #endif
489: return *this;
490: };
491: inline iterator operator++(int n) {iterator tmp(*this); ++(*this); return tmp;};
492: };// class iterator
493: protected:
494: xsieve_type* _xsieve;
495: index_type* _index;
496: bool _keyless;
497: key_type _key;
498: key_extractor_type _kex;
499: value_extractor_type _vex;
500: public:
501: //
502: // Basic interface
503: //
504: ArrowSequence() : _xsieve(NULL), _index(NULL), _keyless(true) {};
505: ArrowSequence(const ArrowSequence& seq) {if(seq._keyless) {reset(seq._xsieve, seq._index);} else {reset(seq._xsieve, seq._index, seq._key);};};
506: ArrowSequence(xsieve_type *xsieve, index_type *index) {reset(xsieve, index);};
507: ArrowSequence(xsieve_type *xsieve, index_type *index, const key_type& key){reset(xsieve, index, key);};
508: virtual ~ArrowSequence() {};
509: //
510: void copy(const ArrowSequence& seq, ArrowSequence& cseq) {
511: cseq._xsieve = seq._xsieve; cseq._index = seq._index; cseq._keyless = seq._keyless; cseq._key = seq._key;
512: };
513: void reset(xsieve_type *xsieve, index_type* index) {
514: this->_xsieve = xsieve; this->_index = index; this->_keyless = true;
515: };
516: void reset(xsieve_type *xsieve, index_type* index, const key_type& key) {
517: this->_xsieve = xsieve; this->_index = index; this->_key = key; this->_keyless = false;
518: };
519: ArrowSequence& operator=(const arrow_sequence_type& seq) {
520: copy(seq,*this); return *this;
521: };
522: const value_type value(const itor_type itor) {return _vex(*itor);};
523: //
524: // Extended interface
525: //
526: const xsieve_type& xsieve() const {return *this->_xsieve;};
527: const index_type& index() const {return *this->_index;};
528: const bool& keyless() const {return this->_keyless;};
529: const key_type& key() const {return this->_key;};
530: const value_type& value(const itor_type& itor) const {this->_vex(*itor);};
531: //
532: // Main interface
533: //
534: #undef __FUNCT__
536: #undef __ALE_XDEBUG__
538: virtual iterator begin() {
539: #ifdef ALE_USE_DEBUGGING
540: if(ALE_XDEBUG) {
541: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << std::endl;
542: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
543: if(this->keyless()) {
544: std::cout << "keyless";
545: }
546: else {
547: std::cout << "key: " << this->key();
548: }
549: std::cout << std::endl;
550: }
551: #endif
552: static itor_type itor;
553: cookie_type cookie;
554: if(!this->keyless()) {
555: itor = this->index().lower_bound(this->key());
556: }
557: else {
558: static std::pair<const_itor_type, const_itor_type> range;
559: static LowerBounder<index_compare_type, key_type> lower;
560: static UpperBounder<index_compare_type, key_type> upper;
561: if(this->index().begin() != this->index().end()){
562: lower.reset(this->_kex(*(this->index().begin())));
563: upper.reset(this->_kex(*(this->index().begin())));
564: range = this->index().range(lower, upper);
565: itor = range.first; cookie.segment_end = range.second;
566: }
567: else {
568: itor = this->index().end(); cookie.segment_end = this->index().end();
569: }
570: }
571: #ifdef ALE_USE_DEBUGGING
572: if(ALE_XDEBUG) {
573: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
574: std::cout << "*itor: " << *itor << ", cookie: " << cookie << "\n";
575: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
576: }
577: #endif
578: return iterator(this, itor, cookie);
579: };// begin()
580: protected:
581: //
582: #undef __FUNCT__
584: #undef __ALE_XDEBUG__
586: virtual void next(itor_type& itor, cookie_type& cookie) {
587: #ifdef ALE_USE_DEBUGGING
588: if(ALE_XDEBUG) {
589: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << "\n";
590: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
591: if(this->keyless()) {
592: std::cout << "keyless";
593: }
594: else {
595: std::cout << "key: " << this->key();
596: }
597: std::cout << "\n";
598: }
599: #endif
600: if(this->keyless()) {
601: if(this->_index->begin() != this->_index->end()){
602: itor = cookie.segment_end;
603: cookie.segment_end = this->index().upper_bound(this->_kex(*itor));
604: }
605: }
606: else {
607: ++(itor); // FIX: use the record's 'next' method
608: }
609: #ifdef ALE_USE_DEBUGGING
610: if(ALE_XDEBUG) {
611: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
612: std::cout << "*itor: " << *itor << ", cookie: " << cookie << "\n";
613: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
614: }
615: #endif
616: };// next()
617: public:
618: //
619: #undef __FUNCT__
621: #undef __ALE_XDEBUG__
623: virtual iterator end() {
624: #ifdef ALE_USE_DEBUGGING
625: if(ALE_XDEBUG) {
626: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << "\n";
627: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
628: if(this->keyless()) {
629: std::cout << "keyless";
630: }
631: else {
632: std::cout << "key: " << this->key();
633: }
634: std::cout << "\n";
635: }
636: #endif
637: static itor_type itor;
638: cookie_type cookie;
639: if(!this->keyless()) {
640: itor = this->index().upper_bound(this->key());
641: }
642: else {
643: itor = this->index().end();
644: cookie.segment_end = itor;
645: }
646: #ifdef ALE_USE_DEBUGGING
647: if(ALE_XDEBUG) {
648: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
649: std::cout << "*itor: " << *itor << ", cookie: " << cookie << "\n";
650: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
651: }
652: #endif
653: return iterator(this, itor, cookie);
654: };// end()
655: //
656: template<typename ostream_type>
657: friend ostream_type& operator<<(ostream_type& os, const ArrowSequence& seq){
658: os << "[[";
659: for(iterator i = seq.begin(); i != seq.end(); i++) {
660: os << " (" << *i << ")";
661: }
662: os << " ]]";
663: return os;
664: };// operator<<()
665: //
666: template<typename ostream_type>
667: void view(ostream_type& os, const char* label = NULL){
668: if(label != NULL) {
669: os << "Viewing " << label << " sequence: ";
670: if(this->keyless()) {
671: os << "(keyless)";
672: }
673: else {
674: os << "(key = " << this->key()<<")";
675: }
676: os << ": ";
677: }
678: os << (*this) << "\n";
679: };
680: void addArrow(const arrow_type& a) {
681: this->_xsieve->addArrow(a);
682: };
683: //
684: };// class ArrowSequence
687: //
688: // Arrow-Link Sequence type
689: //
690: #undef __CLASS__
692: template <typename XSieve_, typename Index_, typename KeyExtractor_, typename NextExtractor_, typename ValueExtractor_>
693: class ArrowLinkSequence {
694: public:
695: typedef ArrowLinkSequence arrow_link_sequence_type;
696: typedef XSieve_ xsieve_type;
697: typedef Index_ index_type;
698: typedef KeyExtractor_ key_extractor_type;
699: typedef NextExtractor_ next_extractor_type;
700: typedef ValueExtractor_ value_extractor_type;
701: //
702: typedef typename key_extractor_type::result_type key_type;
703: typedef typename value_extractor_type::result_type value_type;
704: //
705: typedef typename xsieve_type::rec_type rec_type;
706: typedef typename xsieve_type::arrow_type arrow_type;
707: typedef typename arrow_type::source_type source_type;
708: typedef typename arrow_type::target_type target_type;
709: //
710: typedef typename index_type::key_compare index_compare_type;
711: typedef typename index_type::iterator itor_type;
712: typedef typename index_type::const_iterator const_itor_type;
713: //
714: // iterator_type
715: //
716: friend class iterator;
717: class iterator {
718: public:
719: // Parent sequence type
720: friend class ArrowLinkSequence;
721: typedef ArrowLinkSequence sequence_type;
722: typedef typename sequence_type::itor_type itor_type;
723: typedef typename sequence_type::rec_type rec_type;
724: // Value types
725: typedef typename sequence_type::value_extractor_type value_extractor_type;
726: typedef typename value_extractor_type::result_type value_type;
727: // Standard iterator typedefs
728: typedef std::input_iterator_tag iterator_category;
729: typedef int difference_type;
730: typedef value_type* pointer;
731: typedef value_type& reference;
732: protected:
733: // Parent sequence
734: sequence_type *_sequence;
735: // Underlying record
736: rec_type *_rec, *_seg; // seg == "segment_end"
737: public:
738: iterator() : _sequence(NULL) {};
739: iterator(sequence_type* sequence, rec_type* rec, rec_type* seg) :
740: _sequence(sequence), _rec(rec), _seg(seg) {};
741: iterator(const iterator& iter) :
742: _sequence(iter._sequence), _rec(iter._rec), _seg(iter._seg) {};
743: ~iterator() {};
744: //
745: inline const source_type& source() const {return this->_rec->source();};
746: inline const target_type& target() const {return this->_rec->target();};
747: inline const arrow_type& arrow() const {return *(this->_rec);};
748: inline const rec_type& rec() const {return *(this->_rec);};
749: //
750: inline bool operator==(const iterator& iter) const {bool res; res = (this->_rec == iter._rec); return res;};
751: inline bool operator!=(const iterator& iter) const {bool res; res = (this->_rec != iter._rec); return res;};
752: //
753: // FIX: operator*() should return a const reference, but it won't compile that way, because _ex() returns const value_type
754: inline const value_type operator*() const {return this->_sequence->value(this->_rec);};
755: //
756: #undef __FUNCT__
758: #undef __ALE_XDEBUG__
760: inline iterator operator++() {
761: #ifdef ALE_USE_DEBUGGING
762: if(ALE_XDEBUG) {
763: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << std::endl;
764: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
765: std::cout << "rec: ";
766: if(this->_rec!=NULL){std::cout << *(this->_rec);}else{std::cout << "NULL";};
767: std::cout << "seg: ";
768: if(this->_seg!=NULL){std::cout << *(this->_seg);}else{std::cout << "NULL";};
769: std::cout << std::endl;
770: }
771: #endif
772: this->_sequence->next(this->_rec, this->_seg);
773: #ifdef ALE_USE_DEBUGGING
774: if(ALE_XDEBUG) {
775: std::cout << "rec: ";
776: if(this->_rec!=NULL){std::cout << *(this->_rec);}else{std::cout << "NULL";};
777: std::cout << "seg: ";
778: if(this->_seg!=NULL){std::cout << *(this->_seg);}else{std::cout << "NULL";};
779: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << std::endl;
780: }
781: #endif
782: return *this;
783: };
784: inline iterator operator++(int n) {iterator tmp(*this); ++(*this); return tmp;};
785: };// class iterator
786: protected:
787: xsieve_type* _xsieve;
788: index_type* _index;
789: bool _keyless;
790: key_type _key;
791: key_extractor_type _kex;
792: next_extractor_type _nex;
793: value_extractor_type _vex;
794: public:
795: //
796: // Basic interface
797: //
798: ArrowLinkSequence() : _xsieve(NULL), _index(NULL), _keyless(true) {};
799: ArrowLinkSequence(const ArrowLinkSequence& seq) {if(seq._keyless) {reset(seq._xsieve, seq._index);} else {reset(seq._xsieve, seq._index, seq._key);};};
800: ArrowLinkSequence(xsieve_type *xsieve, index_type *index) {reset(xsieve, index);};
801: ArrowLinkSequence(xsieve_type *xsieve, index_type *index, const key_type& key){reset(xsieve, index, key);};
802: virtual ~ArrowLinkSequence() {};
803: //
804: inline void copy(const ArrowLinkSequence& seq, ArrowLinkSequence& cseq) {
805: cseq._xsieve = seq._xsieve; cseq._index = seq._index; cseq._keyless = seq._keyless; cseq._key = seq._key;
806: };
807: inline void reset(xsieve_type *xsieve, index_type* index) {
808: this->_xsieve = xsieve; this->_index = index; this->_keyless = true;
809: };
810: inline void reset(xsieve_type *xsieve, index_type* index, const key_type& key) {
811: this->_xsieve = xsieve; this->_index = index; this->_key = key; this->_keyless = false;
812: };
813: ArrowLinkSequence& operator=(const arrow_link_sequence_type& seq) {
814: copy(seq,*this); return *this;
815: };
816: inline const value_type value(rec_type const* _rec) {return _vex(*_rec);};
817: //
818: // Extended interface
819: //
820: inline const xsieve_type& xsieve() const {return *this->_xsieve;};
821: inline const index_type& index() const {return *this->_index;};
822: inline const bool& keyless() const {return this->_keyless;};
823: inline const key_type& key() const {return this->_key;};
824: inline const value_type& value(const rec_type*& rec) const {this->_vex(*rec);};
825: protected:
826: // aux
827: inline rec_type* itor_to_rec_ptr(const itor_type& itor) {
828: const rec_type& crec = *(itor);
829: return const_cast<rec_type*>(&crec);
830: };
831: //
832: inline rec_type* itor_to_rec_ptr_safe(const itor_type& itor) {
833: rec_type* _rec;
834: if(itor == this->_index->end()){
835: _rec = NULL;
836: }
837: else {
838: const rec_type& crec = *(itor);
839: _rec = const_cast<rec_type*>(&crec);
840: }
841: return _rec;
842: };
844: public:
845: //
846: // Main interface
847: //
848: #undef __FUNCT__
850: #undef __ALE_XDEBUG__
852: inline iterator begin() {
853: #ifdef ALE_USE_DEBUGGING
854: if(ALE_XDEBUG) {
855: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << std::endl;
856: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
857: if(this->keyless()) {
858: std::cout << "keyless";
859: }
860: else {
861: std::cout << "key: " << this->key();
862: }
863: std::cout << std::endl;
864: }
865: #endif
866: static itor_type itor;
867: static rec_type *_rec, *_seg;
868: if(this->keyless()) {
869: static std::pair<const_itor_type, const_itor_type> range;
870: static LowerBounder<index_compare_type, key_type> lower;
871: static UpperBounder<index_compare_type, key_type> upper;
872: if(this->index().begin() != this->index().end()){
873: lower.reset(this->_kex(*(this->index().begin())));
874: upper.reset(this->_kex(*(this->index().begin())));
875: range = this->index().range(lower, upper);
876: _rec = itor_to_rec_ptr(range.first);
877: _seg = itor_to_rec_ptr_safe(range.second);
878: }
879: else {
880: _rec = NULL; _seg = NULL;
881: }
882: }
883: else {
884: itor = this->index().lower_bound(this->key());
885: _rec = itor_to_rec_ptr_safe(itor);
886: _seg = NULL;
887: }
888: #ifdef ALE_USE_DEBUGGING
889: if(ALE_XDEBUG) {
890: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
891: std::cout << "rec: ";
892: if(_rec!=NULL){std::cout << *(_rec);}else{std::cout << "NULL";};
893: std::cout << "seg: ";
894: if(_seg!=NULL){std::cout << *(_seg);}else{std::cout << "NULL";};
895: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
896: }
897: #endif
898: return iterator(this, _rec, _seg);
899: };// begin()
900: protected:
901: //
902: #undef __FUNCT__
904: #undef __ALE_XDEBUG__
906: inline void next(rec_type*& _rec, rec_type*& _seg) {
907: #ifdef ALE_USE_DEBUGGING
908: if(ALE_XDEBUG) {
909: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << "\n";
910: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
911: if(this->keyless()) {
912: std::cout << "keyless";
913: }
914: else {
915: std::cout << "key: " << this->key();
916: }
917: std::cout << "\n";
918: }
919: #endif
920: if(this->keyless()) {
921: if(this->_index->begin() != this->_index->end()){
922: _rec = _seg;
923: if(_rec != NULL) {
924: itor_type itor = this->index().upper_bound(this->_kex(*_rec));
925: _seg = itor_to_rec_ptr_safe(itor);
926: }
927: // else _seg is already NULL
928: }
929: }
930: else {
931: _rec = this->_nex(*_rec);
932: }
933: #ifdef ALE_USE_DEBUGGING
934: if(ALE_XDEBUG) {
935: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
936: std::cout << "rec: ";
937: if(_rec!=NULL){std::cout << *(_rec);}else{std::cout << "NULL";};
938: std::cout << "seg: ";
939: if(_seg!=NULL){std::cout << *(_seg);}else{std::cout << "NULL";};
940: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
941: }
942: #endif
943: };// next()
944: public:
945: //
946: #undef __FUNCT__
948: #undef __ALE_XDEBUG__
950: inline iterator end() {
951: #ifdef ALE_USE_DEBUGGING
952: if(ALE_XDEBUG) {
953: std::cout << __CLASS__ << "::" << __FUNCT__ << ":>>>" << "\n";
954: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
955: if(this->keyless()) {
956: std::cout << "keyless";
957: }
958: else {
959: std::cout << "key: " << this->key();
960: }
961: std::cout << "\n";
962: }
963: #endif
964: static rec_type *_rec, *_seg;
965: if(this->keyless()){
966: _rec = NULL; _seg = NULL;
967: }
968: else {
969: itor_type itor = this->index().upper_bound(this->key());
970: _rec = itor_to_rec_ptr_safe(itor);
971: }
972: #ifdef ALE_USE_DEBUGGING
973: if(ALE_XDEBUG) {
974: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
975: std::cout << "rec: ";
976: if(_rec!=NULL){std::cout << *(_rec);}else{std::cout << "NULL";};
977: std::cout << "seg: ";
978: if(_seg!=NULL){std::cout << *(_seg);}else{std::cout << "NULL";};
979: std::cout << __CLASS__ << "::" << __FUNCT__ << ":<<<" << "\n";
980: }
981: #endif
982: return iterator(this, _rec, _seg);
983: };// end()
984: //
985: template<typename ostream_type>
986: friend ostream_type& operator<<(ostream_type& os, const ArrowLinkSequence& seq){
987: os << "[[";
988: for(iterator i = seq.begin(); i != seq.end(); i++) {
989: os << " (" << *i << ")";
990: }
991: os << " ]]";
992: return os;
993: };
994: //
995: template<typename ostream_type>
996: void view(ostream_type& os, const char* label = NULL){
997: if(label != NULL) {
998: os << "Viewing " << label << " sequence: ";
999: if(this->keyless()) {
1000: os << "(keyless)";
1001: }
1002: else {
1003: os << "(key = " << this->key()<<")";
1004: }
1005: os << ": ";
1006: }
1007: os << (*this) << "\n";
1008: };
1009: void addArrow(const arrow_type& a) {
1010: this->_xsieve->addArrow(a);
1011: };
1012: //
1013: };// class ArrowLinkSequence
1016: struct NoSlices : public ALE::XException {
1017: NoSlices() : ALE::XException("No slices available for allocation"){};
1018: };
1020: //
1021: // Slicer allocates slices, up to MAX_SLICE_DEPTH
1022: //
1023: template <typename Arrow_, typename Marker_, int MAX_SLICE_DEPTH>
1024: struct Slicer {
1025: //
1026: struct Rec : public Arrow_ {
1027: typedef Arrow_ arrow_type;
1028: typedef Marker_ marker_type;
1029: //
1030: Rec* nexts[MAX_SLICE_DEPTH];
1031: marker_type markers[MAX_SLICE_DEPTH];
1032: Rec(){for(int i = 0; i<MAX_SLICE_DEPTH;++i) {nexts[i] = NULL; markers[i] = marker_type();}};
1033: Rec(const arrow_type& rec) : arrow_type(rec) {for(int i = 0; i<MAX_SLICE_DEPTH;++i) {nexts[i] = NULL; markers[0] = marker_type();}};
1034: };
1035: // encapsulated types
1036: typedef Rec rec_type;
1037: typedef Marker_ marker_type;
1038: typedef typename rec_type::arrow_type arrow_type;
1039: //
1040: struct Slice {
1041: typedef Slicer slicer_type;
1042: typedef Slice slice_type;
1043: typedef Rec rec_type;
1044: //
1045: class iterator {
1046: // Standard iterator typedefs
1047: typedef arrow_type value_type;
1048: typedef std::input_iterator_tag iterator_category;
1049: typedef int difference_type;
1050: typedef value_type* pointer;
1051: typedef value_type& reference;
1052: protected:
1053: slice_type *_slice;
1054: rec_type *_rec;
1055: public:
1056: iterator() :_slice(NULL), _rec(NULL) {};
1057: iterator(slice_type* _slice, rec_type* _rec) : _slice(_slice), _rec(_rec){};
1058: iterator(const iterator& iter) : _slice(iter._slice), _rec(iter._rec){};
1059: public:
1060: iterator operator=(const iterator& iter) {
1061: this->_slice = iter._slice;
1062: this->_rec = iter._rec;
1063: return *this;
1064: };
1065: inline bool operator==(const iterator& iter) const {return this->_slice == iter._slice && this->_rec == iter._rec;};
1066: inline bool operator!=(const iterator& iter) const {return this->_slice != iter._slice || this->_rec != iter._rec;};
1067: inline iterator operator++() {
1068: this->_rec = this->_rec->nexts[this->_slice->rank()];
1069: return *this;
1070: };
1071: inline iterator operator++(int n) {iterator tmp(*this); ++(*this); return tmp;};
1072: //
1073: inline const arrow_type& arrow() const {return *(this->_rec);}; // we assume Rec_ implements the Arrow concept.
1074: inline const arrow_type& operator*() const {return this->arrow();};
1075: inline marker_type marker() const {return this->_slice->marker(*(this->_rec));};
1076: };// iterator
1077: //
1078: // Basic
1079: //
1080: Slice(slicer_type* slicer, int rank) : _slicer(slicer), _head(NULL), _tail(NULL), _rank(rank) {};
1081: virtual ~Slice() {this->_slicer->give_back(this);};
1082: //
1083: // Main interface
1084: //
1085: inline iterator begin(){ return iterator(this, this->_head);};
1086: inline iterator end(){ return iterator(this, NULL);};
1087: inline void add(rec_type& rec, marker_type marker) {
1088: // Add &rec at the tail of the slice linked list; assume that rec is not transient.
1089: // Direct manipulation of rec in principle violates multi_index record update rules,
1090: // since we are directly manipulating the record, but that's okay, since
1091: // slice data that we are updating is not used in the container ordering.
1092: rec.nexts[this->_rank] = NULL;
1093: rec.markers[this->_rank] = marker;
1094: if(this->_tail != NULL) { // slice already has recs in it
1095: this->_tail->nexts[this->_rank] = &rec;
1096: }
1097: else { // first rec in the slice
1098: this->_head = &rec;
1099: }
1100: this->_tail = &rec;
1101:
1102: };
1103: inline marker_type marker(const rec_type& rec) {
1104: return rec.markers[this->_rank];
1105: };
1106: inline void clean() {
1107: for(rec_type *_rec = this->_head; _rec != NULL; ) {
1108: rec_type* tmp = _rec;
1109: _rec = _rec->nexts[this->_rank];
1110: tmp->markers[this->_rank] = marker_type();
1111: /*tmp.nexts[this->_rank] = NULL;*/ // FIX: this is, in principle, unnecessary, as long as the head and tail are wiped out
1112: }
1113: this->_head = NULL; this->_tail = NULL;
1114: };//clean()
1115: //
1116: template <typename Op_>
1117: inline void traverse(const Op_& op) {
1118: for(rec_type *_rec = this->_head; _rec != NULL; _rec = _rec->nexts[this->_rank]) {
1119: op(*_rec);
1120: }
1121: };// traverse()
1122: //
1123: template <typename Op_>
1124: inline void traverseAndClean(const Op_& op) {
1125: for(rec_type *_rec = this->_head; _rec != NULL; ) {
1126: rec_type* tmp = _rec;
1127: _rec = _rec->nexts[this->_rank];
1128: op(*tmp);
1129: tmp->markers[this->rank] = marker_type();
1130: }
1131: };// traverseAndClean()
1132: //
1133: inline int rank() {return this->_rank;};
1134: protected:
1135: slicer_type* _slicer;
1136: rec_type *_head, *_tail;
1137: int _rank;
1138: protected:
1139: inline rec_type& rec(const iterator& iter) const {return *(iter._rec);};
1140: inline void reset_rec(iterator& iter, rec_type& rec) const {iter._rec = &rec;};
1141: };// Slice
1142: typedef Slice slice_type;
1143: //
1144: //
1145: //
1146: template <typename Extractor_>
1147: class SliceSequence : public Obj<slice_type> {
1148: public:
1149: typedef typename slice_type::rec_type rec_type;
1150: typedef typename rec_type::marker_type marker_type;
1151: typedef typename rec_type::arrow_type arrow_type;
1152: //
1153: class iterator : public slice_type::iterator {
1154: public:
1155: typedef Extractor_ extractor_type;
1156: typedef typename slice_type::iterator the_iterator;
1157: // Standard iterator typedefs
1158: typedef typename extractor_type::result_type value_type;
1159: typedef std::input_iterator_tag iterator_category;
1160: typedef int difference_type;
1161: typedef value_type* pointer;
1162: typedef value_type& reference;
1163: public:
1164: iterator() :the_iterator() {};
1165: iterator(const the_iterator& theiter) : the_iterator(theiter) {};
1166: const value_type& operator*() const {
1167: static extractor_type ex;
1168: return ex(this->arrow());
1169: };
1170: };// class iterator
1171: public:
1172: SliceSequence(const Obj<slice_type>& slice) : Obj<slice_type>(slice) {};
1173: //
1174: inline iterator begin() const {return this->pointer()->begin();};
1175: inline iterator end() const {return this->pointer()->end();};
1176: inline void add(const rec_type& crec, marker_type marker = marker_type()){
1177: // crec is typically obtained by referencing a multi_index index iterator,
1178: // hence it is likely to be 'const'.
1179: // It is okay to cast away this const, since we won't be modifying
1180: // any of its elements that affect the index.
1181: // Otherwise we'd need to use a multi_index record modifier,
1182: // which might be costly.
1183: rec_type& rec = const_cast<rec_type&>(crec);
1184: this->pointer()->add(rec,marker);
1185: };
1186: inline marker_type marker(const rec_type& rec){return this->pointer()->marker(rec);};
1187: inline void clean(){this->pointer()->clean();};
1188: //
1189: template <typename Op_>
1190: inline void traverse(const Op_& op) {this->pointer()->traverse(op);};
1191: template <typename Op_>
1192: inline void traverseAndClean(const Op_& op) {this->pointer()->traverseAndClean(op);};
1193: //
1194: template<typename ostream_type>
1195: friend ostream_type& operator<<(ostream_type& os, const SliceSequence& slice){
1196: // FIX: avoiding iterators might make it faster, although it hardly matters when viewing.
1197: os << "[[ ";
1198: iterator sbegin = slice.begin();
1199: iterator send = slice.end();
1200: iterator iter;
1201: for(iter = sbegin; iter!=send; ++iter) {
1202: os << "<" << iter.marker() << ">[" << *iter << "] ";
1203: }
1204: os << "]]";
1205: return os;
1206: };//operator<<()
1207: //
1208: template<typename ostream_type>
1209: void view(ostream_type& os, const char* label = NULL){
1210: os << "Viewing SliceSequence";
1211: if(label != NULL) {
1212: os << " " << label;
1213: }
1214: os << ": ";
1215: os << (*this) << "\n";
1216: };//view()
1217: };//SliceSequence()
1218: public:
1219: //
1220: // Basic
1221: //
1222: Slicer() : _taken(MAX_SLICE_DEPTH, false){};
1223: virtual ~Slicer(){};
1224: //
1225: // Main
1226: //
1227: // take() must return Obj<the_slice_type> rather than the_slice_type*,
1228: // since the latter need not be automatically destroyed and cleaned.
1229: // It would be unnatural (and possibly unallowed by the Obj interface)
1230: // to return a the_slice_type* to be wrapped as Obj later.
1231: inline Obj<slice_type> take() {
1232: for(int i = 0; i < MAX_SLICE_DEPTH; ++i) {
1233: if(!(this->_taken[i])) {
1234: this->_taken[i] = true;
1235: return Obj<slice_type>(new slice_type(this, i));
1236: }
1237: }
1238: static NoSlices e;
1239: throw e;
1240: };// take()
1241: //
1242: // give_back() cannot accept Obj<the_slice_type>, since it is intended
1243: // to be called from the_slice_type's destructor, which has no Obj.
1244: inline void give_back(slice_type* slice) {
1245: slice->clean();
1246: this->_taken[slice->rank()] = false;
1247: };// give_back()
1248: protected:
1249: std::vector<bool> _taken;
1250: };// class Slicer
1251:
1255: // Definitions of typical XSieve usage of records, orderings, etc.
1256: template<typename Arrow_,
1257: typename SourceOrder_ = std::less<typename Arrow_::source_type>,
1258: typename ColorOrder_ = std::less<typename Arrow_::color_type> >
1259: struct SourceColorOrder :
1260: public RecKeyXXXOrder<Arrow_,
1261: ALE_CONST_MEM_FUN(Arrow_, typename Arrow_::source_type&, &Arrow_::source),
1262: SourceOrder_,
1263: RecKeyOrder<Arrow_,
1264: ALE_CONST_MEM_FUN(Arrow_, typename Arrow_::color_type&, &Arrow_::color),
1265: ColorOrder_>
1266: >
1267: {};
1269: }; // namespace XSieveDef
1271:
1272: //
1273: // XSieve definition
1274: //
1275: template<typename Arrow_, int SliceDepth = 1,
1276: typename TailOrder_ = XSieveDef::SourceColorOrder<Arrow_> >
1277: struct XSieve : XParallelObject { // struct XSieve
1278: //
1279: typedef XSieve xsieve_type;
1280: //
1281: // Encapsulated types: re-export types and/or bind parameterized types
1282: //
1283: //
1284: typedef Arrow_ arrow_type;
1285: typedef typename arrow_type::source_type source_type;
1286: typedef typename arrow_type::target_type target_type;
1288:
1289: //
1290: // Key extractors
1291: //
1292: // Despite the fact that extractors will operate on rec_type objects, they must be defined as operating on arrow_type objects.
1293: // This will work because rec_type is assumed to inherit from arrow_type.
1294: // If rec_type with the methods inherited from arrow_type were used to define extractors, there would be a conversion problem:
1295: // an arrow_type member function (even as inherited by rec_type) cannot be converted to (the identical) rec_type member function.
1296: // Just try this, if you want to see what happens:
1297: // typedef ALE_CONST_MEM_FUN(rec_type, source_type&, &rec_type::source) source_extractor_type;
1298: //
1299: typedef ALE_CONST_MEM_FUN(arrow_type, source_type&, &arrow_type::source) source_extractor_type;
1300: typedef ALE_CONST_MEM_FUN(arrow_type, target_type&, &arrow_type::target) target_extractor_type;
1301: typedef ALE_CONST_MEM_FUN(arrow_type, arrow_type&, &arrow_type::arrow) arrow_extractor_type;
1303: //
1304: // Slicing
1305: //
1306: typedef ::ALE::XSieveDef::Slicer<arrow_type, int, SliceDepth> slicer_type;
1307: typedef typename slicer_type::slice_type slice_type;
1309: #ifdef ALE_XSIEVE_USE_ARROW_LINKS
1310: //
1311: // Proto-rec contains a pointer to the next proto-rec for each index,
1312: // creating a linked list through each index.
1313: //
1314: struct proto_rec_type : slicer_type::rec_type {
1315: typedef typename xsieve_type::arrow_type arrow_type;
1316: typedef typename arrow_type::source_type source_type;
1317: typedef typename arrow_type::target_type target_type;
1318: proto_rec_type* cone_next;
1319: //proto_rec_type* support_next;
1320: proto_rec_type(const arrow_type& a) : slicer_type::rec_type(a){};
1321: };
1322: typedef ::boost::multi_index::member<proto_rec_type, proto_rec_type*, &proto_rec_type::cone_next> cone_next_extractor_type;
1323: typedef proto_rec_type rec_type;
1324: #else
1325: typedef typename slicer_type::rec_type rec_type;
1326: #endif
1328: // Pre-defined SliceSequences
1329: typedef typename slicer_type::template SliceSequence<source_extractor_type> SourceSlice;
1330: typedef typename slicer_type::template SliceSequence<target_extractor_type> TargetSlice;
1331: typedef typename slicer_type::template SliceSequence<arrow_extractor_type> ArrowSlice;
1332: //
1333: typedef SourceSlice BoundarySlice;
1334: typedef typename ALE::Set<source_type> BoundarySet;
1336: //
1337: // Comparison operators
1338: //
1339: typedef std::less<typename rec_type::target_type> target_order_type;
1340: typedef TailOrder_ tail_order_type;
1341: //
1342: // Rec 'Cone' order type: first order by target then using a custom tail_order
1343: typedef
1344: XSieveDef::RecKeyXXXOrder<rec_type,
1345: target_extractor_type, target_order_type,
1346: XSieveDef::RecKeyOrder<rec_type, arrow_extractor_type, tail_order_type> >
1347: cone_order_type;
1348: //
1349: // Index tags
1350: //
1351: struct ConeTag{};
1352: struct SupportTag{};
1353: //
1354: // Rec set type
1355: //
1356: typedef ::boost::multi_index::multi_index_container<
1357: rec_type,
1358: ::boost::multi_index::indexed_by<
1359: ::boost::multi_index::ordered_non_unique<
1360: ::boost::multi_index::tag<ConeTag>, ::boost::multi_index::identity<rec_type>, cone_order_type
1361: >
1362: >,
1363: ALE_ALLOCATOR<rec_type> >
1364: rec_set_type;
1365: //
1366: // Index types extracted from the Rec set
1367: //
1368: typedef typename ::boost::multi_index::index<rec_set_type, ConeTag>::type cone_index_type;
1369: //
1370: // Sequence types
1371: //
1372: #ifdef ALE_XSIEVE_USE_ARROW_LINKS
1373: typedef ALE::XSieveDef::ArrowLinkSequence<xsieve_type, cone_index_type, target_extractor_type, cone_next_extractor_type, target_extractor_type> BaseSequence;
1374: typedef ALE::XSieveDef::ArrowLinkSequence<xsieve_type, cone_index_type, target_extractor_type, cone_next_extractor_type, source_extractor_type> ConeSequence;
1375: typedef ALE::XSieveDef::ArrowLinkSequence<xsieve_type, cone_index_type, arrow_extractor_type, cone_next_extractor_type, source_extractor_type> ConeSelectorSequence;
1376: #else
1377: typedef ALE::XSieveDef::ArrowSequence<xsieve_type, cone_index_type, target_extractor_type, target_extractor_type> BaseSequence;
1378: typedef ALE::XSieveDef::ArrowSequence<xsieve_type, cone_index_type, target_extractor_type, source_extractor_type> ConeSequence;
1379: typedef ALE::XSieveDef::ArrowSequence<xsieve_type, cone_index_type, arrow_extractor_type, source_extractor_type> ConeSelectorSequence;
1380: #endif
1381: //
1382: //
1383: // Basic interface
1384: //
1385: //
1386: XSieve(const MPI_Comm comm) :
1387: XParallelObject(comm), _rec_set(),
1388: _cone_index(::boost::multi_index::get<ConeTag>(this->_rec_set))
1389: {};
1390: //
1391: // Extended interface
1392: //
1393: void addArrow(const arrow_type& a) {
1394: static std::pair<typename cone_index_type::iterator, bool> res;
1395: rec_type r = rec_type(a);
1396: res = this->_cone_index.insert(r);
1397: if(res.second) {// successful insertion
1398: #ifdef ALE_XSIEVE_USE_ARROW_LINKS
1399: typename cone_index_type::iterator iter = res.first;
1400: // The following two-stage case seems to be necessary because *iter returns
1401: // a strange thing that cannot be const_cast directly;
1402: // this pattern repeats twice more below for next and prev iterators.
1403: const rec_type& ci_rec = (*iter);
1404: rec_type& i_rec = const_cast<rec_type&>(ci_rec);
1405: if(iter != this->_cone_index.begin()) {// not the first arrow in index
1406: typename cone_index_type::iterator prev = --iter;
1407: const rec_type& cp_rec = (*prev);
1408: rec_type& p_rec = const_cast<rec_type&>(cp_rec);
1409: // insert i_rec between p_rec and its successor
1410: i_rec.proto_rec_type::cone_next = p_rec.proto_rec_type::cone_next;
1411: p_rec.proto_rec_type::cone_next = &i_rec;;
1412:
1413: }
1414: else {
1415: typename cone_index_type::iterator next = ++iter;
1416: if(next != _cone_index.end()){
1417: const rec_type& cn_rec = (*next);
1418: rec_type& n_rec = const_cast<rec_type&>(cn_rec);
1419: i_rec.proto_rec_type::cone_next = &n_rec;
1420: }
1421: else {
1422: i_rec.cone_next = NULL;
1423: }
1424: }// first arrow in index
1425: #endif
1426: }
1427: else {
1428: ALE::XException e;
1429: e << "addArrow of " << a << " failed";
1430: throw e;
1431: }
1432: };// addArrow()
1433: //
1434: void cone(const target_type& t, ConeSequence& cseq) {
1435: cseq.reset(this, &_cone_index, t);
1436: };
1437: ConeSequence& cone(const target_type& t) {
1438: static ConeSequence cseq;
1439: this->cone(t,cseq);
1440: return cseq;
1441: };
1442: //
1443: template <typename Selector_>
1444: void cone(const target_type& t, const Selector_& s, ConeSelectorSequence& csseq) {
1445: static ALE::pair<target_type, Selector_> comb_key;
1446: comb_key.first = t; comb_key.second = s;
1447: csseq.reset(this, &_cone_index, comb_key);
1448: };
1449: //
1450: template <typename Selector_>
1451: ConeSelectorSequence& cone(const target_type& t, const Selector_& s) {
1452: static ConeSelectorSequence csseq;
1453: this->cone(t,s,csseq);
1454: return csseq;
1455: };
1456: //
1457: void base(BaseSequence& seq) {
1458: seq.reset(this, &_cone_index);
1459: };
1460: BaseSequence& base() {
1461: static BaseSequence bseq;
1462: this->base(bseq);
1463: return bseq;
1464: };
1465: //
1466: Obj<slice_type> slice(){return this->_slicer.take();};
1467: //
1468: BoundarySlice boundarySlice(const target_type& t) {
1469: BoundarySlice bd(this->slice());
1470: this->__boundarySlice(bd,t);
1471: return bd;
1472: };//boundarySlice()
1473: //
1474: protected:
1475: // aux function: called recursively
1476: #undef __FUNCT__
1478: #undef __ALE_XDEBUG__
1480: void __boundarySlice(BoundarySlice& bd, const target_type& t) {
1481: #ifdef ALE_USE_DEBUGGING
1482: if(ALE_XDEBUG) {
1483: std::cout << __CLASS__ << "::" << __FUNCT__ << ": >>>";
1484: };
1485: #endif
1486: // CANNOT make cone, cbegin, cend and citer static in this RECURSIVE function
1487: ConeSequence cone;
1488: typename ConeSequence::iterator cbegin, cend, citer;
1489: static typename BoundarySlice::marker_type blank = 0, marked = 1;
1490: #ifdef ALE_USE_DEBUGGING
1491: if(ALE_XDEBUG) {
1492: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
1493: std::cout << "boundary of " << t << "\n";
1494: };
1495: #endif //
1496: try {
1497: // check each arrow in the cone above t and add each unseen arrow
1498: // the proceed to the cone above that arrow's source recursively
1499: this->cone(t,cone);
1500: cbegin = cone.begin(); cend = cone.end();
1501: for(citer = cbegin; citer != cend; ++citer) {
1502: #ifdef ALE_USE_DEBUGGING
1503: if(ALE_XDEBUG) {
1504: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
1505: std::cout << "examining arrow rec: " << citer.rec() << " ... ";
1506: };
1507: #endif //
1508: if(bd.marker(citer.rec()) == blank) { // if arrow has not been marked
1509: bd.add(citer.rec(), marked); // add this arrow and mark it at the same time
1510: #ifdef ALE_USE_DEBUGGING
1511: if(ALE_XDEBUG) {
1512: std::cout << "blank, added: " << citer.rec() << ", making recursive call\n";
1513: };
1514: #endif
1515: __boundarySlice(bd, citer.source()); // recursively compute boundary of s
1516: }// blank
1517: else {
1518: #ifdef ALE_USE_DEBUGGING
1519: if(ALE_XDEBUG) {
1520: std::cout << "marked\n";
1521: };
1522: #endif
1523: }// marked
1524: }
1525: } catch(...) {
1526: std::cout << "Unknown exception caught in " << __CLASS__ << "::" << __FUNCT__ << "\n";
1527: throw;
1528: };
1529: #ifdef ALE_USE_DEBUGGING
1530: if(ALE_XDEBUG) {
1531: std::cout << __CLASS__ << "::" << __FUNCT__ << ": <<<";
1532: };
1533: #endif //
1534: };//__boundarySlice()
1535: public:
1536: //
1537: #undef __FUNCT__
1539: #undef __ALE_XDEBUG__
1541: Obj<BoundarySet> boundarySet(const target_type& t) {
1542: #ifdef ALE_USE_DEBUGGING
1543: if(ALE_XDEBUG) {
1544: std::cout << __CLASS__ << "::" << __FUNCT__ << ": >>>";
1545: };
1546: #endif
1547: Obj<BoundarySet> bd(new BoundarySet());
1548: this->__boundarySet(bd,t);
1549: #ifdef ALE_USE_DEBUGGING
1550: if(ALE_XDEBUG) {
1551: std::cout << __CLASS__ << "::" << __FUNCT__ << ": <<<";
1552: };
1553: #endif
1554: return bd;
1555: };//boundarSet()
1556: //
1557: protected:
1558: // aux function: called recursively
1559: #undef __FUNCT__
1561: #undef __ALE_XDEBUG__
1563: void __boundarySet(Obj<BoundarySet>& bd, const target_type& t) {
1564: #ifdef ALE_USE_DEBUGGING
1565: if(ALE_XDEBUG) {
1566: std::cout << __CLASS__ << "::" << __FUNCT__ << ": >>>";
1567: };
1568: #endif
1569: // CANNOT make cone, cbegin, cend and citer static in this RECURSIVE function
1570: ConeSequence cone;
1571: typename ConeSequence::iterator cbegin, cend, citer;
1572: #ifdef ALE_USE_DEBUGGING
1573: if(ALE_XDEBUG) {
1574: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
1575: std::cout << "boundary of " << t << "\n";
1576: };
1577: #endif //
1578: try {
1579: // check each arrow in the cone above t and add each unseen source
1580: // the proceed to the cone above that arrow's source recursively
1581: this->cone(t,cone);
1582: cbegin = cone.begin(); cend = cone.end();
1583: for(citer = cbegin; citer != cend; ++citer) {
1584: #ifdef ALE_USE_DEBUGGING
1585: if(ALE_XDEBUG) {
1586: std::cout << __CLASS__ << "::" << __FUNCT__ << ": ";
1587: std::cout << "examining arrow rec: " << citer.rec() << " ... ";
1588: };
1589: #endif //
1590: if(bd->find(citer.arrow().source()) == bd->end()) { // don't have this point yet
1591: bd->insert(citer.arrow().source()); // add the source of the arrow
1592: #ifdef ALE_USE_DEBUGGING
1593: if(ALE_XDEBUG) {
1594: std::cout << "source not seen yet, added: " << citer.rec().source() << ", making recursive call\n";
1595: };
1596: #endif
1597: __boundarySet(bd, citer.source()); // recursively compute boundary of s
1598: }
1599: }
1600: } catch(...) {
1601: std::cout << "Unknown exception caught in " << __CLASS__ << "::" << __FUNCT__ << "\n";
1602: throw;
1603: };
1604: #ifdef ALE_USE_DEBUGGING
1605: if(ALE_XDEBUG) {
1606: std::cout << __CLASS__ << "::" << __FUNCT__ << ": <<<";
1607: };
1608: #endif //
1609: };//__boundarySet()
1610: public:
1611: //
1612: //
1613: template<typename ostream_type>
1614: friend ostream_type& operator<<(ostream_type& os, const XSieve& xsieve){
1615: os << "Cone index: [[ ";
1616: for(typename cone_index_type::iterator itor = xsieve._cone_index.begin(); itor != xsieve._cone_index.end(); ++itor) {
1617: os << *itor << " ";
1618: }
1619: os << "]]";
1620: return os;
1621: };
1622: //
1623: template<typename ostream_type>
1624: void view(ostream_type& os, const char* label = NULL){
1625: if(label != NULL) {
1626: os << "Viewing " << label << " XSieve:\n";
1627: }
1628: else {
1629: os << "Viewing an XSieve:\n";
1630: }
1631: os << (*this) << "\n";
1632: };
1633: //
1634: // Direct access (a kind of hack)
1635: //
1636: // Whole container begin/end
1637: typedef typename cone_index_type::iterator iterator;
1638: iterator begin() const {return this->_cone_index.begin();};
1639: iterator end() const {return this->_cone_index.end();};
1641: public:
1642: // set of arrow records
1643: rec_set_type _rec_set;
1644: cone_index_type& _cone_index;
1645: slicer_type _slicer;
1646: public:
1647: //
1648: }; // class XSieve
1650:
1651: } // namespace ALE
1653: #endif