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
33 #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 ex ex::expand(unsigned options) const
118 if (options == 0 && (bp->flags & status_flags::expanded)) // The "expanded" flag only covers the standard options; someone might want to re-expand with different options
121 return bp->expand(options);
124 /** Compute partial derivative of an expression.
126 * @param s symbol by which the expression is derived
127 * @param nth order of derivative (default 1)
128 * @return partial derivative as a new expression */
129 ex ex::diff(const symbol & s, unsigned nth) const
136 return bp->diff(s, nth);
139 /** Check whether expression matches a specified pattern. */
140 bool ex::match(const ex & pattern) const
143 return bp->match(pattern, repl_lst);
146 /** Find all occurrences of a pattern. The found matches are appended to
147 * the "found" list. If the expression itself matches the pattern, the
148 * children are not further examined. This function returns true when any
149 * matches were found. */
150 bool ex::find(const ex & pattern, lst & found) const
152 if (match(pattern)) {
158 bool any_found = false;
159 for (unsigned i=0; i<nops(); i++)
160 if (op(i).find(pattern, found))
165 ex ex::operator[](const ex & index) const
167 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
172 ex ex::operator[](int i) const
174 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
179 /** Return modifyable operand/member at position i. */
180 ex & ex::let_op(int i)
182 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
185 return bp->let_op(i);
188 /** Left hand side of relational expression. */
189 ex ex::lhs(void) const
191 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
192 if (!is_ex_of_type(*this,relational))
193 throw std::runtime_error("ex::lhs(): not a relation");
194 return (*static_cast<relational *>(bp)).lhs();
197 /** Right hand side of relational expression. */
198 ex ex::rhs(void) const
200 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
201 if (!is_ex_of_type(*this,relational))
202 throw std::runtime_error("ex::rhs(): not a relation");
203 return (*static_cast<relational *>(bp)).rhs();
208 /** Make this ex writable (if more than one ex handle the same basic) by
209 * unlinking the object and creating an unshared copy of it. */
210 void ex::makewriteable()
212 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
214 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
215 if (bp->refcount > 1) {
216 basic * bp2 = bp->duplicate();
218 bp2->setflag(status_flags::dynallocated);
222 GINAC_ASSERT(bp->refcount==1);
225 /** Ctor from basic implementation.
226 * @see ex::ex(const basic &) */
227 void ex::construct_from_basic(const basic & other)
229 if (!(other.flags & status_flags::evaluated)) {
230 const ex & tmpex(other.eval(1)); // evaluate only one (top) level
232 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
234 if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
235 delete &const_cast<basic &>(other);
237 if (other.flags & status_flags::dynallocated) {
238 // ok, it is already on the heap, so just copy bp:
239 bp = &const_cast<basic &>(other);
241 // create a duplicate on the heap:
242 bp = other.duplicate();
243 bp->setflag(status_flags::dynallocated);
249 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
252 void ex::construct_from_int(int i)
254 switch (i) { // some tiny efficiency-hack
277 bp->setflag(status_flags::dynallocated);
279 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
280 GINAC_ASSERT(bp->refcount==1);
284 void ex::construct_from_uint(unsigned int i)
286 switch (i) { // some tiny efficiency-hack
301 bp->setflag(status_flags::dynallocated);
303 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
304 GINAC_ASSERT(bp->refcount==1);
308 void ex::construct_from_long(long i)
310 switch (i) { // some tiny efficiency-hack
333 bp->setflag(status_flags::dynallocated);
335 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
336 GINAC_ASSERT(bp->refcount==1);
340 void ex::construct_from_ulong(unsigned long i)
342 switch (i) { // some tiny efficiency-hack
357 bp->setflag(status_flags::dynallocated);
359 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
360 GINAC_ASSERT(bp->refcount==1);
364 void ex::construct_from_double(double d)
367 bp->setflag(status_flags::dynallocated);
369 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
370 GINAC_ASSERT(bp->refcount==1);
373 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
376 set_lexer_symbols(l);
377 ginac_yyrestart(NULL);
379 throw (std::runtime_error(get_parser_error()));
383 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
389 // static member variables
395 // functions which are not member functions