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