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"
41 #include "input_lexer.h"
54 // functions overriding virtual functions from bases classes
60 // new virtual functions which can be overridden by derived classes
66 // non-virtual functions in this class
71 /** Efficiently swap the contents of two expressions. */
72 void ex::swap(ex & other)
74 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
77 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
78 GINAC_ASSERT(other.bp!=0);
79 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
86 /** Output formatted to be useful as ginsh input. */
87 void ex::print(std::ostream & os, unsigned upper_precedence) const
89 debugmsg("ex print",LOGLEVEL_PRINT);
91 bp->print(os,upper_precedence);
94 /** Unreadable output with detailed type information. */
95 void ex::printraw(std::ostream & os) const
97 debugmsg("ex printraw",LOGLEVEL_PRINT);
104 /** Very detailed and unreadable output with type information and all this. */
105 void ex::printtree(std::ostream & os, unsigned indent) const
107 debugmsg("ex printtree",LOGLEVEL_PRINT);
109 // os << "refcount=" << bp->refcount << " ";
110 bp->printtree(os,indent);
113 /** Print expression as a C++ statement. The output looks like
114 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
115 * on how number literals are printed.
117 * @param os output stream
118 * @param type variable type (one of the csrc_types)
119 * @param var_name variable name to be printed */
120 void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const
122 debugmsg("ex print csrc", LOGLEVEL_PRINT);
125 case csrc_types::ctype_float:
128 case csrc_types::ctype_double:
131 case csrc_types::ctype_cl_N:
135 os << var_name << " = ";
136 bp->printcsrc(os, type, 0);
140 /** Little wrapper arount print to be called within a debugger. */
141 void ex::dbgprint(void) const
143 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
148 /** Little wrapper arount printtree to be called within a debugger. */
149 void ex::dbgprinttree(void) const
151 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
156 bool ex::info(unsigned inf) const
158 return bp->info(inf);
161 unsigned ex::nops() const
167 ex ex::expand(unsigned options) const
170 if (bp->flags & status_flags::expanded)
173 return bp->expand(options);
176 bool ex::has(const ex & other) const
179 return bp->has(other);
182 int ex::degree(const ex & s) const
185 return bp->degree(s);
188 int ex::ldegree(const ex & s) const
191 return bp->ldegree(s);
194 ex ex::coeff(const ex & s, int n) const
197 return bp->coeff(s,n);
200 ex ex::collect(const ex & s) const
203 return bp->collect(s);
206 ex ex::eval(int level) const
209 return bp->eval(level);
212 ex ex::evalf(int level) const
215 return bp->evalf(level);
218 /** Compute partial derivative of an expression.
220 * @param s symbol by which the expression is derived
221 * @param nth order of derivative (default 1)
222 * @return partial derivative as a new expression */
223 ex ex::diff(const symbol & s, unsigned nth) const
230 return bp->diff(s, nth);
233 ex ex::subs(const lst & ls, const lst & lr) const
236 return bp->subs(ls,lr);
239 ex ex::subs(const ex & e) const
245 /** Return a vector containing the free indices of the object. */
246 exvector ex::get_free_indices(void) const
249 return bp->get_free_indices();
252 /** Simplify/canonicalize expression containing indexed objects. This
253 * performs contraction of dummy indices where possible and checks whether
254 * the free indices in sums are consistent.
256 * @return simplified expression */
257 ex ex::simplify_indexed(void) const
259 return GiNaC::simplify_indexed(*this);
262 /** Simplify/canonicalize expression containing indexed objects. This
263 * performs contraction of dummy indices where possible, checks whether
264 * the free indices in sums are consistent, and automatically replaces
265 * scalar products by known values if desired.
267 * @param sp Scalar products to be replaced automatically
268 * @return simplified expression */
269 ex ex::simplify_indexed(const scalar_products & sp) const
271 return GiNaC::simplify_indexed(*this, sp);
274 ex ex::simplify_ncmul(const exvector & v) const
277 return bp->simplify_ncmul(v);
280 ex ex::operator[](const ex & index) const
282 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
287 ex ex::operator[](int i) const
289 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
294 /** Return operand/member at position i. */
295 ex ex::op(int i) const
297 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
302 /** Return modifyable operand/member at position i. */
303 ex & ex::let_op(int i)
305 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
308 return bp->let_op(i);
311 /** Left hand side of relational expression. */
312 ex ex::lhs(void) const
314 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
315 GINAC_ASSERT(is_ex_of_type(*this,relational));
316 return (*static_cast<relational *>(bp)).lhs();
319 /** Right hand side of relational expression. */
320 ex ex::rhs(void) const
322 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
323 GINAC_ASSERT(is_ex_of_type(*this,relational));
324 return (*static_cast<relational *>(bp)).rhs();
327 unsigned ex::return_type(void) const
330 return bp->return_type();
333 unsigned ex::return_type_tinfo(void) const
336 return bp->return_type_tinfo();
339 unsigned ex::gethash(void) const
342 return bp->gethash();
345 /** Used internally by operator+() to add two ex objects together. */
346 ex ex::exadd(const ex & rh) const
348 return (new add(*this,rh))->setflag(status_flags::dynallocated);
351 /** Used internally by operator*() to multiply two ex objects together. */
352 ex ex::exmul(const ex & rh) const
354 // Check if we are constructing a mul object or a ncmul object. Due to
355 // ncmul::eval()'s rule to pull out commutative elements we need to check
356 // only one of the elements.
357 if (rh.bp->return_type()==return_types::commutative ||
358 bp->return_type()==return_types::commutative)
359 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
361 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
366 /** Make this ex writable (if more than one ex handle the same basic) by
367 * unlinking the object and creating an unshared copy of it. */
368 void ex::makewriteable()
370 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
372 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
373 if (bp->refcount > 1) {
374 basic * bp2 = bp->duplicate();
376 bp2->setflag(status_flags::dynallocated);
380 GINAC_ASSERT(bp->refcount==1);
383 /** Ctor from basic implementation.
384 * @see ex::ex(const basic &) */
385 void ex::construct_from_basic(const basic & other)
387 if ((other.flags & status_flags::evaluated)==0) {
389 const ex & tmpex = other.eval(1); // evaluate only one (top) level
392 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
394 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
395 delete &const_cast<basic &>(other);
397 if (other.flags & status_flags::dynallocated) {
398 // ok, it is already on the heap, so just copy bp:
399 bp = &const_cast<basic &>(other);
401 // create a duplicate on the heap:
402 bp = other.duplicate();
403 bp->setflag(status_flags::dynallocated);
406 // bp->clearflag(status_flags::evaluated);
410 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
413 void ex::construct_from_int(int i)
415 switch (i) { // some tiny efficiency-hack
438 bp->setflag(status_flags::dynallocated);
440 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
441 GINAC_ASSERT(bp->refcount==1);
445 void ex::construct_from_uint(unsigned int i)
447 switch (i) { // some tiny efficiency-hack
462 bp->setflag(status_flags::dynallocated);
464 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
465 GINAC_ASSERT(bp->refcount==1);
469 void ex::construct_from_long(long i)
471 switch (i) { // some tiny efficiency-hack
494 bp->setflag(status_flags::dynallocated);
496 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
497 GINAC_ASSERT(bp->refcount==1);
501 void ex::construct_from_ulong(unsigned long i)
503 switch (i) { // some tiny efficiency-hack
518 bp->setflag(status_flags::dynallocated);
520 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
521 GINAC_ASSERT(bp->refcount==1);
525 void ex::construct_from_double(double d)
528 bp->setflag(status_flags::dynallocated);
530 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
531 GINAC_ASSERT(bp->refcount==1);
534 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
537 set_lexer_symbols(l);
538 ginac_yyrestart(NULL);
540 throw (std::runtime_error(get_parser_error()));
544 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
550 // static member variables
556 // functions which are not member functions