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 // non-virtual functions in this class
52 /** Efficiently swap the contents of two expressions. */
53 void ex::swap(ex & other)
55 debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
58 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
59 GINAC_ASSERT(other.bp!=0);
60 GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
67 /** Print expression to stream. The formatting of the output is determined
68 * by the kind of print_context object that is passed. Possible formattings
69 * include ginsh-parsable output (the default), tree-like output for
70 * debugging, and C++ source.
71 * @see print_context */
72 void ex::print(const print_context & c, unsigned level) const
74 debugmsg("ex print", LOGLEVEL_PRINT);
79 /** Print expression to stream in a tree-like format suitable for debugging. */
80 void ex::printtree(std::ostream & os) const
82 debugmsg("ex printtree", LOGLEVEL_PRINT);
84 bp->print(print_tree(os));
87 /** Little wrapper arount print to be called within a debugger. */
88 void ex::dbgprint(void) const
90 debugmsg("ex dbgprint", LOGLEVEL_PRINT);
95 /** Little wrapper arount printtree to be called within a debugger. */
96 void ex::dbgprinttree(void) const
98 debugmsg("ex dbgprinttree", LOGLEVEL_PRINT);
103 ex ex::expand(unsigned options) const
106 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
109 return bp->expand(options);
112 /** Compute partial derivative of an expression.
114 * @param s symbol by which the expression is derived
115 * @param nth order of derivative (default 1)
116 * @return partial derivative as a new expression */
117 ex ex::diff(const symbol & s, unsigned nth) const
124 return bp->diff(s, nth);
127 /** Check whether expression matches a specified pattern. */
128 bool ex::match(const ex & pattern) const
131 return bp->match(pattern, repl_lst);
134 /** Find all occurrences of a pattern. The found matches are appended to
135 * the "found" list. If the expression itself matches the pattern, the
136 * children are not further examined. This function returns true when any
137 * matches were found. */
138 bool ex::find(const ex & pattern, lst & found) const
140 if (match(pattern)) {
146 bool any_found = false;
147 for (unsigned i=0; i<nops(); i++)
148 if (op(i).find(pattern, found))
153 ex ex::operator[](const ex & index) const
155 debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
160 ex ex::operator[](int i) const
162 debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
167 /** Return modifyable operand/member at position i. */
168 ex & ex::let_op(int i)
170 debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
173 return bp->let_op(i);
176 /** Left hand side of relational expression. */
177 ex ex::lhs(void) const
179 debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
180 if (!is_ex_of_type(*this,relational))
181 throw std::runtime_error("ex::lhs(): not a relation");
182 return (*static_cast<relational *>(bp)).lhs();
185 /** Right hand side of relational expression. */
186 ex ex::rhs(void) const
188 debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
189 if (!is_ex_of_type(*this,relational))
190 throw std::runtime_error("ex::rhs(): not a relation");
191 return (*static_cast<relational *>(bp)).rhs();
196 /** Make this ex writable (if more than one ex handle the same basic) by
197 * unlinking the object and creating an unshared copy of it. */
198 void ex::makewriteable()
200 debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
202 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
203 if (bp->refcount > 1) {
204 basic * bp2 = bp->duplicate();
206 bp2->setflag(status_flags::dynallocated);
210 GINAC_ASSERT(bp->refcount==1);
213 /** Ctor from basic implementation.
214 * @see ex::ex(const basic &) */
215 void ex::construct_from_basic(const basic & other)
217 if (!(other.flags & status_flags::evaluated)) {
218 const ex & tmpex = other.eval(1); // evaluate only one (top) level
220 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
222 if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
223 delete &const_cast<basic &>(other);
225 if (other.flags & status_flags::dynallocated) {
226 // ok, it is already on the heap, so just copy bp:
227 bp = &const_cast<basic &>(other);
229 // create a duplicate on the heap:
230 bp = other.duplicate();
231 bp->setflag(status_flags::dynallocated);
237 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
240 void ex::construct_from_int(int i)
242 switch (i) { // prefer flyweights over new objects
244 bp = (basic*)_num_12_p;
248 bp = (basic*)_num_11_p;
252 bp = (basic*)_num_10_p;
256 bp = (basic*)_num_9_p;
260 bp = (basic*)_num_8_p;
264 bp = (basic*)_num_7_p;
268 bp = (basic*)_num_6_p;
272 bp = (basic*)_num_5_p;
276 bp = (basic*)_num_4_p;
280 bp = (basic*)_num_3_p;
284 bp = (basic*)_num_2_p;
288 bp = (basic*)_num_1_p;
292 bp = (basic*)_num0_p;
296 bp = (basic*)_num1_p;
300 bp = (basic*)_num2_p;
304 bp = (basic*)_num3_p;
308 bp = (basic*)_num4_p;
312 bp = (basic*)_num5_p;
316 bp = (basic*)_num6_p;
320 bp = (basic*)_num7_p;
324 bp = (basic*)_num8_p;
328 bp = (basic*)_num9_p;
332 bp = (basic*)_num10_p;
336 bp = (basic*)_num11_p;
340 bp = (basic*)_num12_p;
345 bp->setflag(status_flags::dynallocated);
347 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
348 GINAC_ASSERT(bp->refcount==1);
352 void ex::construct_from_uint(unsigned int i)
354 switch (i) { // prefer flyweights over new objects
356 bp = (basic*)_num0_p;
360 bp = (basic*)_num1_p;
364 bp = (basic*)_num2_p;
368 bp = (basic*)_num3_p;
372 bp = (basic*)_num4_p;
376 bp = (basic*)_num5_p;
380 bp = (basic*)_num6_p;
384 bp = (basic*)_num7_p;
388 bp = (basic*)_num8_p;
392 bp = (basic*)_num9_p;
396 bp = (basic*)_num10_p;
400 bp = (basic*)_num11_p;
404 bp = (basic*)_num12_p;
409 bp->setflag(status_flags::dynallocated);
411 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
412 GINAC_ASSERT(bp->refcount==1);
416 void ex::construct_from_long(long i)
418 switch (i) { // prefer flyweights over new objects
420 bp = (basic*)_num_12_p;
424 bp = (basic*)_num_11_p;
428 bp = (basic*)_num_10_p;
432 bp = (basic*)_num_9_p;
436 bp = (basic*)_num_8_p;
440 bp = (basic*)_num_7_p;
444 bp = (basic*)_num_6_p;
448 bp = (basic*)_num_5_p;
452 bp = (basic*)_num_4_p;
456 bp = (basic*)_num_3_p;
460 bp = (basic*)_num_2_p;
464 bp = (basic*)_num_1_p;
468 bp = (basic*)_num0_p;
472 bp = (basic*)_num1_p;
476 bp = (basic*)_num2_p;
480 bp = (basic*)_num3_p;
484 bp = (basic*)_num4_p;
488 bp = (basic*)_num5_p;
492 bp = (basic*)_num6_p;
496 bp = (basic*)_num7_p;
500 bp = (basic*)_num8_p;
504 bp = (basic*)_num9_p;
508 bp = (basic*)_num10_p;
512 bp = (basic*)_num11_p;
516 bp = (basic*)_num12_p;
521 bp->setflag(status_flags::dynallocated);
523 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
524 GINAC_ASSERT(bp->refcount==1);
528 void ex::construct_from_ulong(unsigned long i)
530 switch (i) { // prefer flyweights over new objects
532 bp = (basic*)_num0_p;
536 bp = (basic*)_num1_p;
540 bp = (basic*)_num2_p;
544 bp = (basic*)_num3_p;
548 bp = (basic*)_num4_p;
552 bp = (basic*)_num5_p;
556 bp = (basic*)_num6_p;
560 bp = (basic*)_num7_p;
564 bp = (basic*)_num8_p;
568 bp = (basic*)_num9_p;
572 bp = (basic*)_num10_p;
576 bp = (basic*)_num11_p;
580 bp = (basic*)_num12_p;
585 bp->setflag(status_flags::dynallocated);
587 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
588 GINAC_ASSERT(bp->refcount==1);
592 void ex::construct_from_double(double d)
595 bp->setflag(status_flags::dynallocated);
597 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
598 GINAC_ASSERT(bp->refcount==1);
601 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
604 set_lexer_symbols(l);
605 ginac_yyrestart(NULL);
607 throw (std::runtime_error(get_parser_error()));
611 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
617 // static member variables
623 // functions which are not member functions