3 * Interface to GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifndef __GINAC_EX_H__
24 #define __GINAC_EX_H__
33 /** Helper class to initialize the library. There must be one static object
34 * of this class in every object file that makes use of our flyweights in
35 * order to guarantee proper initialization. Hence we put it into this
36 * file which is included by every relevant file anyways. This is modeled
37 * after section 27.4.2.1.6 of the C++ standard, where cout and friends are
48 /** For construction of flyweights, etc. */
49 static library_init library_initializer;
51 // Current versions of Cint don't link data declared extern within functions.
52 // FIXME: Fix Cint and later remove this from here.
53 #if defined(G__CINTVERSION)
54 extern const class numeric *_num0_p;
60 class scalar_products;
63 /** Lightweight wrapper for GiNaC's symbolic objects. Basically all it does is
64 * to hold a pointer to the other objects, manage the reference counting and
65 * provide methods for manipulation of these objects. (Some people call such
66 * a thing a proxy class.) */
69 friend class archive_node;
70 friend bool are_ex_trivially_equal(const ex &, const ex &);
71 template<class T> friend const T &ex_to(const ex &);
72 template<class T> friend bool is_a(const ex &);
73 template<class T> friend bool is_exactly_a(const ex &);
77 // default ctor, dtor, copy ctor, assignment operator and helpers
82 ex & operator=(const ex & other);
85 ex(const basic & other);
91 /** Construct ex from string and a list of symbols. The input grammar is
92 * similar to the GiNaC output format. All symbols to be used in the
93 * expression must be specified in a lst in the second argument. Undefined
94 * symbols and other parser errors will throw an exception. */
95 ex(const std::string &s, const ex &l);
97 // non-virtual functions in this class
99 /** Efficiently swap the contents of two expressions. */
100 void swap(ex & other)
103 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
104 GINAC_ASSERT(other.bp!=0);
105 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
112 void print(const print_context & c, unsigned level = 0) const;
113 void printtree(std::ostream & os) const;
114 void dbgprint(void) const;
115 void dbgprinttree(void) const;
116 bool info(unsigned inf) const { return bp->info(inf); }
117 unsigned nops() const { return bp->nops(); }
118 ex expand(unsigned options=0) const;
119 bool has(const ex & pattern) const { return bp->has(pattern); }
120 ex map(map_function & f) const { return bp->map(f); }
121 ex map(ex (*f)(const ex & e)) const;
122 bool find(const ex & pattern, lst & found) const;
123 int degree(const ex & s) const { return bp->degree(s); }
124 int ldegree(const ex & s) const { return bp->ldegree(s); }
125 ex coeff(const ex & s, int n = 1) const { return bp->coeff(s, n); }
126 ex lcoeff(const ex & s) const { return coeff(s, degree(s)); }
127 ex tcoeff(const ex & s) const { return coeff(s, ldegree(s)); }
128 ex numer(void) const;
129 ex denom(void) const;
130 ex numer_denom(void) const;
131 ex unit(const symbol &x) const;
132 ex content(const symbol &x) const;
133 numeric integer_content(void) const;
134 ex primpart(const symbol &x) const;
135 ex primpart(const symbol &x, const ex &cont) const;
136 ex normal(int level = 0) const;
137 ex to_rational(lst &repl_lst) const { return bp->to_rational(repl_lst); }
138 ex smod(const numeric &xi) const { return bp->smod(xi); }
139 numeric max_coefficient(void) const;
140 ex collect(const ex & s, bool distributed = false) const { return bp->collect(s, distributed); }
141 ex eval(int level = 0) const { return bp->eval(level); }
142 ex evalf(int level = 0) const { return bp->evalf(level); }
143 ex evalm(void) const { return bp->evalm(); }
144 ex diff(const symbol & s, unsigned nth = 1) const;
145 ex series(const ex & r, int order, unsigned options = 0) const;
146 bool match(const ex & pattern) const;
147 bool match(const ex & pattern, lst & repl_lst) const { return bp->match(pattern, repl_lst); }
148 ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const { return bp->subs(ls, lr, no_pattern); }
149 ex subs(const ex & e, bool no_pattern = false) const { return bp->subs(e, no_pattern); }
150 exvector get_free_indices(void) const { return bp->get_free_indices(); }
151 ex simplify_indexed(void) const;
152 ex simplify_indexed(const scalar_products & sp) const;
153 ex symmetrize(void) const;
154 ex symmetrize(const lst & l) const;
155 ex antisymmetrize(void) const;
156 ex antisymmetrize(const lst & l) const;
157 ex symmetrize_cyclic(void) const;
158 ex symmetrize_cyclic(const lst & l) const;
159 ex simplify_ncmul(const exvector & v) const { return bp->simplify_ncmul(v); }
160 ex operator[](const ex & index) const;
161 ex operator[](int i) const;
162 ex op(int i) const { return bp->op(i); }
166 int compare(const ex & other) const;
167 bool is_equal(const ex & other) const;
168 bool is_zero(void) const { extern const ex _ex0; return is_equal(_ex0); }
170 unsigned return_type(void) const { return bp->return_type(); }
171 unsigned return_type_tinfo(void) const { return bp->return_type_tinfo(); }
172 unsigned gethash(void) const { return bp->gethash(); }
174 void construct_from_basic(const basic & other);
175 void construct_from_int(int i);
176 void construct_from_uint(unsigned int i);
177 void construct_from_long(long i);
178 void construct_from_ulong(unsigned long i);
179 void construct_from_double(double d);
180 void construct_from_string_and_lst(const std::string &s, const ex &l);
181 void makewriteable();
183 #ifdef OBSCURE_CINT_HACK
185 static bool last_created_or_assigned_bp_can_be_converted_to_ex(void)
187 if (last_created_or_assigned_bp==0) return false;
188 if ((last_created_or_assigned_bp->flags &
189 status_flags::dynallocated)==0) return false;
190 if ((last_created_or_assigned_bp->flags &
191 status_flags::evaluated)==0) return false;
195 void update_last_created_or_assigned_bp(void)
197 if (last_created_or_assigned_bp!=0) {
198 if (--last_created_or_assigned_bp->refcount == 0) {
199 delete last_created_or_assigned_bp;
202 last_created_or_assigned_bp = bp;
203 ++last_created_or_assigned_bp->refcount;
204 last_created_or_assigned_exp = (long)(void *)(this);
206 #endif // def OBSCURE_CINT_HACK
211 basic *bp; ///< pointer to basic object managed by this
212 #ifdef OBSCURE_CINT_HACK
214 static basic * last_created_or_assigned_bp;
215 static basic * dummy_bp;
216 static long last_created_or_assigned_exp;
217 #endif // def OBSCURE_CINT_HACK
221 // performance-critical inlined method implementations
226 extern const class numeric *_num0_p;
227 bp = (basic*)_num0_p;
229 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
231 #ifdef OBSCURE_CINT_HACK
232 update_last_created_or_assigned_bp();
233 #endif // def OBSCURE_CINT_HACK
240 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
241 if (--bp->refcount == 0)
246 ex::ex(const ex & other) : bp(other.bp)
249 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
251 #ifdef OBSCURE_CINT_HACK
252 update_last_created_or_assigned_bp();
253 #endif // def OBSCURE_CINT_HACK
257 ex & ex::operator=(const ex & other)
260 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
261 GINAC_ASSERT(other.bp!=0);
262 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
263 // NB: must first increment other.bp->refcount, since other might be *this.
264 ++other.bp->refcount;
265 if (--bp->refcount==0)
268 #ifdef OBSCURE_CINT_HACK
269 update_last_created_or_assigned_bp();
270 #endif // def OBSCURE_CINT_HACK
275 ex::ex(const basic & other)
277 construct_from_basic(other);
278 #ifdef OBSCURE_CINT_HACK
279 update_last_created_or_assigned_bp();
280 #endif // def OBSCURE_CINT_HACK
286 construct_from_int(i);
287 #ifdef OBSCURE_CINT_HACK
288 update_last_created_or_assigned_bp();
289 #endif // def OBSCURE_CINT_HACK
293 ex::ex(unsigned int i)
295 construct_from_uint(i);
296 #ifdef OBSCURE_CINT_HACK
297 update_last_created_or_assigned_bp();
298 #endif // def OBSCURE_CINT_HACK
304 construct_from_long(i);
305 #ifdef OBSCURE_CINT_HACK
306 update_last_created_or_assigned_bp();
307 #endif // def OBSCURE_CINT_HACK
311 ex::ex(unsigned long i)
313 construct_from_ulong(i);
314 #ifdef OBSCURE_CINT_HACK
315 update_last_created_or_assigned_bp();
316 #endif // def OBSCURE_CINT_HACK
320 ex::ex(double const d)
322 construct_from_double(d);
323 #ifdef OBSCURE_CINT_HACK
324 update_last_created_or_assigned_bp();
325 #endif // def OBSCURE_CINT_HACK
329 ex::ex(const std::string &s, const ex &l)
331 construct_from_string_and_lst(s, l);
332 #ifdef OBSCURE_CINT_HACK
333 update_last_created_or_assigned_bp();
334 #endif // def OBSCURE_CINT_HACK
338 int ex::compare(const ex & other) const
341 GINAC_ASSERT(other.bp!=0);
342 if (bp==other.bp) // trivial case: both expressions point to same basic
344 return bp->compare(*other.bp);
348 bool ex::is_equal(const ex & other) const
351 GINAC_ASSERT(other.bp!=0);
352 if (bp==other.bp) // trivial case: both expressions point to same basic
354 return bp->is_equal(*other.bp);
360 /** Compare two objects of class quickly without doing a deep tree traversal.
361 * @return "true" if they are equal
362 * "false" if equality cannot be established quickly (e1 and e2 may
363 * still be equal, in this case. */
364 inline bool are_ex_trivially_equal(const ex &e1, const ex &e2)
366 return e1.bp == e2.bp;
369 // wrapper functions around member functions
370 inline unsigned nops(const ex & thisex)
371 { return thisex.nops(); }
373 inline ex expand(const ex & thisex, unsigned options = 0)
374 { return thisex.expand(options); }
376 inline bool has(const ex & thisex, const ex & pattern)
377 { return thisex.has(pattern); }
379 inline bool find(const ex & thisex, const ex & pattern, lst & found)
380 { return thisex.find(pattern, found); }
382 inline int degree(const ex & thisex, const ex & s)
383 { return thisex.degree(s); }
385 inline int ldegree(const ex & thisex, const ex & s)
386 { return thisex.ldegree(s); }
388 inline ex coeff(const ex & thisex, const ex & s, int n=1)
389 { return thisex.coeff(s, n); }
391 inline ex numer(const ex & thisex)
392 { return thisex.numer(); }
394 inline ex denom(const ex & thisex)
395 { return thisex.denom(); }
397 inline ex numer_denom(const ex & thisex)
398 { return thisex.numer_denom(); }
400 inline ex normal(const ex & thisex, int level=0)
401 { return thisex.normal(level); }
403 inline ex to_rational(const ex & thisex, lst & repl_lst)
404 { return thisex.to_rational(repl_lst); }
406 inline ex collect(const ex & thisex, const ex & s, bool distributed = false)
407 { return thisex.collect(s, distributed); }
409 inline ex eval(const ex & thisex, int level = 0)
410 { return thisex.eval(level); }
412 inline ex evalf(const ex & thisex, int level = 0)
413 { return thisex.evalf(level); }
415 inline ex evalm(const ex & thisex)
416 { return thisex.evalm(); }
418 inline ex diff(const ex & thisex, const symbol & s, unsigned nth = 1)
419 { return thisex.diff(s, nth); }
421 inline ex series(const ex & thisex, const ex & r, int order, unsigned options = 0)
422 { return thisex.series(r, order, options); }
424 inline bool match(const ex & thisex, const ex & pattern, lst & repl_lst)
425 { return thisex.match(pattern, repl_lst); }
427 inline ex subs(const ex & thisex, const ex & e)
428 { return thisex.subs(e); }
430 inline ex subs(const ex & thisex, const lst & ls, const lst & lr)
431 { return thisex.subs(ls, lr); }
433 inline ex simplify_indexed(const ex & thisex)
434 { return thisex.simplify_indexed(); }
436 inline ex simplify_indexed(const ex & thisex, const scalar_products & sp)
437 { return thisex.simplify_indexed(sp); }
439 inline ex symmetrize(const ex & thisex)
440 { return thisex.symmetrize(); }
442 inline ex symmetrize(const ex & thisex, const lst & l)
443 { return thisex.symmetrize(l); }
445 inline ex antisymmetrize(const ex & thisex)
446 { return thisex.antisymmetrize(); }
448 inline ex antisymmetrize(const ex & thisex, const lst & l)
449 { return thisex.antisymmetrize(l); }
451 inline ex symmetrize_cyclic(const ex & thisex)
452 { return thisex.symmetrize_cyclic(); }
454 inline ex symmetrize_cyclic(const ex & thisex, const lst & l)
455 { return thisex.symmetrize_cyclic(l); }
457 inline ex op(const ex & thisex, int i)
458 { return thisex.op(i); }
460 inline ex lhs(const ex & thisex)
461 { return thisex.lhs(); }
463 inline ex rhs(const ex & thisex)
464 { return thisex.rhs(); }
466 inline bool is_zero(const ex & thisex)
467 { return thisex.is_zero(); }
469 inline void swap(ex & e1, ex & e2)
472 // This makes STL algorithms use the more efficient swap operation for ex objects
473 inline void iter_swap(std::vector<ex>::iterator i1, std::vector<ex>::iterator i2)
477 /* Function objects for STL sort() etc. */
478 struct ex_is_less : public std::binary_function<ex, ex, bool> {
479 bool operator() (const ex &lh, const ex &rh) const { return lh.compare(rh) < 0; }
482 struct ex_is_equal : public std::binary_function<ex, ex, bool> {
483 bool operator() (const ex &lh, const ex &rh) const { return lh.is_equal(rh); }
486 struct ex_swap : public std::binary_function<ex, ex, void> {
487 void operator() (ex &lh, ex &rh) const { lh.swap(rh); }
491 /* Convert function pointer to function object suitable for map(). */
492 class pointer_to_map_function : public map_function {
494 ex (*ptr)(const ex &);
496 explicit pointer_to_map_function(ex (*x)(const ex &)) : ptr(x) {}
497 ex operator()(const ex & e) { return ptr(e); }
501 class pointer_to_map_function_1arg : public map_function {
503 ex (*ptr)(const ex &, T1);
506 explicit pointer_to_map_function_1arg(ex (*x)(const ex &, T1), T1 a1) : ptr(x), arg1(a1) {}
507 ex operator()(const ex & e) { return ptr(e, arg1); }
510 template<class T1, class T2>
511 class pointer_to_map_function_2args : public map_function {
513 ex (*ptr)(const ex &, T1, T2);
517 explicit pointer_to_map_function_2args(ex (*x)(const ex &, T1, T2), T1 a1, T2 a2) : ptr(x), arg1(a1), arg2(a2) {}
518 ex operator()(const ex & e) { return ptr(e, arg1, arg2); }
521 template<class T1, class T2, class T3>
522 class pointer_to_map_function_3args : public map_function {
524 ex (*ptr)(const ex &, T1, T2, T3);
529 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) {}
530 ex operator()(const ex & e) { return ptr(e, arg1, arg2, arg3); }
533 inline ex ex::map(ex (*f)(const ex & e)) const
535 pointer_to_map_function fcn(f);
542 #endif // ndef __GINAC_EX_H__