]> www.ginac.de Git - ginac.git/blob - ginac/ex.cpp
mention the subs(exmap &) form
[ginac.git] / ginac / ex.cpp
1 /** @file ex.cpp
2  *
3  *  Implementation of GiNaC's light-weight expression handles. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <iostream>
24 #include <stdexcept>
25
26 #include "ex.h"
27 #include "add.h"
28 #include "mul.h"
29 #include "ncmul.h"
30 #include "numeric.h"
31 #include "power.h"
32 #include "lst.h"
33 #include "relational.h"
34 #include "input_lexer.h"
35 #include "utils.h"
36
37 namespace GiNaC {
38
39 //////////
40 // other constructors
41 //////////
42
43 // none (all inlined)
44
45 //////////
46 // non-virtual functions in this class
47 //////////
48
49 // public
50         
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
57 {
58         bp->print(c, level);
59 }
60
61 /** Little wrapper arount print to be called within a debugger. */
62 void ex::dbgprint() const
63 {
64         bp->dbgprint();
65 }
66
67 /** Little wrapper arount printtree to be called within a debugger. */
68 void ex::dbgprinttree() const
69 {
70         bp->dbgprinttree();
71 }
72
73 ex ex::expand(unsigned options) const
74 {
75         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
76                 return *bp;
77         else
78                 return bp->expand(options);
79 }
80
81 /** Compute partial derivative of an expression.
82  *
83  *  @param s  symbol by which the expression is derived
84  *  @param nth  order of derivative (default 1)
85  *  @return partial derivative as a new expression */
86 ex ex::diff(const symbol & s, unsigned nth) const
87 {
88         if (!nth)
89                 return *this;
90         else
91                 return bp->diff(s, nth);
92 }
93
94 /** Check whether expression matches a specified pattern. */
95 bool ex::match(const ex & pattern) const
96 {
97         lst repl_lst;
98         return bp->match(pattern, repl_lst);
99 }
100
101 /** Find all occurrences of a pattern. The found matches are appended to
102  *  the "found" list. If the expression itself matches the pattern, the
103  *  children are not further examined. This function returns true when any
104  *  matches were found. */
105 bool ex::find(const ex & pattern, lst & found) const
106 {
107         if (match(pattern)) {
108                 found.append(*this);
109                 found.sort();
110                 found.unique();
111                 return true;
112         }
113         bool any_found = false;
114         for (size_t i=0; i<nops(); i++)
115                 if (op(i).find(pattern, found))
116                         any_found = true;
117         return any_found;
118 }
119
120 /** Substitute objects in an expression (syntactic substitution) and return
121  *  the result as a new expression. */
122 ex ex::subs(const lst & ls, const lst & lr, unsigned options) const
123 {
124         GINAC_ASSERT(ls.nops() == lr.nops());
125
126         // Convert the lists to a map
127         exmap m;
128         for (lst::const_iterator its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
129                 m.insert(std::make_pair(*its, *itr));
130
131                 // Search for products and powers in the expressions to be substituted
132                 // (for an optimization in expairseq::subs())
133                 if (is_exactly_a<mul>(*its) || is_exactly_a<power>(*its))
134                         options |= subs_options::pattern_is_product;
135         }
136         if (!(options & subs_options::pattern_is_product))
137                 options |= subs_options::pattern_is_not_product;
138
139         return bp->subs(m, options);
140 }
141
142 /** Substitute objects in an expression (syntactic substitution) and return
143  *  the result as a new expression.  There are two valid types of
144  *  replacement arguments: 1) a relational like object==ex and 2) a list of
145  *  relationals lst(object1==ex1,object2==ex2,...). */
146 ex ex::subs(const ex & e, unsigned options) const
147 {
148         if (e.info(info_flags::relation_equal)) {
149                 exmap m;
150                 const ex & s = e.op(0);
151                 m.insert(std::make_pair(s, e.op(1)));
152                 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
153                         options |= subs_options::pattern_is_product;
154                 else
155                         options |= subs_options::pattern_is_not_product;
156                 return bp->subs(m, options);
157         } else if (!e.info(info_flags::list))
158                 throw(std::invalid_argument("basic::subs(ex): argument must be a list"));
159
160         // Convert the list to a map
161         exmap m;
162         GINAC_ASSERT(is_a<lst>(e));
163         for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
164                 ex r = *it;
165                 if (!r.info(info_flags::relation_equal))
166                         throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
167                 const ex & s = r.op(0);
168                 m.insert(std::make_pair(s, r.op(1)));
169
170                 // Search for products and powers in the expressions to be substituted
171                 // (for an optimization in expairseq::subs())
172                 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
173                         options |= subs_options::pattern_is_product;
174         }
175         if (!(options & subs_options::pattern_is_product))
176                 options |= subs_options::pattern_is_not_product;
177
178         return bp->subs(m, options);
179 }
180
181 /** Traverse expression tree with given visitor, preorder traversal. */
182 void ex::traverse_preorder(visitor & v) const
183 {
184         accept(v);
185
186         size_t n = nops();
187         for (size_t i = 0; i < n; ++i)
188                 op(i).traverse_preorder(v);
189 }
190
191 /** Traverse expression tree with given visitor, postorder traversal. */
192 void ex::traverse_postorder(visitor & v) const
193 {
194         size_t n = nops();
195         for (size_t i = 0; i < n; ++i)
196                 op(i).traverse_postorder(v);
197
198         accept(v);
199 }
200
201 /** Return modifyable operand/member at position i. */
202 ex & ex::let_op(size_t i)
203 {
204         makewriteable();
205         return bp->let_op(i);
206 }
207
208 ex & ex::operator[](const ex & index)
209 {
210         makewriteable();
211         return (*bp)[index];
212 }
213
214 ex & ex::operator[](size_t i)
215 {
216         makewriteable();
217         return (*bp)[i];
218 }
219
220 /** Left hand side of relational expression. */
221 ex ex::lhs() const
222 {
223         if (!is_a<relational>(*this))
224                 throw std::runtime_error("ex::lhs(): not a relation");
225         return bp->op(0);
226 }
227
228 /** Right hand side of relational expression. */
229 ex ex::rhs() const
230 {
231         if (!is_a<relational>(*this))
232                 throw std::runtime_error("ex::rhs(): not a relation");
233         return bp->op(1);
234 }
235
236 // private
237
238 /** Make this ex writable (if more than one ex handle the same basic) by 
239  *  unlinking the object and creating an unshared copy of it. */
240 void ex::makewriteable()
241 {
242         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
243         bp.makewritable();
244         GINAC_ASSERT(bp->get_refcount() == 1);
245 }
246
247 /** Share equal objects between expressions.
248  *  @see ex::compare(const basic &) */
249 void ex::share(const ex & other) const
250 {
251         if ((bp->flags | other.bp->flags) & status_flags::not_shareable)
252                 return;
253
254         if (bp->get_refcount() <= other.bp->get_refcount())
255                 bp = other.bp;
256         else
257                 other.bp = bp;
258 }
259
260 /** Helper function for the ex-from-basic constructor. This is where GiNaC's
261  *  automatic evaluator and memory management are implemented.
262  *  @see ex::ex(const basic &) */
263 ptr<basic> ex::construct_from_basic(const basic & other)
264 {
265         if (!(other.flags & status_flags::evaluated)) {
266
267                 // The object is not yet evaluated, so call eval() to evaluate
268                 // the top level. This will return either
269                 //  a) the original object with status_flags::evaluated set (when the
270                 //     eval() implementation calls hold())
271                 // or
272                 //  b) a different expression.
273                 //
274                 // eval() returns an ex, not a basic&, so this will go through
275                 // construct_from_basic() a second time. In case a) we end up in
276                 // the "else" branch below. In case b) we end up here again and
277                 // apply eval() once more. The recursion stops when eval() calls
278                 // hold() or returns an object that already has its "evaluated"
279                 // flag set, such as a symbol or a numeric.
280                 const ex & tmpex = other.eval(1);
281
282                 // Eventually, the eval() recursion goes through the "else" branch
283                 // below, which assures that the object pointed to by tmpex.bp is
284                 // allocated on the heap (either it was already on the heap or it
285                 // is a heap-allocated duplicate of another object).
286                 GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated); 
287
288                 // If the original object is not referenced but heap-allocated,
289                 // it means that eval() hit case b) above. The original object is
290                 // no longer needed (it evaluated into something different), so we
291                 // delete it (because nobody else will).
292                 if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated))
293                         delete &other; // yes, you can apply delete to a const pointer
294
295                 // We can't return a basic& here because the tmpex is destroyed as
296                 // soon as we leave the function, which would deallocate the
297                 // evaluated object.
298                 return tmpex.bp;
299
300         } else {
301
302                 // The easy case: making an "ex" out of an evaluated object.
303                 if (other.flags & status_flags::dynallocated) {
304
305                         // The object is already heap-allocated, so we can just make
306                         // another reference to it.
307                         return ptr<basic>(const_cast<basic &>(other));
308
309                 } else {
310
311                         // The object is not heap-allocated, so we create a duplicate
312                         // on the heap.
313                         basic *bp = other.duplicate();
314                         bp->setflag(status_flags::dynallocated);
315                         GINAC_ASSERT(bp->get_refcount() == 0);
316                         return bp;
317                 }
318         }
319 }
320
321 basic & ex::construct_from_int(int i)
322 {
323         switch (i) {  // prefer flyweights over new objects
324         case -12:
325                 return const_cast<numeric &>(_num_12);
326         case -11:
327                 return const_cast<numeric &>(_num_11);
328         case -10:
329                 return const_cast<numeric &>(_num_10);
330         case -9:
331                 return const_cast<numeric &>(_num_9);
332         case -8:
333                 return const_cast<numeric &>(_num_8);
334         case -7:
335                 return const_cast<numeric &>(_num_7);
336         case -6:
337                 return const_cast<numeric &>(_num_6);
338         case -5:
339                 return const_cast<numeric &>(_num_5);
340         case -4:
341                 return const_cast<numeric &>(_num_4);
342         case -3:
343                 return const_cast<numeric &>(_num_3);
344         case -2:
345                 return const_cast<numeric &>(_num_2);
346         case -1:
347                 return const_cast<numeric &>(_num_1);
348         case 0:
349                 return const_cast<numeric &>(_num0);
350         case 1:
351                 return const_cast<numeric &>(_num1);
352         case 2:
353                 return const_cast<numeric &>(_num2);
354         case 3:
355                 return const_cast<numeric &>(_num3);
356         case 4:
357                 return const_cast<numeric &>(_num4);
358         case 5:
359                 return const_cast<numeric &>(_num5);
360         case 6:
361                 return const_cast<numeric &>(_num6);
362         case 7:
363                 return const_cast<numeric &>(_num7);
364         case 8:
365                 return const_cast<numeric &>(_num8);
366         case 9:
367                 return const_cast<numeric &>(_num9);
368         case 10:
369                 return const_cast<numeric &>(_num10);
370         case 11:
371                 return const_cast<numeric &>(_num11);
372         case 12:
373                 return const_cast<numeric &>(_num12);
374         default:
375                 basic *bp = new numeric(i);
376                 bp->setflag(status_flags::dynallocated);
377                 GINAC_ASSERT(bp->get_refcount() == 0);
378                 return *bp;
379         }
380 }
381         
382 basic & ex::construct_from_uint(unsigned int i)
383 {
384         switch (i) {  // prefer flyweights over new objects
385         case 0:
386                 return const_cast<numeric &>(_num0);
387         case 1:
388                 return const_cast<numeric &>(_num1);
389         case 2:
390                 return const_cast<numeric &>(_num2);
391         case 3:
392                 return const_cast<numeric &>(_num3);
393         case 4:
394                 return const_cast<numeric &>(_num4);
395         case 5:
396                 return const_cast<numeric &>(_num5);
397         case 6:
398                 return const_cast<numeric &>(_num6);
399         case 7:
400                 return const_cast<numeric &>(_num7);
401         case 8:
402                 return const_cast<numeric &>(_num8);
403         case 9:
404                 return const_cast<numeric &>(_num9);
405         case 10:
406                 return const_cast<numeric &>(_num10);
407         case 11:
408                 return const_cast<numeric &>(_num11);
409         case 12:
410                 return const_cast<numeric &>(_num12);
411         default:
412                 basic *bp = new numeric(i);
413                 bp->setflag(status_flags::dynallocated);
414                 GINAC_ASSERT(bp->get_refcount() == 0);
415                 return *bp;
416         }
417 }
418         
419 basic & ex::construct_from_long(long i)
420 {
421         switch (i) {  // prefer flyweights over new objects
422         case -12:
423                 return const_cast<numeric &>(_num_12);
424         case -11:
425                 return const_cast<numeric &>(_num_11);
426         case -10:
427                 return const_cast<numeric &>(_num_10);
428         case -9:
429                 return const_cast<numeric &>(_num_9);
430         case -8:
431                 return const_cast<numeric &>(_num_8);
432         case -7:
433                 return const_cast<numeric &>(_num_7);
434         case -6:
435                 return const_cast<numeric &>(_num_6);
436         case -5:
437                 return const_cast<numeric &>(_num_5);
438         case -4:
439                 return const_cast<numeric &>(_num_4);
440         case -3:
441                 return const_cast<numeric &>(_num_3);
442         case -2:
443                 return const_cast<numeric &>(_num_2);
444         case -1:
445                 return const_cast<numeric &>(_num_1);
446         case 0:
447                 return const_cast<numeric &>(_num0);
448         case 1:
449                 return const_cast<numeric &>(_num1);
450         case 2:
451                 return const_cast<numeric &>(_num2);
452         case 3:
453                 return const_cast<numeric &>(_num3);
454         case 4:
455                 return const_cast<numeric &>(_num4);
456         case 5:
457                 return const_cast<numeric &>(_num5);
458         case 6:
459                 return const_cast<numeric &>(_num6);
460         case 7:
461                 return const_cast<numeric &>(_num7);
462         case 8:
463                 return const_cast<numeric &>(_num8);
464         case 9:
465                 return const_cast<numeric &>(_num9);
466         case 10:
467                 return const_cast<numeric &>(_num10);
468         case 11:
469                 return const_cast<numeric &>(_num11);
470         case 12:
471                 return const_cast<numeric &>(_num12);
472         default:
473                 basic *bp = new numeric(i);
474                 bp->setflag(status_flags::dynallocated);
475                 GINAC_ASSERT(bp->get_refcount() == 0);
476                 return *bp;
477         }
478 }
479         
480 basic & ex::construct_from_ulong(unsigned long i)
481 {
482         switch (i) {  // prefer flyweights over new objects
483         case 0:
484                 return const_cast<numeric &>(_num0);
485         case 1:
486                 return const_cast<numeric &>(_num1);
487         case 2:
488                 return const_cast<numeric &>(_num2);
489         case 3:
490                 return const_cast<numeric &>(_num3);
491         case 4:
492                 return const_cast<numeric &>(_num4);
493         case 5:
494                 return const_cast<numeric &>(_num5);
495         case 6:
496                 return const_cast<numeric &>(_num6);
497         case 7:
498                 return const_cast<numeric &>(_num7);
499         case 8:
500                 return const_cast<numeric &>(_num8);
501         case 9:
502                 return const_cast<numeric &>(_num9);
503         case 10:
504                 return const_cast<numeric &>(_num10);
505         case 11:
506                 return const_cast<numeric &>(_num11);
507         case 12:
508                 return const_cast<numeric &>(_num12);
509         default:
510                 basic *bp = new numeric(i);
511                 bp->setflag(status_flags::dynallocated);
512                 GINAC_ASSERT(bp->get_refcount() == 0);
513                 return *bp;
514         }
515 }
516         
517 basic & ex::construct_from_double(double d)
518 {
519         basic *bp = new numeric(d);
520         bp->setflag(status_flags::dynallocated);
521         GINAC_ASSERT(bp->get_refcount() == 0);
522         return *bp;
523 }
524
525 ptr<basic> ex::construct_from_string_and_lst(const std::string &s, const ex &l)
526 {
527         set_lexer_string(s);
528         set_lexer_symbols(l);
529         ginac_yyrestart(NULL);
530         if (ginac_yyparse())
531                 throw (std::runtime_error(get_parser_error()));
532         else
533                 return parsed_ex.bp;
534 }
535         
536 //////////
537 // static member variables
538 //////////
539
540 // none
541
542 //////////
543 // functions which are not member functions
544 //////////
545
546 // none
547
548 //////////
549 // global functions
550 //////////
551
552 // none
553
554
555 } // namespace GiNaC