GiNaC  1.6.2
container.h
Go to the documentation of this file.
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

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.