]> www.ginac.de Git - ginac.git/blob - ginac/ex.cpp
- No,
[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-2004 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 *this;
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
150                 // Argument is a relation: convert it to a map
151                 exmap m;
152                 const ex & s = e.op(0);
153                 m.insert(std::make_pair(s, e.op(1)));
154
155                 if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
156                         options |= subs_options::pattern_is_product;
157                 else
158                         options |= subs_options::pattern_is_not_product;
159
160                 return bp->subs(m, options);
161
162         } else if (e.info(info_flags::list)) {
163
164                 // Argument is a list: convert it to a map
165                 exmap m;
166                 GINAC_ASSERT(is_a<lst>(e));
167                 for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
168                         ex r = *it;
169                         if (!r.info(info_flags::relation_equal))
170                                 throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
171                         const ex & s = r.op(0);
172                         m.insert(std::make_pair(s, r.op(1)));
173
174                         // Search for products and powers in the expressions to be substituted
175                         // (for an optimization in expairseq::subs())
176                         if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
177                                 options |= subs_options::pattern_is_product;
178                 }
179                 if (!(options & subs_options::pattern_is_product))
180                         options |= subs_options::pattern_is_not_product;
181
182                 return bp->subs(m, options);
183
184         } else
185                 throw(std::invalid_argument("ex::subs(ex): argument must be a relation_equal or a list"));
186 }
187
188 /** Traverse expression tree with given visitor, preorder traversal. */
189 void ex::traverse_preorder(visitor & v) const
190 {
191         accept(v);
192
193         size_t n = nops();
194         for (size_t i = 0; i < n; ++i)
195                 op(i).traverse_preorder(v);
196 }
197
198 /** Traverse expression tree with given visitor, postorder traversal. */
199 void ex::traverse_postorder(visitor & v) const
200 {
201         size_t n = nops();
202         for (size_t i = 0; i < n; ++i)
203                 op(i).traverse_postorder(v);
204
205         accept(v);
206 }
207
208 /** Return modifyable operand/member at position i. */
209 ex & ex::let_op(size_t i)
210 {
211         makewriteable();
212         return bp->let_op(i);
213 }
214
215 ex & ex::operator[](const ex & index)
216 {
217         makewriteable();
218         return (*bp)[index];
219 }
220
221 ex & ex::operator[](size_t i)
222 {
223         makewriteable();
224         return (*bp)[i];
225 }
226
227 /** Left hand side of relational expression. */
228 ex ex::lhs() const
229 {
230         if (!is_a<relational>(*this))
231                 throw std::runtime_error("ex::lhs(): not a relation");
232         return bp->op(0);
233 }
234
235 /** Right hand side of relational expression. */
236 ex ex::rhs() const
237 {
238         if (!is_a<relational>(*this))
239                 throw std::runtime_error("ex::rhs(): not a relation");
240         return bp->op(1);
241 }
242
243 // private
244
245 /** Make this ex writable (if more than one ex handle the same basic) by 
246  *  unlinking the object and creating an unshared copy of it. */
247 void ex::makewriteable()
248 {
249         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
250         bp.makewritable();
251         GINAC_ASSERT(bp->get_refcount() == 1);
252 }
253
254 /** Share equal objects between expressions.
255  *  @see ex::compare(const ex &) */
256 void ex::share(const ex & other) const
257 {
258         if ((bp->flags | other.bp->flags) & status_flags::not_shareable)
259                 return;
260
261         if (bp->get_refcount() <= other.bp->get_refcount())
262                 bp = other.bp;
263         else
264                 other.bp = bp;
265 }
266
267 /** Helper function for the ex-from-basic constructor. This is where GiNaC's
268  *  automatic evaluator and memory management are implemented.
269  *  @see ex::ex(const basic &) */
270 ptr<basic> ex::construct_from_basic(const basic & other)
271 {
272         if (!(other.flags & status_flags::evaluated)) {
273
274                 // The object is not yet evaluated, so call eval() to evaluate
275                 // the top level. This will return either
276                 //  a) the original object with status_flags::evaluated set (when the
277                 //     eval() implementation calls hold())
278                 // or
279                 //  b) a different expression.
280                 //
281                 // eval() returns an ex, not a basic&, so this will go through
282                 // construct_from_basic() a second time. In case a) we end up in
283                 // the "else" branch below. In case b) we end up here again and
284                 // apply eval() once more. The recursion stops when eval() calls
285                 // hold() or returns an object that already has its "evaluated"
286                 // flag set, such as a symbol or a numeric.
287                 const ex & tmpex = other.eval(1);
288
289                 // Eventually, the eval() recursion goes through the "else" branch
290                 // below, which assures that the object pointed to by tmpex.bp is
291                 // allocated on the heap (either it was already on the heap or it
292                 // is a heap-allocated duplicate of another object).
293                 GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated); 
294
295                 // If the original object is not referenced but heap-allocated,
296                 // it means that eval() hit case b) above. The original object is
297                 // no longer needed (it evaluated into something different), so we
298                 // delete it (because nobody else will).
299                 if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated))
300                         delete &other; // yes, you can apply delete to a const pointer
301
302                 // We can't return a basic& here because the tmpex is destroyed as
303                 // soon as we leave the function, which would deallocate the
304                 // evaluated object.
305                 return tmpex.bp;
306
307         } else {
308
309                 // The easy case: making an "ex" out of an evaluated object.
310                 if (other.flags & status_flags::dynallocated) {
311
312                         // The object is already heap-allocated, so we can just make
313                         // another reference to it.
314                         return ptr<basic>(const_cast<basic &>(other));
315
316                 } else {
317
318                         // The object is not heap-allocated, so we create a duplicate
319                         // on the heap.
320                         basic *bp = other.duplicate();
321                         bp->setflag(status_flags::dynallocated);
322                         GINAC_ASSERT(bp->get_refcount() == 0);
323                         return bp;
324                 }
325         }
326 }
327
328 basic & ex::construct_from_int(int i)
329 {
330         switch (i) {  // prefer flyweights over new objects
331         case -12:
332                 return *const_cast<numeric *>(_num_12_p);
333         case -11:
334                 return *const_cast<numeric *>(_num_11_p);
335         case -10:
336                 return *const_cast<numeric *>(_num_10_p);
337         case -9:
338                 return *const_cast<numeric *>(_num_9_p);
339         case -8:
340                 return *const_cast<numeric *>(_num_8_p);
341         case -7:
342                 return *const_cast<numeric *>(_num_7_p);
343         case -6:
344                 return *const_cast<numeric *>(_num_6_p);
345         case -5:
346                 return *const_cast<numeric *>(_num_5_p);
347         case -4:
348                 return *const_cast<numeric *>(_num_4_p);
349         case -3:
350                 return *const_cast<numeric *>(_num_3_p);
351         case -2:
352                 return *const_cast<numeric *>(_num_2_p);
353         case -1:
354                 return *const_cast<numeric *>(_num_1_p);
355         case 0:
356                 return *const_cast<numeric *>(_num0_p);
357         case 1:
358                 return *const_cast<numeric *>(_num1_p);
359         case 2:
360                 return *const_cast<numeric *>(_num2_p);
361         case 3:
362                 return *const_cast<numeric *>(_num3_p);
363         case 4:
364                 return *const_cast<numeric *>(_num4_p);
365         case 5:
366                 return *const_cast<numeric *>(_num5_p);
367         case 6:
368                 return *const_cast<numeric *>(_num6_p);
369         case 7:
370                 return *const_cast<numeric *>(_num7_p);
371         case 8:
372                 return *const_cast<numeric *>(_num8_p);
373         case 9:
374                 return *const_cast<numeric *>(_num9_p);
375         case 10:
376                 return *const_cast<numeric *>(_num10_p);
377         case 11:
378                 return *const_cast<numeric *>(_num11_p);
379         case 12:
380                 return *const_cast<numeric *>(_num12_p);
381         default:
382                 basic *bp = new numeric(i);
383                 bp->setflag(status_flags::dynallocated);
384                 GINAC_ASSERT(bp->get_refcount() == 0);
385                 return *bp;
386         }
387 }
388         
389 basic & ex::construct_from_uint(unsigned int i)
390 {
391         switch (i) {  // prefer flyweights over new objects
392         case 0:
393                 return *const_cast<numeric *>(_num0_p);
394         case 1:
395                 return *const_cast<numeric *>(_num1_p);
396         case 2:
397                 return *const_cast<numeric *>(_num2_p);
398         case 3:
399                 return *const_cast<numeric *>(_num3_p);
400         case 4:
401                 return *const_cast<numeric *>(_num4_p);
402         case 5:
403                 return *const_cast<numeric *>(_num5_p);
404         case 6:
405                 return *const_cast<numeric *>(_num6_p);
406         case 7:
407                 return *const_cast<numeric *>(_num7_p);
408         case 8:
409                 return *const_cast<numeric *>(_num8_p);
410         case 9:
411                 return *const_cast<numeric *>(_num9_p);
412         case 10:
413                 return *const_cast<numeric *>(_num10_p);
414         case 11:
415                 return *const_cast<numeric *>(_num11_p);
416         case 12:
417                 return *const_cast<numeric *>(_num12_p);
418         default:
419                 basic *bp = new numeric(i);
420                 bp->setflag(status_flags::dynallocated);
421                 GINAC_ASSERT(bp->get_refcount() == 0);
422                 return *bp;
423         }
424 }
425         
426 basic & ex::construct_from_long(long i)
427 {
428         switch (i) {  // prefer flyweights over new objects
429         case -12:
430                 return *const_cast<numeric *>(_num_12_p);
431         case -11:
432                 return *const_cast<numeric *>(_num_11_p);
433         case -10:
434                 return *const_cast<numeric *>(_num_10_p);
435         case -9:
436                 return *const_cast<numeric *>(_num_9_p);
437         case -8:
438                 return *const_cast<numeric *>(_num_8_p);
439         case -7:
440                 return *const_cast<numeric *>(_num_7_p);
441         case -6:
442                 return *const_cast<numeric *>(_num_6_p);
443         case -5:
444                 return *const_cast<numeric *>(_num_5_p);
445         case -4:
446                 return *const_cast<numeric *>(_num_4_p);
447         case -3:
448                 return *const_cast<numeric *>(_num_3_p);
449         case -2:
450                 return *const_cast<numeric *>(_num_2_p);
451         case -1:
452                 return *const_cast<numeric *>(_num_1_p);
453         case 0:
454                 return *const_cast<numeric *>(_num0_p);
455         case 1:
456                 return *const_cast<numeric *>(_num1_p);
457         case 2:
458                 return *const_cast<numeric *>(_num2_p);
459         case 3:
460                 return *const_cast<numeric *>(_num3_p);
461         case 4:
462                 return *const_cast<numeric *>(_num4_p);
463         case 5:
464                 return *const_cast<numeric *>(_num5_p);
465         case 6:
466                 return *const_cast<numeric *>(_num6_p);
467         case 7:
468                 return *const_cast<numeric *>(_num7_p);
469         case 8:
470                 return *const_cast<numeric *>(_num8_p);
471         case 9:
472                 return *const_cast<numeric *>(_num9_p);
473         case 10:
474                 return *const_cast<numeric *>(_num10_p);
475         case 11:
476                 return *const_cast<numeric *>(_num11_p);
477         case 12:
478                 return *const_cast<numeric *>(_num12_p);
479         default:
480                 basic *bp = new numeric(i);
481                 bp->setflag(status_flags::dynallocated);
482                 GINAC_ASSERT(bp->get_refcount() == 0);
483                 return *bp;
484         }
485 }
486         
487 basic & ex::construct_from_ulong(unsigned long i)
488 {
489         switch (i) {  // prefer flyweights over new objects
490         case 0:
491                 return *const_cast<numeric *>(_num0_p);
492         case 1:
493                 return *const_cast<numeric *>(_num1_p);
494         case 2:
495                 return *const_cast<numeric *>(_num2_p);
496         case 3:
497                 return *const_cast<numeric *>(_num3_p);
498         case 4:
499                 return *const_cast<numeric *>(_num4_p);
500         case 5:
501                 return *const_cast<numeric *>(_num5_p);
502         case 6:
503                 return *const_cast<numeric *>(_num6_p);
504         case 7:
505                 return *const_cast<numeric *>(_num7_p);
506         case 8:
507                 return *const_cast<numeric *>(_num8_p);
508         case 9:
509                 return *const_cast<numeric *>(_num9_p);
510         case 10:
511                 return *const_cast<numeric *>(_num10_p);
512         case 11:
513                 return *const_cast<numeric *>(_num11_p);
514         case 12:
515                 return *const_cast<numeric *>(_num12_p);
516         default:
517                 basic *bp = new numeric(i);
518                 bp->setflag(status_flags::dynallocated);
519                 GINAC_ASSERT(bp->get_refcount() == 0);
520                 return *bp;
521         }
522 }
523         
524 basic & ex::construct_from_double(double d)
525 {
526         basic *bp = new numeric(d);
527         bp->setflag(status_flags::dynallocated);
528         GINAC_ASSERT(bp->get_refcount() == 0);
529         return *bp;
530 }
531
532 ptr<basic> ex::construct_from_string_and_lst(const std::string &s, const ex &l)
533 {
534         set_lexer_string(s);
535         set_lexer_symbols(l);
536         ginac_yyrestart(NULL);
537         if (ginac_yyparse())
538                 throw (std::runtime_error(get_parser_error()));
539         else
540                 return parsed_ex.bp;
541 }
542         
543 //////////
544 // static member variables
545 //////////
546
547 // none
548
549 //////////
550 // functions which are not member functions
551 //////////
552
553 // none
554
555 //////////
556 // global functions
557 //////////
558
559 // none
560
561
562 } // namespace GiNaC