basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/include/basix/chain.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : chain.hpp
00004 * DESCRIPTION: Chains (balanced trees considered as lists)
00005 * COPYRIGHT  : (C) 2006  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX_CHAIN_HPP
00014 #define __MMX_CHAIN_HPP
00015 #include <basix/vector.hpp>
00016 
00018 
00019 namespace mmx {
00020 #define TMPL_DEF template<typename C>
00021 #define TMPL template<typename C>
00022 #define Format format<C>
00023 #define Chain chain<C>
00024 #define Chain_rep chain_rep<C>
00025 TMPL class chain_rep;
00026 TMPL class chain;
00027 TMPL inline Chain left (const Chain& c);
00028 TMPL inline C middle (const Chain& c);
00029 TMPL inline Chain right (const Chain& c);
00030 TMPL inline bool is_nil (const Chain& c);
00031 TMPL inline nat N (const Chain& c);
00032 TMPL Chain balance_left (const Chain& c);
00033 TMPL Chain balance_right (const Chain& c);
00034 TMPL Chain operator * (const Chain& l, const Chain& r);
00035 
00036 /******************************************************************************
00037 * Chain class and its representation class
00038 ******************************************************************************/
00039 
00040 TMPL_DEF
00041 class chain_rep REP_STRUCT {
00042   nat   size;
00043   Chain l;
00044   C     m;
00045   Chain r;
00046   // Invariant: #l < 2 (#r + 1) and #r < 2 (#l + 1)
00047 
00048 public:
00049   inline Chain_rep (const Chain& l2, const C& m2, const Chain& r2);
00050   friend class Chain;
00051   friend Chain left LESSGTR (const Chain& c);
00052   friend C middle LESSGTR (const Chain& c);
00053   friend Chain right LESSGTR (const Chain& c);
00054   friend nat N LESSGTR (const Chain& c);
00055 };
00056 
00057 TMPL_DEF
00058 class chain: public format<C> {
00059 INDIRECT_PROTO_1 (chain, chain_rep, C)
00060 public:
00061   inline chain ():
00062     Format (no_format ()),
00063     rep (NULL) {}
00064   inline chain (const C& c1):
00065     Format (get_format (c1)),
00066     rep (new Chain_rep (Chain (), c1, Chain ())) {}
00067   inline chain (const C& c1, const C& c2):
00068     Format (get_format (c1)),
00069     rep (new Chain_rep (Chain (c1), c2, Chain ())) {}
00070   inline chain (const C& c1, const C& c2, const C& c3):
00071     Format (get_format (c1)),
00072     rep (new Chain_rep (Chain (c1), c2, Chain (c3))) {}
00073   inline chain (const Chain& l, const C& m, const Chain& r):
00074     Format (get_format (m)),
00075     rep (new Chain_rep (l, m, r)) {}
00076   chain (const iterator<C>& it):
00077     Format (CF(it)) {
00078     rep= NULL;
00079     for (; busy (it); ++it) *this= (*this) * Chain (*it); }
00080   C operator [] (nat i) const {
00081     ASSERT (rep != NULL, "non-empty chain expected");
00082     if (i < N (rep->l)) return rep->l[i];
00083     if (i > N (rep->l)) return rep->r[i-N(rep->l)];
00084     return rep->m; }
00085   friend Chain left LESSGTR (const Chain& c);
00086   friend C middle LESSGTR (const Chain& c);
00087   friend Chain right LESSGTR (const Chain& c);
00088   friend bool is_nil LESSGTR (const Chain& c);
00089   friend nat N LESSGTR (const Chain& c);
00090 };
00091 DEFINE_UNARY_FORMAT_1 (chain)
00092 
00093 TMPL inline Format CF (const Chain& l) {
00094   return (Format) l; }
00095 TMPL inline Chain::chain (Chain_rep* rep2):
00096   Format (no_format ()), rep(rep2) {}
00097 TMPL inline Chain::chain (const Chain_rep* rep2, bool with_inc):
00098   Format (no_format ()), rep((Chain_rep*) (void*) rep2) {
00099   (void) with_inc; INC_NULL_COUNT (rep); }
00100 TMPL inline Chain::chain (const Chain& x):
00101   Format (CF(x)), rep(x.rep) {
00102   INC_NULL_COUNT (rep); }
00103 TMPL inline Chain::~chain () {
00104   DEC_NULL_COUNT (rep); }
00105 TMPL inline const Chain_rep* Chain::operator -> () const {
00106   return rep; }
00107 TMPL inline Chain_rep* Chain::operator -> () {
00108   return rep; }
00109 TMPL inline Chain& Chain::operator = (const Chain& x) {
00110   INC_NULL_COUNT (x.rep); DEC_NULL_COUNT (rep);
00111   rep=x.rep; return *this; }
00112 TMPL inline void Chain::secure () {
00113   if (rep->ref_count>1) *this= copy (*this); }
00114 TMPL Chain_rep* inside (const Chain& x) {
00115   return const_cast<Chain_rep*> (x.operator -> ()); }
00116 TMPL inline nat hard_hash (const Chain& x) {
00117   return as_hash (x.operator -> ()); }
00118 TMPL inline bool hard_eq (const Chain& x, const Chain& y) {
00119   return (x.operator -> ()) == (y.operator -> ()); }
00120 TMPL inline bool hard_neq (const Chain& x, const Chain& y) {
00121   return (x.operator -> ()) != (y.operator -> ()); }
00122 
00123 /******************************************************************************
00124 * Basic constructors and accessors
00125 ******************************************************************************/
00126 
00127 TMPL inline
00128 Chain_rep::chain_rep (const Chain& l2, const C& m2, const Chain& r2):
00129   size (N (l2) + N (r2) + 1), l (l2), m (m2), r (r2) {}
00130 
00131 TMPL inline Chain left (const Chain& c) { return c.rep->l; }
00132 TMPL inline C middle (const Chain& c) { return c.rep->m; }
00133 TMPL inline Chain right (const Chain& c) { return c.rep->r; }
00134 TMPL inline bool is_nil (const Chain& c) { return c.rep == NULL; }
00135 TMPL inline nat N (const Chain& c) { return (c.rep == NULL? 0: c.rep->size); }
00136 
00137 /******************************************************************************
00138 * Chain iteration and output
00139 ******************************************************************************/
00140 
00141 TMPL iterator<C>
00142 iterate (const Chain& c) {
00143   if (is_nil (c)) return iterator<C> ();
00144   return
00145     lazy_iterator<C,Chain > (left (c), get_format (middle (c))) *
00146     iterator<C> (middle (c)) *
00147     lazy_iterator<C,Chain > (right (c), get_format (middle (c)));
00148 }
00149 
00150 TMPL syntactic
00151 flatten (const Chain& c) {
00152   return flatten (syntactic ("chain"), iterate (c));
00153 }
00154 
00155 TMPL
00156 struct binary_helper<Chain >: public void_binary_helper<Chain > {
00157   static inline string short_type_name () {
00158     return "Ch" * Short_type_name (C); }
00159   static inline generic full_type_name () {
00160     return gen ("Chain", Full_type_name (C)); }
00161   static generic disassemble (const Chain& c) {
00162     if (N(c) == 0) return gen_vec ();
00163     else if (N(c) == 1) return gen_vec (as<generic> (middle (c)));
00164     else return gen_vec (as<generic> (left (c)),
00165                          as<generic> (middle (c)),
00166                          as<generic> (right (c))); }
00167   static Chain assemble (const generic& g) {
00168     vector<generic> v= as<vector<generic> > (g);
00169     if (N(v) == 0) return Chain ();
00170     else if (N(v) == 1) return Chain (as<C> (v[0]));
00171     else return Chain (as<Chain > (v[0]), as<C> (v[1]), as<Chain > (v[2])); }
00172   static void write_bis (const port& out, const Chain& c) {
00173     write_bis (out, left (c));
00174     binary_write<C> (out, middle (c));
00175     write_bis (out, right (c)); }
00176   static inline void write (const port& out, const Chain& c) {
00177     binary_write<nat> (out, N(c));
00178     write_bis (out, c); }
00179   static Chain read (const port& in, nat n) {
00180     if (n == 0) return Chain ();
00181     else if (n == 1) return Chain (binary_read<C> (in));
00182     else return Chain (binary_read<Chain > (in, n >> 1),
00183                        binary_read<C> (in),
00184                        binary_read<Chain > (in, (n-1) >> 1)); }
00185   static inline Chain read (const port& in) {
00186     nat n = binary_read<nat> (in);
00187     return read (in, n); }
00188 };
00189 
00190 /******************************************************************************
00191 * Operations on chains
00192 ******************************************************************************/
00193 
00194 TMPL Chain
00195 copy (const Chain& c) {
00196   if (is_nil (c)) return c;
00197   return Chain (left (c), middle (c), right (c));
00198 }
00199 
00200 TMPL Chain
00201 reverse (const Chain& c) {
00202   if (is_nil (c)) return c;
00203   return Chain (reverse (right (c)), middle (c), reverse (left (c)));
00204 }
00205 
00206 TMPL C
00207 car (const Chain& c) {
00208   ASSERT (!is_nil (c), "non-empty chain expected");
00209   if (is_nil (left (c))) return middle (c);
00210   return car (left (c));
00211 }
00212 
00213 TMPL C
00214 cAr (const Chain& c) {
00215   ASSERT (!is_nil (c), "non-empty chain expected");
00216   if (is_nil (right (c))) return middle (c);
00217   return cAr (right (c));
00218 }
00219 
00220 template<typename Op, typename C> nat
00221 unary_hash (const Chain& c) {
00222   if (is_nil (c)) return 1928;
00223   nat h1= Op::op (left (c));
00224   nat h2= Op::op (middle (c));
00225   nat h3= Op::op (right (c));
00226   return h1 ^ (h2>>1) ^ (h2<<31) ^ (h3>>3) ^ (h3>>29);
00227 }
00228 
00229 template<typename Op, typename C> bool
00230 binary_test (const Chain& c1, const Chain& c2) {
00231   if (N (c1) != N (c2)) return false;
00232   if (N (c1) == 0) return true;
00233   return binary_test<Op> (left (c1), left(c2)) &&
00234     Op::op (middle (c1), middle (c2)) &&
00235     binary_test<Op> (right (c1), right(c2));
00236 }
00237 
00238 TRUE_IDENTITY_OP_SUGAR(TMPL,Chain)
00239 EXACT_IDENTITY_OP_SUGAR(TMPL,Chain)
00240 
00241 /******************************************************************************
00242 * Operations that need balancing
00243 ******************************************************************************/
00244 
00245 TMPL Chain
00246 shift_left (const Chain& c) {
00247   return Chain (Chain (left (c), middle (c), left (right (c))),
00248                 middle (right (c)),
00249                 right (right (c)));
00250 }
00251 
00252 TMPL Chain
00253 shift_right (const Chain& c) {
00254   return Chain (left (left (c)),
00255                 middle (left (c)),
00256                 Chain (right (left (c)), middle (c), right (c)));
00257 }
00258 
00259 TMPL Chain
00260 balance_left (const Chain& c) {
00261   // Ensure that #left(c) >= #right(c)
00262   switch (N(c)) {
00263   case 0:
00264   case 1:
00265     return c;
00266   case 2:
00267     if (is_nil (right (c))) return c;
00268     return Chain (Chain (middle (c)), middle (right (c)), Chain ());
00269   case 3:
00270     return c;
00271   default:
00272     if (N (left (c)) >= N (right (c))) return c;
00273     else {
00274       Chain aux= balance_right (right (c));
00275       return shift_left (Chain (left (c), middle (c), aux));
00276     }
00277   }
00278 }
00279 
00280 TMPL Chain
00281 balance_right (const Chain& c) {
00282   // Ensure that #left(c) <= #right(c)
00283   switch (N(c)) {
00284   case 0:
00285   case 1:
00286     return c;
00287   case 2:
00288     if (is_nil (left (c))) return c;
00289     return Chain (Chain (), middle (left (c)), Chain (middle (c)));
00290   case 3:
00291     return c;
00292   default:
00293     if (N (left (c)) <= N (right (c))) return c;
00294     else {
00295       Chain aux= balance_left (left (c));
00296       return shift_right (Chain (aux, middle (c), right (c)));
00297     }
00298   }
00299 }
00300 
00301 TMPL Chain
00302 cdr (const Chain& c) {
00303   ASSERT (!is_nil (c), "non-empty chain expected");
00304   if (N (c) == 1) return Chain ();
00305   if (2 * N (left (c)) <= N (right (c))) return cdr (balance_left (c));
00306   return Chain (cdr (left (c)), middle (c), right (c));
00307 }
00308 
00309 TMPL Chain
00310 cDr (const Chain& c) {
00311   ASSERT (!is_nil (c), "non-empty chain expected");
00312   if (N (c) == 1) return Chain ();
00313   if (2 * N (right (c)) <= N (left (c))) return cDr (balance_right (c));
00314   return Chain (left (c), middle (c), cDr (right (c)));
00315 }
00316 
00317 TMPL Chain
00318 operator * (const Chain& l, const Chain& r) {
00319   nat nl= N (l), nr= N (r);
00320   if (nl < nr) {
00321     if (nl == 0) return r;
00322     if (nr < 2*nl + 3) return Chain (l, car (r), cdr (r));
00323     Chain br= balance_right (r);
00324     return Chain (l * left (br), middle (br), right (br));
00325   }
00326   else {
00327     if (nr == 0) return l;
00328     if (nl < 2*nr + 3) return Chain (cDr (l), cAr (l), r);
00329     Chain bl= balance_left (l);
00330     return Chain (left (bl), middle (bl), right (bl) * r);
00331   }
00332 }
00333 
00334 TMPL Chain
00335 range (const Chain& c, nat start, nat end) {
00336   if (start >= end) return Chain ();
00337   ASSERT (!is_nil (c), "non-empty chain expected");
00338   nat n= N (left (c));
00339   if (end <= n) return range (left (c), start, end);
00340   if (start > n) return range (right (c), start-n-1, end-n-1);
00341   Chain l= range (left (c), start, n);
00342   C     m= middle (c);
00343   Chain r= range (right (c), 0, end-n-1);
00344   if (N(l) < 2*(N(r) + 1) && N(r) < 2*(N(l) + 1)) return Chain (l, m, r);
00345   return l * Chain (m) * r;
00346 }
00347 
00348 /******************************************************************************
00349 * Dynamic mappers
00350 ******************************************************************************/
00351 
00352 template<typename S1, typename D> chain<D>
00353 map (const function_1<D,Argument(S1) >& fun,
00354      const chain<S1>& c1, const format<D>& fm)
00355 {
00356   if (is_nil (c1)) return chain<D> (fm);
00357   return chain<D> (map (fun, left (c1), fm),
00358                    fun (middle (c1)),
00359                    map (fun, right (c1), fm));
00360 }
00361 
00362 template<typename S1, typename D> inline chain<D>
00363 map (D (*fun) (const S1&), const chain<S1>& x1, const format<D>& fm) {
00364   return map (function_1<D,Argument(S1) > (fun), x1, fm);
00365 }
00366 
00367 #undef TMPL_DEF
00368 #undef TMPL
00369 #undef Format
00370 #undef Chain
00371 #undef Chain_rep
00372 } // namespace mmx
00373 #endif // __MMX_CHAIN_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines