|
GiNaC
1.6.2
|
00001 00005 /* 00006 * GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #ifndef GINAC_CONTAINER_H 00024 #define GINAC_CONTAINER_H 00025 00026 #include "ex.h" 00027 #include "print.h" 00028 #include "archive.h" 00029 #include "assertion.h" 00030 00031 #include <algorithm> 00032 #include <iterator> 00033 #include <list> 00034 #include <memory> 00035 #include <stdexcept> 00036 #include <vector> 00037 00038 namespace GiNaC { 00039 00041 template <template <class T, class = std::allocator<T> > class C> 00042 class container_storage { 00043 protected: 00044 typedef C<ex> STLT; 00045 00046 container_storage() {} 00047 container_storage(size_t n, const ex & e) : seq(n, e) {} 00048 00049 template <class In> 00050 container_storage(In b, In e) : seq(b, e) {} 00051 00052 void reserve(size_t) {} 00053 static void reserve(STLT &, size_t) {} 00054 00055 STLT seq; 00056 00057 // disallow destruction of container through a container_storage* 00058 protected: 00059 ~container_storage() {} 00060 }; 00061 00062 template <> 00063 inline void container_storage<std::vector>::reserve(size_t n) { seq.reserve(n); } 00064 00065 template <> 00066 inline void container_storage<std::vector>::reserve(std::vector<ex> & v, size_t n) { v.reserve(n); } 00067 00068 00071 template <typename T, typename STLT> 00072 class container_init { 00073 public: 00074 container_init(STLT & s) : stlt(s) {} 00075 00076 container_init<T, STLT> operator,(const T & x) 00077 { 00078 stlt.push_back(x); 00079 return container_init<T, STLT>(stlt); 00080 } 00081 00082 // The following specializations produce much tighter code than the 00083 // general case above 00084 00085 container_init<T, STLT> operator,(int x) 00086 { 00087 stlt.push_back(x); 00088 return container_init<T, STLT>(stlt); 00089 } 00090 00091 container_init<T, STLT> operator,(unsigned int x) 00092 { 00093 stlt.push_back(x); 00094 return container_init<T, STLT>(stlt); 00095 } 00096 00097 container_init<T, STLT> operator,(long x) 00098 { 00099 stlt.push_back(x); 00100 return container_init<T, STLT>(stlt); 00101 } 00102 00103 container_init<T, STLT> operator,(unsigned long x) 00104 { 00105 stlt.push_back(x); 00106 return container_init<T, STLT>(stlt); 00107 } 00108 00109 container_init<T, STLT> operator,(double x) 00110 { 00111 stlt.push_back(x); 00112 return container_init<T, STLT>(stlt); 00113 } 00114 00115 container_init<T, STLT> operator,(const symbol & x) 00116 { 00117 stlt.push_back(T(x)); 00118 return container_init<T, STLT>(stlt); 00119 } 00120 00121 private: 00122 container_init(); 00123 STLT & stlt; 00124 }; 00125 00127 template <template <class T, class = std::allocator<T> > class C> 00128 class container : public basic, public container_storage<C> { 00129 GINAC_DECLARE_REGISTERED_CLASS(container, basic) 00130 protected: 00131 typedef typename container_storage<C>::STLT STLT; 00132 00133 public: 00134 typedef typename STLT::const_iterator const_iterator; 00135 typedef typename STLT::const_reverse_iterator const_reverse_iterator; 00136 00137 protected: 00138 // helpers 00139 static unsigned get_default_flags() { return 0; } 00140 static char get_open_delim() { return '('; } 00141 static char get_close_delim() { return ')'; } 00142 00143 // constructors 00144 public: 00145 container(STLT const & s, bool discardable = false) 00146 { 00147 setflag(get_default_flags()); 00148 00149 if (discardable) 00150 this->seq.swap(const_cast<STLT &>(s)); 00151 else 00152 this->seq = s; 00153 } 00154 00155 explicit container(std::auto_ptr<STLT> vp) 00156 { 00157 setflag(get_default_flags()); 00158 this->seq.swap(*vp); 00159 } 00160 00161 container(exvector::const_iterator b, exvector::const_iterator e) 00162 : container_storage<C>(b, e) 00163 { 00164 setflag(get_default_flags()); 00165 } 00166 00167 explicit container(const ex & p1) 00168 : container_storage<C>(1, p1) 00169 { 00170 setflag(get_default_flags()); 00171 } 00172 00173 container(const ex & p1, const ex & p2) 00174 { 00175 setflag(get_default_flags()); 00176 this->reserve(this->seq, 2); 00177 this->seq.push_back(p1); this->seq.push_back(p2); 00178 } 00179 00180 container(const ex & p1, const ex & p2, const ex & p3) 00181 { 00182 setflag(get_default_flags()); 00183 this->reserve(this->seq, 3); 00184 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00185 } 00186 00187 container(const ex & p1, const ex & p2, const ex & p3, 00188 const ex & p4) 00189 { 00190 setflag(get_default_flags()); 00191 this->reserve(this->seq, 4); 00192 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00193 this->seq.push_back(p4); 00194 } 00195 00196 container(const ex & p1, const ex & p2, const ex & p3, 00197 const ex & p4, const ex & p5) 00198 { 00199 setflag(get_default_flags()); 00200 this->reserve(this->seq, 5); 00201 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00202 this->seq.push_back(p4); this->seq.push_back(p5); 00203 } 00204 00205 container(const ex & p1, const ex & p2, const ex & p3, 00206 const ex & p4, const ex & p5, const ex & p6) 00207 { 00208 setflag(get_default_flags()); 00209 this->reserve(this->seq, 6); 00210 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00211 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00212 } 00213 00214 container(const ex & p1, const ex & p2, const ex & p3, 00215 const ex & p4, const ex & p5, const ex & p6, 00216 const ex & p7) 00217 { 00218 setflag(get_default_flags()); 00219 this->reserve(this->seq, 7); 00220 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00221 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00222 this->seq.push_back(p7); 00223 } 00224 00225 container(const ex & p1, const ex & p2, const ex & p3, 00226 const ex & p4, const ex & p5, const ex & p6, 00227 const ex & p7, const ex & p8) 00228 { 00229 setflag(get_default_flags()); 00230 this->reserve(this->seq, 8); 00231 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00232 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00233 this->seq.push_back(p7); this->seq.push_back(p8); 00234 } 00235 00236 container(const ex & p1, const ex & p2, const ex & p3, 00237 const ex & p4, const ex & p5, const ex & p6, 00238 const ex & p7, const ex & p8, const ex & p9) 00239 { 00240 setflag(get_default_flags()); 00241 this->reserve(this->seq, 9); 00242 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00243 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00244 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00245 } 00246 00247 container(const ex & p1, const ex & p2, const ex & p3, 00248 const ex & p4, const ex & p5, const ex & p6, 00249 const ex & p7, const ex & p8, const ex & p9, 00250 const ex & p10) 00251 { 00252 setflag(get_default_flags()); 00253 this->reserve(this->seq, 10); 00254 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00255 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00256 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00257 this->seq.push_back(p10); 00258 } 00259 00260 container(const ex & p1, const ex & p2, const ex & p3, 00261 const ex & p4, const ex & p5, const ex & p6, 00262 const ex & p7, const ex & p8, const ex & p9, 00263 const ex & p10, const ex & p11) 00264 { 00265 setflag(get_default_flags()); 00266 this->reserve(this->seq, 11); 00267 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00268 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00269 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00270 this->seq.push_back(p10); this->seq.push_back(p11); 00271 } 00272 00273 container(const ex & p1, const ex & p2, const ex & p3, 00274 const ex & p4, const ex & p5, const ex & p6, 00275 const ex & p7, const ex & p8, const ex & p9, 00276 const ex & p10, const ex & p11, const ex & p12) 00277 { 00278 setflag(get_default_flags()); 00279 this->reserve(this->seq, 12); 00280 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00281 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00282 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00283 this->seq.push_back(p10); this->seq.push_back(p11); this->seq.push_back(p12); 00284 } 00285 00286 container(const ex & p1, const ex & p2, const ex & p3, 00287 const ex & p4, const ex & p5, const ex & p6, 00288 const ex & p7, const ex & p8, const ex & p9, 00289 const ex & p10, const ex & p11, const ex & p12, 00290 const ex & p13) 00291 { 00292 setflag(get_default_flags()); 00293 this->reserve(this->seq, 13); 00294 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00295 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00296 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00297 this->seq.push_back(p10); this->seq.push_back(p11); this->seq.push_back(p12); 00298 this->seq.push_back(p13); 00299 } 00300 00301 container(const ex & p1, const ex & p2, const ex & p3, 00302 const ex & p4, const ex & p5, const ex & p6, 00303 const ex & p7, const ex & p8, const ex & p9, 00304 const ex & p10, const ex & p11, const ex & p12, 00305 const ex & p13, const ex & p14) 00306 { 00307 setflag(get_default_flags()); 00308 this->reserve(this->seq, 14); 00309 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00310 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00311 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00312 this->seq.push_back(p10); this->seq.push_back(p11); this->seq.push_back(p12); 00313 this->seq.push_back(p13); this->seq.push_back(p14); 00314 } 00315 00316 container(const ex & p1, const ex & p2, const ex & p3, 00317 const ex & p4, const ex & p5, const ex & p6, 00318 const ex & p7, const ex & p8, const ex & p9, 00319 const ex & p10, const ex & p11, const ex & p12, 00320 const ex & p13, const ex & p14, const ex & p15) 00321 { 00322 setflag(get_default_flags()); 00323 this->reserve(this->seq, 15); 00324 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00325 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00326 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00327 this->seq.push_back(p10); this->seq.push_back(p11); this->seq.push_back(p12); 00328 this->seq.push_back(p13); this->seq.push_back(p14); this->seq.push_back(p15); 00329 } 00330 00331 container(const ex & p1, const ex & p2, const ex & p3, 00332 const ex & p4, const ex & p5, const ex & p6, 00333 const ex & p7, const ex & p8, const ex & p9, 00334 const ex & p10, const ex & p11, const ex & p12, 00335 const ex & p13, const ex & p14, const ex & p15, 00336 const ex & p16) 00337 { 00338 setflag(get_default_flags()); 00339 this->reserve(this->seq, 16); 00340 this->seq.push_back(p1); this->seq.push_back(p2); this->seq.push_back(p3); 00341 this->seq.push_back(p4); this->seq.push_back(p5); this->seq.push_back(p6); 00342 this->seq.push_back(p7); this->seq.push_back(p8); this->seq.push_back(p9); 00343 this->seq.push_back(p10); this->seq.push_back(p11); this->seq.push_back(p12); 00344 this->seq.push_back(p13); this->seq.push_back(p14); this->seq.push_back(p15); 00345 this->seq.push_back(p16); 00346 } 00347 00348 // First step of initialization of container with a comma-separated 00349 // sequence of expressions. Subsequent steps are handled by 00350 // container_init<>::operator,(). 00351 container_init<ex, STLT> operator=(const ex & x) 00352 { 00353 this->seq.push_back(x); 00354 return container_init<ex, STLT>(this->seq); 00355 } 00356 00357 // functions overriding virtual functions from base classes 00358 public: 00359 bool info(unsigned inf) const { return inherited::info(inf); } 00360 unsigned precedence() const { return 10; } 00361 size_t nops() const { return this->seq.size(); } 00362 ex op(size_t i) const; 00363 ex & let_op(size_t i); 00364 ex eval(int level = 0) const; 00365 ex subs(const exmap & m, unsigned options = 0) const; 00366 00367 void read_archive(const archive_node &n, lst &sym_lst) 00368 { 00369 inherited::read_archive(n, sym_lst); 00370 setflag(get_default_flags()); 00371 00372 archive_node::archive_node_cit first = n.find_first("seq"); 00373 archive_node::archive_node_cit last = n.find_last("seq"); 00374 ++last; 00375 this->reserve(this->seq, last - first); 00376 for (archive_node::archive_node_cit i=first; i<last; ++i) { 00377 ex e; 00378 n.find_ex_by_loc(i, e, sym_lst); 00379 this->seq.push_back(e); 00380 } 00381 } 00382 00384 void archive(archive_node &n) const 00385 { 00386 inherited::archive(n); 00387 const_iterator i = this->seq.begin(), end = this->seq.end(); 00388 while (i != end) { 00389 n.add_ex("seq", *i); 00390 ++i; 00391 } 00392 } 00393 00394 protected: 00395 ex conjugate() const 00396 { 00397 STLT *newcont = NULL; 00398 for (const_iterator i=this->seq.begin(); i!=this->seq.end(); ++i) { 00399 if (newcont) { 00400 newcont->push_back(i->conjugate()); 00401 continue; 00402 } 00403 ex x = i->conjugate(); 00404 if (are_ex_trivially_equal(x, *i)) { 00405 continue; 00406 } 00407 newcont = new STLT; 00408 this->reserve(*newcont, this->seq.size()); 00409 for (const_iterator j=this->seq.begin(); j!=i; ++j) { 00410 newcont->push_back(*j); 00411 } 00412 newcont->push_back(x); 00413 } 00414 if (newcont) { 00415 ex result = thiscontainer(*newcont); 00416 delete newcont; 00417 return result; 00418 } 00419 return *this; 00420 } 00421 00422 ex real_part() const 00423 { 00424 STLT cont; 00425 this->reserve(cont, nops()); 00426 const_iterator b = begin(); 00427 const_iterator e = end(); 00428 for(const_iterator i=b; i!=e; ++i) 00429 cont.push_back(i->real_part()); 00430 return thiscontainer(cont); 00431 } 00432 00433 ex imag_part() const 00434 { 00435 STLT cont; 00436 this->reserve(cont, nops()); 00437 const_iterator b = begin(); 00438 const_iterator e = end(); 00439 for(const_iterator i=b; i!=e; ++i) 00440 cont.push_back(i->imag_part()); 00441 return thiscontainer(cont); 00442 } 00443 00444 bool is_equal_same_type(const basic & other) const; 00445 00446 // new virtual functions which can be overridden by derived classes 00447 protected: 00450 virtual ex thiscontainer(const STLT & v) const { return container(v); } 00451 00454 virtual ex thiscontainer(std::auto_ptr<STLT> vp) const { return container(vp); } 00455 00456 virtual void printseq(const print_context & c, char openbracket, char delim, 00457 char closebracket, unsigned this_precedence, 00458 unsigned upper_precedence = 0) const; 00459 00460 // non-virtual functions in this class 00461 private: 00462 void sort_(std::random_access_iterator_tag) 00463 { 00464 std::sort(this->seq.begin(), this->seq.end(), ex_is_less()); 00465 } 00466 00467 void sort_(std::input_iterator_tag) 00468 { 00469 this->seq.sort(ex_is_less()); 00470 } 00471 00472 void unique_() 00473 { 00474 typename STLT::iterator p = std::unique(this->seq.begin(), this->seq.end(), ex_is_equal()); 00475 this->seq.erase(p, this->seq.end()); 00476 } 00477 00478 public: 00479 container & prepend(const ex & b); 00480 container & append(const ex & b); 00481 container & remove_first(); 00482 container & remove_last(); 00483 container & remove_all(); 00484 container & sort(); 00485 container & unique(); 00486 00487 const_iterator begin() const {return this->seq.begin();} 00488 const_iterator end() const {return this->seq.end();} 00489 const_reverse_iterator rbegin() const {return this->seq.rbegin();} 00490 const_reverse_iterator rend() const {return this->seq.rend();} 00491 00492 protected: 00493 void do_print(const print_context & c, unsigned level) const; 00494 void do_print_tree(const print_tree & c, unsigned level) const; 00495 void do_print_python(const print_python & c, unsigned level) const; 00496 void do_print_python_repr(const print_python_repr & c, unsigned level) const; 00497 STLT evalchildren(int level) const; 00498 std::auto_ptr<STLT> subschildren(const exmap & m, unsigned options = 0) const; 00499 }; 00500 00502 template <template <class T, class = std::allocator<T> > class C> 00503 container<C>::container() 00504 { 00505 setflag(get_default_flags()); 00506 } 00507 00508 00509 template <template <class T, class = std::allocator<T> > class C> 00510 void container<C>::do_print(const print_context & c, unsigned level) const 00511 { 00512 // always print brackets around seq, ignore upper_precedence 00513 printseq(c, get_open_delim(), ',', get_close_delim(), precedence(), precedence()+1); 00514 } 00515 00516 template <template <class T, class = std::allocator<T> > class C> 00517 void container<C>::do_print_tree(const print_tree & c, unsigned level) const 00518 { 00519 c.s << std::string(level, ' ') << class_name() << " @" << this 00520 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec 00521 << ", nops=" << nops() 00522 << std::endl; 00523 const_iterator i = this->seq.begin(), end = this->seq.end(); 00524 while (i != end) { 00525 i->print(c, level + c.delta_indent); 00526 ++i; 00527 } 00528 c.s << std::string(level + c.delta_indent,' ') << "=====" << std::endl; 00529 } 00530 00531 template <template <class T, class = std::allocator<T> > class C> 00532 void container<C>::do_print_python(const print_python & c, unsigned level) const 00533 { 00534 printseq(c, '[', ',', ']', precedence(), precedence()+1); 00535 } 00536 00537 template <template <class T, class = std::allocator<T> > class C> 00538 void container<C>::do_print_python_repr(const print_python_repr & c, unsigned level) const 00539 { 00540 c.s << class_name(); 00541 printseq(c, '(', ',', ')', precedence(), precedence()+1); 00542 } 00543 00544 template <template <class T, class = std::allocator<T> > class C> 00545 ex container<C>::op(size_t i) const 00546 { 00547 GINAC_ASSERT(i < nops()); 00548 00549 const_iterator it = this->seq.begin(); 00550 advance(it, i); 00551 return *it; 00552 } 00553 00554 template <template <class T, class = std::allocator<T> > class C> 00555 ex & container<C>::let_op(size_t i) 00556 { 00557 GINAC_ASSERT(i < nops()); 00558 00559 ensure_if_modifiable(); 00560 typename STLT::iterator it = this->seq.begin(); 00561 advance(it, i); 00562 return *it; 00563 } 00564 00565 template <template <class T, class = std::allocator<T> > class C> 00566 ex container<C>::eval(int level) const 00567 { 00568 if (level == 1) 00569 return hold(); 00570 else 00571 return thiscontainer(evalchildren(level)); 00572 } 00573 00574 template <template <class T, class = std::allocator<T> > class C> 00575 ex container<C>::subs(const exmap & m, unsigned options) const 00576 { 00577 // After having subs'ed all children, this method subs'es one final 00578 // level, but only if the intermediate result is a container! This is 00579 // because if the intermediate result has eval'ed to a non-container a 00580 // last level substitution would be wrong, as this example involving a 00581 // function f and its inverse f^-1 shows: 00582 // f(x).subs(x==f^-1(x)) 00583 // -> f(f^-1(x)) [subschildren] 00584 // -> x [eval] /* must not subs(x==f^-1(x))! */ 00585 std::auto_ptr<STLT> vp = subschildren(m, options); 00586 if (vp.get()) { 00587 ex result(thiscontainer(vp)); 00588 if (is_a<container<C> >(result)) 00589 return ex_to<basic>(result).subs_one_level(m, options); 00590 else 00591 return result; 00592 } else { 00593 if (is_a<container<C> >(*this)) 00594 return subs_one_level(m, options); 00595 else 00596 return *this; 00597 } 00598 } 00599 00601 template <template <class T, class = std::allocator<T> > class C> 00602 int container<C>::compare_same_type(const basic & other) const 00603 { 00604 GINAC_ASSERT(is_a<container>(other)); 00605 const container & o = static_cast<const container &>(other); 00606 00607 const_iterator it1 = this->seq.begin(), it1end = this->seq.end(), 00608 it2 = o.seq.begin(), it2end = o.seq.end(); 00609 00610 while (it1 != it1end && it2 != it2end) { 00611 int cmpval = it1->compare(*it2); 00612 if (cmpval) 00613 return cmpval; 00614 ++it1; ++it2; 00615 } 00616 00617 return (it1 == it1end) ? (it2 == it2end ? 0 : -1) : 1; 00618 } 00619 00620 template <template <class T, class = std::allocator<T> > class C> 00621 bool container<C>::is_equal_same_type(const basic & other) const 00622 { 00623 GINAC_ASSERT(is_a<container>(other)); 00624 const container & o = static_cast<const container &>(other); 00625 00626 if (this->seq.size() != o.seq.size()) 00627 return false; 00628 00629 const_iterator it1 = this->seq.begin(), it1end = this->seq.end(), it2 = o.seq.begin(); 00630 while (it1 != it1end) { 00631 if (!it1->is_equal(*it2)) 00632 return false; 00633 ++it1; ++it2; 00634 } 00635 00636 return true; 00637 } 00638 00640 template <template <class T, class = std::allocator<T> > class C> 00641 container<C> & container<C>::prepend(const ex & b) 00642 { 00643 ensure_if_modifiable(); 00644 this->seq.push_front(b); 00645 return *this; 00646 } 00647 00649 template <template <class T, class = std::allocator<T> > class C> 00650 container<C> & container<C>::append(const ex & b) 00651 { 00652 ensure_if_modifiable(); 00653 this->seq.push_back(b); 00654 return *this; 00655 } 00656 00658 template <template <class T, class = std::allocator<T> > class C> 00659 container<C> & container<C>::remove_first() 00660 { 00661 ensure_if_modifiable(); 00662 this->seq.pop_front(); 00663 return *this; 00664 } 00665 00667 template <template <class T, class = std::allocator<T> > class C> 00668 container<C> & container<C>::remove_last() 00669 { 00670 ensure_if_modifiable(); 00671 this->seq.pop_back(); 00672 return *this; 00673 } 00674 00676 template <template <class T, class = std::allocator<T> > class C> 00677 container<C> & container<C>::remove_all() 00678 { 00679 ensure_if_modifiable(); 00680 this->seq.clear(); 00681 return *this; 00682 } 00683 00685 template <template <class T, class = std::allocator<T> > class C> 00686 container<C> & container<C>::sort() 00687 { 00688 ensure_if_modifiable(); 00689 sort_(typename std::iterator_traits<typename STLT::iterator>::iterator_category()); 00690 return *this; 00691 } 00692 00694 template<> inline void container<std::list>::unique_() 00695 { 00696 this->seq.unique(ex_is_equal()); 00697 } 00698 00700 template <template <class T, class = std::allocator<T> > class C> 00701 container<C> & container<C>::unique() 00702 { 00703 ensure_if_modifiable(); 00704 unique_(); 00705 return *this; 00706 } 00707 00709 template <template <class T, class = std::allocator<T> > class C> 00710 void container<C>::printseq(const print_context & c, char openbracket, char delim, 00711 char closebracket, unsigned this_precedence, 00712 unsigned upper_precedence) const 00713 { 00714 if (this_precedence <= upper_precedence) 00715 c.s << openbracket; 00716 00717 if (!this->seq.empty()) { 00718 const_iterator it = this->seq.begin(), itend = this->seq.end(); 00719 --itend; 00720 while (it != itend) { 00721 it->print(c, this_precedence); 00722 c.s << delim; 00723 ++it; 00724 } 00725 it->print(c, this_precedence); 00726 } 00727 00728 if (this_precedence <= upper_precedence) 00729 c.s << closebracket; 00730 } 00731 00732 template <template <class T, class = std::allocator<T> > class C> 00733 typename container<C>::STLT container<C>::evalchildren(int level) const 00734 { 00735 if (level == 1) 00736 return this->seq; 00737 else if (level == -max_recursion_level) 00738 throw std::runtime_error("max recursion level reached"); 00739 00740 STLT s; 00741 this->reserve(s, this->seq.size()); 00742 00743 --level; 00744 const_iterator it = this->seq.begin(), itend = this->seq.end(); 00745 while (it != itend) { 00746 s.push_back(it->eval(level)); 00747 ++it; 00748 } 00749 00750 return s; 00751 } 00752 00753 template <template <class T, class = std::allocator<T> > class C> 00754 std::auto_ptr<typename container<C>::STLT> container<C>::subschildren(const exmap & m, unsigned options) const 00755 { 00756 // returns a NULL pointer if nothing had to be substituted 00757 // returns a pointer to a newly created STLT otherwise 00758 // (and relinquishes responsibility for the STLT) 00759 00760 const_iterator cit = this->seq.begin(), end = this->seq.end(); 00761 while (cit != end) { 00762 const ex & subsed_ex = cit->subs(m, options); 00763 if (!are_ex_trivially_equal(*cit, subsed_ex)) { 00764 00765 // copy first part of seq which hasn't changed 00766 std::auto_ptr<STLT> s(new STLT(this->seq.begin(), cit)); 00767 this->reserve(*s, this->seq.size()); 00768 00769 // insert changed element 00770 s->push_back(subsed_ex); 00771 ++cit; 00772 00773 // copy rest 00774 while (cit != end) { 00775 s->push_back(cit->subs(m, options)); 00776 ++cit; 00777 } 00778 00779 return s; 00780 } 00781 00782 ++cit; 00783 } 00784 00785 return std::auto_ptr<STLT>(0); // nothing has changed 00786 } 00787 00788 } // namespace GiNaC 00789 00790 #endif // ndef GINAC_CONTAINER_H