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
32 #include "relational.h"
34 #include "input_lexer.h"
47 // functions overriding virtual functions from bases classes
53 // new virtual functions which can be overridden by derived classes
59 // non-virtual functions in this class
64 /** Efficiently swap the contents of two expressions. */
65 void ex::swap(ex & other)
67 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
70 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
71 GINAC_ASSERT(other.bp!=0);
72 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
79 /** Output formatted to be useful as ginsh input. */
80 void ex::print(std::ostream & os, unsigned upper_precedence) const
82 debugmsg("ex print",LOGLEVEL_PRINT);
84 bp->print(os,upper_precedence);
87 /** Unreadable output with detailed type information. */
88 void ex::printraw(std::ostream & os) const
90 debugmsg("ex printraw",LOGLEVEL_PRINT);
97 /** Very detailed and unreadable output with type information and all this. */
98 void ex::printtree(std::ostream & os, unsigned indent) const
100 debugmsg("ex printtree",LOGLEVEL_PRINT);
102 // os << "refcount=" << bp->refcount << " ";
103 bp->printtree(os,indent);
106 /** Print expression as a C++ statement. The output looks like
107 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
108 * on how number literals are printed.
110 * @param os output stream
111 * @param type variable type (one of the csrc_types)
112 * @param var_name variable name to be printed */
113 void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const
115 debugmsg("ex print csrc", LOGLEVEL_PRINT);
118 case csrc_types::ctype_float:
121 case csrc_types::ctype_double:
124 case csrc_types::ctype_cl_N:
128 os << var_name << " = ";
129 bp->printcsrc(os, type, 0);
133 /** Little wrapper arount print to be called within a debugger. */
134 void ex::dbgprint(void) const
136 debugmsg("ex dbgprint",LOGLEVEL_PRINT);
141 /** Little wrapper arount printtree to be called within a debugger. */
142 void ex::dbgprinttree(void) const
144 debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
149 bool ex::info(unsigned inf) const
151 return bp->info(inf);
154 unsigned ex::nops() const
160 ex ex::expand(unsigned options) const
163 if (bp->flags & status_flags::expanded)
166 return bp->expand(options);
169 bool ex::has(const ex & other) const
172 return bp->has(other);
175 int ex::degree(const ex & s) const
178 return bp->degree(s);
181 int ex::ldegree(const ex & s) const
184 return bp->ldegree(s);
187 ex ex::coeff(const ex & s, int n) const
190 return bp->coeff(s,n);
193 ex ex::collect(const ex & s) const
196 return bp->collect(s);
199 ex ex::eval(int level) const
202 return bp->eval(level);
205 ex ex::evalf(int level) const
208 return bp->evalf(level);
211 /** Compute partial derivative of an expression.
213 * @param s symbol by which the expression is derived
214 * @param nth order of derivative (default 1)
215 * @return partial derivative as a new expression */
216 ex ex::diff(const symbol & s, unsigned nth) const
223 return bp->diff(s, nth);
226 ex ex::subs(const lst & ls, const lst & lr) const
229 return bp->subs(ls,lr);
232 ex ex::subs(const ex & e) const
238 /** Return a vector containing the free indices of the object. */
239 exvector ex::get_free_indices(void) const
242 return bp->get_free_indices();
245 /** Simplify/canonicalize expression containing indexed objects. This
246 * performs contraction of dummy indices where possible and checks whether
247 * the free indices in sums are consistent.
249 * @return simplified expression */
250 ex ex::simplify_indexed(void) const
252 return GiNaC::simplify_indexed(*this);
255 /** Simplify/canonicalize expression containing indexed objects. This
256 * performs contraction of dummy indices where possible, checks whether
257 * the free indices in sums are consistent, and automatically replaces
258 * scalar products by known values if desired.
260 * @param sp Scalar products to be replaced automatically
261 * @return simplified expression */
262 ex ex::simplify_indexed(const scalar_products & sp) const
264 return GiNaC::simplify_indexed(*this, sp);
267 ex ex::simplify_ncmul(const exvector & v) const
270 return bp->simplify_ncmul(v);
273 ex ex::operator[](const ex & index) const
275 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
280 ex ex::operator[](int i) const
282 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
287 /** Return operand/member at position i. */
288 ex ex::op(int i) const
290 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
295 /** Return modifyable operand/member at position i. */
296 ex & ex::let_op(int i)
298 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
301 return bp->let_op(i);
304 /** Left hand side of relational expression. */
305 ex ex::lhs(void) const
307 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
308 GINAC_ASSERT(is_ex_of_type(*this,relational));
309 return (*static_cast<relational *>(bp)).lhs();
312 /** Right hand side of relational expression. */
313 ex ex::rhs(void) const
315 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
316 GINAC_ASSERT(is_ex_of_type(*this,relational));
317 return (*static_cast<relational *>(bp)).rhs();
320 unsigned ex::return_type(void) const
323 return bp->return_type();
326 unsigned ex::return_type_tinfo(void) const
329 return bp->return_type_tinfo();
332 unsigned ex::gethash(void) const
335 return bp->gethash();
338 /** Used internally by operator+() to add two ex objects together. */
339 ex ex::exadd(const ex & rh) const
341 return (new add(*this,rh))->setflag(status_flags::dynallocated);
344 /** Used internally by operator*() to multiply two ex objects together. */
345 ex ex::exmul(const ex & rh) const
347 // Check if we are constructing a mul object or a ncmul object. Due to
348 // ncmul::eval()'s rule to pull out commutative elements we need to check
349 // only one of the elements.
350 if (rh.bp->return_type()==return_types::commutative ||
351 bp->return_type()==return_types::commutative)
352 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
354 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
359 /** Make this ex writable (if more than one ex handle the same basic) by
360 * unlinking the object and creating an unshared copy of it. */
361 void ex::makewriteable()
363 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
365 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
366 if (bp->refcount > 1) {
367 basic * bp2 = bp->duplicate();
369 bp2->setflag(status_flags::dynallocated);
373 GINAC_ASSERT(bp->refcount==1);
376 /** Ctor from basic implementation.
377 * @see ex::ex(const basic &) */
378 void ex::construct_from_basic(const basic & other)
380 if ((other.flags & status_flags::evaluated)==0) {
382 const ex & tmpex = other.eval(1); // evaluate only one (top) level
385 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
387 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
388 delete &const_cast<basic &>(other);
390 if (other.flags & status_flags::dynallocated) {
391 // ok, it is already on the heap, so just copy bp:
392 bp = &const_cast<basic &>(other);
394 // create a duplicate on the heap:
395 bp = other.duplicate();
396 bp->setflag(status_flags::dynallocated);
402 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
405 void ex::construct_from_int(int i)
407 switch (i) { // some tiny efficiency-hack
430 bp->setflag(status_flags::dynallocated);
432 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
433 GINAC_ASSERT(bp->refcount==1);
437 void ex::construct_from_uint(unsigned int i)
439 switch (i) { // some tiny efficiency-hack
454 bp->setflag(status_flags::dynallocated);
456 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
457 GINAC_ASSERT(bp->refcount==1);
461 void ex::construct_from_long(long i)
463 switch (i) { // some tiny efficiency-hack
486 bp->setflag(status_flags::dynallocated);
488 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
489 GINAC_ASSERT(bp->refcount==1);
493 void ex::construct_from_ulong(unsigned long i)
495 switch (i) { // some tiny efficiency-hack
510 bp->setflag(status_flags::dynallocated);
512 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
513 GINAC_ASSERT(bp->refcount==1);
517 void ex::construct_from_double(double d)
520 bp->setflag(status_flags::dynallocated);
522 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
523 GINAC_ASSERT(bp->refcount==1);
526 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
529 set_lexer_symbols(l);
530 ginac_yyrestart(NULL);
532 throw (std::runtime_error(get_parser_error()));
536 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
542 // static member variables
548 // functions which are not member functions