3 * Implementation of GiNaC's light-weight expression handles. */
6 * GiNaC Copyright (C) 1999-2002 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 /** Print expression to stream. The formatting of the output is determined
52 * by the kind of print_context object that is passed. Possible formattings
53 * include ginsh-parsable output (the default), tree-like output for
54 * debugging, and C++ source.
55 * @see print_context */
56 void ex::print(const print_context & c, unsigned level) const
62 /** Print expression to stream in a tree-like format suitable for debugging. */
63 void ex::printtree(std::ostream & os) const
66 bp->print(print_tree(os));
69 /** Little wrapper arount print to be called within a debugger. */
70 void ex::dbgprint(void) const
76 /** Little wrapper arount printtree to be called within a debugger. */
77 void ex::dbgprinttree(void) const
83 ex ex::expand(unsigned options) const
86 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
89 return bp->expand(options);
92 /** Compute partial derivative of an expression.
94 * @param s symbol by which the expression is derived
95 * @param nth order of derivative (default 1)
96 * @return partial derivative as a new expression */
97 ex ex::diff(const symbol & s, unsigned nth) const
104 return bp->diff(s, nth);
107 /** Check whether expression matches a specified pattern. */
108 bool ex::match(const ex & pattern) const
111 return bp->match(pattern, repl_lst);
114 /** Find all occurrences of a pattern. The found matches are appended to
115 * the "found" list. If the expression itself matches the pattern, the
116 * children are not further examined. This function returns true when any
117 * matches were found. */
118 bool ex::find(const ex & pattern, lst & found) const
120 if (match(pattern)) {
126 bool any_found = false;
127 for (unsigned i=0; i<nops(); i++)
128 if (op(i).find(pattern, found))
133 ex ex::operator[](const ex & index) const
139 ex ex::operator[](int i) const
145 /** Return modifyable operand/member at position i. */
146 ex & ex::let_op(int i)
150 return bp->let_op(i);
153 /** Left hand side of relational expression. */
154 ex ex::lhs(void) const
156 if (!is_a<relational>(*this))
157 throw std::runtime_error("ex::lhs(): not a relation");
158 return (*static_cast<relational *>(bp)).lhs();
161 /** Right hand side of relational expression. */
162 ex ex::rhs(void) const
164 if (!is_a<relational>(*this))
165 throw std::runtime_error("ex::rhs(): not a relation");
166 return (*static_cast<relational *>(bp)).rhs();
171 /** Make this ex writable (if more than one ex handle the same basic) by
172 * unlinking the object and creating an unshared copy of it. */
173 void ex::makewriteable()
176 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
177 if (bp->refcount > 1) {
178 basic * bp2 = bp->duplicate();
180 bp2->setflag(status_flags::dynallocated);
184 GINAC_ASSERT(bp->refcount==1);
187 /** Ctor from basic implementation.
188 * @see ex::ex(const basic &) */
189 void ex::construct_from_basic(const basic & other)
191 if (!(other.flags & status_flags::evaluated)) {
192 const ex & tmpex = other.eval(1); // evaluate only one (top) level
194 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
196 if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
197 delete &const_cast<basic &>(other);
199 if (other.flags & status_flags::dynallocated) {
200 // ok, it is already on the heap, so just copy bp:
201 bp = &const_cast<basic &>(other);
203 // create a duplicate on the heap:
204 bp = other.duplicate();
205 bp->setflag(status_flags::dynallocated);
211 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
214 void ex::construct_from_int(int i)
216 switch (i) { // prefer flyweights over new objects
218 bp = (basic*)_num_12_p;
222 bp = (basic*)_num_11_p;
226 bp = (basic*)_num_10_p;
230 bp = (basic*)_num_9_p;
234 bp = (basic*)_num_8_p;
238 bp = (basic*)_num_7_p;
242 bp = (basic*)_num_6_p;
246 bp = (basic*)_num_5_p;
250 bp = (basic*)_num_4_p;
254 bp = (basic*)_num_3_p;
258 bp = (basic*)_num_2_p;
262 bp = (basic*)_num_1_p;
266 bp = (basic*)_num0_p;
270 bp = (basic*)_num1_p;
274 bp = (basic*)_num2_p;
278 bp = (basic*)_num3_p;
282 bp = (basic*)_num4_p;
286 bp = (basic*)_num5_p;
290 bp = (basic*)_num6_p;
294 bp = (basic*)_num7_p;
298 bp = (basic*)_num8_p;
302 bp = (basic*)_num9_p;
306 bp = (basic*)_num10_p;
310 bp = (basic*)_num11_p;
314 bp = (basic*)_num12_p;
319 bp->setflag(status_flags::dynallocated);
321 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
322 GINAC_ASSERT(bp->refcount==1);
326 void ex::construct_from_uint(unsigned int i)
328 switch (i) { // prefer flyweights over new objects
330 bp = (basic*)_num0_p;
334 bp = (basic*)_num1_p;
338 bp = (basic*)_num2_p;
342 bp = (basic*)_num3_p;
346 bp = (basic*)_num4_p;
350 bp = (basic*)_num5_p;
354 bp = (basic*)_num6_p;
358 bp = (basic*)_num7_p;
362 bp = (basic*)_num8_p;
366 bp = (basic*)_num9_p;
370 bp = (basic*)_num10_p;
374 bp = (basic*)_num11_p;
378 bp = (basic*)_num12_p;
383 bp->setflag(status_flags::dynallocated);
385 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
386 GINAC_ASSERT(bp->refcount==1);
390 void ex::construct_from_long(long i)
392 switch (i) { // prefer flyweights over new objects
394 bp = (basic*)_num_12_p;
398 bp = (basic*)_num_11_p;
402 bp = (basic*)_num_10_p;
406 bp = (basic*)_num_9_p;
410 bp = (basic*)_num_8_p;
414 bp = (basic*)_num_7_p;
418 bp = (basic*)_num_6_p;
422 bp = (basic*)_num_5_p;
426 bp = (basic*)_num_4_p;
430 bp = (basic*)_num_3_p;
434 bp = (basic*)_num_2_p;
438 bp = (basic*)_num_1_p;
442 bp = (basic*)_num0_p;
446 bp = (basic*)_num1_p;
450 bp = (basic*)_num2_p;
454 bp = (basic*)_num3_p;
458 bp = (basic*)_num4_p;
462 bp = (basic*)_num5_p;
466 bp = (basic*)_num6_p;
470 bp = (basic*)_num7_p;
474 bp = (basic*)_num8_p;
478 bp = (basic*)_num9_p;
482 bp = (basic*)_num10_p;
486 bp = (basic*)_num11_p;
490 bp = (basic*)_num12_p;
495 bp->setflag(status_flags::dynallocated);
497 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
498 GINAC_ASSERT(bp->refcount==1);
502 void ex::construct_from_ulong(unsigned long i)
504 switch (i) { // prefer flyweights over new objects
506 bp = (basic*)_num0_p;
510 bp = (basic*)_num1_p;
514 bp = (basic*)_num2_p;
518 bp = (basic*)_num3_p;
522 bp = (basic*)_num4_p;
526 bp = (basic*)_num5_p;
530 bp = (basic*)_num6_p;
534 bp = (basic*)_num7_p;
538 bp = (basic*)_num8_p;
542 bp = (basic*)_num9_p;
546 bp = (basic*)_num10_p;
550 bp = (basic*)_num11_p;
554 bp = (basic*)_num12_p;
559 bp->setflag(status_flags::dynallocated);
561 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
562 GINAC_ASSERT(bp->refcount==1);
566 void ex::construct_from_double(double d)
569 bp->setflag(status_flags::dynallocated);
571 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
572 GINAC_ASSERT(bp->refcount==1);
575 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
578 set_lexer_symbols(l);
579 ginac_yyrestart(NULL);
581 throw (std::runtime_error(get_parser_error()));
585 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
591 // static member variables
597 // functions which are not member functions