3 * Implementation of GiNaC's light-weight expression handles. */
10 // default constructor, destructor, copy constructor assignment operator and helpers
15 #ifndef INLINE_EX_CONSTRUCTORS
17 ex::ex() : bp(exZERO().bp)
19 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
20 ASSERT(exZERO().bp!=0);
21 ASSERT(exZERO().bp->flags & status_flags::dynallocated);
28 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
30 ASSERT(bp->flags & status_flags::dynallocated);
31 if (--bp->refcount == 0) {
36 ex::ex(ex const & other) : bp(other.bp)
38 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
40 ASSERT((bp->flags) & status_flags::dynallocated);
44 ex const & ex::operator=(ex const & other)
46 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
48 ASSERT(bp->flags & status_flags::dynallocated);
50 ASSERT(other.bp->flags & status_flags::dynallocated);
52 basic * tmpbp=other.bp;
53 if (--bp->refcount==0) {
60 #endif // ndef INLINE_EX_CONSTRUCTORS
68 #ifndef INLINE_EX_CONSTRUCTORS
69 ex::ex(basic const & other)
71 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
72 construct_from_basic(other);
78 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
79 construct_from_basic(numeric(i));
82 ex::ex(unsigned int const i)
84 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
85 construct_from_basic(numeric(i));
90 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
91 construct_from_basic(numeric(i));
94 ex::ex(unsigned long const i)
96 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
97 construct_from_basic(numeric(i));
100 ex::ex(double const d)
102 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
103 construct_from_basic(numeric(d));
107 // functions overriding virtual functions from bases classes
113 // new virtual functions which can be overridden by derived classes
119 // non-virtual functions in this class
124 void ex::swap(ex & other)
126 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
129 ASSERT(bp->flags & status_flags::dynallocated);
131 ASSERT(other.bp->flags & status_flags::dynallocated);
138 bool ex::info(unsigned inf) const
140 if (inf == info_flags::normal_form) {
142 // Polynomials are in normal form
143 if (info(info_flags::polynomial))
146 // polynomial^(-int) is in normal form
147 if (is_ex_exactly_of_type(*this, power))
148 return op(1).info(info_flags::negint);
150 // polynomial^(int) * polynomial^(int) * ... is in normal form
151 if (!is_ex_exactly_of_type(*this, mul))
153 for (int i=0; i<nops(); i++) {
154 if (is_ex_exactly_of_type(op(i), power)) {
155 if (!op(i).op(1).info(info_flags::integer))
157 if (!op(i).op(0).info(info_flags::polynomial))
160 if (!op(i).info(info_flags::polynomial))
165 return bp->info(inf);
175 ex ex::expand(unsigned options) const
178 return bp->expand(options);
181 bool ex::has(ex const & other) const
184 return bp->has(other);
187 int ex::degree(symbol const & s) const
190 return bp->degree(s);
193 int ex::ldegree(symbol const & s) const
196 return bp->ldegree(s);
199 ex ex::coeff(symbol const & s, int const n) const
202 return bp->coeff(s,n);
205 ex ex::numer(bool normalize) const
208 if (normalize && !info(info_flags::normal_form))
214 if (n.info(info_flags::polynomial))
218 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
221 // something^(int) * something^(int) * ...
222 if (!is_ex_exactly_of_type(n, mul))
225 for (int i=0; i<n.nops(); i++) {
226 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
232 ex ex::denom(bool normalize) const
235 if (normalize && !info(info_flags::normal_form))
241 if (n.info(info_flags::polynomial))
245 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
246 return power(n.op(0), -(n.op(1)));
248 // something^(int) * something^(int) * ...
249 if (!is_ex_exactly_of_type(n, mul))
252 for (int i=0; i<n.nops(); i++) {
253 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
254 res *= power(n.op(i), -1);
259 ex ex::collect(symbol const & s) const
262 return bp->collect(s);
265 ex ex::eval(int level) const
268 return bp->eval(level);
271 ex ex::evalf(int level) const
274 return bp->evalf(level);
277 ex ex::subs(lst const & ls, lst const & lr) const
280 return bp->subs(ls,lr);
283 ex ex::subs(ex const & e) const
289 exvector ex::get_indices(void) const
292 return bp->get_indices();
295 ex ex::simplify_ncmul(exvector const & v) const
298 return bp->simplify_ncmul(v);
301 ex ex::operator[](ex const & index) const
303 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
308 ex ex::operator[](int const i) const
310 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
315 ex ex::op(int const i) const
317 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
322 ex & ex::let_op(int const i)
324 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
327 return bp->let_op(i);
330 #ifndef INLINE_EX_CONSTRUCTORS
331 int ex::compare(ex const & other) const
336 // special case: both expression point to same basic, trivially equal
339 return bp->compare(*other.bp);
341 #endif // ndef INLINE_EX_CONSTRUCTORS
343 #ifndef INLINE_EX_CONSTRUCTORS
344 bool ex::is_equal(ex const & other) const
349 // special case: both expression point to same basic, trivially equal
352 return bp->is_equal(*other.bp);
354 #endif // ndef INLINE_EX_CONSTRUCTORS
356 unsigned ex::return_type(void) const
359 return bp->return_type();
362 unsigned ex::return_type_tinfo(void) const
365 return bp->return_type_tinfo();
368 unsigned ex::gethash(void) const
371 return bp->gethash();
374 ex ex::exadd(ex const & rh) const
376 return (new add(*this,rh))->setflag(status_flags::dynallocated);
379 ex ex::exmul(ex const & rh) const
381 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
384 ex ex::exncmul(ex const & rh) const
386 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
391 void ex::makewriteable()
393 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
395 ASSERT(bp->flags & status_flags::dynallocated);
396 if (bp->refcount > 1) {
397 basic * bp2=bp->duplicate();
399 bp2->setflag(status_flags::dynallocated);
403 ASSERT(bp->refcount == 1);
406 void ex::construct_from_basic(basic const & other)
408 if ( (other.flags & status_flags::evaluated)==0 ) {
409 // cf. copy constructor
410 ex const & tmpex = other.eval(1); // evaluate only one (top) level
413 ASSERT(bp->flags & status_flags::dynallocated);
415 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
416 delete &const_cast<basic &>(other);
419 if (other.flags & status_flags::dynallocated) {
420 bp=&const_cast<basic &>(other);
422 bp=other.duplicate();
423 bp->setflag(status_flags::dynallocated);
426 // bp->clearflag(status_flags::evaluated);
430 ASSERT(bp->flags & status_flags::dynallocated);
434 // static member variables
440 // functions which are not member functions
449 ex const & exZERO(void)
451 static ex * eZERO=new ex(numZERO());
455 ex const & exONE(void)
457 static ex * eONE=new ex(numONE());
461 ex const & exTWO(void)
463 static ex * eTWO=new ex(numTWO());
467 ex const & exTHREE(void)
469 static ex * eTHREE=new ex(numTHREE());
473 ex const & exMINUSONE(void)
475 static ex * eMINUSONE=new ex(numMINUSONE());
479 ex const & exHALF(void)
481 static ex * eHALF=new ex(ex(1)/ex(2));
485 ex const & exMINUSHALF(void)
487 static ex * eMINUSHALF=new ex(numeric(-1,2));