3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "relational.h"
35 #include "input_lexer.h"
47 // non-virtual functions in this class
52 /** Print expression to stream. The formatting of the output is determined
53 * by the kind of print_context object that is passed. Possible formattings
54 * include ginsh-parsable output (the default), tree-like output for
55 * debugging, and C++ source.
56 * @see print_context */
57 void ex::print(const print_context & c, unsigned level) const
62 /** Little wrapper arount print to be called within a debugger. */
63 void ex::dbgprint() const
68 /** Little wrapper arount printtree to be called within a debugger. */
69 void ex::dbgprinttree() const
74 ex ex::expand(unsigned options) const
76 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
79 return bp->expand(options);
82 /** Compute partial derivative of an expression.
84 * @param s symbol by which the expression is derived
85 * @param nth order of derivative (default 1)
86 * @return partial derivative as a new expression */
87 ex ex::diff(const symbol & s, unsigned nth) const
92 return bp->diff(s, nth);
95 /** Check whether expression matches a specified pattern. */
96 bool ex::match(const ex & pattern) const
99 return bp->match(pattern, repl_lst);
102 /** Find all occurrences of a pattern. The found matches are appended to
103 * the "found" list. If the expression itself matches the pattern, the
104 * children are not further examined. This function returns true when any
105 * matches were found. */
106 bool ex::find(const ex & pattern, exset& found) const
108 if (match(pattern)) {
112 bool any_found = false;
113 for (size_t i=0; i<nops(); i++)
114 if (op(i).find(pattern, found))
119 /** Substitute objects in an expression (syntactic substitution) and return
120 * the result as a new expression. */
121 ex ex::subs(const lst & ls, const lst & lr, unsigned options) const
123 GINAC_ASSERT(ls.nops() == lr.nops());
125 // Convert the lists to a map
127 for (lst::const_iterator its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
128 m.insert(std::make_pair(*its, *itr));
130 // Search for products and powers in the expressions to be substituted
131 // (for an optimization in expairseq::subs())
132 if (is_exactly_a<mul>(*its) || is_exactly_a<power>(*its))
133 options |= subs_options::pattern_is_product;
135 if (!(options & subs_options::pattern_is_product))
136 options |= subs_options::pattern_is_not_product;
138 return bp->subs(m, options);
141 /** Substitute objects in an expression (syntactic substitution) and return
142 * the result as a new expression. There are two valid types of
143 * replacement arguments: 1) a relational like object==ex and 2) a list of
144 * relationals lst(object1==ex1,object2==ex2,...). */
145 ex ex::subs(const ex & e, unsigned options) const
147 if (e.info(info_flags::relation_equal)) {
149 // Argument is a relation: convert it to a map
151 const ex & s = e.op(0);
152 m.insert(std::make_pair(s, e.op(1)));
154 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
155 options |= subs_options::pattern_is_product;
157 options |= subs_options::pattern_is_not_product;
159 return bp->subs(m, options);
161 } else if (e.info(info_flags::list)) {
163 // Argument is a list: convert it to a map
165 GINAC_ASSERT(is_a<lst>(e));
166 for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
168 if (!r.info(info_flags::relation_equal))
169 throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
170 const ex & s = r.op(0);
171 m.insert(std::make_pair(s, r.op(1)));
173 // Search for products and powers in the expressions to be substituted
174 // (for an optimization in expairseq::subs())
175 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
176 options |= subs_options::pattern_is_product;
178 if (!(options & subs_options::pattern_is_product))
179 options |= subs_options::pattern_is_not_product;
181 return bp->subs(m, options);
184 throw(std::invalid_argument("ex::subs(ex): argument must be a relation_equal or a list"));
187 /** Traverse expression tree with given visitor, preorder traversal. */
188 void ex::traverse_preorder(visitor & v) const
193 for (size_t i = 0; i < n; ++i)
194 op(i).traverse_preorder(v);
197 /** Traverse expression tree with given visitor, postorder traversal. */
198 void ex::traverse_postorder(visitor & v) const
201 for (size_t i = 0; i < n; ++i)
202 op(i).traverse_postorder(v);
207 /** Return modifyable operand/member at position i. */
208 ex & ex::let_op(size_t i)
211 return bp->let_op(i);
214 ex & ex::operator[](const ex & index)
220 ex & ex::operator[](size_t i)
226 /** Left hand side of relational expression. */
229 if (!is_a<relational>(*this))
230 throw std::runtime_error("ex::lhs(): not a relation");
234 /** Right hand side of relational expression. */
237 if (!is_a<relational>(*this))
238 throw std::runtime_error("ex::rhs(): not a relation");
242 /** Check whether expression is a polynomial. */
243 bool ex::is_polynomial(const ex & vars) const
245 if (is_a<lst>(vars)) {
246 const lst & varlst = ex_to<lst>(vars);
247 for (lst::const_iterator i=varlst.begin(); i!=varlst.end(); ++i)
248 if (!bp->is_polynomial(*i))
253 return bp->is_polynomial(vars);
256 /** Check whether expression is zero or zero matrix. */
257 bool ex::is_zero_matrix() const
263 return is_a<matrix>(e) && ex_to<matrix>(e).is_zero_matrix();
269 /** Make this ex writable (if more than one ex handle the same basic) by
270 * unlinking the object and creating an unshared copy of it. */
271 void ex::makewriteable()
273 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
275 GINAC_ASSERT(bp->get_refcount() == 1);
278 /** Share equal objects between expressions.
279 * @see ex::compare(const ex &) */
280 void ex::share(const ex & other) const
282 if ((bp->flags | other.bp->flags) & status_flags::not_shareable)
285 if (bp->get_refcount() <= other.bp->get_refcount())
291 /** Helper function for the ex-from-basic constructor. This is where GiNaC's
292 * automatic evaluator and memory management are implemented.
293 * @see ex::ex(const basic &) */
294 ptr<basic> ex::construct_from_basic(const basic & other)
296 if (!(other.flags & status_flags::evaluated)) {
298 // The object is not yet evaluated, so call eval() to evaluate
299 // the top level. This will return either
300 // a) the original object with status_flags::evaluated set (when the
301 // eval() implementation calls hold())
303 // b) a different expression.
305 // eval() returns an ex, not a basic&, so this will go through
306 // construct_from_basic() a second time. In case a) we end up in
307 // the "else" branch below. In case b) we end up here again and
308 // apply eval() once more. The recursion stops when eval() calls
309 // hold() or returns an object that already has its "evaluated"
310 // flag set, such as a symbol or a numeric.
311 const ex & tmpex = other.eval(1);
313 // Eventually, the eval() recursion goes through the "else" branch
314 // below, which assures that the object pointed to by tmpex.bp is
315 // allocated on the heap (either it was already on the heap or it
316 // is a heap-allocated duplicate of another object).
317 GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated);
319 // If the original object is not referenced but heap-allocated,
320 // it means that eval() hit case b) above. The original object is
321 // no longer needed (it evaluated into something different), so we
322 // delete it (because nobody else will).
323 if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated))
324 delete &other; // yes, you can apply delete to a const pointer
326 // We can't return a basic& here because the tmpex is destroyed as
327 // soon as we leave the function, which would deallocate the
333 // The easy case: making an "ex" out of an evaluated object.
334 if (other.flags & status_flags::dynallocated) {
336 // The object is already heap-allocated, so we can just make
337 // another reference to it.
338 return ptr<basic>(const_cast<basic &>(other));
342 // The object is not heap-allocated, so we create a duplicate
344 basic *bp = other.duplicate();
345 bp->setflag(status_flags::dynallocated);
346 GINAC_ASSERT(bp->get_refcount() == 0);
352 basic & ex::construct_from_int(int i)
354 switch (i) { // prefer flyweights over new objects
356 return *const_cast<numeric *>(_num_12_p);
358 return *const_cast<numeric *>(_num_11_p);
360 return *const_cast<numeric *>(_num_10_p);
362 return *const_cast<numeric *>(_num_9_p);
364 return *const_cast<numeric *>(_num_8_p);
366 return *const_cast<numeric *>(_num_7_p);
368 return *const_cast<numeric *>(_num_6_p);
370 return *const_cast<numeric *>(_num_5_p);
372 return *const_cast<numeric *>(_num_4_p);
374 return *const_cast<numeric *>(_num_3_p);
376 return *const_cast<numeric *>(_num_2_p);
378 return *const_cast<numeric *>(_num_1_p);
380 return *const_cast<numeric *>(_num0_p);
382 return *const_cast<numeric *>(_num1_p);
384 return *const_cast<numeric *>(_num2_p);
386 return *const_cast<numeric *>(_num3_p);
388 return *const_cast<numeric *>(_num4_p);
390 return *const_cast<numeric *>(_num5_p);
392 return *const_cast<numeric *>(_num6_p);
394 return *const_cast<numeric *>(_num7_p);
396 return *const_cast<numeric *>(_num8_p);
398 return *const_cast<numeric *>(_num9_p);
400 return *const_cast<numeric *>(_num10_p);
402 return *const_cast<numeric *>(_num11_p);
404 return *const_cast<numeric *>(_num12_p);
406 basic *bp = new numeric(i);
407 bp->setflag(status_flags::dynallocated);
408 GINAC_ASSERT(bp->get_refcount() == 0);
413 basic & ex::construct_from_uint(unsigned int i)
415 switch (i) { // prefer flyweights over new objects
417 return *const_cast<numeric *>(_num0_p);
419 return *const_cast<numeric *>(_num1_p);
421 return *const_cast<numeric *>(_num2_p);
423 return *const_cast<numeric *>(_num3_p);
425 return *const_cast<numeric *>(_num4_p);
427 return *const_cast<numeric *>(_num5_p);
429 return *const_cast<numeric *>(_num6_p);
431 return *const_cast<numeric *>(_num7_p);
433 return *const_cast<numeric *>(_num8_p);
435 return *const_cast<numeric *>(_num9_p);
437 return *const_cast<numeric *>(_num10_p);
439 return *const_cast<numeric *>(_num11_p);
441 return *const_cast<numeric *>(_num12_p);
443 basic *bp = new numeric(i);
444 bp->setflag(status_flags::dynallocated);
445 GINAC_ASSERT(bp->get_refcount() == 0);
450 basic & ex::construct_from_long(long i)
452 switch (i) { // prefer flyweights over new objects
454 return *const_cast<numeric *>(_num_12_p);
456 return *const_cast<numeric *>(_num_11_p);
458 return *const_cast<numeric *>(_num_10_p);
460 return *const_cast<numeric *>(_num_9_p);
462 return *const_cast<numeric *>(_num_8_p);
464 return *const_cast<numeric *>(_num_7_p);
466 return *const_cast<numeric *>(_num_6_p);
468 return *const_cast<numeric *>(_num_5_p);
470 return *const_cast<numeric *>(_num_4_p);
472 return *const_cast<numeric *>(_num_3_p);
474 return *const_cast<numeric *>(_num_2_p);
476 return *const_cast<numeric *>(_num_1_p);
478 return *const_cast<numeric *>(_num0_p);
480 return *const_cast<numeric *>(_num1_p);
482 return *const_cast<numeric *>(_num2_p);
484 return *const_cast<numeric *>(_num3_p);
486 return *const_cast<numeric *>(_num4_p);
488 return *const_cast<numeric *>(_num5_p);
490 return *const_cast<numeric *>(_num6_p);
492 return *const_cast<numeric *>(_num7_p);
494 return *const_cast<numeric *>(_num8_p);
496 return *const_cast<numeric *>(_num9_p);
498 return *const_cast<numeric *>(_num10_p);
500 return *const_cast<numeric *>(_num11_p);
502 return *const_cast<numeric *>(_num12_p);
504 basic *bp = new numeric(i);
505 bp->setflag(status_flags::dynallocated);
506 GINAC_ASSERT(bp->get_refcount() == 0);
511 basic & ex::construct_from_ulong(unsigned long i)
513 switch (i) { // prefer flyweights over new objects
515 return *const_cast<numeric *>(_num0_p);
517 return *const_cast<numeric *>(_num1_p);
519 return *const_cast<numeric *>(_num2_p);
521 return *const_cast<numeric *>(_num3_p);
523 return *const_cast<numeric *>(_num4_p);
525 return *const_cast<numeric *>(_num5_p);
527 return *const_cast<numeric *>(_num6_p);
529 return *const_cast<numeric *>(_num7_p);
531 return *const_cast<numeric *>(_num8_p);
533 return *const_cast<numeric *>(_num9_p);
535 return *const_cast<numeric *>(_num10_p);
537 return *const_cast<numeric *>(_num11_p);
539 return *const_cast<numeric *>(_num12_p);
541 basic *bp = new numeric(i);
542 bp->setflag(status_flags::dynallocated);
543 GINAC_ASSERT(bp->get_refcount() == 0);
548 basic & ex::construct_from_double(double d)
550 basic *bp = new numeric(d);
551 bp->setflag(status_flags::dynallocated);
552 GINAC_ASSERT(bp->get_refcount() == 0);
556 ptr<basic> ex::construct_from_string_and_lst(const std::string &s, const ex &l)
559 set_lexer_symbols(l);
560 ginac_yyrestart(NULL);
562 throw (std::runtime_error(get_parser_error()));
568 // static member variables
574 // functions which are not member functions