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
31 #include "relational.h"
35 #ifndef NO_NAMESPACE_GINAC
37 #endif // ndef NO_NAMESPACE_GINAC
40 // default constructor, destructor, copy constructor assignment operator and helpers
45 #ifndef INLINE_EX_CONSTRUCTORS
47 ex::ex() : bp(ex0().bp)
49 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
50 GINAC_ASSERT(ex0().bp!=0);
51 GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
58 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
60 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
61 if (--bp->refcount == 0) {
66 ex::ex(const ex & other) : bp(other.bp)
68 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
70 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
74 const ex & ex::operator=(const ex & other)
76 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
78 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
79 GINAC_ASSERT(other.bp!=0);
80 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
82 basic * tmpbp=other.bp;
83 if (--bp->refcount==0) {
90 #endif // ndef INLINE_EX_CONSTRUCTORS
98 #ifndef INLINE_EX_CONSTRUCTORS
100 ex::ex(const basic & other)
102 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
103 construct_from_basic(other);
108 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
109 construct_from_int(i);
112 ex::ex(unsigned int i)
114 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
115 construct_from_uint(i);
120 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
121 construct_from_long(i);
124 ex::ex(unsigned long i)
126 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
127 construct_from_ulong(i);
130 ex::ex(double const d)
132 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
133 construct_from_double(d);
136 #endif // ndef INLINE_EX_CONSTRUCTORS
139 // functions overriding virtual functions from bases classes
145 // new virtual functions which can be overridden by derived classes
151 // non-virtual functions in this class
156 /** Swap the contents of two expressions. */
157 void ex::swap(ex & other)
159 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
162 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
163 GINAC_ASSERT(other.bp!=0);
164 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
171 /** Output formatted to be useful as ginsh input. */
172 void ex::print(ostream & os, unsigned upper_precedence) const
174 debugmsg("ex print",LOGLEVEL_PRINT);
176 bp->print(os,upper_precedence);
179 void ex::printraw(ostream & os) const
181 debugmsg("ex printraw",LOGLEVEL_PRINT);
188 void ex::printtree(ostream & os, unsigned indent) const
190 debugmsg("ex printtree",LOGLEVEL_PRINT);
192 // os << "refcount=" << bp->refcount << " ";
193 bp->printtree(os,indent);
196 /** Print expression as a C++ statement. The output looks like
197 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
198 * on how number literals are printed.
200 * @param os output stream
201 * @param type variable type (one of the csrc_types)
202 * @param var_name variable name to be printed */
203 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
205 debugmsg("ex print csrc", LOGLEVEL_PRINT);
208 case csrc_types::ctype_float:
211 case csrc_types::ctype_double:
214 case csrc_types::ctype_cl_N:
218 os << var_name << " = ";
219 bp->printcsrc(os, type, 0);
223 /** Little wrapper arount print to be called within a debugger. */
224 void ex::dbgprint(void) const
226 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
231 /** Little wrapper arount printtree to be called within a debugger. */
232 void ex::dbgprinttree(void) const
234 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
239 bool ex::info(unsigned inf) const
241 return bp->info(inf);
244 unsigned ex::nops() const
250 ex ex::expand(unsigned options) const
253 if (bp->flags & status_flags::expanded)
256 return bp->expand(options);
259 bool ex::has(const ex & other) const
262 return bp->has(other);
265 int ex::degree(const symbol & s) const
268 return bp->degree(s);
271 int ex::ldegree(const symbol & s) const
274 return bp->ldegree(s);
277 ex ex::coeff(const symbol & s, int n) const
280 return bp->coeff(s,n);
283 ex ex::collect(const symbol & s) const
286 return bp->collect(s);
289 ex ex::eval(int level) const
292 return bp->eval(level);
295 ex ex::evalf(int level) const
298 return bp->evalf(level);
301 /** Compute partial derivative of an expression.
303 * @param s symbol by which the expression is derived
304 * @param nth order of derivative (default 1)
305 * @return partial derivative as a new expression */
306 ex ex::diff(const symbol & s, unsigned nth) const
313 return bp->diff(s, nth);
316 ex ex::subs(const lst & ls, const lst & lr) const
319 return bp->subs(ls,lr);
322 ex ex::subs(const ex & e) const
328 exvector ex::get_indices(void) const
331 return bp->get_indices();
334 ex ex::simplify_ncmul(const exvector & v) const
337 return bp->simplify_ncmul(v);
340 ex ex::operator[](const ex & index) const
342 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
347 ex ex::operator[](int i) const
349 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
354 /** Return operand/member at position i. */
355 ex ex::op(int i) const
357 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
362 /** Return modifyable operand/member at position i. */
363 ex & ex::let_op(int i)
365 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
368 return bp->let_op(i);
371 /** Left hand side of relational expression. */
372 ex ex::lhs(void) const
374 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
375 GINAC_ASSERT(is_ex_of_type(*this,relational));
376 return (*static_cast<relational *>(bp)).lhs();
379 /** Right hand side of relational expression. */
380 ex ex::rhs(void) const
382 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
383 GINAC_ASSERT(is_ex_of_type(*this,relational));
384 return (*static_cast<relational *>(bp)).rhs();
387 #ifndef INLINE_EX_CONSTRUCTORS
388 int ex::compare(const ex & other) const
391 GINAC_ASSERT(other.bp!=0);
393 // special case: both expression point to same basic, trivially equal
396 return bp->compare(*other.bp);
398 #endif // ndef INLINE_EX_CONSTRUCTORS
400 #ifndef INLINE_EX_CONSTRUCTORS
401 bool ex::is_equal(const ex & other) const
404 GINAC_ASSERT(other.bp!=0);
406 // special case: both expression point to same basic, trivially equal
409 return bp->is_equal(*other.bp);
411 #endif // ndef INLINE_EX_CONSTRUCTORS
413 unsigned ex::return_type(void) const
416 return bp->return_type();
419 unsigned ex::return_type_tinfo(void) const
422 return bp->return_type_tinfo();
425 unsigned ex::gethash(void) const
428 return bp->gethash();
431 ex ex::exadd(const ex & rh) const
433 return (new add(*this,rh))->setflag(status_flags::dynallocated);
436 ex ex::exmul(const ex & rh) const
438 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
441 ex ex::exncmul(const ex & rh) const
443 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
448 void ex::makewriteable()
450 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
452 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
453 if (bp->refcount > 1) {
454 basic * bp2 = bp->duplicate();
456 bp2->setflag(status_flags::dynallocated);
460 GINAC_ASSERT(bp->refcount == 1);
463 void ex::construct_from_basic(const basic & other)
465 if ((other.flags & status_flags::evaluated)==0) {
466 // cf. copy constructor
467 const ex & tmpex = other.eval(1); // evaluate only one (top) level
470 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
472 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
473 delete &const_cast<basic &>(other);
476 if (other.flags & status_flags::dynallocated) {
477 bp = &const_cast<basic &>(other);
479 bp = other.duplicate();
480 bp->setflag(status_flags::dynallocated);
483 // bp->clearflag(status_flags::evaluated);
487 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
490 void ex::construct_from_int(int i)
492 switch (i) { // some tiny efficiency-hack
515 bp->setflag(status_flags::dynallocated);
517 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
518 GINAC_ASSERT(bp->refcount=1);
522 void ex::construct_from_uint(unsigned int i)
524 switch (i) { // some tiny efficiency-hack
547 bp->setflag(status_flags::dynallocated);
549 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
550 GINAC_ASSERT(bp->refcount=1);
554 void ex::construct_from_long(long i)
556 switch (i) { // some tiny efficiency-hack
579 bp->setflag(status_flags::dynallocated);
581 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
582 GINAC_ASSERT(bp->refcount=1);
586 void ex::construct_from_ulong(unsigned long i)
588 switch (i) { // some tiny efficiency-hack
611 bp->setflag(status_flags::dynallocated);
613 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
614 GINAC_ASSERT(bp->refcount=1);
618 void ex::construct_from_double(double d)
621 bp->setflag(status_flags::dynallocated);
623 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
624 GINAC_ASSERT(bp->refcount=1);
628 // static member variables
634 // functions which are not member functions
646 #ifndef NO_NAMESPACE_GINAC
648 #endif // ndef NO_NAMESPACE_GINAC