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 return bp->expand(options);
256 bool ex::has(const ex & other) const
259 return bp->has(other);
262 int ex::degree(const symbol & s) const
265 return bp->degree(s);
268 int ex::ldegree(const symbol & s) const
271 return bp->ldegree(s);
274 ex ex::coeff(const symbol & s, int n) const
277 return bp->coeff(s,n);
280 ex ex::collect(const symbol & s) const
283 return bp->collect(s);
286 ex ex::eval(int level) const
289 return bp->eval(level);
292 ex ex::evalf(int level) const
295 return bp->evalf(level);
298 /** Compute partial derivative of an expression.
300 * @param s symbol by which the expression is derived
301 * @param nth order of derivative (default 1)
302 * @return partial derivative as a new expression */
303 ex ex::diff(const symbol & s, unsigned nth) const
310 return bp->diff(s, nth);
313 ex ex::subs(const lst & ls, const lst & lr) const
316 return bp->subs(ls,lr);
319 ex ex::subs(const ex & e) const
325 exvector ex::get_indices(void) const
328 return bp->get_indices();
331 ex ex::simplify_ncmul(const exvector & v) const
334 return bp->simplify_ncmul(v);
337 ex ex::operator[](const ex & index) const
339 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
344 ex ex::operator[](int i) const
346 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
351 /** Return operand/member at position i. */
352 ex ex::op(int i) const
354 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
359 /** Return modifyable operand/member at position i. */
360 ex & ex::let_op(int i)
362 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
365 return bp->let_op(i);
368 /** Left hand side of relational expression. */
369 ex ex::lhs(void) const
371 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
372 GINAC_ASSERT(is_ex_of_type(*this,relational));
373 return (*static_cast<relational *>(bp)).lhs();
376 /** Right hand side of relational expression. */
377 ex ex::rhs(void) const
379 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
380 GINAC_ASSERT(is_ex_of_type(*this,relational));
381 return (*static_cast<relational *>(bp)).rhs();
384 #ifndef INLINE_EX_CONSTRUCTORS
385 int ex::compare(const ex & other) const
388 GINAC_ASSERT(other.bp!=0);
390 // special case: both expression point to same basic, trivially equal
393 return bp->compare(*other.bp);
395 #endif // ndef INLINE_EX_CONSTRUCTORS
397 #ifndef INLINE_EX_CONSTRUCTORS
398 bool ex::is_equal(const ex & other) const
401 GINAC_ASSERT(other.bp!=0);
403 // special case: both expression point to same basic, trivially equal
406 return bp->is_equal(*other.bp);
408 #endif // ndef INLINE_EX_CONSTRUCTORS
410 unsigned ex::return_type(void) const
413 return bp->return_type();
416 unsigned ex::return_type_tinfo(void) const
419 return bp->return_type_tinfo();
422 unsigned ex::gethash(void) const
425 return bp->gethash();
428 ex ex::exadd(const ex & rh) const
430 return (new add(*this,rh))->setflag(status_flags::dynallocated);
433 ex ex::exmul(const ex & rh) const
435 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
438 ex ex::exncmul(const ex & rh) const
440 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
445 void ex::makewriteable()
447 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
449 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
450 if (bp->refcount > 1) {
451 basic * bp2 = bp->duplicate();
453 bp2->setflag(status_flags::dynallocated);
457 GINAC_ASSERT(bp->refcount == 1);
460 void ex::construct_from_basic(const basic & other)
462 if ((other.flags & status_flags::evaluated)==0) {
463 // cf. copy constructor
464 const ex & tmpex = other.eval(1); // evaluate only one (top) level
467 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
469 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
470 delete &const_cast<basic &>(other);
473 if (other.flags & status_flags::dynallocated) {
474 bp = &const_cast<basic &>(other);
476 bp = other.duplicate();
477 bp->setflag(status_flags::dynallocated);
480 // bp->clearflag(status_flags::evaluated);
484 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
487 void ex::construct_from_int(int i)
489 switch (i) { // some tiny efficiency-hack
512 bp->setflag(status_flags::dynallocated);
514 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
515 GINAC_ASSERT(bp->refcount=1);
519 void ex::construct_from_uint(unsigned int i)
521 switch (i) { // some tiny efficiency-hack
544 bp->setflag(status_flags::dynallocated);
546 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
547 GINAC_ASSERT(bp->refcount=1);
551 void ex::construct_from_long(long i)
553 switch (i) { // some tiny efficiency-hack
576 bp->setflag(status_flags::dynallocated);
578 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
579 GINAC_ASSERT(bp->refcount=1);
583 void ex::construct_from_ulong(unsigned long i)
585 switch (i) { // some tiny efficiency-hack
608 bp->setflag(status_flags::dynallocated);
610 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
611 GINAC_ASSERT(bp->refcount=1);
615 void ex::construct_from_double(double d)
618 bp->setflag(status_flags::dynallocated);
620 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
621 GINAC_ASSERT(bp->refcount=1);
625 // static member variables
631 // functions which are not member functions
643 #ifndef NO_NAMESPACE_GINAC
645 #endif // ndef NO_NAMESPACE_GINAC