level.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016 // Boston, MA 02110-1301, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_TOPO_COMBINATORIAL_MAP_INTERNAL_LEVEL_HH
00029 # define OLENA_TOPO_COMBINATORIAL_MAP_INTERNAL_LEVEL_HH
00030 
00031 # include <mlc/contract.hh>
00032 
00033 # include <iostream>
00034 # include <vector>
00035 
00036 namespace oln {
00037 
00038   namespace topo {
00039 
00040     namespace combinatorial_map {
00041 
00042       namespace internal {
00043         /* Node of a tree
00044         **
00045         ** \var node::lb left brother.
00046         ** \var node::rb right brother.
00047         ** \var node::fchild first child.
00048         ** \var node::father father.
00049         */
00050         template <class U>
00051         struct node
00052         {
00053           node() : fchild(0), lb(0), rb(0), father(0) {}
00054 
00055           U fchild, lb, rb, father;
00056         };
00057 
00058         /* Level function.
00059         **
00060         ** \todo FIXME: add doc.
00061         */
00062         template <class U>
00063         class level
00064         {
00065         public:
00066           level(unsigned n) : tree_(n+1)
00067           {
00068             assertion(n != 0);
00069           }
00070 
00071           U father(const U & child) const
00072           {
00073             assertion(child < tree_.size());
00074 
00075             return tree_[child].father;
00076           }
00077 
00078           U children(const U & father) const
00079           {
00080             static unsigned f = 0;
00081             static unsigned last = 0;
00082 
00083             assertion(father < tree_.size());
00084 
00085             if (f != father)
00086               {
00087                 f = father;
00088                 last = tree_[f].fchild;
00089               }
00090             else
00091               last = (!last || tree_[last].rb == tree_[f].fchild) ?
00092                 0 : tree_[last].rb;
00093 
00094             return last;
00095           }
00096 
00097           void insert(const U & father, const U & child)
00098           {
00099             node<U> & f = tree_[father];
00100             node<U> & c = tree_[child];
00101 
00102             if (!f.lb)
00103               f.lb = f.rb = father;
00104 
00105             unsigned fchild = f.fchild;
00106 
00107             if (fchild)
00108               {
00109                 unsigned tail = tree_[fchild].lb;
00110 
00111                 tree_[tail].rb = child;
00112                 c.lb = tail;
00113                 tree_[fchild].lb = child;
00114                 c.rb = fchild;
00115               }
00116             else
00117               f.fchild = c.lb = c.rb = child;
00118 
00119             c.father = father;
00120           }
00121 
00122           void merge(const U & l1, const U & l2)
00123           {
00124             node<U> & a = tree_[l1];
00125             node<U> & b = tree_[l2];
00126 
00127             // assert l2 is not the first child of its father
00128             if (tree_[b.father].fchild == l2)
00129               tree_[b.father].fchild = (l2 != b.rb) ? b.rb : 0;
00130 
00131             // append l2' children to l1 ones
00132             if (b.fchild)
00133               {
00134                 // FIXME: find a way to get this constant time
00135                 unsigned l = 0;
00136                 while ((l = children(l2)))
00137                   tree_[l].father = l1;
00138 
00139                 if (a.fchild)
00140                   {
00141                     tree_[tree_[a.fchild].lb].rb = b.fchild;
00142                     tree_[b.fchild].lb = tree_[a.fchild].lb;
00143 
00144                     tree_[a.fchild].lb = tree_[b.fchild].lb;
00145                     tree_[b.fchild].rb = a.fchild;
00146                   }
00147                 else
00148                   a.fchild = b.fchild;
00149               }
00150 
00151             // pop up l2 from the list child
00152             tree_[b.rb].lb = b.lb;
00153             tree_[b.lb].rb = b.rb;
00154 
00155             b.fchild = b.lb = b.rb = b.father = 0;
00156           }
00157 
00158         public:
00159           std::ostream & print(std::ostream & ostr) const
00160           {
00161             for (unsigned i = 1; i < tree_.size(); ++i)
00162               ostr << "father(" << i << ") = " << father(i) << std::endl;
00163 
00164             ostr << std::endl;
00165 
00166             for (unsigned i = 1; i < tree_.size(); ++i)
00167               {
00168                 ostr << "children(" << i << ") = ";
00169 
00170                 unsigned l = children(i);
00171 
00172                 if (l)
00173                   {
00174                     ostr << l;
00175                     while ((l = children(i)))
00176                       ostr << ", " << l;
00177                     ostr << std::endl;
00178                   }
00179                 else
00180                   ostr << "none" << std::endl;
00181               }
00182 
00183             return ostr;
00184           }
00185 
00186         private:
00187           std::vector< node<U> > tree_;
00188         };
00189 
00190       } // end of namespace internal
00191 
00192     } // end of namespace combinatorial_map
00193 
00194   } // end of namespace topo
00195 
00196 } // end of namespace oln
00197 
00198 template<class U>
00199 inline std::ostream &
00200 operator<<(std::ostream & ostr,
00201            const oln::topo::combinatorial_map::internal::level<U> & l)
00202 {
00203   return l.print(ostr);
00204 }
00205 
00206 #endif // ! OLENA_TOPO_COMBINATORIAL_MAP_INTERNAL_LEVEL_HH

Generated on Tue Feb 20 20:20:07 2007 for Olena by  doxygen 1.5.1