3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999 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
33 // default constructor, destructor, copy constructor assignment operator and helpers
38 #ifndef INLINE_EX_CONSTRUCTORS
40 ex::ex() : bp(exZERO().bp)
42 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
43 ASSERT(exZERO().bp!=0);
44 ASSERT(exZERO().bp->flags & status_flags::dynallocated);
51 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
53 ASSERT(bp->flags & status_flags::dynallocated);
54 if (--bp->refcount == 0) {
59 ex::ex(ex const & other) : bp(other.bp)
61 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
63 ASSERT((bp->flags) & status_flags::dynallocated);
67 ex const & ex::operator=(ex const & other)
69 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
71 ASSERT(bp->flags & status_flags::dynallocated);
73 ASSERT(other.bp->flags & status_flags::dynallocated);
75 basic * tmpbp=other.bp;
76 if (--bp->refcount==0) {
83 #endif // ndef INLINE_EX_CONSTRUCTORS
91 #ifndef INLINE_EX_CONSTRUCTORS
92 ex::ex(basic const & other)
94 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
95 construct_from_basic(other);
101 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
102 construct_from_basic(numeric(i));
105 ex::ex(unsigned int const i)
107 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
108 construct_from_basic(numeric(i));
113 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
114 construct_from_basic(numeric(i));
117 ex::ex(unsigned long const i)
119 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
120 construct_from_basic(numeric(i));
123 ex::ex(double const d)
125 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
126 construct_from_basic(numeric(d));
130 // functions overriding virtual functions from bases classes
136 // new virtual functions which can be overridden by derived classes
142 // non-virtual functions in this class
147 void ex::swap(ex & other)
149 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
152 ASSERT(bp->flags & status_flags::dynallocated);
154 ASSERT(other.bp->flags & status_flags::dynallocated);
161 bool ex::info(unsigned inf) const
163 if (inf == info_flags::normal_form) {
165 // Polynomials are in normal form
166 if (info(info_flags::polynomial))
169 // polynomial^(-int) is in normal form
170 if (is_ex_exactly_of_type(*this, power))
171 return op(1).info(info_flags::negint);
173 // polynomial^(int) * polynomial^(int) * ... is in normal form
174 if (!is_ex_exactly_of_type(*this, mul))
176 for (int i=0; i<nops(); i++) {
177 if (is_ex_exactly_of_type(op(i), power)) {
178 if (!op(i).op(1).info(info_flags::integer))
180 if (!op(i).op(0).info(info_flags::polynomial))
183 if (!op(i).info(info_flags::polynomial))
188 return bp->info(inf);
198 ex ex::expand(unsigned options) const
201 return bp->expand(options);
204 bool ex::has(ex const & other) const
207 return bp->has(other);
210 int ex::degree(symbol const & s) const
213 return bp->degree(s);
216 int ex::ldegree(symbol const & s) const
219 return bp->ldegree(s);
222 ex ex::coeff(symbol const & s, int const n) const
225 return bp->coeff(s,n);
228 ex ex::numer(bool normalize) const
231 if (normalize && !info(info_flags::normal_form))
237 if (n.info(info_flags::polynomial))
241 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
244 // something^(int) * something^(int) * ...
245 if (!is_ex_exactly_of_type(n, mul))
248 for (int i=0; i<n.nops(); i++) {
249 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
255 ex ex::denom(bool normalize) const
258 if (normalize && !info(info_flags::normal_form))
264 if (n.info(info_flags::polynomial))
268 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
269 return power(n.op(0), -(n.op(1)));
271 // something^(int) * something^(int) * ...
272 if (!is_ex_exactly_of_type(n, mul))
275 for (int i=0; i<n.nops(); i++) {
276 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
277 res *= power(n.op(i), -1);
282 ex ex::collect(symbol const & s) const
285 return bp->collect(s);
288 ex ex::eval(int level) const
291 return bp->eval(level);
294 ex ex::evalf(int level) const
297 return bp->evalf(level);
300 ex ex::subs(lst const & ls, lst const & lr) const
303 return bp->subs(ls,lr);
306 ex ex::subs(ex const & e) const
312 exvector ex::get_indices(void) const
315 return bp->get_indices();
318 ex ex::simplify_ncmul(exvector const & v) const
321 return bp->simplify_ncmul(v);
324 ex ex::operator[](ex const & index) const
326 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
331 ex ex::operator[](int const i) const
333 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
338 ex ex::op(int const i) const
340 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
345 ex & ex::let_op(int const i)
347 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
350 return bp->let_op(i);
353 #ifndef INLINE_EX_CONSTRUCTORS
354 int ex::compare(ex const & other) const
359 // special case: both expression point to same basic, trivially equal
362 return bp->compare(*other.bp);
364 #endif // ndef INLINE_EX_CONSTRUCTORS
366 #ifndef INLINE_EX_CONSTRUCTORS
367 bool ex::is_equal(ex const & other) const
372 // special case: both expression point to same basic, trivially equal
375 return bp->is_equal(*other.bp);
377 #endif // ndef INLINE_EX_CONSTRUCTORS
379 unsigned ex::return_type(void) const
382 return bp->return_type();
385 unsigned ex::return_type_tinfo(void) const
388 return bp->return_type_tinfo();
391 unsigned ex::gethash(void) const
394 return bp->gethash();
397 ex ex::exadd(ex const & rh) const
399 return (new add(*this,rh))->setflag(status_flags::dynallocated);
402 ex ex::exmul(ex const & rh) const
404 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
407 ex ex::exncmul(ex const & rh) const
409 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
414 void ex::makewriteable()
416 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
418 ASSERT(bp->flags & status_flags::dynallocated);
419 if (bp->refcount > 1) {
420 basic * bp2=bp->duplicate();
422 bp2->setflag(status_flags::dynallocated);
426 ASSERT(bp->refcount == 1);
429 void ex::construct_from_basic(basic const & other)
431 if ( (other.flags & status_flags::evaluated)==0 ) {
432 // cf. copy constructor
433 ex const & tmpex = other.eval(1); // evaluate only one (top) level
436 ASSERT(bp->flags & status_flags::dynallocated);
438 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
439 delete &const_cast<basic &>(other);
442 if (other.flags & status_flags::dynallocated) {
443 bp=&const_cast<basic &>(other);
445 bp=other.duplicate();
446 bp->setflag(status_flags::dynallocated);
449 // bp->clearflag(status_flags::evaluated);
453 ASSERT(bp->flags & status_flags::dynallocated);
457 // static member variables
463 // functions which are not member functions
472 ex const & exZERO(void)
474 static ex * eZERO=new ex(numZERO());
478 ex const & exONE(void)
480 static ex * eONE=new ex(numONE());
484 ex const & exTWO(void)
486 static ex * eTWO=new ex(numTWO());
490 ex const & exTHREE(void)
492 static ex * eTHREE=new ex(numTHREE());
496 ex const & exMINUSONE(void)
498 static ex * eMINUSONE=new ex(numMINUSONE());
502 ex const & exHALF(void)
504 static ex * eHALF=new ex(ex(1)/ex(2));
508 ex const & exMINUSHALF(void)
510 static ex * eMINUSHALF=new ex(numeric(-1,2));