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 /** Print expression to stream. The formatting of the output is determined
80 * by the kind of print_context object that is passed. Possible formattings
81 * include ginsh-parsable output (the default), tree-like output for
82 * debugging, and C++ source.
83 * @see print_context */
84 void ex::print(const print_context & c, unsigned level) const
86 debugmsg("ex print", LOGLEVEL_PRINT);
91 /** Print expression to stream in a tree-like format suitable for debugging. */
92 void ex::printtree(std::ostream & os) const
94 debugmsg("ex printtree", LOGLEVEL_PRINT);
96 bp->print(print_tree(os));
99 /** Little wrapper arount print to be called within a debugger. */
100 void ex::dbgprint(void) const
102 debugmsg("ex dbgprint", LOGLEVEL_PRINT);
107 /** Little wrapper arount printtree to be called within a debugger. */
108 void ex::dbgprinttree(void) const
110 debugmsg("ex dbgprinttree", LOGLEVEL_PRINT);
115 bool ex::info(unsigned inf) const
117 return bp->info(inf);
120 unsigned ex::nops() const
126 ex ex::expand(unsigned options) const
129 if (bp->flags & status_flags::expanded)
132 return bp->expand(options);
135 bool ex::has(const ex & other) const
138 return bp->has(other);
141 int ex::degree(const ex & s) const
144 return bp->degree(s);
147 int ex::ldegree(const ex & s) const
150 return bp->ldegree(s);
153 ex ex::coeff(const ex & s, int n) const
156 return bp->coeff(s,n);
159 ex ex::collect(const ex & s) const
162 return bp->collect(s);
165 ex ex::eval(int level) const
168 return bp->eval(level);
171 ex ex::evalf(int level) const
174 return bp->evalf(level);
177 /** Compute partial derivative of an expression.
179 * @param s symbol by which the expression is derived
180 * @param nth order of derivative (default 1)
181 * @return partial derivative as a new expression */
182 ex ex::diff(const symbol & s, unsigned nth) const
189 return bp->diff(s, nth);
192 ex ex::subs(const lst & ls, const lst & lr) const
195 return bp->subs(ls,lr);
198 ex ex::subs(const ex & e) const
204 /** Return a vector containing the free indices of the object. */
205 exvector ex::get_free_indices(void) const
208 return bp->get_free_indices();
211 /** Simplify/canonicalize expression containing indexed objects. This
212 * performs contraction of dummy indices where possible and checks whether
213 * the free indices in sums are consistent.
215 * @return simplified expression */
216 ex ex::simplify_indexed(void) const
218 return GiNaC::simplify_indexed(*this);
221 /** Simplify/canonicalize expression containing indexed objects. This
222 * performs contraction of dummy indices where possible, checks whether
223 * the free indices in sums are consistent, and automatically replaces
224 * scalar products by known values if desired.
226 * @param sp Scalar products to be replaced automatically
227 * @return simplified expression */
228 ex ex::simplify_indexed(const scalar_products & sp) const
230 return GiNaC::simplify_indexed(*this, sp);
233 ex ex::simplify_ncmul(const exvector & v) const
236 return bp->simplify_ncmul(v);
239 ex ex::operator[](const ex & index) const
241 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
246 ex ex::operator[](int i) const
248 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
253 /** Return operand/member at position i. */
254 ex ex::op(int i) const
256 debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
261 /** Return modifyable operand/member at position i. */
262 ex & ex::let_op(int i)
264 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
267 return bp->let_op(i);
270 /** Left hand side of relational expression. */
271 ex ex::lhs(void) const
273 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
274 GINAC_ASSERT(is_ex_of_type(*this,relational));
275 return (*static_cast<relational *>(bp)).lhs();
278 /** Right hand side of relational expression. */
279 ex ex::rhs(void) const
281 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
282 GINAC_ASSERT(is_ex_of_type(*this,relational));
283 return (*static_cast<relational *>(bp)).rhs();
286 unsigned ex::return_type(void) const
289 return bp->return_type();
292 unsigned ex::return_type_tinfo(void) const
295 return bp->return_type_tinfo();
298 unsigned ex::gethash(void) const
301 return bp->gethash();
304 /** Used internally by operator+() to add two ex objects together. */
305 ex ex::exadd(const ex & rh) const
307 return (new add(*this,rh))->setflag(status_flags::dynallocated);
310 /** Used internally by operator*() to multiply two ex objects together. */
311 ex ex::exmul(const ex & rh) const
313 // Check if we are constructing a mul object or a ncmul object. Due to
314 // ncmul::eval()'s rule to pull out commutative elements we need to check
315 // only one of the elements.
316 if (rh.bp->return_type()==return_types::commutative ||
317 bp->return_type()==return_types::commutative)
318 return (new mul(*this,rh))->setflag(status_flags::dynallocated);
320 return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
325 /** Make this ex writable (if more than one ex handle the same basic) by
326 * unlinking the object and creating an unshared copy of it. */
327 void ex::makewriteable()
329 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
331 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
332 if (bp->refcount > 1) {
333 basic * bp2 = bp->duplicate();
335 bp2->setflag(status_flags::dynallocated);
339 GINAC_ASSERT(bp->refcount==1);
342 /** Ctor from basic implementation.
343 * @see ex::ex(const basic &) */
344 void ex::construct_from_basic(const basic & other)
346 if ((other.flags & status_flags::evaluated)==0) {
348 const ex & tmpex = other.eval(1); // evaluate only one (top) level
351 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
353 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
354 delete &const_cast<basic &>(other);
356 if (other.flags & status_flags::dynallocated) {
357 // ok, it is already on the heap, so just copy bp:
358 bp = &const_cast<basic &>(other);
360 // create a duplicate on the heap:
361 bp = other.duplicate();
362 bp->setflag(status_flags::dynallocated);
368 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
371 void ex::construct_from_int(int i)
373 switch (i) { // some tiny efficiency-hack
396 bp->setflag(status_flags::dynallocated);
398 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
399 GINAC_ASSERT(bp->refcount==1);
403 void ex::construct_from_uint(unsigned int i)
405 switch (i) { // some tiny efficiency-hack
420 bp->setflag(status_flags::dynallocated);
422 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
423 GINAC_ASSERT(bp->refcount==1);
427 void ex::construct_from_long(long i)
429 switch (i) { // some tiny efficiency-hack
452 bp->setflag(status_flags::dynallocated);
454 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
455 GINAC_ASSERT(bp->refcount==1);
459 void ex::construct_from_ulong(unsigned long i)
461 switch (i) { // some tiny efficiency-hack
476 bp->setflag(status_flags::dynallocated);
478 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
479 GINAC_ASSERT(bp->refcount==1);
483 void ex::construct_from_double(double d)
486 bp->setflag(status_flags::dynallocated);
488 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
489 GINAC_ASSERT(bp->refcount==1);
492 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
495 set_lexer_symbols(l);
496 ginac_yyrestart(NULL);
498 throw (std::runtime_error(get_parser_error()));
502 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
508 // static member variables
514 // functions which are not member functions