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