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