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"
35 #include "input_lexer.h"
48 // functions overriding virtual functions from bases classes
54 // new virtual functions which can be overridden by derived classes
60 // non-virtual functions in this class
65 /** Efficiently swap the contents of two expressions. */
66 void ex::swap(ex & other)
68 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
71 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
72 GINAC_ASSERT(other.bp!=0);
73 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
80 /** Print expression to stream. The formatting of the output is determined
81 * by the kind of print_context object that is passed. Possible formattings
82 * include ginsh-parsable output (the default), tree-like output for
83 * debugging, and C++ source.
84 * @see print_context */
85 void ex::print(const print_context & c, unsigned level) const
87 debugmsg("ex print", LOGLEVEL_PRINT);
92 /** Print expression to stream in a tree-like format suitable for debugging. */
93 void ex::printtree(std::ostream & os) const
95 debugmsg("ex printtree", LOGLEVEL_PRINT);
97 bp->print(print_tree(os));
100 /** Little wrapper arount print to be called within a debugger. */
101 void ex::dbgprint(void) const
103 debugmsg("ex dbgprint", LOGLEVEL_PRINT);
108 /** Little wrapper arount printtree to be called within a debugger. */
109 void ex::dbgprinttree(void) const
111 debugmsg("ex dbgprinttree", LOGLEVEL_PRINT);
116 ex ex::expand(unsigned options) const
119 if (bp->flags & status_flags::expanded)
122 return bp->expand(options);
125 /** Compute partial derivative of an expression.
127 * @param s symbol by which the expression is derived
128 * @param nth order of derivative (default 1)
129 * @return partial derivative as a new expression */
130 ex ex::diff(const symbol & s, unsigned nth) const
137 return bp->diff(s, nth);
140 /** Check whether expression matches a specified pattern. */
141 bool ex::match(const ex & pattern) const
144 return bp->match(pattern, repl_lst);
147 /** Simplify/canonicalize expression containing indexed objects. This
148 * performs contraction of dummy indices where possible and checks whether
149 * the free indices in sums are consistent.
151 * @return simplified expression */
152 ex ex::simplify_indexed(void) const
154 return GiNaC::simplify_indexed(*this);
157 /** Simplify/canonicalize expression containing indexed objects. This
158 * performs contraction of dummy indices where possible, checks whether
159 * the free indices in sums are consistent, and automatically replaces
160 * scalar products by known values if desired.
162 * @param sp Scalar products to be replaced automatically
163 * @return simplified expression */
164 ex ex::simplify_indexed(const scalar_products & sp) const
166 return GiNaC::simplify_indexed(*this, sp);
169 ex ex::operator[](const ex & index) const
171 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
176 ex ex::operator[](int i) const
178 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
183 /** Return modifyable operand/member at position i. */
184 ex & ex::let_op(int i)
186 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
189 return bp->let_op(i);
192 /** Left hand side of relational expression. */
193 ex ex::lhs(void) const
195 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
196 if (!is_ex_of_type(*this,relational))
197 throw std::runtime_error("ex::lhs(): not a relation");
198 return (*static_cast<relational *>(bp)).lhs();
201 /** Right hand side of relational expression. */
202 ex ex::rhs(void) const
204 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
205 if (!is_ex_of_type(*this,relational))
206 throw std::runtime_error("ex::rhs(): not a relation");
207 return (*static_cast<relational *>(bp)).rhs();
212 /** Make this ex writable (if more than one ex handle the same basic) by
213 * unlinking the object and creating an unshared copy of it. */
214 void ex::makewriteable()
216 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
218 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
219 if (bp->refcount > 1) {
220 basic * bp2 = bp->duplicate();
222 bp2->setflag(status_flags::dynallocated);
226 GINAC_ASSERT(bp->refcount==1);
229 /** Ctor from basic implementation.
230 * @see ex::ex(const basic &) */
231 void ex::construct_from_basic(const basic & other)
233 if ((other.flags & status_flags::evaluated)==0) {
235 const ex & tmpex = other.eval(1); // evaluate only one (top) level
238 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
240 if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
241 delete &const_cast<basic &>(other);
243 if (other.flags & status_flags::dynallocated) {
244 // ok, it is already on the heap, so just copy bp:
245 bp = &const_cast<basic &>(other);
247 // create a duplicate on the heap:
248 bp = other.duplicate();
249 bp->setflag(status_flags::dynallocated);
255 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
258 void ex::construct_from_int(int i)
260 switch (i) { // some tiny efficiency-hack
283 bp->setflag(status_flags::dynallocated);
285 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
286 GINAC_ASSERT(bp->refcount==1);
290 void ex::construct_from_uint(unsigned int i)
292 switch (i) { // some tiny efficiency-hack
307 bp->setflag(status_flags::dynallocated);
309 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
310 GINAC_ASSERT(bp->refcount==1);
314 void ex::construct_from_long(long i)
316 switch (i) { // some tiny efficiency-hack
339 bp->setflag(status_flags::dynallocated);
341 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
342 GINAC_ASSERT(bp->refcount==1);
346 void ex::construct_from_ulong(unsigned long i)
348 switch (i) { // some tiny efficiency-hack
363 bp->setflag(status_flags::dynallocated);
365 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
366 GINAC_ASSERT(bp->refcount==1);
370 void ex::construct_from_double(double d)
373 bp->setflag(status_flags::dynallocated);
375 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
376 GINAC_ASSERT(bp->refcount==1);
379 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
382 set_lexer_symbols(l);
383 ginac_yyrestart(NULL);
385 throw (std::runtime_error(get_parser_error()));
389 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
395 // static member variables
401 // functions which are not member functions