]> www.ginac.de Git - ginac.git/blob - ginac/ex.cpp
* Finilize version 1.0.4 (version numbers, copyrights and such rubbish).
[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-2002 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 ctors
41 //////////
42
43 // none (all inlined)
44
45 //////////
46 // non-virtual functions in this class
47 //////////
48
49 // public
50         
51 /** Efficiently swap the contents of two expressions. */
52 void ex::swap(ex & other)
53 {
54         GINAC_ASSERT(bp!=0);
55         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
56         GINAC_ASSERT(other.bp!=0);
57         GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
58         
59         basic * tmpbp = bp;
60         bp = other.bp;
61         other.bp = tmpbp;
62 }
63
64 /** Print expression to stream. The formatting of the output is determined
65  *  by the kind of print_context object that is passed. Possible formattings
66  *  include ginsh-parsable output (the default), tree-like output for
67  *  debugging, and C++ source.
68  *  @see print_context */
69 void ex::print(const print_context & c, unsigned level) const
70 {
71         GINAC_ASSERT(bp!=0);
72         bp->print(c, level);
73 }
74
75 /** Print expression to stream in a tree-like format suitable for debugging. */
76 void ex::printtree(std::ostream & os) const
77 {
78         GINAC_ASSERT(bp!=0);
79         bp->print(print_tree(os));
80 }
81
82 /** Little wrapper arount print to be called within a debugger. */
83 void ex::dbgprint(void) const
84 {
85         GINAC_ASSERT(bp!=0);
86         bp->dbgprint();
87 }
88
89 /** Little wrapper arount printtree to be called within a debugger. */
90 void ex::dbgprinttree(void) const
91 {
92         GINAC_ASSERT(bp!=0);
93         bp->dbgprinttree();
94 }
95
96 ex ex::expand(unsigned options) const
97 {
98         GINAC_ASSERT(bp!=0);
99         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
100                 return *bp;
101         else
102                 return bp->expand(options);
103 }
104
105 /** Compute partial derivative of an expression.
106  *
107  *  @param s  symbol by which the expression is derived
108  *  @param nth  order of derivative (default 1)
109  *  @return partial derivative as a new expression */
110 ex ex::diff(const symbol & s, unsigned nth) const
111 {
112         GINAC_ASSERT(bp!=0);
113
114         if (!nth)
115                 return *this;
116         else
117                 return bp->diff(s, nth);
118 }
119
120 /** Check whether expression matches a specified pattern. */
121 bool ex::match(const ex & pattern) const
122 {
123         lst repl_lst;
124         return bp->match(pattern, repl_lst);
125 }
126
127 /** Find all occurrences of a pattern. The found matches are appended to
128  *  the "found" list. If the expression itself matches the pattern, the
129  *  children are not further examined. This function returns true when any
130  *  matches were found. */
131 bool ex::find(const ex & pattern, lst & found) const
132 {
133         if (match(pattern)) {
134                 found.append(*this);
135                 found.sort();
136                 found.unique();
137                 return true;
138         }
139         bool any_found = false;
140         for (unsigned i=0; i<nops(); i++)
141                 if (op(i).find(pattern, found))
142                         any_found = true;
143         return any_found;
144 }
145
146 ex ex::operator[](const ex & index) const
147 {
148         GINAC_ASSERT(bp!=0);
149         return (*bp)[index];
150 }
151
152 ex ex::operator[](int i) const
153 {
154         GINAC_ASSERT(bp!=0);
155         return (*bp)[i];
156 }
157
158 /** Return modifyable operand/member at position i. */
159 ex & ex::let_op(int i)
160 {
161         makewriteable();
162         GINAC_ASSERT(bp!=0);
163         return bp->let_op(i);
164 }
165
166 /** Left hand side of relational expression. */
167 ex ex::lhs(void) const
168 {
169         if (!is_ex_of_type(*this,relational))
170                 throw std::runtime_error("ex::lhs(): not a relation");
171         return (*static_cast<relational *>(bp)).lhs();
172 }
173
174 /** Right hand side of relational expression. */
175 ex ex::rhs(void) const
176 {
177         if (!is_ex_of_type(*this,relational))
178                 throw std::runtime_error("ex::rhs(): not a relation");
179         return (*static_cast<relational *>(bp)).rhs();
180 }
181
182 // private
183
184 /** Make this ex writable (if more than one ex handle the same basic) by 
185  *  unlinking the object and creating an unshared copy of it. */
186 void ex::makewriteable()
187 {
188         GINAC_ASSERT(bp!=0);
189         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
190         if (bp->refcount > 1) {
191                 basic * bp2 = bp->duplicate();
192                 ++bp2->refcount;
193                 bp2->setflag(status_flags::dynallocated);
194                 --bp->refcount;
195                 bp = bp2;
196         }
197         GINAC_ASSERT(bp->refcount==1);
198 }
199
200 /** Ctor from basic implementation.
201  *  @see ex::ex(const basic &) */
202 void ex::construct_from_basic(const basic & other)
203 {
204         if (!(other.flags & status_flags::evaluated)) {
205                 const ex & tmpex = other.eval(1); // evaluate only one (top) level
206                 bp = tmpex.bp;
207                 GINAC_ASSERT(bp->flags & status_flags::dynallocated);
208                 ++bp->refcount;
209                 if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
210                         delete &const_cast<basic &>(other);
211         } else {
212                 if (other.flags & status_flags::dynallocated) {
213                         // ok, it is already on the heap, so just copy bp:
214                         bp = &const_cast<basic &>(other);
215                 } else {
216                         // create a duplicate on the heap:
217                         bp = other.duplicate();
218                         bp->setflag(status_flags::dynallocated);
219                 }
220                 GINAC_ASSERT(bp!=0);
221                 ++bp->refcount;
222         }
223         GINAC_ASSERT(bp!=0);
224         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
225 }
226
227 void ex::construct_from_int(int i)
228 {
229         switch (i) {  // prefer flyweights over new objects
230         case -12:
231                 bp = (basic*)_num_12_p;
232                 ++bp->refcount;
233                 break;
234         case -11:
235                 bp = (basic*)_num_11_p;
236                 ++bp->refcount;
237                 break;
238         case -10:
239                 bp = (basic*)_num_10_p;
240                 ++bp->refcount;
241                 break;
242         case -9:
243                 bp = (basic*)_num_9_p;
244                 ++bp->refcount;
245                 break;
246         case -8:
247                 bp = (basic*)_num_8_p;
248                 ++bp->refcount;
249                 break;
250         case -7:
251                 bp = (basic*)_num_7_p;
252                 ++bp->refcount;
253                 break;
254         case -6:
255                 bp = (basic*)_num_6_p;
256                 ++bp->refcount;
257                 break;
258         case -5:
259                 bp = (basic*)_num_5_p;
260                 ++bp->refcount;
261                 break;
262         case -4:
263                 bp = (basic*)_num_4_p;
264                 ++bp->refcount;
265                 break;
266         case -3:
267                 bp = (basic*)_num_3_p;
268                 ++bp->refcount;
269                 break;
270         case -2:
271                 bp = (basic*)_num_2_p;
272                 ++bp->refcount;
273                 break;
274         case -1:
275                 bp = (basic*)_num_1_p;
276                 ++bp->refcount;
277                 break;
278         case 0:
279                 bp = (basic*)_num0_p;
280                 ++bp->refcount;
281                 break;
282         case 1:
283                 bp = (basic*)_num1_p;
284                 ++bp->refcount;
285                 break;
286         case 2:
287                 bp = (basic*)_num2_p;
288                 ++bp->refcount;
289                 break;
290         case 3:
291                 bp = (basic*)_num3_p;
292                 ++bp->refcount;
293                 break;
294         case 4:
295                 bp = (basic*)_num4_p;
296                 ++bp->refcount;
297                 break;
298         case 5:
299                 bp = (basic*)_num5_p;
300                 ++bp->refcount;
301                 break;
302         case 6:
303                 bp = (basic*)_num6_p;
304                 ++bp->refcount;
305                 break;
306         case 7:
307                 bp = (basic*)_num7_p;
308                 ++bp->refcount;
309                 break;
310         case 8:
311                 bp = (basic*)_num8_p;
312                 ++bp->refcount;
313                 break;
314         case 9:
315                 bp = (basic*)_num9_p;
316                 ++bp->refcount;
317                 break;
318         case 10:
319                 bp = (basic*)_num10_p;
320                 ++bp->refcount;
321                 break;
322         case 11:
323                 bp = (basic*)_num11_p;
324                 ++bp->refcount;
325                 break;
326         case 12:
327                 bp = (basic*)_num12_p;
328                 ++bp->refcount;
329                 break;
330         default:
331                 bp = new numeric(i);
332                 bp->setflag(status_flags::dynallocated);
333                 ++bp->refcount;
334                 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
335                 GINAC_ASSERT(bp->refcount==1);
336         }
337 }
338         
339 void ex::construct_from_uint(unsigned int i)
340 {
341         switch (i) {  // prefer flyweights over new objects
342         case 0:
343                 bp = (basic*)_num0_p;
344                 ++bp->refcount;
345                 break;
346         case 1:
347                 bp = (basic*)_num1_p;
348                 ++bp->refcount;
349                 break;
350         case 2:
351                 bp = (basic*)_num2_p;
352                 ++bp->refcount;
353                 break;
354         case 3:
355                 bp = (basic*)_num3_p;
356                 ++bp->refcount;
357                 break;
358         case 4:
359                 bp = (basic*)_num4_p;
360                 ++bp->refcount;
361                 break;
362         case 5:
363                 bp = (basic*)_num5_p;
364                 ++bp->refcount;
365                 break;
366         case 6:
367                 bp = (basic*)_num6_p;
368                 ++bp->refcount;
369                 break;
370         case 7:
371                 bp = (basic*)_num7_p;
372                 ++bp->refcount;
373                 break;
374         case 8:
375                 bp = (basic*)_num8_p;
376                 ++bp->refcount;
377                 break;
378         case 9:
379                 bp = (basic*)_num9_p;
380                 ++bp->refcount;
381                 break;
382         case 10:
383                 bp = (basic*)_num10_p;
384                 ++bp->refcount;
385                 break;
386         case 11:
387                 bp = (basic*)_num11_p;
388                 ++bp->refcount;
389                 break;
390         case 12:
391                 bp = (basic*)_num12_p;
392                 ++bp->refcount;
393                 break;
394         default:
395                 bp = new numeric(i);
396                 bp->setflag(status_flags::dynallocated);
397                 ++bp->refcount;
398                 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
399                 GINAC_ASSERT(bp->refcount==1);
400         }
401 }
402         
403 void ex::construct_from_long(long i)
404 {
405         switch (i) {  // prefer flyweights over new objects
406         case -12:
407                 bp = (basic*)_num_12_p;
408                 ++bp->refcount;
409                 break;
410         case -11:
411                 bp = (basic*)_num_11_p;
412                 ++bp->refcount;
413                 break;
414         case -10:
415                 bp = (basic*)_num_10_p;
416                 ++bp->refcount;
417                 break;
418         case -9:
419                 bp = (basic*)_num_9_p;
420                 ++bp->refcount;
421                 break;
422         case -8:
423                 bp = (basic*)_num_8_p;
424                 ++bp->refcount;
425                 break;
426         case -7:
427                 bp = (basic*)_num_7_p;
428                 ++bp->refcount;
429                 break;
430         case -6:
431                 bp = (basic*)_num_6_p;
432                 ++bp->refcount;
433                 break;
434         case -5:
435                 bp = (basic*)_num_5_p;
436                 ++bp->refcount;
437                 break;
438         case -4:
439                 bp = (basic*)_num_4_p;
440                 ++bp->refcount;
441                 break;
442         case -3:
443                 bp = (basic*)_num_3_p;
444                 ++bp->refcount;
445                 break;
446         case -2:
447                 bp = (basic*)_num_2_p;
448                 ++bp->refcount;
449                 break;
450         case -1:
451                 bp = (basic*)_num_1_p;
452                 ++bp->refcount;
453                 break;
454         case 0:
455                 bp = (basic*)_num0_p;
456                 ++bp->refcount;
457                 break;
458         case 1:
459                 bp = (basic*)_num1_p;
460                 ++bp->refcount;
461                 break;
462         case 2:
463                 bp = (basic*)_num2_p;
464                 ++bp->refcount;
465                 break;
466         case 3:
467                 bp = (basic*)_num3_p;
468                 ++bp->refcount;
469                 break;
470         case 4:
471                 bp = (basic*)_num4_p;
472                 ++bp->refcount;
473                 break;
474         case 5:
475                 bp = (basic*)_num5_p;
476                 ++bp->refcount;
477                 break;
478         case 6:
479                 bp = (basic*)_num6_p;
480                 ++bp->refcount;
481                 break;
482         case 7:
483                 bp = (basic*)_num7_p;
484                 ++bp->refcount;
485                 break;
486         case 8:
487                 bp = (basic*)_num8_p;
488                 ++bp->refcount;
489                 break;
490         case 9:
491                 bp = (basic*)_num9_p;
492                 ++bp->refcount;
493                 break;
494         case 10:
495                 bp = (basic*)_num10_p;
496                 ++bp->refcount;
497                 break;
498         case 11:
499                 bp = (basic*)_num11_p;
500                 ++bp->refcount;
501                 break;
502         case 12:
503                 bp = (basic*)_num12_p;
504                 ++bp->refcount;
505                 break;
506         default:
507                 bp = new numeric(i);
508                 bp->setflag(status_flags::dynallocated);
509                 ++bp->refcount;
510                 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
511                 GINAC_ASSERT(bp->refcount==1);
512         }
513 }
514         
515 void ex::construct_from_ulong(unsigned long i)
516 {
517         switch (i) {  // prefer flyweights over new objects
518         case 0:
519                 bp = (basic*)_num0_p;
520                 ++bp->refcount;
521                 break;
522         case 1:
523                 bp = (basic*)_num1_p;
524                 ++bp->refcount;
525                 break;
526         case 2:
527                 bp = (basic*)_num2_p;
528                 ++bp->refcount;
529                 break;
530         case 3:
531                 bp = (basic*)_num3_p;
532                 ++bp->refcount;
533                 break;
534         case 4:
535                 bp = (basic*)_num4_p;
536                 ++bp->refcount;
537                 break;
538         case 5:
539                 bp = (basic*)_num5_p;
540                 ++bp->refcount;
541                 break;
542         case 6:
543                 bp = (basic*)_num6_p;
544                 ++bp->refcount;
545                 break;
546         case 7:
547                 bp = (basic*)_num7_p;
548                 ++bp->refcount;
549                 break;
550         case 8:
551                 bp = (basic*)_num8_p;
552                 ++bp->refcount;
553                 break;
554         case 9:
555                 bp = (basic*)_num9_p;
556                 ++bp->refcount;
557                 break;
558         case 10:
559                 bp = (basic*)_num10_p;
560                 ++bp->refcount;
561                 break;
562         case 11:
563                 bp = (basic*)_num11_p;
564                 ++bp->refcount;
565                 break;
566         case 12:
567                 bp = (basic*)_num12_p;
568                 ++bp->refcount;
569                 break;
570         default:
571                 bp = new numeric(i);
572                 bp->setflag(status_flags::dynallocated);
573                 ++bp->refcount;
574                 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
575                 GINAC_ASSERT(bp->refcount==1);
576         }
577 }
578         
579 void ex::construct_from_double(double d)
580 {
581         bp = new numeric(d);
582         bp->setflag(status_flags::dynallocated);
583         ++bp->refcount;
584         GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
585         GINAC_ASSERT(bp->refcount==1);
586 }
587
588 void ex::construct_from_string_and_lst(const std::string &s, const ex &l)
589 {
590         set_lexer_string(s);
591         set_lexer_symbols(l);
592         ginac_yyrestart(NULL);
593         if (ginac_yyparse())
594                 throw (std::runtime_error(get_parser_error()));
595         else {
596                 bp = parsed_ex.bp;
597                 GINAC_ASSERT(bp!=0);
598                 GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
599                 ++bp->refcount;
600         }
601 }
602         
603 //////////
604 // static member variables
605 //////////
606
607 // none
608
609 //////////
610 // functions which are not member functions
611 //////////
612
613 // none
614
615 //////////
616 // global functions
617 //////////
618
619 // none
620
621
622 } // namespace GiNaC