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