3 * Implementation of GiNaC's light-weight expression handles.
5 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 // default constructor, destructor, copy constructor assignment operator and helpers
37 #ifndef INLINE_EX_CONSTRUCTORS
39 ex::ex() : bp(exZERO().bp)
41 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
42 ASSERT(exZERO().bp!=0);
43 ASSERT(exZERO().bp->flags & status_flags::dynallocated);
50 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
52 ASSERT(bp->flags & status_flags::dynallocated);
53 if (--bp->refcount == 0) {
58 ex::ex(ex const & other) : bp(other.bp)
60 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
62 ASSERT((bp->flags) & status_flags::dynallocated);
66 ex const & ex::operator=(ex const & other)
68 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
70 ASSERT(bp->flags & status_flags::dynallocated);
72 ASSERT(other.bp->flags & status_flags::dynallocated);
74 basic * tmpbp=other.bp;
75 if (--bp->refcount==0) {
82 #endif // ndef INLINE_EX_CONSTRUCTORS
90 #ifndef INLINE_EX_CONSTRUCTORS
91 ex::ex(basic const & other)
93 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
94 construct_from_basic(other);
100 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
101 construct_from_basic(numeric(i));
104 ex::ex(unsigned int const i)
106 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
107 construct_from_basic(numeric(i));
112 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
113 construct_from_basic(numeric(i));
116 ex::ex(unsigned long const i)
118 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
119 construct_from_basic(numeric(i));
122 ex::ex(double const d)
124 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
125 construct_from_basic(numeric(d));
129 // functions overriding virtual functions from bases classes
135 // new virtual functions which can be overridden by derived classes
141 // non-virtual functions in this class
146 void ex::swap(ex & other)
148 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
151 ASSERT(bp->flags & status_flags::dynallocated);
153 ASSERT(other.bp->flags & status_flags::dynallocated);
160 bool ex::info(unsigned inf) const
162 if (inf == info_flags::normal_form) {
164 // Polynomials are in normal form
165 if (info(info_flags::polynomial))
168 // polynomial^(-int) is in normal form
169 if (is_ex_exactly_of_type(*this, power))
170 return op(1).info(info_flags::negint);
172 // polynomial^(int) * polynomial^(int) * ... is in normal form
173 if (!is_ex_exactly_of_type(*this, mul))
175 for (int i=0; i<nops(); i++) {
176 if (is_ex_exactly_of_type(op(i), power)) {
177 if (!op(i).op(1).info(info_flags::integer))
179 if (!op(i).op(0).info(info_flags::polynomial))
182 if (!op(i).info(info_flags::polynomial))
187 return bp->info(inf);
197 ex ex::expand(unsigned options) const
200 return bp->expand(options);
203 bool ex::has(ex const & other) const
206 return bp->has(other);
209 int ex::degree(symbol const & s) const
212 return bp->degree(s);
215 int ex::ldegree(symbol const & s) const
218 return bp->ldegree(s);
221 ex ex::coeff(symbol const & s, int const n) const
224 return bp->coeff(s,n);
227 ex ex::numer(bool normalize) const
230 if (normalize && !info(info_flags::normal_form))
236 if (n.info(info_flags::polynomial))
240 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
243 // something^(int) * something^(int) * ...
244 if (!is_ex_exactly_of_type(n, mul))
247 for (int i=0; i<n.nops(); i++) {
248 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
254 ex ex::denom(bool normalize) const
257 if (normalize && !info(info_flags::normal_form))
263 if (n.info(info_flags::polynomial))
267 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
268 return power(n.op(0), -(n.op(1)));
270 // something^(int) * something^(int) * ...
271 if (!is_ex_exactly_of_type(n, mul))
274 for (int i=0; i<n.nops(); i++) {
275 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
276 res *= power(n.op(i), -1);
281 ex ex::collect(symbol const & s) const
284 return bp->collect(s);
287 ex ex::eval(int level) const
290 return bp->eval(level);
293 ex ex::evalf(int level) const
296 return bp->evalf(level);
299 ex ex::subs(lst const & ls, lst const & lr) const
302 return bp->subs(ls,lr);
305 ex ex::subs(ex const & e) const
311 exvector ex::get_indices(void) const
314 return bp->get_indices();
317 ex ex::simplify_ncmul(exvector const & v) const
320 return bp->simplify_ncmul(v);
323 ex ex::operator[](ex const & index) const
325 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
330 ex ex::operator[](int const i) const
332 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
337 ex ex::op(int const i) const
339 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
344 ex & ex::let_op(int const i)
346 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
349 return bp->let_op(i);
352 #ifndef INLINE_EX_CONSTRUCTORS
353 int ex::compare(ex const & other) const
358 // special case: both expression point to same basic, trivially equal
361 return bp->compare(*other.bp);
363 #endif // ndef INLINE_EX_CONSTRUCTORS
365 #ifndef INLINE_EX_CONSTRUCTORS
366 bool ex::is_equal(ex const & other) const
371 // special case: both expression point to same basic, trivially equal
374 return bp->is_equal(*other.bp);
376 #endif // ndef INLINE_EX_CONSTRUCTORS
378 unsigned ex::return_type(void) const
381 return bp->return_type();
384 unsigned ex::return_type_tinfo(void) const
387 return bp->return_type_tinfo();
390 unsigned ex::gethash(void) const
393 return bp->gethash();
396 ex ex::exadd(ex const & rh) const
398 return (new add(*this,rh))->setflag(status_flags::dynallocated);
401 ex ex::exmul(ex const & rh) const
403 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
406 ex ex::exncmul(ex const & rh) const
408 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
413 void ex::makewriteable()
415 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
417 ASSERT(bp->flags & status_flags::dynallocated);
418 if (bp->refcount > 1) {
419 basic * bp2=bp->duplicate();
421 bp2->setflag(status_flags::dynallocated);
425 ASSERT(bp->refcount == 1);
428 void ex::construct_from_basic(basic const & other)
430 if ( (other.flags & status_flags::evaluated)==0 ) {
431 // cf. copy constructor
432 ex const & tmpex = other.eval(1); // evaluate only one (top) level
435 ASSERT(bp->flags & status_flags::dynallocated);
437 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
438 delete &const_cast<basic &>(other);
441 if (other.flags & status_flags::dynallocated) {
442 bp=&const_cast<basic &>(other);
444 bp=other.duplicate();
445 bp->setflag(status_flags::dynallocated);
448 // bp->clearflag(status_flags::evaluated);
452 ASSERT(bp->flags & status_flags::dynallocated);
456 // static member variables
462 // functions which are not member functions
471 ex const & exZERO(void)
473 static ex * eZERO=new ex(numZERO());
477 ex const & exONE(void)
479 static ex * eONE=new ex(numONE());
483 ex const & exTWO(void)
485 static ex * eTWO=new ex(numTWO());
489 ex const & exTHREE(void)
491 static ex * eTHREE=new ex(numTHREE());
495 ex const & exMINUSONE(void)
497 static ex * eMINUSONE=new ex(numMINUSONE());
501 ex const & exHALF(void)
503 static ex * eHALF=new ex(ex(1)/ex(2));
507 ex const & exMINUSHALF(void)
509 static ex * eMINUSHALF=new ex(numeric(-1,2));