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)
91 #endif // ndef INLINE_EX_CONSTRUCTORS
99 #ifndef INLINE_EX_CONSTRUCTORS
101 ex::ex(const basic & other)
103 debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
104 construct_from_basic(other);
109 debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
110 construct_from_int(i);
113 ex::ex(unsigned int i)
115 debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
116 construct_from_uint(i);
121 debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
122 construct_from_long(i);
125 ex::ex(unsigned long i)
127 debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
128 construct_from_ulong(i);
131 ex::ex(double const d)
133 debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
134 construct_from_double(d);
137 ex::ex(const std::string &s, const ex &l)
139 debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT);
140 construct_from_string_and_lst(s, l);
143 #endif // ndef INLINE_EX_CONSTRUCTORS
146 // functions overriding virtual functions from bases classes
152 // new virtual functions which can be overridden by derived classes
158 // non-virtual functions in this class
163 /** Swap the contents of two expressions. */
164 void ex::swap(ex & other)
166 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
169 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
170 GINAC_ASSERT(other.bp!=0);
171 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
178 /** Output formatted to be useful as ginsh input. */
179 void ex::print(std::ostream & os, unsigned upper_precedence) const
181 debugmsg("ex print",LOGLEVEL_PRINT);
183 bp->print(os,upper_precedence);
186 void ex::printraw(std::ostream & os) const
188 debugmsg("ex printraw",LOGLEVEL_PRINT);
195 void ex::printtree(std::ostream & os, unsigned indent) const
197 debugmsg("ex printtree",LOGLEVEL_PRINT);
199 // os << "refcount=" << bp->refcount << " ";
200 bp->printtree(os,indent);
203 /** Print expression as a C++ statement. The output looks like
204 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
205 * on how number literals are printed.
207 * @param os output stream
208 * @param type variable type (one of the csrc_types)
209 * @param var_name variable name to be printed */
210 void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const
212 debugmsg("ex print csrc", LOGLEVEL_PRINT);
215 case csrc_types::ctype_float:
218 case csrc_types::ctype_double:
221 case csrc_types::ctype_cl_N:
225 os << var_name << " = ";
226 bp->printcsrc(os, type, 0);
230 /** Little wrapper arount print to be called within a debugger. */
231 void ex::dbgprint(void) const
233 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
238 /** Little wrapper arount printtree to be called within a debugger. */
239 void ex::dbgprinttree(void) const
241 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
246 bool ex::info(unsigned inf) const
248 return bp->info(inf);
251 unsigned ex::nops() const
257 ex ex::expand(unsigned options) const
260 if (bp->flags & status_flags::expanded)
263 return bp->expand(options);
266 bool ex::has(const ex & other) const
269 return bp->has(other);
272 int ex::degree(const symbol & s) const
275 return bp->degree(s);
278 int ex::ldegree(const symbol & s) const
281 return bp->ldegree(s);
284 ex ex::coeff(const symbol & s, int n) const
287 return bp->coeff(s,n);
290 ex ex::collect(const symbol & s) const
293 return bp->collect(s);
296 ex ex::eval(int level) const
299 return bp->eval(level);
302 ex ex::evalf(int level) const
305 return bp->evalf(level);
308 /** Compute partial derivative of an expression.
310 * @param s symbol by which the expression is derived
311 * @param nth order of derivative (default 1)
312 * @return partial derivative as a new expression */
313 ex ex::diff(const symbol & s, unsigned nth) const
320 return bp->diff(s, nth);
323 ex ex::subs(const lst & ls, const lst & lr) const
326 return bp->subs(ls,lr);
329 ex ex::subs(const ex & e) const
335 exvector ex::get_indices(void) const
338 return bp->get_indices();
341 ex ex::simplify_ncmul(const exvector & v) const
344 return bp->simplify_ncmul(v);
347 ex ex::operator[](const ex & index) const
349 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
354 ex ex::operator[](int i) const
356 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
361 /** Return operand/member at position i. */
362 ex ex::op(int i) const
364 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
369 /** Return modifyable operand/member at position i. */
370 ex & ex::let_op(int i)
372 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
375 return bp->let_op(i);
378 /** Left hand side of relational expression. */
379 ex ex::lhs(void) const
381 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
382 GINAC_ASSERT(is_ex_of_type(*this,relational));
383 return (*static_cast<relational *>(bp)).lhs();
386 /** Right hand side of relational expression. */
387 ex ex::rhs(void) const
389 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
390 GINAC_ASSERT(is_ex_of_type(*this,relational));
391 return (*static_cast<relational *>(bp)).rhs();
394 #ifndef INLINE_EX_CONSTRUCTORS
395 int ex::compare(const ex & other) const
398 GINAC_ASSERT(other.bp!=0);
400 // special case: both expression point to same basic, trivially equal
403 return bp->compare(*other.bp);
405 #endif // ndef INLINE_EX_CONSTRUCTORS
407 #ifndef INLINE_EX_CONSTRUCTORS
408 bool ex::is_equal(const ex & other) const
411 GINAC_ASSERT(other.bp!=0);
412 // if both expression point to same basic they are trivially equal
416 return bp->is_equal(*other.bp);
418 #endif // ndef INLINE_EX_CONSTRUCTORS
420 unsigned ex::return_type(void) const
423 return bp->return_type();
426 unsigned ex::return_type_tinfo(void) const
429 return bp->return_type_tinfo();
432 unsigned ex::gethash(void) const
435 return bp->gethash();
438 ex ex::exadd(const ex & rh) const
440 return (new add(*this,rh))->setflag(status_flags::dynallocated);
443 ex ex::exmul(const ex & rh) const
445 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
448 ex ex::exncmul(const ex & rh) const
450 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
455 void ex::makewriteable()
457 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
459 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
460 if (bp->refcount > 1) {
461 basic * bp2 = bp->duplicate();
463 bp2->setflag(status_flags::dynallocated);
467 GINAC_ASSERT(bp->refcount==1);
470 void ex::construct_from_basic(const basic & other)
472 if ((other.flags & status_flags::evaluated)==0) {
473 // cf. copy constructor
474 const ex & tmpex = other.eval(1); // evaluate only one (top) level
477 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
479 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
480 delete &const_cast<basic &>(other);
483 if (other.flags & status_flags::dynallocated) {
484 // it's on the heap, so just copy bp:
485 bp = &const_cast<basic &>(other);
487 // create a duplicate on the heap:
488 bp = other.duplicate();
489 bp->setflag(status_flags::dynallocated);
492 // bp->clearflag(status_flags::evaluated);
496 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
499 void ex::construct_from_int(int i)
501 switch (i) { // some tiny efficiency-hack
524 bp->setflag(status_flags::dynallocated);
526 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
527 GINAC_ASSERT(bp->refcount==1);
531 void ex::construct_from_uint(unsigned int i)
533 switch (i) { // some tiny efficiency-hack
548 bp->setflag(status_flags::dynallocated);
550 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
551 GINAC_ASSERT(bp->refcount==1);
555 void ex::construct_from_long(long i)
557 switch (i) { // some tiny efficiency-hack
580 bp->setflag(status_flags::dynallocated);
582 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
583 GINAC_ASSERT(bp->refcount==1);
587 void ex::construct_from_ulong(unsigned long i)
589 switch (i) { // some tiny efficiency-hack
604 bp->setflag(status_flags::dynallocated);
606 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
607 GINAC_ASSERT(bp->refcount==1);
611 void ex::construct_from_double(double d)
614 bp->setflag(status_flags::dynallocated);
616 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
617 GINAC_ASSERT(bp->refcount==1);
620 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
623 set_lexer_symbols(l);
624 ginac_yyrestart(NULL);
626 throw (std::runtime_error(get_parser_error()));
630 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
636 // static member variables
642 // functions which are not member functions
654 #ifndef NO_NAMESPACE_GINAC
656 #endif // ndef NO_NAMESPACE_GINAC