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