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
32 #include "relational.h"
33 #include "input_lexer.h"
37 #ifndef NO_NAMESPACE_GINAC
39 #endif // ndef NO_NAMESPACE_GINAC
42 // default constructor, destructor, copy constructor assignment operator and helpers
47 #ifndef INLINE_EX_CONSTRUCTORS
49 ex::ex() : bp(_ex0().bp)
51 debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
52 GINAC_ASSERT(_ex0().bp!=0);
53 GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated);
60 debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
62 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
63 if (--bp->refcount == 0) {
68 ex::ex(const ex & other) : bp(other.bp)
70 debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
72 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
76 const ex & ex::operator=(const ex & other)
78 debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
80 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
81 GINAC_ASSERT(other.bp!=0);
82 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
84 basic * tmpbp=other.bp;
85 if (--bp->refcount==0) {
92 #endif // ndef INLINE_EX_CONSTRUCTORS
100 #ifndef INLINE_EX_CONSTRUCTORS
102 ex::ex(const basic & other)
104 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
105 construct_from_basic(other);
110 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
111 construct_from_int(i);
114 ex::ex(unsigned int i)
116 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
117 construct_from_uint(i);
122 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
123 construct_from_long(i);
126 ex::ex(unsigned long i)
128 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
129 construct_from_ulong(i);
132 ex::ex(double const d)
134 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
135 construct_from_double(d);
138 ex::ex(const std::string &s, const ex &l)
140 debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT);
141 construct_from_string_and_lst(s, l);
144 #endif // ndef INLINE_EX_CONSTRUCTORS
147 // functions overriding virtual functions from bases classes
153 // new virtual functions which can be overridden by derived classes
159 // non-virtual functions in this class
164 /** Swap the contents of two expressions. */
165 void ex::swap(ex & other)
167 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
170 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
171 GINAC_ASSERT(other.bp!=0);
172 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
179 /** Output formatted to be useful as ginsh input. */
180 void ex::print(std::ostream & os, unsigned upper_precedence) const
182 debugmsg("ex print",LOGLEVEL_PRINT);
184 bp->print(os,upper_precedence);
187 void ex::printraw(std::ostream & os) const
189 debugmsg("ex printraw",LOGLEVEL_PRINT);
196 void ex::printtree(std::ostream & os, unsigned indent) const
198 debugmsg("ex printtree",LOGLEVEL_PRINT);
200 // os << "refcount=" << bp->refcount << " ";
201 bp->printtree(os,indent);
204 /** Print expression as a C++ statement. The output looks like
205 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
206 * on how number literals are printed.
208 * @param os output stream
209 * @param type variable type (one of the csrc_types)
210 * @param var_name variable name to be printed */
211 void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const
213 debugmsg("ex print csrc", LOGLEVEL_PRINT);
216 case csrc_types::ctype_float:
219 case csrc_types::ctype_double:
222 case csrc_types::ctype_cl_N:
226 os << var_name << " = ";
227 bp->printcsrc(os, type, 0);
231 /** Little wrapper arount print to be called within a debugger. */
232 void ex::dbgprint(void) const
234 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
239 /** Little wrapper arount printtree to be called within a debugger. */
240 void ex::dbgprinttree(void) const
242 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
247 bool ex::info(unsigned inf) const
249 return bp->info(inf);
252 unsigned ex::nops() const
258 ex ex::expand(unsigned options) const
261 if (bp->flags & status_flags::expanded)
264 return bp->expand(options);
267 bool ex::has(const ex & other) const
270 return bp->has(other);
273 int ex::degree(const symbol & s) const
276 return bp->degree(s);
279 int ex::ldegree(const symbol & s) const
282 return bp->ldegree(s);
285 ex ex::coeff(const symbol & s, int n) const
288 return bp->coeff(s,n);
291 ex ex::collect(const symbol & s) const
294 return bp->collect(s);
297 ex ex::eval(int level) const
300 return bp->eval(level);
303 ex ex::evalf(int level) const
306 return bp->evalf(level);
309 /** Compute partial derivative of an expression.
311 * @param s symbol by which the expression is derived
312 * @param nth order of derivative (default 1)
313 * @return partial derivative as a new expression */
314 ex ex::diff(const symbol & s, unsigned nth) const
321 return bp->diff(s, nth);
324 ex ex::subs(const lst & ls, const lst & lr) const
327 return bp->subs(ls,lr);
330 ex ex::subs(const ex & e) const
336 exvector ex::get_indices(void) const
339 return bp->get_indices();
342 ex ex::simplify_ncmul(const exvector & v) const
345 return bp->simplify_ncmul(v);
348 ex ex::operator[](const ex & index) const
350 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
355 ex ex::operator[](int i) const
357 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
362 /** Return operand/member at position i. */
363 ex ex::op(int i) const
365 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
370 /** Return modifyable operand/member at position i. */
371 ex & ex::let_op(int i)
373 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
376 return bp->let_op(i);
379 /** Left hand side of relational expression. */
380 ex ex::lhs(void) const
382 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
383 GINAC_ASSERT(is_ex_of_type(*this,relational));
384 return (*static_cast<relational *>(bp)).lhs();
387 /** Right hand side of relational expression. */
388 ex ex::rhs(void) const
390 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
391 GINAC_ASSERT(is_ex_of_type(*this,relational));
392 return (*static_cast<relational *>(bp)).rhs();
395 #ifndef INLINE_EX_CONSTRUCTORS
396 int ex::compare(const ex & other) const
399 GINAC_ASSERT(other.bp!=0);
401 // special case: both expression point to same basic, trivially equal
404 return bp->compare(*other.bp);
406 #endif // ndef INLINE_EX_CONSTRUCTORS
408 #ifndef INLINE_EX_CONSTRUCTORS
409 bool ex::is_equal(const ex & other) const
412 GINAC_ASSERT(other.bp!=0);
413 // if both expression point to same basic they are trivially equal
417 return bp->is_equal(*other.bp);
419 #endif // ndef INLINE_EX_CONSTRUCTORS
421 unsigned ex::return_type(void) const
424 return bp->return_type();
427 unsigned ex::return_type_tinfo(void) const
430 return bp->return_type_tinfo();
433 unsigned ex::gethash(void) const
436 return bp->gethash();
439 ex ex::exadd(const ex & rh) const
441 return (new add(*this,rh))->setflag(status_flags::dynallocated);
444 ex ex::exmul(const ex & rh) const
446 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
449 ex ex::exncmul(const ex & rh) const
451 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
456 void ex::makewriteable()
458 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
460 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
461 if (bp->refcount > 1) {
462 basic * bp2 = bp->duplicate();
464 bp2->setflag(status_flags::dynallocated);
468 GINAC_ASSERT(bp->refcount == 1);
471 void ex::construct_from_basic(const basic & other)
473 if ((other.flags & status_flags::evaluated)==0) {
474 // cf. copy constructor
475 const ex & tmpex = other.eval(1); // evaluate only one (top) level
478 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
480 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
481 delete &const_cast<basic &>(other);
484 if (other.flags & status_flags::dynallocated) {
485 // it's on the heap, so just copy bp:
486 bp = &const_cast<basic &>(other);
488 // create a duplicate on the heap:
489 bp = other.duplicate();
490 bp->setflag(status_flags::dynallocated);
493 // bp->clearflag(status_flags::evaluated);
497 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
500 void ex::construct_from_int(int i)
502 switch (i) { // some tiny efficiency-hack
525 bp->setflag(status_flags::dynallocated);
527 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
528 GINAC_ASSERT(bp->refcount=1);
532 void ex::construct_from_uint(unsigned int i)
534 switch (i) { // some tiny efficiency-hack
557 bp->setflag(status_flags::dynallocated);
559 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
560 GINAC_ASSERT(bp->refcount=1);
564 void ex::construct_from_long(long i)
566 switch (i) { // some tiny efficiency-hack
589 bp->setflag(status_flags::dynallocated);
591 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
592 GINAC_ASSERT(bp->refcount=1);
596 void ex::construct_from_ulong(unsigned long i)
598 switch (i) { // some tiny efficiency-hack
621 bp->setflag(status_flags::dynallocated);
623 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
624 GINAC_ASSERT(bp->refcount=1);
628 void ex::construct_from_double(double d)
631 bp->setflag(status_flags::dynallocated);
633 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
634 GINAC_ASSERT(bp->refcount=1);
637 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
640 set_lexer_symbols(l);
641 ginac_yyrestart(NULL);
643 throw (std::runtime_error(get_parser_error()));
647 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
653 // static member variables
659 // functions which are not member functions
671 #ifndef NO_NAMESPACE_GINAC
673 #endif // ndef NO_NAMESPACE_GINAC