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
27 // default constructor, destructor, copy constructor assignment operator and helpers
32 #ifndef INLINE_EX_CONSTRUCTORS
34 ex::ex() : bp(exZERO().bp)
36 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
37 ASSERT(exZERO().bp!=0);
38 ASSERT(exZERO().bp->flags & status_flags::dynallocated);
45 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
47 ASSERT(bp->flags & status_flags::dynallocated);
48 if (--bp->refcount == 0) {
53 ex::ex(ex const & other) : bp(other.bp)
55 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
57 ASSERT((bp->flags) & status_flags::dynallocated);
61 ex const & ex::operator=(ex const & other)
63 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
65 ASSERT(bp->flags & status_flags::dynallocated);
67 ASSERT(other.bp->flags & status_flags::dynallocated);
69 basic * tmpbp=other.bp;
70 if (--bp->refcount==0) {
77 #endif // ndef INLINE_EX_CONSTRUCTORS
85 #ifndef INLINE_EX_CONSTRUCTORS
86 ex::ex(basic const & other)
88 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
89 construct_from_basic(other);
95 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
96 construct_from_basic(numeric(i));
99 ex::ex(unsigned int const i)
101 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
102 construct_from_basic(numeric(i));
107 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
108 construct_from_basic(numeric(i));
111 ex::ex(unsigned long const i)
113 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
114 construct_from_basic(numeric(i));
117 ex::ex(double const d)
119 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
120 construct_from_basic(numeric(d));
124 // functions overriding virtual functions from bases classes
130 // new virtual functions which can be overridden by derived classes
136 // non-virtual functions in this class
141 void ex::swap(ex & other)
143 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
146 ASSERT(bp->flags & status_flags::dynallocated);
148 ASSERT(other.bp->flags & status_flags::dynallocated);
155 bool ex::info(unsigned inf) const
157 if (inf == info_flags::normal_form) {
159 // Polynomials are in normal form
160 if (info(info_flags::polynomial))
163 // polynomial^(-int) is in normal form
164 if (is_ex_exactly_of_type(*this, power))
165 return op(1).info(info_flags::negint);
167 // polynomial^(int) * polynomial^(int) * ... is in normal form
168 if (!is_ex_exactly_of_type(*this, mul))
170 for (int i=0; i<nops(); i++) {
171 if (is_ex_exactly_of_type(op(i), power)) {
172 if (!op(i).op(1).info(info_flags::integer))
174 if (!op(i).op(0).info(info_flags::polynomial))
177 if (!op(i).info(info_flags::polynomial))
182 return bp->info(inf);
192 ex ex::expand(unsigned options) const
195 return bp->expand(options);
198 bool ex::has(ex const & other) const
201 return bp->has(other);
204 int ex::degree(symbol const & s) const
207 return bp->degree(s);
210 int ex::ldegree(symbol const & s) const
213 return bp->ldegree(s);
216 ex ex::coeff(symbol const & s, int const n) const
219 return bp->coeff(s,n);
222 ex ex::numer(bool normalize) const
225 if (normalize && !info(info_flags::normal_form))
231 if (n.info(info_flags::polynomial))
235 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
238 // something^(int) * something^(int) * ...
239 if (!is_ex_exactly_of_type(n, mul))
242 for (int i=0; i<n.nops(); i++) {
243 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
249 ex ex::denom(bool normalize) const
252 if (normalize && !info(info_flags::normal_form))
258 if (n.info(info_flags::polynomial))
262 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
263 return power(n.op(0), -(n.op(1)));
265 // something^(int) * something^(int) * ...
266 if (!is_ex_exactly_of_type(n, mul))
269 for (int i=0; i<n.nops(); i++) {
270 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
271 res *= power(n.op(i), -1);
276 ex ex::collect(symbol const & s) const
279 return bp->collect(s);
282 ex ex::eval(int level) const
285 return bp->eval(level);
288 ex ex::evalf(int level) const
291 return bp->evalf(level);
294 ex ex::subs(lst const & ls, lst const & lr) const
297 return bp->subs(ls,lr);
300 ex ex::subs(ex const & e) const
306 exvector ex::get_indices(void) const
309 return bp->get_indices();
312 ex ex::simplify_ncmul(exvector const & v) const
315 return bp->simplify_ncmul(v);
318 ex ex::operator[](ex const & index) const
320 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
325 ex ex::operator[](int const i) const
327 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
332 ex ex::op(int const i) const
334 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
339 ex & ex::let_op(int const i)
341 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
344 return bp->let_op(i);
347 #ifndef INLINE_EX_CONSTRUCTORS
348 int ex::compare(ex const & other) const
353 // special case: both expression point to same basic, trivially equal
356 return bp->compare(*other.bp);
358 #endif // ndef INLINE_EX_CONSTRUCTORS
360 #ifndef INLINE_EX_CONSTRUCTORS
361 bool ex::is_equal(ex const & other) const
366 // special case: both expression point to same basic, trivially equal
369 return bp->is_equal(*other.bp);
371 #endif // ndef INLINE_EX_CONSTRUCTORS
373 unsigned ex::return_type(void) const
376 return bp->return_type();
379 unsigned ex::return_type_tinfo(void) const
382 return bp->return_type_tinfo();
385 unsigned ex::gethash(void) const
388 return bp->gethash();
391 ex ex::exadd(ex const & rh) const
393 return (new add(*this,rh))->setflag(status_flags::dynallocated);
396 ex ex::exmul(ex const & rh) const
398 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
401 ex ex::exncmul(ex const & rh) const
403 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
408 void ex::makewriteable()
410 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
412 ASSERT(bp->flags & status_flags::dynallocated);
413 if (bp->refcount > 1) {
414 basic * bp2=bp->duplicate();
416 bp2->setflag(status_flags::dynallocated);
420 ASSERT(bp->refcount == 1);
423 void ex::construct_from_basic(basic const & other)
425 if ( (other.flags & status_flags::evaluated)==0 ) {
426 // cf. copy constructor
427 ex const & tmpex = other.eval(1); // evaluate only one (top) level
430 ASSERT(bp->flags & status_flags::dynallocated);
432 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
433 delete &const_cast<basic &>(other);
436 if (other.flags & status_flags::dynallocated) {
437 bp=&const_cast<basic &>(other);
439 bp=other.duplicate();
440 bp->setflag(status_flags::dynallocated);
443 // bp->clearflag(status_flags::evaluated);
447 ASSERT(bp->flags & status_flags::dynallocated);
451 // static member variables
457 // functions which are not member functions
466 ex const & exZERO(void)
468 static ex * eZERO=new ex(numZERO());
472 ex const & exONE(void)
474 static ex * eONE=new ex(numONE());
478 ex const & exTWO(void)
480 static ex * eTWO=new ex(numTWO());
484 ex const & exTHREE(void)
486 static ex * eTHREE=new ex(numTHREE());
490 ex const & exMINUSONE(void)
492 static ex * eMINUSONE=new ex(numMINUSONE());
496 ex const & exHALF(void)
498 static ex * eHALF=new ex(ex(1)/ex(2));
502 ex const & exMINUSHALF(void)
504 static ex * eMINUSHALF=new ex(numeric(-1,2));