3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2001 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
27 # define GINAC_CONDITIONAL_INLINE
29 # undef GINAC_CONDITIONAL_INLINE
39 #include "relational.h"
40 #include "input_lexer.h"
53 // functions overriding virtual functions from bases classes
59 // new virtual functions which can be overridden by derived classes
65 // non-virtual functions in this class
70 /** Efficiently swap the contents of two expressions. */
71 void ex::swap(ex & other)
73 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
76 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
77 GINAC_ASSERT(other.bp!=0);
78 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
85 /** Output formatted to be useful as ginsh input. */
86 void ex::print(std::ostream & os, unsigned upper_precedence) const
88 debugmsg("ex print",LOGLEVEL_PRINT);
90 bp->print(os,upper_precedence);
93 /** Unreadable output with detailed type information. */
94 void ex::printraw(std::ostream & os) const
96 debugmsg("ex printraw",LOGLEVEL_PRINT);
103 /** Very detailed and unreadable output with type information and all this. */
104 void ex::printtree(std::ostream & os, unsigned indent) const
106 debugmsg("ex printtree",LOGLEVEL_PRINT);
108 // os << "refcount=" << bp->refcount << " ";
109 bp->printtree(os,indent);
112 /** Print expression as a C++ statement. The output looks like
113 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
114 * on how number literals are printed.
116 * @param os output stream
117 * @param type variable type (one of the csrc_types)
118 * @param var_name variable name to be printed */
119 void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const
121 debugmsg("ex print csrc", LOGLEVEL_PRINT);
124 case csrc_types::ctype_float:
127 case csrc_types::ctype_double:
130 case csrc_types::ctype_cl_N:
134 os << var_name << " = ";
135 bp->printcsrc(os, type, 0);
139 /** Little wrapper arount print to be called within a debugger. */
140 void ex::dbgprint(void) const
142 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
147 /** Little wrapper arount printtree to be called within a debugger. */
148 void ex::dbgprinttree(void) const
150 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
155 bool ex::info(unsigned inf) const
157 return bp->info(inf);
160 unsigned ex::nops() const
166 ex ex::expand(unsigned options) const
169 if (bp->flags & status_flags::expanded)
172 return bp->expand(options);
175 bool ex::has(const ex & other) const
178 return bp->has(other);
181 int ex::degree(const symbol & s) const
184 return bp->degree(s);
187 int ex::ldegree(const symbol & s) const
190 return bp->ldegree(s);
193 ex ex::coeff(const symbol & s, int n) const
196 return bp->coeff(s,n);
199 ex ex::collect(const symbol & s) const
202 return bp->collect(s);
205 ex ex::eval(int level) const
208 return bp->eval(level);
211 ex ex::evalf(int level) const
214 return bp->evalf(level);
217 /** Compute partial derivative of an expression.
219 * @param s symbol by which the expression is derived
220 * @param nth order of derivative (default 1)
221 * @return partial derivative as a new expression */
222 ex ex::diff(const symbol & s, unsigned nth) const
229 return bp->diff(s, nth);
232 ex ex::subs(const lst & ls, const lst & lr) const
235 return bp->subs(ls,lr);
238 ex ex::subs(const ex & e) const
244 exvector ex::get_indices(void) const
247 return bp->get_indices();
250 ex ex::simplify_ncmul(const exvector & v) const
253 return bp->simplify_ncmul(v);
256 ex ex::operator[](const ex & index) const
258 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
263 ex ex::operator[](int i) const
265 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
270 /** Return operand/member at position i. */
271 ex ex::op(int i) const
273 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
278 /** Return modifyable operand/member at position i. */
279 ex & ex::let_op(int i)
281 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
284 return bp->let_op(i);
287 /** Left hand side of relational expression. */
288 ex ex::lhs(void) const
290 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
291 GINAC_ASSERT(is_ex_of_type(*this,relational));
292 return (*static_cast<relational *>(bp)).lhs();
295 /** Right hand side of relational expression. */
296 ex ex::rhs(void) const
298 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
299 GINAC_ASSERT(is_ex_of_type(*this,relational));
300 return (*static_cast<relational *>(bp)).rhs();
303 unsigned ex::return_type(void) const
306 return bp->return_type();
309 unsigned ex::return_type_tinfo(void) const
312 return bp->return_type_tinfo();
315 unsigned ex::gethash(void) const
318 return bp->gethash();
321 ex ex::exadd(const ex & rh) const
323 return (new add(*this,rh))->setflag(status_flags::dynallocated);
326 ex ex::exmul(const ex & rh) const
328 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
331 ex ex::exncmul(const ex & rh) const
333 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
338 /** Make this ex writable (if more than one ex handle the same basic) by
339 * unlinking the object and creating an unshared copy of it. */
340 void ex::makewriteable()
342 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
344 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
345 if (bp->refcount > 1) {
346 basic * bp2 = bp->duplicate();
348 bp2->setflag(status_flags::dynallocated);
352 GINAC_ASSERT(bp->refcount==1);
355 /** Ctor from basic implementation.
356 * @see ex::ex(const basic &) */
357 void ex::construct_from_basic(const basic & other)
359 if ((other.flags & status_flags::evaluated)==0) {
361 const ex & tmpex = other.eval(1); // evaluate only one (top) level
364 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
366 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
367 delete &const_cast<basic &>(other);
369 if (other.flags & status_flags::dynallocated) {
370 // ok, it is already on the heap, so just copy bp:
371 bp = &const_cast<basic &>(other);
373 // create a duplicate on the heap:
374 bp = other.duplicate();
375 bp->setflag(status_flags::dynallocated);
378 // bp->clearflag(status_flags::evaluated);
382 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
385 void ex::construct_from_int(int i)
387 switch (i) { // some tiny efficiency-hack
410 bp->setflag(status_flags::dynallocated);
412 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
413 GINAC_ASSERT(bp->refcount==1);
417 void ex::construct_from_uint(unsigned int i)
419 switch (i) { // some tiny efficiency-hack
434 bp->setflag(status_flags::dynallocated);
436 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
437 GINAC_ASSERT(bp->refcount==1);
441 void ex::construct_from_long(long i)
443 switch (i) { // some tiny efficiency-hack
466 bp->setflag(status_flags::dynallocated);
468 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
469 GINAC_ASSERT(bp->refcount==1);
473 void ex::construct_from_ulong(unsigned long i)
475 switch (i) { // some tiny efficiency-hack
490 bp->setflag(status_flags::dynallocated);
492 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
493 GINAC_ASSERT(bp->refcount==1);
497 void ex::construct_from_double(double d)
500 bp->setflag(status_flags::dynallocated);
502 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
503 GINAC_ASSERT(bp->refcount==1);
506 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
509 set_lexer_symbols(l);
510 ginac_yyrestart(NULL);
512 throw (std::runtime_error(get_parser_error()));
516 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
522 // static member variables
528 // functions which are not member functions