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"
46 // non-virtual functions in this class
51 /** Efficiently swap the contents of two expressions. */
52 void ex::swap(ex & other)
55 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
56 GINAC_ASSERT(other.bp!=0);
57 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
64 /** Print expression to stream. The formatting of the output is determined
65 * by the kind of print_context object that is passed. Possible formattings
66 * include ginsh-parsable output (the default), tree-like output for
67 * debugging, and C++ source.
68 * @see print_context */
69 void ex::print(const print_context & c, unsigned level) const
75 /** Print expression to stream in a tree-like format suitable for debugging. */
76 void ex::printtree(std::ostream & os) const
79 bp->print(print_tree(os));
82 /** Little wrapper arount print to be called within a debugger. */
83 void ex::dbgprint(void) const
89 /** Little wrapper arount printtree to be called within a debugger. */
90 void ex::dbgprinttree(void) const
96 ex ex::expand(unsigned options) const
99 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
102 return bp->expand(options);
105 /** Compute partial derivative of an expression.
107 * @param s symbol by which the expression is derived
108 * @param nth order of derivative (default 1)
109 * @return partial derivative as a new expression */
110 ex ex::diff(const symbol & s, unsigned nth) const
117 return bp->diff(s, nth);
120 /** Check whether expression matches a specified pattern. */
121 bool ex::match(const ex & pattern) const
124 return bp->match(pattern, repl_lst);
127 /** Find all occurrences of a pattern. The found matches are appended to
128 * the "found" list. If the expression itself matches the pattern, the
129 * children are not further examined. This function returns true when any
130 * matches were found. */
131 bool ex::find(const ex & pattern, lst & found) const
133 if (match(pattern)) {
139 bool any_found = false;
140 for (unsigned i=0; i<nops(); i++)
141 if (op(i).find(pattern, found))
146 ex ex::operator[](const ex & index) const
152 ex ex::operator[](int i) const
158 /** Return modifyable operand/member at position i. */
159 ex & ex::let_op(int i)
163 return bp->let_op(i);
166 /** Left hand side of relational expression. */
167 ex ex::lhs(void) const
169 if (!is_ex_of_type(*this,relational))
170 throw std::runtime_error("ex::lhs(): not a relation");
171 return (*static_cast<relational *>(bp)).lhs();
174 /** Right hand side of relational expression. */
175 ex ex::rhs(void) const
177 if (!is_ex_of_type(*this,relational))
178 throw std::runtime_error("ex::rhs(): not a relation");
179 return (*static_cast<relational *>(bp)).rhs();
184 /** Make this ex writable (if more than one ex handle the same basic) by
185 * unlinking the object and creating an unshared copy of it. */
186 void ex::makewriteable()
189 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
190 if (bp->refcount > 1) {
191 basic * bp2 = bp->duplicate();
193 bp2->setflag(status_flags::dynallocated);
197 GINAC_ASSERT(bp->refcount==1);
200 /** Ctor from basic implementation.
201 * @see ex::ex(const basic &) */
202 void ex::construct_from_basic(const basic & other)
204 if (!(other.flags & status_flags::evaluated)) {
205 const ex & tmpex = other.eval(1); // evaluate only one (top) level
207 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
209 if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
210 delete &const_cast<basic &>(other);
212 if (other.flags & status_flags::dynallocated) {
213 // ok, it is already on the heap, so just copy bp:
214 bp = &const_cast<basic &>(other);
216 // create a duplicate on the heap:
217 bp = other.duplicate();
218 bp->setflag(status_flags::dynallocated);
224 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
227 void ex::construct_from_int(int i)
229 switch (i) { // prefer flyweights over new objects
231 bp = (basic*)_num_12_p;
235 bp = (basic*)_num_11_p;
239 bp = (basic*)_num_10_p;
243 bp = (basic*)_num_9_p;
247 bp = (basic*)_num_8_p;
251 bp = (basic*)_num_7_p;
255 bp = (basic*)_num_6_p;
259 bp = (basic*)_num_5_p;
263 bp = (basic*)_num_4_p;
267 bp = (basic*)_num_3_p;
271 bp = (basic*)_num_2_p;
275 bp = (basic*)_num_1_p;
279 bp = (basic*)_num0_p;
283 bp = (basic*)_num1_p;
287 bp = (basic*)_num2_p;
291 bp = (basic*)_num3_p;
295 bp = (basic*)_num4_p;
299 bp = (basic*)_num5_p;
303 bp = (basic*)_num6_p;
307 bp = (basic*)_num7_p;
311 bp = (basic*)_num8_p;
315 bp = (basic*)_num9_p;
319 bp = (basic*)_num10_p;
323 bp = (basic*)_num11_p;
327 bp = (basic*)_num12_p;
332 bp->setflag(status_flags::dynallocated);
334 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
335 GINAC_ASSERT(bp->refcount==1);
339 void ex::construct_from_uint(unsigned int i)
341 switch (i) { // prefer flyweights over new objects
343 bp = (basic*)_num0_p;
347 bp = (basic*)_num1_p;
351 bp = (basic*)_num2_p;
355 bp = (basic*)_num3_p;
359 bp = (basic*)_num4_p;
363 bp = (basic*)_num5_p;
367 bp = (basic*)_num6_p;
371 bp = (basic*)_num7_p;
375 bp = (basic*)_num8_p;
379 bp = (basic*)_num9_p;
383 bp = (basic*)_num10_p;
387 bp = (basic*)_num11_p;
391 bp = (basic*)_num12_p;
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_long(long i)
405 switch (i) { // prefer flyweights over new objects
407 bp = (basic*)_num_12_p;
411 bp = (basic*)_num_11_p;
415 bp = (basic*)_num_10_p;
419 bp = (basic*)_num_9_p;
423 bp = (basic*)_num_8_p;
427 bp = (basic*)_num_7_p;
431 bp = (basic*)_num_6_p;
435 bp = (basic*)_num_5_p;
439 bp = (basic*)_num_4_p;
443 bp = (basic*)_num_3_p;
447 bp = (basic*)_num_2_p;
451 bp = (basic*)_num_1_p;
455 bp = (basic*)_num0_p;
459 bp = (basic*)_num1_p;
463 bp = (basic*)_num2_p;
467 bp = (basic*)_num3_p;
471 bp = (basic*)_num4_p;
475 bp = (basic*)_num5_p;
479 bp = (basic*)_num6_p;
483 bp = (basic*)_num7_p;
487 bp = (basic*)_num8_p;
491 bp = (basic*)_num9_p;
495 bp = (basic*)_num10_p;
499 bp = (basic*)_num11_p;
503 bp = (basic*)_num12_p;
508 bp->setflag(status_flags::dynallocated);
510 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
511 GINAC_ASSERT(bp->refcount==1);
515 void ex::construct_from_ulong(unsigned long i)
517 switch (i) { // prefer flyweights over new objects
519 bp = (basic*)_num0_p;
523 bp = (basic*)_num1_p;
527 bp = (basic*)_num2_p;
531 bp = (basic*)_num3_p;
535 bp = (basic*)_num4_p;
539 bp = (basic*)_num5_p;
543 bp = (basic*)_num6_p;
547 bp = (basic*)_num7_p;
551 bp = (basic*)_num8_p;
555 bp = (basic*)_num9_p;
559 bp = (basic*)_num10_p;
563 bp = (basic*)_num11_p;
567 bp = (basic*)_num12_p;
572 bp->setflag(status_flags::dynallocated);
574 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
575 GINAC_ASSERT(bp->refcount==1);
579 void ex::construct_from_double(double d)
582 bp->setflag(status_flags::dynallocated);
584 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
585 GINAC_ASSERT(bp->refcount==1);
588 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
591 set_lexer_symbols(l);
592 ginac_yyrestart(NULL);
594 throw (std::runtime_error(get_parser_error()));
598 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
604 // static member variables
610 // functions which are not member functions