basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : list.hpp 00004 * DESCRIPTION: Linked lists 00005 * COPYRIGHT : (C) 2004 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_LIST_HPP 00014 #define __MMX_LIST_HPP 00015 #include <basix/vector.hpp> 00016 00018 // Linked lists 00019 00020 namespace mmx { 00021 #define TMPL_DEF template<typename C> 00022 #define TMPL template<typename C> 00023 #define Format format<C> 00024 #define List list<C> 00025 #define List_rep list_rep<C> 00026 TMPL class list_rep; 00027 TMPL class list; 00029 TMPL inline List cons (const C& c, const List& l); 00031 TMPL inline const C& car (const List& l); 00033 TMPL inline C& car (List& l); 00035 TMPL inline const List& cdr (const List& l); 00037 TMPL inline List& cdr (List& l); 00039 TMPL inline bool is_nil (const List& l); 00040 00041 /****************************************************************************** 00042 * List class and its representation class 00043 ******************************************************************************/ 00044 00045 TMPL_DEF 00046 class list_rep REP_STRUCT { 00047 C item; 00048 List next; 00049 00050 public: 00051 inline List_rep (const C& item2, const List& next2): 00052 item(item2), next(next2) {} 00053 friend class List; 00054 friend const C& car LESSGTR (const List& l); 00055 friend C& car LESSGTR (List& l); 00056 friend const List& cdr LESSGTR (const List& l); 00057 friend List& cdr LESSGTR (List& l); 00058 }; 00059 00060 TMPL_DEF 00061 class list: public format<C> { 00062 INDIRECT_PROTO_1 (list, list_rep, C) 00063 private: 00064 inline list (const C& item, const List& next): 00065 Format (get_format (item)), rep (new List_rep (item, next)) {} 00066 public: 00067 inline list (): 00068 Format (no_format ()), rep (NULL) {} 00069 inline list (const Format& fm): 00070 Format (fm), rep (NULL) {} 00071 inline list (const C& c1): 00072 Format (get_format (c1)), rep (new List_rep (c1, List ())) {} 00073 inline list (const C& c1, const C& c2): 00074 Format (get_format (c1)), rep (new List_rep (c1, List (c2))) {} 00075 inline list (const C& c1, const C& c2, const C& c3): 00076 Format (get_format (c1)), rep (new List_rep (c1, List (c2, c3))) {} 00077 inline list (const C& c1, const C& c2, const C& c3, const C& c4): 00078 Format (get_format (c1)), rep (new List_rep (c1, List (c2, c3, c4))) {} 00079 list (const vector<C>& v): 00080 Format (CF(v)), rep (NULL) { 00081 for (nat i=N(v)-1; i!=((nat) -1); i--) rep= new List_rep (v[i], *this); } 00082 list (const iterator<C>& it): 00083 Format (CF(it)) { 00084 if (busy (it)) { C c= *it; ++it; rep= new List_rep (c, it); } 00085 else rep= NULL; } 00086 const C& operator [] (nat i) const { 00087 ASSERT (rep != NULL, "non-empty list expected"); 00088 return i==0? rep->item: read_only (rep->next) [i-1]; } 00089 C& operator [] (nat i) { 00090 ASSERT (rep != NULL, "non-empty list expected"); 00091 secure (); 00092 return i==0? rep->item: rep->next[i-1]; } 00093 friend List cons LESSGTR (const C& c, const List& l); 00094 friend const C& car LESSGTR (const List& l); 00095 friend C& car LESSGTR (List& l); 00096 friend const List& cdr LESSGTR (const List& l); 00097 friend List& cdr LESSGTR (List& l); 00098 friend bool is_nil LESSGTR (const List& l); 00099 }; 00100 DEFINE_UNARY_FORMAT_1 (list) 00101 00102 TMPL inline Format CF (const List& l) { 00103 return (Format) l; } 00104 TMPL inline List::list (List_rep* rep2): 00105 Format (no_format ()), rep(rep2) {} 00106 TMPL inline List::list (const List_rep* rep2, bool with_inc): 00107 Format (no_format ()), rep((List_rep*) (void*) rep2) { 00108 (void) with_inc; INC_NULL_COUNT (rep); } 00109 TMPL inline List::list (const List& x): 00110 Format (CF(x)), rep(x.rep) { 00111 INC_NULL_COUNT (rep); } 00112 TMPL inline List::~list () { 00113 DEC_NULL_COUNT (rep); } 00114 TMPL inline const List_rep* List::operator -> () const { 00115 return rep; } 00116 TMPL inline List_rep* List::operator -> () { 00117 return rep; } 00118 TMPL inline List& List::operator = (const List& x) { 00119 INC_NULL_COUNT (x.rep); DEC_NULL_COUNT (rep); 00120 rep=x.rep; return *this; } 00121 TMPL inline void List::secure () { 00122 if (rep->ref_count>1) *this= copy (*this); } 00123 TMPL List_rep* inside (const List& x) { 00124 return const_cast<List_rep*> (x.operator -> ()); } 00125 TMPL inline nat hard_hash (const List& x) { 00126 return as_hash (x.operator -> ()); } 00127 TMPL inline bool hard_eq (const List& x, const List& y) { 00128 return (x.operator -> ()) == (y.operator -> ()); } 00129 TMPL inline bool hard_neq (const List& x, const List& y) { 00130 return (x.operator -> ()) != (y.operator -> ()); } 00131 00132 TMPL struct species_type_information<List > { 00133 static const nat id= SPECIES_LIST; }; 00134 00135 /****************************************************************************** 00136 * Basic constructors and accessors 00137 ******************************************************************************/ 00138 00139 TMPL inline List cons (const C& c, const List& l) { return List (c, l); } 00140 TMPL inline const C& car (const List& l) { return l.rep->item; } 00142 TMPL inline const C& read_car (const List& l) { return car (l); } 00144 TMPL inline C& car (List& l) { l.secure(); return l.rep->item; } 00145 TMPL inline const List& cdr (const List& l) { return l.rep->next; } 00147 TMPL inline const List& read_cdr (const List& l) { return cdr (l); } 00149 TMPL inline List& cdr (List& l) { l.secure(); return l.rep->next; } 00150 TMPL inline bool is_nil (const List& l) { return l.rep == NULL; } 00152 TMPL inline bool is_atom (const List& l) { 00153 return !is_nil (l) && is_nil (cdr (l)); } 00155 TMPL nat N (const List& l) { return is_nil (l)? 0: N (cdr (l)) + 1; } 00157 TMPL inline const C& read (const List& l, nat i) { return l[i]; } 00158 00159 template<typename T, typename F> 00160 struct as_helper<list<T>,list<F> > { 00161 static inline list<T> 00162 cv (const list<F>& l) { 00163 if (is_nil (l)) return list<T> (); 00164 else return cons (as<T> (car (l)), cv (cdr (l))); 00165 } 00166 }; 00167 00168 template<typename T, typename F> inline void 00169 set_as (list<T>& r, const vector<F>& l) { 00170 if (is_nil (l)) r= list<T> (CF(r)); 00171 else { 00172 T c; set_as (c, car (l)); 00173 list<T> s (CF (r)); set_as (s, cdr (l)); 00174 r= cons (c, s); 00175 } 00176 } 00177 00178 template<typename C, typename T> inline void 00179 set_as (List& r, const T& x) { 00180 T c; set_as (c, x); 00181 r= list<T> (c); 00182 } 00183 00184 /****************************************************************************** 00185 * List iteration 00186 ******************************************************************************/ 00187 00188 TMPL_DEF 00189 class list_iterator_rep: public iterator_rep<C> { 00190 List l; // the list to traverse 00191 public: 00192 list_iterator_rep (const List& l2): l(l2) {} 00193 protected: 00194 bool is_busy () { return !is_nil (l); } 00195 void advance () { l= read_cdr (l); } 00196 C current () { return read_car (l); } 00197 iterator_rep<C>* clone () { return new list_iterator_rep (l); } 00198 }; 00199 00200 TMPL iterator<C> 00201 iterate (const List& l) { 00202 return iterator<C> (new list_iterator_rep<C> (l)); 00203 } 00204 00205 /****************************************************************************** 00206 * Hashing and equality testing 00207 ******************************************************************************/ 00208 00209 template<typename Op,typename C> nat 00210 unary_hash (const List& ll) { 00211 List l= ll; 00212 register nat h= 253648; 00213 while (!is_nil (l)) { 00214 h= (h<<1) ^ (h<<5) ^ (h>>27) ^ Op::op (read_car (l)); 00215 l= read_cdr (l); 00216 } 00217 return h; 00218 } 00219 00220 template<typename Op, typename C> bool 00221 binary_test (const List& l1, const List& l2) { 00222 if (is_nil (l1) || is_nil (l2)) return is_nil (l1) && is_nil (l2); 00223 return Op::op (read_car (l1), read_car (l2)) && 00224 binary_test<Op> (read_cdr (l1), read_cdr (l2)); 00225 } 00226 00227 TRUE_IDENTITY_OP_SUGAR(TMPL,List) 00228 EXACT_IDENTITY_OP_SUGAR(TMPL,List) 00229 00230 /****************************************************************************** 00231 * Printing lists 00232 ******************************************************************************/ 00233 00234 TMPL syntactic 00235 flatten (const List& l) { 00236 vector<syntactic> v; 00237 List counter= l; 00238 while (!is_nil (counter)) { 00239 v << flatten (read_car (counter)); 00240 counter= read_cdr (counter); 00241 } 00242 return apply (GEN_SQTUPLE, v); 00243 } 00244 00245 TMPL 00246 struct binary_helper<List >: public void_binary_helper<List > { 00247 static inline string short_type_name () { 00248 return "Li" * Short_type_name (C); } 00249 static inline generic full_type_name () { 00250 return gen ("List", Full_type_name (C)); } 00251 static inline generic disassemble (const List& l) { 00252 if (is_nil (l)) return gen_vec (); 00253 else return gen_vec (as<generic> (car (l)), as<generic> (cdr (l))); } 00254 static inline List assemble (const generic& x) { 00255 vector<generic> v= as<vector<generic> > (x); 00256 if (N(v) == 0) return List (); 00257 else return cons (as<C> (v[0]), as<List > (v[1])); } 00258 static inline void write (const port& out, const List& l) { 00259 if (is_nil (l)) binary_write<char> (out, '.'); 00260 else { 00261 binary_write<char> (out, ','); 00262 binary_write<C> (out, car (l)); 00263 binary_write<List > (out, cdr (l)); 00264 } } 00265 static inline List read (const port& in) { 00266 if (binary_read<char> (in) == '.') return List (); 00267 else return cons (binary_read<C> (in), binary_read<List > (in)); } 00268 }; 00269 00270 /****************************************************************************** 00271 * Operations on lists 00272 ******************************************************************************/ 00273 00274 TMPL List 00275 copy (const List& l) { 00276 if (is_nil (l)) return l; 00277 return cons (car (l), cdr (l)); 00278 } 00279 00281 TMPL List 00282 append (const List& l1, const List& l2) { 00283 if (is_nil (l1)) return copy (l2); 00284 return cons (car (l1), append (cdr (l1), l2)); 00285 } 00286 00287 TMPL inline List 00288 operator * (const List& l1, const List& l2) { 00289 return append (l1, l2); 00290 } 00291 00293 TMPL List 00294 reverse (const List& ll) { 00295 List l= ll, r; 00296 while (!is_nil (l)) { 00297 r= cons (read_car (l), r); 00298 l= read_cdr (l); 00299 } 00300 return r; 00301 } 00302 00304 TMPL List 00305 range (const List& l, nat start, nat end) { 00306 if (start >= end) return List (); 00307 ASSERT (!is_nil (l), "non-empty list expected"); 00308 if (start > 0) return range (cdr (l), start-1, end-1); 00309 return cons (car (l), range (cdr (l), 0, end-1)); 00310 } 00311 00312 TMPL List 00313 insert (const List& l, const C& x) { 00314 if (is_nil (l)) return List (x); 00315 else if (car (l) == x) return l; 00316 else return cons (car (l), insert<C> (cdr (l), x)); 00317 } 00318 00319 TMPL int 00320 find (const List& l, const C& x) { 00321 if (is_nil (l) || car (l) == x) return 0; 00322 else return find<C> (cdr (l), x) + 1; 00323 } 00324 00325 TMPL bool 00326 contains (const List& l, const C& x) { 00327 if (is_nil (l)) return false; 00328 else return car (l) == x || contains<C> (cdr (l), x); 00329 } 00330 00331 /****************************************************************************** 00332 * Dynamic mappers 00333 ******************************************************************************/ 00334 00335 template<typename S1, typename D> list<D> 00336 map (const function_1<D,Argument(S1) >& fun, 00337 const list<S1>& l1, const format<D>& fm) 00338 { 00339 if (is_nil (l1)) return list<D> (fm); 00340 else return cons (fun (car (l1)), map (fun, cdr (l1), fm)); 00341 } 00342 00343 template<typename S1, typename D> inline list<D> 00344 map (D (*fun) (const S1&), 00345 const list<S1>& x1, const format<D>& fm) { 00346 return map (function_1<D,Argument(S1) > (fun), x1, fm); 00347 } 00348 00349 #undef TMPL_DEF 00350 #undef TMPL 00351 #undef Format 00352 #undef List 00353 #undef List_rep 00354 } // namespace mmx 00355 #endif // __MMX_LIST_HPP