Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:19:37

0001 /* This software is distributed under the GNU Lesser General Public License */
0002 //==========================================================================
0003 //
0004 //   symlist.h
0005 //
0006 //==========================================================================
0007 // $Id: symlist.h,v 1.17 2002/12/20 08:26:08 chris Exp $
0008 
0009 #ifndef SYMLIST_H
0010 #define SYMLIST_H
0011 
0012 #include <GTL/GTL.h> 
0013 
0014 #include <cassert>
0015 
0016 __GTL_BEGIN_NAMESPACE
0017 
0018 /**
0019  * @internal
0020  */
0021 template <class T>
0022 struct symnode 
0023 {
0024     /**
0025      * @internal
0026      */
0027     symnode()
0028     {
0029     }
0030 
0031     /**
0032      * @internal
0033      */
0034     symnode(const T& n) : data(n)
0035     {
0036     }
0037 
0038     /**
0039      * @internal
0040      */
0041     symnode* adj[2];
0042 
0043     /**
0044      * @internal
0045      */
0046     T data;
0047 };
0048 
0049 /**
0050  * @internal
0051  */
0052 template <class T, class Ref>
0053 struct symlist_iterator 
0054 {
0055     /**
0056      * @internal
0057      */
0058     typedef symlist_iterator<T, Ref> self;
0059 
0060     /**
0061      * @internal
0062      */
0063     typedef symnode<T>* linktype;
0064 
0065     /**
0066      * @internal
0067      */
0068     symlist_iterator() : act (0)
0069     {
0070     }
0071 
0072     /**
0073      * @internal
0074      */
0075     symlist_iterator(const self& it) : act(it.act), dir(it.dir)
0076     {
0077     }
0078 
0079     /**
0080      * @internal
0081      */
0082     symlist_iterator(linktype _act, int _dir) : act(_act), dir(_dir)
0083     {
0084     }
0085     
0086     /**
0087      * @internal
0088      */
0089     symlist_iterator(linktype _act, linktype _prev) :
0090     act(_act),
0091     dir (where_not (_act, _prev))
0092     {
0093     }
0094 
0095     /**
0096      * @internal
0097      */
0098     self& operator=(const self& it)
0099     {
0100     act = it.act;
0101     dir = it.dir;
0102     return *this;
0103     }
0104 
0105     /**
0106      * @internal
0107      */
0108     bool operator==(const self& it) const
0109     {
0110     return act == it.act;
0111     }
0112     
0113     /**
0114      * @internal
0115      */
0116     bool operator!=(const self& it) const
0117     {
0118     return act != it.act;
0119     }
0120     
0121     /**
0122      * @internal
0123      */
0124     Ref operator*() 
0125     {
0126     return act->data;
0127     }
0128 
0129     /**
0130      * @internal
0131      */
0132     self& operator++();
0133 
0134     /**
0135      * @internal
0136      */
0137     self& operator--();
0138     
0139     /**
0140      * @internal
0141      */
0142     static int where(linktype _act, linktype _prev) 
0143     {
0144     return _prev == _act->adj[0] ? 0 : 1;
0145     }
0146 
0147     /**
0148      * @internal
0149      */
0150     static int where_not(linktype _act, linktype _prev)
0151     {
0152     return _prev == _act->adj[1] ? 0 : 1;
0153     }
0154 
0155     /**
0156      * @internal
0157      */
0158     void reverse()
0159     {
0160     dir = 1 - dir;
0161     }
0162     
0163     /**
0164      * @internal
0165      */
0166     linktype& next()
0167     {
0168     return act->adj[dir];
0169     }
0170 
0171     /**
0172      * @internal
0173      */
0174     linktype& prev()
0175     {
0176     return act->adj[1 - dir];
0177     }
0178 
0179     /**
0180      * @internal
0181      */
0182     linktype act;
0183 
0184     /**
0185      * @internal
0186      */
0187     int dir;
0188 };
0189 
0190 /**
0191  * @brief List which can be reversed in @f$\mathcal{O}(1)@f$. 
0192  *
0193  * The problem with the STL class list - as with most doubly linked lists --
0194  * is that isn't possible to turn it in constant time, because each entry in
0195  * the list contains next and prev pointer and turning the list means to
0196  * switch these two in @em each element in the list. Another point is the
0197  * splice operation in STL lists, which is constant time, but for the same
0198  * reason as mentioned above it is not possible to splice a list in reverse
0199  * order into another in constant time.
0200  * <p>
0201  * The problems arise from the fact that each element "knows" what its next
0202  * and previous elements are. An element in a symlist only knows what its
0203  * neighbors are, what is next and what previous depends on the direction of
0204  * iteration. This of course imposes some overhead in iteration (one
0205  * if-statement) but allows reversion and a splice in reversed order in
0206  * constant time.
0207  */
0208 template <class T>
0209 class symlist 
0210 {
0211 public:
0212     /**
0213      * @internal
0214      */
0215     typedef symlist_iterator<T, T&> iterator;
0216 
0217     /**
0218      * @internal
0219      */
0220     typedef symlist_iterator<T, const T&> const_iterator;
0221 
0222     /**
0223      * @brief Creates empty symlist.
0224      */
0225     symlist()
0226     {
0227     link = new symnode<T>;
0228     link->adj[0] = link->adj[1] = link;
0229     }
0230 
0231     /**
0232      * @brief Makes the created list a copy of @c li.
0233      *
0234      * @param li symlist.
0235      */
0236     symlist(const symlist<T>& li);
0237 
0238     /**
0239      * @brief Assignes @c li to this list.
0240      *
0241      * @note All elements in this list will be deleted.
0242      *
0243      * @param li 
0244      *
0245      * @return this list
0246      */
0247     symlist<T>& operator=(const symlist<T>& li);
0248 
0249     /**
0250      * @brief Destructor 
0251      */
0252     ~symlist();
0253 
0254     /**
0255      * @brief Checks whether list is empty.
0256      *
0257      * Takes constant time.
0258      *
0259      * @retval true iff list is empty
0260      */
0261     bool empty() const
0262     {
0263     return link->adj[0] == link && link->adj[1] == link;
0264     }
0265 
0266     /**
0267      * @brief First element in list.
0268      *
0269      * Assumes that list ins't empty.
0270      *
0271      * @return first element
0272      */
0273     T& front()
0274     {
0275     return link->adj[0]->data;
0276     }
0277 
0278     /**
0279      * @brief Last element in list.
0280      *
0281      * Assumes that list ins't empty.
0282      *
0283      * @return last element
0284      */
0285     T& back()
0286     {
0287     return link->adj[1]->data;
0288     }
0289 
0290     /**
0291      * @brief Start iteration through elements of list.
0292      *
0293      * @return start iterator
0294      */
0295     iterator begin()
0296     {
0297     return ++end();
0298     }
0299 
0300     /**
0301      * @brief End of iteration through elements of list.
0302      *
0303      * @return end iterator
0304      */
0305     iterator end()
0306     {
0307     return iterator(link, 0);
0308     }
0309 
0310     /**
0311      * @brief Start iteration through elements of list.
0312      *
0313      * @return start iterator
0314      */
0315     const_iterator begin() const
0316     {
0317     return ++end();
0318     }
0319 
0320     /**
0321      * @brief End of iteration through elements of list.
0322      *
0323      * @return end iterator
0324      */
0325     const_iterator end () const
0326     {
0327     return const_iterator (link, 0);
0328     }
0329 
0330     /**
0331      * @brief Start iteration through element of list in reverse order.
0332      *
0333      * @return start iterator 
0334      */
0335     iterator rbegin()
0336     {
0337     return ++rend();
0338     }
0339 
0340     /**
0341      * @brief End of iteration through elements of list in reverse order.
0342      *
0343      * @return end iterator
0344      */
0345     iterator rend()
0346     {
0347     return iterator (link, 1);
0348     }
0349 
0350     /**
0351      * @brief Start iteration through element of list in reverse order.
0352      *
0353      * @return start iterator 
0354      */
0355     const_iterator rbegin() const
0356     {
0357     return ++rend();
0358     }
0359 
0360     /**
0361      * @brief End of iteration through elements of list in reverse order.
0362      *
0363      * @return end iterator
0364      */
0365     const_iterator rend() const
0366     {
0367     return const_iterator(link, 1);
0368     }
0369 
0370     /**
0371      * @brief Inserts @p data before @p pos in list.
0372      *
0373      * @param pos position
0374      * @param data element to be inserted
0375      *
0376      * @return position of insertion
0377      */
0378     iterator insert (iterator pos, const T& data);
0379 
0380     /**
0381      * @brief Inserts the element @p it points to before @p pos into this
0382      *        list.
0383      *
0384      * It is assumed that the element @p it refers lies in a different list.
0385      * All iterators to elements in either of the two lists stay valid.
0386      * Takes constant time.
0387      *
0388      * @param pos position 
0389      * @param it position of element to be inserted
0390      */
0391     void splice (iterator pos, iterator it);
0392 
0393     /**
0394      * @brief Inserts the elements <tt>[it,end)</tt> refers to before @p pos
0395      *        into this list.
0396      *
0397      * It is assumed that <tt>[it,end)</tt> lies in a different
0398      * list. All iterators to elements in either of the two lists stay
0399      * valid. Takes constant time.
0400      *
0401      * @param pos position 
0402      * @param it position of first element to be inserted
0403      * @param end position of one-past the last element to be inserted
0404      */
0405     void splice (iterator pos, iterator it, iterator end);
0406 
0407     /**
0408      * @brief Deletes element at position @p pos from list.
0409      *
0410      * @param pos position to be deleted
0411      *
0412      * @return position of next element
0413      */
0414     iterator erase (iterator pos);
0415 
0416     /**
0417      * @brief Deletes the elements <tt>[it, end)</tt> from list.
0418      *
0419      * @param it first position to be deleted
0420      * @param end one-past the last position to be deleted
0421      *
0422      * @return position of next element.
0423      */
0424     iterator erase (iterator it, iterator end);
0425 
0426     /**
0427      * @internal
0428      */
0429     void attach_sublist (iterator, iterator);
0430 
0431     /**
0432      * @internal
0433      */
0434     void detach_sublist ();
0435 
0436     /**
0437      * @brief Change the direction of list.
0438      *
0439      * Takes constant time.
0440      */
0441     void reverse ();
0442 private:
0443     /**
0444      * @internal
0445      */
0446     symnode<T>* link;
0447 
0448     /**
0449      * @internal
0450      *
0451      * @note Needed only when used as sublist.
0452      */
0453     iterator _prev;
0454 
0455     /**
0456      * @internal
0457      *
0458      * @note Needed only when used as sublist.
0459      */
0460     iterator _next;
0461 };
0462 
0463 
0464 // Implementation Begin
0465 
0466 template <class T, class Ref>
0467 symlist_iterator<T, Ref>& symlist_iterator<T, Ref>::operator++()
0468 {
0469     symnode<T>* prev = act; 
0470     act = act->adj[dir];
0471     dir = where_not(act, prev);
0472     return *this;
0473 }
0474 
0475 
0476 template <class T, class Ref>
0477 symlist_iterator<T, Ref>& symlist_iterator<T, Ref>::operator--()
0478 {
0479     symnode<T>* prev = act;
0480     act = act->adj[1 - dir];
0481     dir = where(act, prev); 
0482     return *this;
0483 }
0484 
0485 
0486 template <class T>
0487 symlist<T>::symlist (const symlist<T>& l)
0488 {
0489     link = new symnode<T>;
0490     link->adj[0] = link->adj[1] = link;    
0491     
0492     const_iterator it = l.begin();
0493     const_iterator e = l.end();
0494 
0495     while (it != e)
0496     {
0497     insert(end(), *it);
0498     ++it;
0499     }
0500 }
0501 
0502 
0503 template <class T>
0504 symlist<T>::~symlist()
0505 {
0506     if (_next == iterator())
0507     {
0508     erase (begin(), end());
0509     }
0510     else
0511     {
0512     detach_sublist();
0513     }
0514     
0515     delete link;
0516 }
0517 
0518 
0519 template <class T>
0520 symlist<T>& symlist<T>::operator=(const symlist<T>& l) 
0521 {
0522     erase(begin(), end());
0523 
0524     const_iterator it = l.begin();
0525     const_iterator e = l.end();
0526 
0527     while (it != e)
0528     {
0529     insert(end(), *it);
0530     ++it;
0531     }
0532     
0533     return *this;
0534 }
0535 
0536 
0537 template <class T>
0538 symlist_iterator<T, T&> symlist<T>::insert(
0539     symlist_iterator<T,T&> pos,
0540     const T& ins)
0541 {
0542     iterator prev = pos;
0543     --prev;
0544     symnode<T>* n = new symnode<T>(ins);
0545     n->adj[0] = pos.act;
0546     n->adj[1] = prev.act;
0547 
0548     if (pos == prev)
0549     {
0550     pos = prev;
0551     }
0552 
0553     pos.prev() = n;
0554     prev.next() = n;
0555 
0556     return iterator(n, 0);
0557 }
0558 
0559 
0560 template <class T>
0561 void symlist<T>::splice(symlist_iterator<T, T&> pos,
0562             symlist_iterator<T, T&> beg,
0563             symlist_iterator<T, T&> end) 
0564 {
0565     if (beg != end)
0566     {
0567     iterator prev = beg;
0568     --prev;
0569     iterator last = end;
0570     --last;
0571 
0572     //
0573     // The following seems to be rather senseless, but it is required
0574     // since two iterator are equal, iff the point to the same element.
0575     // This implies that they might have different directions. Suppose
0576     // that prev == end is true and they have different directions,
0577     // than prev.next() and end.prev() return the same element !! Thus
0578     // the assignment prev = end corrects this, since the direction
0579     // gets copied, too.
0580     //
0581     if (prev == end)
0582     {
0583         prev = end;
0584     }
0585         
0586     prev.next() = end.act;
0587     end.prev() = prev.act;
0588 
0589     prev = pos;
0590     --prev;
0591 
0592     if (pos == prev)
0593     {
0594         pos = prev;
0595     }
0596 
0597     if (last == beg)
0598     {
0599         last = beg;
0600     }
0601     
0602     prev.next() = beg.act;
0603     beg.prev() = prev.act;
0604     pos.prev() = last.act;
0605     last.next() = pos.act;
0606     }
0607 }
0608 
0609 
0610 template <class T>
0611 void symlist<T>::splice(symlist_iterator<T,T&> pos, 
0612             symlist_iterator<T,T&> beg)
0613 {
0614     iterator tmp = beg;
0615     ++tmp;
0616     splice(pos, beg, tmp);
0617 }
0618 
0619 
0620 template <class T>
0621 symlist_iterator<T,T&> symlist<T>::erase(symlist_iterator<T,T&> pos) 
0622 {
0623     assert (pos.act != link);
0624     iterator prev = pos;
0625     --prev;
0626     iterator next = pos;
0627     ++next;
0628     
0629     if (next == prev)
0630     {
0631     next = prev;
0632     }
0633 
0634     next.prev() = prev.act;
0635     prev.next() = next.act;
0636 
0637     delete (pos.act);
0638 
0639     return next;
0640 }
0641 
0642 template <class T>
0643 symlist_iterator<T,T&> symlist<T>::erase(symlist_iterator<T,T&> beg, 
0644                      symlist_iterator<T,T&> end)
0645 {
0646     iterator prev = beg;
0647     --prev;
0648     iterator it = beg;
0649     symnode<T>* act;
0650 
0651     while (it != end)
0652     {
0653     assert (it.act != link);
0654     act = it.act;
0655     ++it;
0656     delete (act);
0657     }
0658 
0659     if (prev == end)
0660     {
0661     prev = end;
0662     }   
0663     
0664     end.prev() = prev.act;
0665     prev.next() = end.act;
0666    
0667     return end;
0668 }    
0669 
0670 
0671 template <class T>
0672 void symlist<T>::attach_sublist(symlist_iterator<T,T&> it, 
0673                 symlist_iterator<T,T&> end) 
0674 { 
0675     assert (empty());
0676     iterator last = end;
0677     --last;
0678     _prev = it;
0679     --_prev;
0680     _next = end;
0681 
0682     if (it == last)
0683     {
0684     it = last;
0685     }
0686 
0687     link->adj[0] = it.act;
0688     it.prev() = link;
0689     link->adj[1] = last.act;
0690     last.next() = link;
0691 }   
0692 
0693     
0694 template <class T>
0695 void symlist<T>::detach_sublist() 
0696 {
0697     if (_next != iterator())
0698     {
0699     iterator it(begin());
0700     iterator e(end());
0701     
0702     --e;
0703     
0704     if (e == it)
0705     {
0706         e = it;
0707     }
0708 
0709     _prev.next() = it.act;
0710     it.prev() = _prev.act;
0711     _next.prev() = e.act;
0712     e.next() = _next.act;
0713     link->adj[0] = link->adj[1] = link;
0714 
0715     _next = iterator();
0716     _prev = iterator();
0717     }
0718 }
0719 
0720 
0721 template <class T>
0722 inline void symlist<T>::reverse()
0723 {
0724     symnode<T>* tmp = link->adj[0];
0725     link->adj[0] = link->adj[1];
0726     link->adj[1] = tmp;
0727 }
0728 
0729 // Implementation End
0730 
0731 __GTL_END_NAMESPACE
0732 
0733 #endif // SYMLIST_H
0734 
0735 //--------------------------------------------------------------------------
0736 //   end of file
0737 //--------------------------------------------------------------------------