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