3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2000 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
34 #ifndef NO_NAMESPACE_GINAC
36 #endif // ndef NO_NAMESPACE_GINAC
39 // default constructor, destructor, copy constructor assignment operator and helpers
44 #ifndef INLINE_EX_CONSTRUCTORS
46 ex::ex() : bp(ex0().bp)
48 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
49 GINAC_ASSERT(ex0().bp!=0);
50 GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
57 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
59 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
60 if (--bp->refcount == 0) {
65 ex::ex(const ex & other) : bp(other.bp)
67 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
69 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
73 const ex & ex::operator=(const ex & other)
75 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
77 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
78 GINAC_ASSERT(other.bp!=0);
79 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
81 basic * tmpbp=other.bp;
82 if (--bp->refcount==0) {
89 #endif // ndef INLINE_EX_CONSTRUCTORS
97 #ifndef INLINE_EX_CONSTRUCTORS
99 ex::ex(const basic & other)
101 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
102 construct_from_basic(other);
107 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
108 construct_from_int(i);
111 ex::ex(unsigned int i)
113 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
114 construct_from_uint(i);
119 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
120 construct_from_long(i);
123 ex::ex(unsigned long i)
125 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
126 construct_from_ulong(i);
129 ex::ex(double const d)
131 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
132 construct_from_double(d);
135 #endif // ndef INLINE_EX_CONSTRUCTORS
138 // functions overriding virtual functions from bases classes
144 // new virtual functions which can be overridden by derived classes
150 // non-virtual functions in this class
155 /** Swap the contents of two expressions. */
156 void ex::swap(ex & other)
158 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
161 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
162 GINAC_ASSERT(other.bp!=0);
163 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
170 /** Output formatted to be useful as ginsh input. */
171 void ex::print(ostream & os, unsigned upper_precedence) const
173 debugmsg("ex print",LOGLEVEL_PRINT);
175 bp->print(os,upper_precedence);
178 void ex::printraw(ostream & os) const
180 debugmsg("ex printraw",LOGLEVEL_PRINT);
187 void ex::printtree(ostream & os, unsigned indent) const
189 debugmsg("ex printtree",LOGLEVEL_PRINT);
191 // os << "refcount=" << bp->refcount << " ";
192 bp->printtree(os,indent);
195 /** Print expression as a C++ statement. The output looks like
196 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
197 * on how number literals are printed.
199 * @param os output stream
200 * @param type variable type (one of the csrc_types)
201 * @param var_name variable name to be printed */
202 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
204 debugmsg("ex print csrc", LOGLEVEL_PRINT);
207 case csrc_types::ctype_float:
210 case csrc_types::ctype_double:
213 case csrc_types::ctype_cl_N:
217 os << var_name << " = ";
218 bp->printcsrc(os, type, 0);
222 /** Little wrapper arount print to be called within a debugger. */
223 void ex::dbgprint(void) const
225 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
230 /** Little wrapper arount printtree to be called within a debugger. */
231 void ex::dbgprinttree(void) const
233 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
238 bool ex::info(unsigned inf) const
240 if (inf == info_flags::normal_form) {
242 // Polynomials are in normal form
243 if (info(info_flags::polynomial))
246 // polynomial^(-int) is in normal form
247 if (is_ex_exactly_of_type(*this, power))
248 return op(1).info(info_flags::negint);
250 // polynomial^(int) * polynomial^(int) * ... is in normal form
251 if (!is_ex_exactly_of_type(*this, mul))
253 for (unsigned i=0; i<nops(); i++) {
254 if (is_ex_exactly_of_type(op(i), power)) {
255 if (!op(i).op(1).info(info_flags::integer))
257 if (!op(i).op(0).info(info_flags::polynomial))
260 if (!op(i).info(info_flags::polynomial))
265 return bp->info(inf);
269 unsigned ex::nops() const
275 ex ex::expand(unsigned options) const
278 return bp->expand(options);
281 bool ex::has(const ex & other) const
284 return bp->has(other);
287 int ex::degree(const symbol & s) const
290 return bp->degree(s);
293 int ex::ldegree(const symbol & s) const
296 return bp->ldegree(s);
299 ex ex::coeff(const symbol & s, int n) const
302 return bp->coeff(s,n);
305 ex ex::numer(bool normalize) const
308 if (normalize && !info(info_flags::normal_form))
314 if (n.info(info_flags::polynomial))
318 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
321 // something^(int) * something^(int) * ...
322 if (!is_ex_exactly_of_type(n, mul))
325 for (unsigned i=0; i<n.nops(); i++) {
326 if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
332 ex ex::denom(bool normalize) const
335 if (normalize && !info(info_flags::normal_form))
341 if (n.info(info_flags::polynomial))
345 if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
346 return power(n.op(0), -(n.op(1)));
348 // something^(int) * something^(int) * ...
349 if (!is_ex_exactly_of_type(n, mul))
352 for (unsigned i=0; i<n.nops(); i++) {
353 if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
354 res *= power(n.op(i), -1);
359 ex ex::collect(const symbol & s) const
362 return bp->collect(s);
365 ex ex::eval(int level) const
368 return bp->eval(level);
371 ex ex::evalf(int level) const
374 return bp->evalf(level);
377 ex ex::subs(const lst & ls, const lst & lr) const
380 return bp->subs(ls,lr);
383 ex ex::subs(const ex & e) const
389 exvector ex::get_indices(void) const
392 return bp->get_indices();
395 ex ex::simplify_ncmul(const exvector & v) const
398 return bp->simplify_ncmul(v);
401 ex ex::operator[](const ex & index) const
403 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
408 ex ex::operator[](int i) const
410 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
415 ex ex::op(int i) const
417 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
422 ex & ex::let_op(int i)
424 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
427 return bp->let_op(i);
430 #ifndef INLINE_EX_CONSTRUCTORS
431 int ex::compare(const ex & other) const
434 GINAC_ASSERT(other.bp!=0);
436 // special case: both expression point to same basic, trivially equal
439 return bp->compare(*other.bp);
441 #endif // ndef INLINE_EX_CONSTRUCTORS
443 #ifndef INLINE_EX_CONSTRUCTORS
444 bool ex::is_equal(const ex & other) const
447 GINAC_ASSERT(other.bp!=0);
449 // special case: both expression point to same basic, trivially equal
452 return bp->is_equal(*other.bp);
454 #endif // ndef INLINE_EX_CONSTRUCTORS
456 unsigned ex::return_type(void) const
459 return bp->return_type();
462 unsigned ex::return_type_tinfo(void) const
465 return bp->return_type_tinfo();
468 unsigned ex::gethash(void) const
471 return bp->gethash();
474 ex ex::exadd(const ex & rh) const
476 return (new add(*this,rh))->setflag(status_flags::dynallocated);
479 ex ex::exmul(const ex & rh) const
481 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
484 ex ex::exncmul(const ex & rh) const
486 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
491 void ex::makewriteable()
493 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
495 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
496 if (bp->refcount > 1) {
497 basic * bp2 = bp->duplicate();
499 bp2->setflag(status_flags::dynallocated);
503 GINAC_ASSERT(bp->refcount == 1);
506 void ex::construct_from_basic(const basic & other)
508 if ((other.flags & status_flags::evaluated)==0) {
509 // cf. copy constructor
510 const ex & tmpex = other.eval(1); // evaluate only one (top) level
513 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
515 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
516 delete &const_cast<basic &>(other);
519 if (other.flags & status_flags::dynallocated) {
520 bp = &const_cast<basic &>(other);
522 bp = other.duplicate();
523 bp->setflag(status_flags::dynallocated);
526 // bp->clearflag(status_flags::evaluated);
530 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
533 void ex::construct_from_int(int i)
535 switch (i) { // some tiny efficiency-hack
558 bp->setflag(status_flags::dynallocated);
560 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
561 GINAC_ASSERT(bp->refcount=1);
565 void ex::construct_from_uint(unsigned int i)
567 switch (i) { // some tiny efficiency-hack
590 bp->setflag(status_flags::dynallocated);
592 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
593 GINAC_ASSERT(bp->refcount=1);
597 void ex::construct_from_long(long i)
599 switch (i) { // some tiny efficiency-hack
622 bp->setflag(status_flags::dynallocated);
624 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
625 GINAC_ASSERT(bp->refcount=1);
629 void ex::construct_from_ulong(unsigned long i)
631 switch (i) { // some tiny efficiency-hack
654 bp->setflag(status_flags::dynallocated);
656 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
657 GINAC_ASSERT(bp->refcount=1);
661 void ex::construct_from_double(double d)
664 bp->setflag(status_flags::dynallocated);
666 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
667 GINAC_ASSERT(bp->refcount=1);
671 // static member variables
677 // functions which are not member functions
689 #ifndef NO_NAMESPACE_GINAC
691 #endif // ndef NO_NAMESPACE_GINAC