00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef GINAC_EX_H
00024 #define GINAC_EX_H
00025
00026 #include "basic.h"
00027 #include "ptr.h"
00028
00029 #include <functional>
00030 #include <iosfwd>
00031 #include <iterator>
00032 #include <stack>
00033
00034 namespace GiNaC {
00035
00044 class library_init {
00045 static void init_unarchivers();
00046 public:
00047 library_init();
00048 ~library_init();
00049 private:
00050 static int count;
00051 };
00053 static library_init library_initializer;
00054
00055 class scalar_products;
00056 class const_iterator;
00057 class const_preorder_iterator;
00058 class const_postorder_iterator;
00059
00060
00066 class ex {
00067 friend class archive_node;
00068 friend inline bool are_ex_trivially_equal(const ex &, const ex &);
00069 template<class T> friend inline const T &ex_to(const ex &);
00070 template<class T> friend inline bool is_a(const ex &);
00071 template<class T> friend inline bool is_exactly_a(const ex &);
00072
00073
00074 public:
00075 ex() throw();
00076
00077
00078 public:
00079 ex(const basic & other);
00080 ex(int i);
00081 ex(unsigned int i);
00082 ex(long i);
00083 ex(unsigned long i);
00084 ex(double const d);
00085
00090 ex(const std::string &s, const ex &l);
00091
00092 public:
00093
00094 public:
00096 void swap(ex & other) throw()
00097 {
00098 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00099 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
00100 bp.swap(other.bp);
00101 }
00102
00103
00104 const_iterator begin() const throw();
00105 const_iterator end() const throw();
00106 const_preorder_iterator preorder_begin() const;
00107 const_preorder_iterator preorder_end() const throw();
00108 const_postorder_iterator postorder_begin() const;
00109 const_postorder_iterator postorder_end() const throw();
00110
00111
00112 ex eval(int level = 0) const { return bp->eval(level); }
00113 ex evalf(int level = 0) const { return bp->evalf(level); }
00114 ex evalm() const { return bp->evalm(); }
00115 ex eval_ncmul(const exvector & v) const { return bp->eval_ncmul(v); }
00116 ex eval_integ() const { return bp->eval_integ(); }
00117
00118
00119 void print(const print_context & c, unsigned level = 0) const;
00120 void dbgprint() const;
00121 void dbgprinttree() const;
00122
00123
00124 bool info(unsigned inf) const { return bp->info(inf); }
00125
00126
00127 size_t nops() const { return bp->nops(); }
00128 ex op(size_t i) const { return bp->op(i); }
00129 ex operator[](const ex & index) const { return (*bp)[index]; }
00130 ex operator[](size_t i) const { return (*bp)[i]; }
00131 ex & let_op(size_t i);
00132 ex & operator[](const ex & index);
00133 ex & operator[](size_t i);
00134 ex lhs() const;
00135 ex rhs() const;
00136
00137
00138 ex conjugate() const { return bp->conjugate(); }
00139 ex real_part() const { return bp->real_part(); }
00140 ex imag_part() const { return bp->imag_part(); }
00141
00142
00143 bool has(const ex & pattern, unsigned options = 0) const { return bp->has(pattern, options); }
00144 bool find(const ex & pattern, exset& found) const;
00145 bool match(const ex & pattern) const;
00146 bool match(const ex & pattern, exmap & repls) const { return bp->match(pattern, repls); }
00147
00148
00149 ex subs(const exmap & m, unsigned options = 0) const;
00150 ex subs(const lst & ls, const lst & lr, unsigned options = 0) const;
00151 ex subs(const ex & e, unsigned options = 0) const;
00152
00153
00154 ex map(map_function & f) const { return bp->map(f); }
00155 ex map(ex (*f)(const ex & e)) const;
00156
00157
00158 void accept(visitor & v) const { bp->accept(v); }
00159 void traverse_preorder(visitor & v) const;
00160 void traverse_postorder(visitor & v) const;
00161 void traverse(visitor & v) const { traverse_preorder(v); }
00162
00163
00164 bool is_polynomial(const ex & vars) const;
00165 int degree(const ex & s) const { return bp->degree(s); }
00166 int ldegree(const ex & s) const { return bp->ldegree(s); }
00167 ex coeff(const ex & s, int n = 1) const { return bp->coeff(s, n); }
00168 ex lcoeff(const ex & s) const { return coeff(s, degree(s)); }
00169 ex tcoeff(const ex & s) const { return coeff(s, ldegree(s)); }
00170
00171
00172 ex expand(unsigned options=0) const;
00173 ex collect(const ex & s, bool distributed = false) const { return bp->collect(s, distributed); }
00174
00175
00176 ex diff(const symbol & s, unsigned nth = 1) const;
00177 ex series(const ex & r, int order, unsigned options = 0) const;
00178
00179
00180 ex normal(int level = 0) const;
00181 ex to_rational(exmap & repl) const;
00182 ex to_rational(lst & repl_lst) const;
00183 ex to_polynomial(exmap & repl) const;
00184 ex to_polynomial(lst & repl_lst) const;
00185 ex numer() const;
00186 ex denom() const;
00187 ex numer_denom() const;
00188
00189
00190 ex unit(const ex &x) const;
00191 ex content(const ex &x) const;
00192 numeric integer_content() const;
00193 ex primpart(const ex &x) const;
00194 ex primpart(const ex &x, const ex &cont) const;
00195 void unitcontprim(const ex &x, ex &u, ex &c, ex &p) const;
00196 ex smod(const numeric &xi) const { return bp->smod(xi); }
00197 numeric max_coefficient() const;
00198
00199
00200 exvector get_free_indices() const { return bp->get_free_indices(); }
00201 ex simplify_indexed(unsigned options = 0) const;
00202 ex simplify_indexed(const scalar_products & sp, unsigned options = 0) const;
00203
00204
00205 int compare(const ex & other) const;
00206 bool is_equal(const ex & other) const;
00207 bool is_zero() const { extern const ex _ex0; return is_equal(_ex0); }
00208 bool is_zero_matrix() const;
00209
00210
00211 ex symmetrize() const;
00212 ex symmetrize(const lst & l) const;
00213 ex antisymmetrize() const;
00214 ex antisymmetrize(const lst & l) const;
00215 ex symmetrize_cyclic() const;
00216 ex symmetrize_cyclic(const lst & l) const;
00217
00218
00219 unsigned return_type() const { return bp->return_type(); }
00220 return_type_t return_type_tinfo() const { return bp->return_type_tinfo(); }
00221
00222 unsigned gethash() const { return bp->gethash(); }
00223
00224 private:
00225 static ptr<basic> construct_from_basic(const basic & other);
00226 static basic & construct_from_int(int i);
00227 static basic & construct_from_uint(unsigned int i);
00228 static basic & construct_from_long(long i);
00229 static basic & construct_from_ulong(unsigned long i);
00230 static basic & construct_from_double(double d);
00231 static ptr<basic> construct_from_string_and_lst(const std::string &s, const ex &l);
00232 void makewriteable();
00233 void share(const ex & other) const;
00234
00235
00236
00237 private:
00238 mutable ptr<basic> bp;
00239 };
00240
00241
00242
00243
00244
00245
00246 extern const basic *_num0_bp;
00247
00248 inline
00249 ex::ex() throw() : bp(*const_cast<basic *>(_num0_bp))
00250 {
00251 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00252 }
00253
00254 inline
00255 ex::ex(const basic & other) : bp(construct_from_basic(other))
00256 {
00257 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00258 }
00259
00260 inline
00261 ex::ex(int i) : bp(construct_from_int(i))
00262 {
00263 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00264 }
00265
00266 inline
00267 ex::ex(unsigned int i) : bp(construct_from_uint(i))
00268 {
00269 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00270 }
00271
00272 inline
00273 ex::ex(long i) : bp(construct_from_long(i))
00274 {
00275 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00276 }
00277
00278 inline
00279 ex::ex(unsigned long i) : bp(construct_from_ulong(i))
00280 {
00281 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00282 }
00283
00284 inline
00285 ex::ex(double const d) : bp(construct_from_double(d))
00286 {
00287 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00288 }
00289
00290 inline
00291 ex::ex(const std::string &s, const ex &l) : bp(construct_from_string_and_lst(s, l))
00292 {
00293 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
00294 }
00295
00296 inline
00297 int ex::compare(const ex & other) const
00298 {
00299 #ifdef GINAC_COMPARE_STATISTICS
00300 compare_statistics.total_compares++;
00301 #endif
00302 if (bp == other.bp)
00303 return 0;
00304 #ifdef GINAC_COMPARE_STATISTICS
00305 compare_statistics.nontrivial_compares++;
00306 #endif
00307 const int cmpval = bp->compare(*other.bp);
00308 #if 1
00309 if (cmpval == 0) {
00310
00311
00312
00313 share(other);
00314 }
00315 #endif
00316 return cmpval;
00317 }
00318
00319 inline
00320 bool ex::is_equal(const ex & other) const
00321 {
00322 #ifdef GINAC_COMPARE_STATISTICS
00323 compare_statistics.total_is_equals++;
00324 #endif
00325 if (bp == other.bp)
00326 return true;
00327 #ifdef GINAC_COMPARE_STATISTICS
00328 compare_statistics.nontrivial_is_equals++;
00329 #endif
00330 const bool equal = bp->is_equal(*other.bp);
00331 #if 0
00332 if (equal) {
00333
00334
00335
00336 share(other);
00337 }
00338 #endif
00339 return equal;
00340 }
00341
00342
00343
00344
00345 class const_iterator : public std::iterator<std::random_access_iterator_tag, ex, ptrdiff_t, const ex *, const ex &> {
00346 friend class ex;
00347 friend class const_preorder_iterator;
00348 friend class const_postorder_iterator;
00349
00350 public:
00351 const_iterator() throw() {}
00352
00353 private:
00354 const_iterator(const ex &e_, size_t i_) throw() : e(e_), i(i_) {}
00355
00356 public:
00357
00358
00359 ex operator*() const
00360 {
00361 return e.op(i);
00362 }
00363
00364
00365
00366 std::auto_ptr<ex> operator->() const
00367 {
00368 return std::auto_ptr<ex>(new ex(operator*()));
00369 }
00370
00371 ex operator[](difference_type n) const
00372 {
00373 return e.op(i + n);
00374 }
00375
00376 const_iterator &operator++() throw()
00377 {
00378 ++i;
00379 return *this;
00380 }
00381
00382 const_iterator operator++(int) throw()
00383 {
00384 const_iterator tmp = *this;
00385 ++i;
00386 return tmp;
00387 }
00388
00389 const_iterator &operator+=(difference_type n) throw()
00390 {
00391 i += n;
00392 return *this;
00393 }
00394
00395 const_iterator operator+(difference_type n) const throw()
00396 {
00397 return const_iterator(e, i + n);
00398 }
00399
00400 inline friend const_iterator operator+(difference_type n, const const_iterator &it) throw()
00401 {
00402 return const_iterator(it.e, it.i + n);
00403 }
00404
00405 const_iterator &operator--() throw()
00406 {
00407 --i;
00408 return *this;
00409 }
00410
00411 const_iterator operator--(int) throw()
00412 {
00413 const_iterator tmp = *this;
00414 --i;
00415 return tmp;
00416 }
00417
00418 const_iterator &operator-=(difference_type n) throw()
00419 {
00420 i -= n;
00421 return *this;
00422 }
00423
00424 const_iterator operator-(difference_type n) const throw()
00425 {
00426 return const_iterator(e, i - n);
00427 }
00428
00429 inline friend difference_type operator-(const const_iterator &lhs, const const_iterator &rhs) throw()
00430 {
00431 return lhs.i - rhs.i;
00432 }
00433
00434 bool operator==(const const_iterator &other) const throw()
00435 {
00436 return are_ex_trivially_equal(e, other.e) && i == other.i;
00437 }
00438
00439 bool operator!=(const const_iterator &other) const throw()
00440 {
00441 return !(*this == other);
00442 }
00443
00444 bool operator<(const const_iterator &other) const throw()
00445 {
00446 return i < other.i;
00447 }
00448
00449 bool operator>(const const_iterator &other) const throw()
00450 {
00451 return other < *this;
00452 }
00453
00454 bool operator<=(const const_iterator &other) const throw()
00455 {
00456 return !(other < *this);
00457 }
00458
00459 bool operator>=(const const_iterator &other) const throw()
00460 {
00461 return !(*this < other);
00462 }
00463
00464 protected:
00465 ex e;
00466 size_t i;
00467 };
00468
00469 namespace internal {
00470
00471 struct _iter_rep {
00472 _iter_rep(const ex &e_, size_t i_, size_t i_end_) : e(e_), i(i_), i_end(i_end_) {}
00473
00474 bool operator==(const _iter_rep &other) const throw()
00475 {
00476 return are_ex_trivially_equal(e, other.e) && i == other.i;
00477 }
00478
00479 bool operator!=(const _iter_rep &other) const throw()
00480 {
00481 return !(*this == other);
00482 }
00483
00484 ex e;
00485 size_t i;
00486 size_t i_end;
00487 };
00488
00489 }
00490
00491 class const_preorder_iterator : public std::iterator<std::forward_iterator_tag, ex, ptrdiff_t, const ex *, const ex &> {
00492 public:
00493 const_preorder_iterator() throw() {}
00494
00495 const_preorder_iterator(const ex &e, size_t n)
00496 {
00497 s.push(internal::_iter_rep(e, 0, n));
00498 }
00499
00500 public:
00501 reference operator*() const
00502 {
00503 return s.top().e;
00504 }
00505
00506 pointer operator->() const
00507 {
00508 return &(s.top().e);
00509 }
00510
00511 const_preorder_iterator &operator++()
00512 {
00513 increment();
00514 return *this;
00515 }
00516
00517 const_preorder_iterator operator++(int)
00518 {
00519 const_preorder_iterator tmp = *this;
00520 increment();
00521 return tmp;
00522 }
00523
00524 bool operator==(const const_preorder_iterator &other) const throw()
00525 {
00526 return s == other.s;
00527 }
00528
00529 bool operator!=(const const_preorder_iterator &other) const throw()
00530 {
00531 return !(*this == other);
00532 }
00533
00534 private:
00535 std::stack<internal::_iter_rep, std::vector<internal::_iter_rep> > s;
00536
00537 void increment()
00538 {
00539 while (!s.empty() && s.top().i == s.top().i_end) {
00540 s.pop();
00541 if (s.empty())
00542 return;
00543 ++s.top().i;
00544 }
00545
00546 internal::_iter_rep & current = s.top();
00547
00548 if (current.i != current.i_end) {
00549 const ex & child = current.e.op(current.i);
00550 s.push(internal::_iter_rep(child, 0, child.nops()));
00551 }
00552 }
00553 };
00554
00555 class const_postorder_iterator : public std::iterator<std::forward_iterator_tag, ex, ptrdiff_t, const ex *, const ex &> {
00556 public:
00557 const_postorder_iterator() throw() {}
00558
00559 const_postorder_iterator(const ex &e, size_t n)
00560 {
00561 s.push(internal::_iter_rep(e, 0, n));
00562 descend();
00563 }
00564
00565 public:
00566 reference operator*() const
00567 {
00568 return s.top().e;
00569 }
00570
00571 pointer operator->() const
00572 {
00573 return &(s.top().e);
00574 }
00575
00576 const_postorder_iterator &operator++()
00577 {
00578 increment();
00579 return *this;
00580 }
00581
00582 const_postorder_iterator operator++(int)
00583 {
00584 const_postorder_iterator tmp = *this;
00585 increment();
00586 return tmp;
00587 }
00588
00589 bool operator==(const const_postorder_iterator &other) const throw()
00590 {
00591 return s == other.s;
00592 }
00593
00594 bool operator!=(const const_postorder_iterator &other) const throw()
00595 {
00596 return !(*this == other);
00597 }
00598
00599 private:
00600 std::stack<internal::_iter_rep, std::vector<internal::_iter_rep> > s;
00601
00602 void descend()
00603 {
00604 while (s.top().i != s.top().i_end) {
00605 internal::_iter_rep & current = s.top();
00606 const ex & child = current.e.op(current.i);
00607 s.push(internal::_iter_rep(child, 0, child.nops()));
00608 }
00609 }
00610
00611 void increment()
00612 {
00613 if (s.top().i == s.top().i_end)
00614 s.pop();
00615 if (!s.empty()) {
00616 ++s.top().i;
00617 descend();
00618 }
00619 }
00620 };
00621
00622 inline const_iterator ex::begin() const throw()
00623 {
00624 return const_iterator(*this, 0);
00625 }
00626
00627 inline const_iterator ex::end() const throw()
00628 {
00629 return const_iterator(*this, nops());
00630 }
00631
00632 inline const_preorder_iterator ex::preorder_begin() const
00633 {
00634 return const_preorder_iterator(*this, nops());
00635 }
00636
00637 inline const_preorder_iterator ex::preorder_end() const throw()
00638 {
00639 return const_preorder_iterator();
00640 }
00641
00642 inline const_postorder_iterator ex::postorder_begin() const
00643 {
00644 return const_postorder_iterator(*this, nops());
00645 }
00646
00647 inline const_postorder_iterator ex::postorder_end() const throw()
00648 {
00649 return const_postorder_iterator();
00650 }
00651
00652
00653
00654
00659 inline bool are_ex_trivially_equal(const ex &e1, const ex &e2)
00660 {
00661 return e1.bp == e2.bp;
00662 }
00663
00664
00665 struct ex_is_less : public std::binary_function<ex, ex, bool> {
00666 bool operator() (const ex &lh, const ex &rh) const { return lh.compare(rh) < 0; }
00667 };
00668
00669 struct ex_is_equal : public std::binary_function<ex, ex, bool> {
00670 bool operator() (const ex &lh, const ex &rh) const { return lh.is_equal(rh); }
00671 };
00672
00673 struct op0_is_equal : public std::binary_function<ex, ex, bool> {
00674 bool operator() (const ex &lh, const ex &rh) const { return lh.op(0).is_equal(rh.op(0)); }
00675 };
00676
00677 struct ex_swap : public std::binary_function<ex, ex, void> {
00678 void operator() (ex &lh, ex &rh) const { lh.swap(rh); }
00679 };
00680
00681
00682 std::ostream & operator<<(std::ostream & os, const exvector & e);
00683 std::ostream & operator<<(std::ostream & os, const exset & e);
00684 std::ostream & operator<<(std::ostream & os, const exmap & e);
00685
00686
00687 inline size_t nops(const ex & thisex)
00688 { return thisex.nops(); }
00689
00690 inline ex expand(const ex & thisex, unsigned options = 0)
00691 { return thisex.expand(options); }
00692
00693 inline ex conjugate(const ex & thisex)
00694 { return thisex.conjugate(); }
00695
00696 inline ex real_part(const ex & thisex)
00697 { return thisex.real_part(); }
00698
00699 inline ex imag_part(const ex & thisex)
00700 { return thisex.imag_part(); }
00701
00702 inline bool has(const ex & thisex, const ex & pattern, unsigned options = 0)
00703 { return thisex.has(pattern, options); }
00704
00705 inline bool find(const ex & thisex, const ex & pattern, exset& found)
00706 { return thisex.find(pattern, found); }
00707
00708 inline bool is_polynomial(const ex & thisex, const ex & vars)
00709 { return thisex.is_polynomial(vars); }
00710
00711 inline int degree(const ex & thisex, const ex & s)
00712 { return thisex.degree(s); }
00713
00714 inline int ldegree(const ex & thisex, const ex & s)
00715 { return thisex.ldegree(s); }
00716
00717 inline ex coeff(const ex & thisex, const ex & s, int n=1)
00718 { return thisex.coeff(s, n); }
00719
00720 inline ex numer(const ex & thisex)
00721 { return thisex.numer(); }
00722
00723 inline ex denom(const ex & thisex)
00724 { return thisex.denom(); }
00725
00726 inline ex numer_denom(const ex & thisex)
00727 { return thisex.numer_denom(); }
00728
00729 inline ex normal(const ex & thisex, int level=0)
00730 { return thisex.normal(level); }
00731
00732 inline ex to_rational(const ex & thisex, lst & repl_lst)
00733 { return thisex.to_rational(repl_lst); }
00734
00735 inline ex to_rational(const ex & thisex, exmap & repl)
00736 { return thisex.to_rational(repl); }
00737
00738 inline ex to_polynomial(const ex & thisex, exmap & repl)
00739 { return thisex.to_polynomial(repl); }
00740
00741 inline ex to_polynomial(const ex & thisex, lst & repl_lst)
00742 { return thisex.to_polynomial(repl_lst); }
00743
00744 inline ex collect(const ex & thisex, const ex & s, bool distributed = false)
00745 { return thisex.collect(s, distributed); }
00746
00747 inline ex eval(const ex & thisex, int level = 0)
00748 { return thisex.eval(level); }
00749
00750 inline ex evalf(const ex & thisex, int level = 0)
00751 { return thisex.evalf(level); }
00752
00753 inline ex evalm(const ex & thisex)
00754 { return thisex.evalm(); }
00755
00756 inline ex eval_integ(const ex & thisex)
00757 { return thisex.eval_integ(); }
00758
00759 inline ex diff(const ex & thisex, const symbol & s, unsigned nth = 1)
00760 { return thisex.diff(s, nth); }
00761
00762 inline ex series(const ex & thisex, const ex & r, int order, unsigned options = 0)
00763 { return thisex.series(r, order, options); }
00764
00765 inline bool match(const ex & thisex, const ex & pattern, exmap& repl_lst)
00766 { return thisex.match(pattern, repl_lst); }
00767
00768 inline ex simplify_indexed(const ex & thisex, unsigned options = 0)
00769 { return thisex.simplify_indexed(options); }
00770
00771 inline ex simplify_indexed(const ex & thisex, const scalar_products & sp, unsigned options = 0)
00772 { return thisex.simplify_indexed(sp, options); }
00773
00774 inline ex symmetrize(const ex & thisex)
00775 { return thisex.symmetrize(); }
00776
00777 inline ex symmetrize(const ex & thisex, const lst & l)
00778 { return thisex.symmetrize(l); }
00779
00780 inline ex antisymmetrize(const ex & thisex)
00781 { return thisex.antisymmetrize(); }
00782
00783 inline ex antisymmetrize(const ex & thisex, const lst & l)
00784 { return thisex.antisymmetrize(l); }
00785
00786 inline ex symmetrize_cyclic(const ex & thisex)
00787 { return thisex.symmetrize_cyclic(); }
00788
00789 inline ex symmetrize_cyclic(const ex & thisex, const lst & l)
00790 { return thisex.symmetrize_cyclic(l); }
00791
00792 inline ex op(const ex & thisex, size_t i)
00793 { return thisex.op(i); }
00794
00795 inline ex lhs(const ex & thisex)
00796 { return thisex.lhs(); }
00797
00798 inline ex rhs(const ex & thisex)
00799 { return thisex.rhs(); }
00800
00801 inline bool is_zero(const ex & thisex)
00802 { return thisex.is_zero(); }
00803
00804 inline void swap(ex & e1, ex & e2)
00805 { e1.swap(e2); }
00806
00807 inline ex ex::subs(const exmap & m, unsigned options) const
00808 {
00809 return bp->subs(m, options);
00810 }
00811
00812 inline ex subs(const ex & thisex, const exmap & m, unsigned options = 0)
00813 { return thisex.subs(m, options); }
00814
00815 inline ex subs(const ex & thisex, const lst & ls, const lst & lr, unsigned options = 0)
00816 { return thisex.subs(ls, lr, options); }
00817
00818 inline ex subs(const ex & thisex, const ex & e, unsigned options = 0)
00819 { return thisex.subs(e, options); }
00820
00821
00822
00823 class pointer_to_map_function : public map_function {
00824 protected:
00825 ex (*ptr)(const ex &);
00826 public:
00827 explicit pointer_to_map_function(ex x(const ex &)) : ptr(x) {}
00828 ex operator()(const ex & e) { return ptr(e); }
00829 };
00830
00831 template<class T1>
00832 class pointer_to_map_function_1arg : public map_function {
00833 protected:
00834 ex (*ptr)(const ex &, T1);
00835 T1 arg1;
00836 public:
00837 explicit pointer_to_map_function_1arg(ex x(const ex &, T1), T1 a1) : ptr(x), arg1(a1) {}
00838 ex operator()(const ex & e) { return ptr(e, arg1); }
00839 };
00840
00841 template<class T1, class T2>
00842 class pointer_to_map_function_2args : public map_function {
00843 protected:
00844 ex (*ptr)(const ex &, T1, T2);
00845 T1 arg1;
00846 T2 arg2;
00847 public:
00848 explicit pointer_to_map_function_2args(ex x(const ex &, T1, T2), T1 a1, T2 a2) : ptr(x), arg1(a1), arg2(a2) {}
00849 ex operator()(const ex & e) { return ptr(e, arg1, arg2); }
00850 };
00851
00852 template<class T1, class T2, class T3>
00853 class pointer_to_map_function_3args : public map_function {
00854 protected:
00855 ex (*ptr)(const ex &, T1, T2, T3);
00856 T1 arg1;
00857 T2 arg2;
00858 T3 arg3;
00859 public:
00860 explicit pointer_to_map_function_3args(ex x(const ex &, T1, T2, T3), T1 a1, T2 a2, T3 a3) : ptr(x), arg1(a1), arg2(a2), arg3(a3) {}
00861 ex operator()(const ex & e) { return ptr(e, arg1, arg2, arg3); }
00862 };
00863
00864 template<class C>
00865 class pointer_to_member_to_map_function : public map_function {
00866 protected:
00867 ex (C::*ptr)(const ex &);
00868 C &c;
00869 public:
00870 explicit pointer_to_member_to_map_function(ex (C::*member)(const ex &), C &obj) : ptr(member), c(obj) {}
00871 ex operator()(const ex & e) { return (c.*ptr)(e); }
00872 };
00873
00874 template<class C, class T1>
00875 class pointer_to_member_to_map_function_1arg : public map_function {
00876 protected:
00877 ex (C::*ptr)(const ex &, T1);
00878 C &c;
00879 T1 arg1;
00880 public:
00881 explicit pointer_to_member_to_map_function_1arg(ex (C::*member)(const ex &, T1), C &obj, T1 a1) : ptr(member), c(obj), arg1(a1) {}
00882 ex operator()(const ex & e) { return (c.*ptr)(e, arg1); }
00883 };
00884
00885 template<class C, class T1, class T2>
00886 class pointer_to_member_to_map_function_2args : public map_function {
00887 protected:
00888 ex (C::*ptr)(const ex &, T1, T2);
00889 C &c;
00890 T1 arg1;
00891 T2 arg2;
00892 public:
00893 explicit pointer_to_member_to_map_function_2args(ex (C::*member)(const ex&, T1, T2), C &obj, T1 a1, T2 a2) : ptr(member), c(obj), arg1(a1), arg2(a2) {}
00894 ex operator()(const ex & e) { return (c.*ptr)(e, arg1, arg2); }
00895 };
00896
00897 template<class C, class T1, class T2, class T3>
00898 class pointer_to_member_to_map_function_3args : public map_function {
00899 protected:
00900 ex (C::*ptr)(const ex &, T1, T2, T3);
00901 C &c;
00902 T1 arg1;
00903 T2 arg2;
00904 T3 arg3;
00905 public:
00906 explicit pointer_to_member_to_map_function_3args(ex (C::*member)(const ex &, T1, T2, T3), C &obj, T1 a1, T2 a2, T3 a3) : ptr(member), c(obj), arg1(a1), arg2(a2), arg3(a3) {}
00907 ex operator()(const ex & e) { return (c.*ptr)(e, arg1, arg2, arg3); }
00908 };
00909
00910 inline ex ex::map(ex f(const ex &)) const
00911 {
00912 pointer_to_map_function fcn(f);
00913 return bp->map(fcn);
00914 }
00915
00916
00917
00919 template <class T>
00920 inline bool is_a(const ex &obj)
00921 {
00922 return is_a<T>(*obj.bp);
00923 }
00924
00926 template <class T>
00927 inline bool is_exactly_a(const ex &obj)
00928 {
00929 return is_exactly_a<T>(*obj.bp);
00930 }
00931
00942 template <class T>
00943 inline const T &ex_to(const ex &e)
00944 {
00945 GINAC_ASSERT(is_a<T>(e));
00946 return static_cast<const T &>(*e.bp);
00947 }
00948
00949 }
00950
00951
00952
00953 namespace std {
00954
00956 template <>
00957 inline void swap(GiNaC::ex &a, GiNaC::ex &b)
00958 {
00959 a.swap(b);
00960 }
00961
00963 template <>
00964 inline void iter_swap(vector<GiNaC::ex>::iterator i1, vector<GiNaC::ex>::iterator i2)
00965 {
00966 i1->swap(*i2);
00967 }
00968
00970 template <>
00971 inline void iter_swap(list<GiNaC::ex>::iterator i1, list<GiNaC::ex>::iterator i2)
00972 {
00973 i1->swap(*i2);
00974 }
00975
00976 }
00977
00978 #endif // ndef GINAC_EX_H