]> www.ginac.de Git - ginac.git/blob - ginac/ex.cpp
412f8c95509fb3af03367b5a4a9de4d90474e44d
[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-2000 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
25 #include "ex.h"
26 #include "add.h"
27 #include "mul.h"
28 #include "ncmul.h"
29 #include "numeric.h"
30 #include "power.h"
31 #include "relational.h"
32 #include "debugmsg.h"
33 #include "utils.h"
34
35 #ifndef NO_NAMESPACE_GINAC
36 namespace GiNaC {
37 #endif // ndef NO_NAMESPACE_GINAC
38
39 //////////
40 // default constructor, destructor, copy constructor assignment operator and helpers
41 //////////
42
43 // public
44
45 #ifndef INLINE_EX_CONSTRUCTORS
46
47 ex::ex() : bp(ex0().bp)
48 {
49     debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
50     GINAC_ASSERT(ex0().bp!=0);
51     GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
52     GINAC_ASSERT(bp!=0);
53     ++bp->refcount;
54 }
55
56 ex::~ex()
57 {
58     debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
59     GINAC_ASSERT(bp!=0);
60     GINAC_ASSERT(bp->flags & status_flags::dynallocated);
61     if (--bp->refcount == 0) {
62         delete bp;
63     }
64 }
65
66 ex::ex(const ex & other) : bp(other.bp)
67 {
68     debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
69     GINAC_ASSERT(bp!=0);
70     GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
71     ++bp->refcount;
72 }
73
74 const ex & ex::operator=(const ex & other)
75 {
76     debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
77     GINAC_ASSERT(bp!=0);
78     GINAC_ASSERT(bp->flags & status_flags::dynallocated);
79     GINAC_ASSERT(other.bp!=0);
80     GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
81     ++other.bp->refcount;
82     basic * tmpbp=other.bp;
83     if (--bp->refcount==0) {
84             delete bp;
85     }
86     bp=tmpbp;
87     return *this;
88 }
89
90 #endif // ndef INLINE_EX_CONSTRUCTORS
91
92 //////////
93 // other constructors
94 //////////
95
96 // public
97
98 #ifndef INLINE_EX_CONSTRUCTORS
99
100 ex::ex(const basic & other)
101 {
102     debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
103     construct_from_basic(other);
104 }
105
106 ex::ex(int i)
107 {
108     debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
109     construct_from_int(i);
110 }
111
112 ex::ex(unsigned int i)
113 {
114     debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
115     construct_from_uint(i);
116 }
117
118 ex::ex(long i)
119 {
120     debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
121     construct_from_long(i);
122 }
123
124 ex::ex(unsigned long i)
125 {
126     debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
127     construct_from_ulong(i);
128 }
129
130 ex::ex(double const d)
131 {
132     debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
133     construct_from_double(d);
134 }
135
136 #endif // ndef INLINE_EX_CONSTRUCTORS
137
138 //////////
139 // functions overriding virtual functions from bases classes
140 //////////
141
142 // none
143
144 //////////
145 // new virtual functions which can be overridden by derived classes
146 //////////
147
148 // none
149
150 //////////
151 // non-virtual functions in this class
152 //////////
153
154 // public
155
156 /** Swap the contents of two expressions. */
157 void ex::swap(ex & other)
158 {
159     debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
160
161     GINAC_ASSERT(bp!=0);
162     GINAC_ASSERT(bp->flags & status_flags::dynallocated);
163     GINAC_ASSERT(other.bp!=0);
164     GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
165     
166     basic * tmpbp=bp;
167     bp=other.bp;
168     other.bp=tmpbp;
169 }
170
171 /** Output formatted to be useful as ginsh input. */
172 void ex::print(ostream & os, unsigned upper_precedence) const
173 {
174     debugmsg("ex print",LOGLEVEL_PRINT);
175     GINAC_ASSERT(bp!=0);
176     bp->print(os,upper_precedence);
177 }
178
179 void ex::printraw(ostream & os) const
180 {
181     debugmsg("ex printraw",LOGLEVEL_PRINT);
182     GINAC_ASSERT(bp!=0);
183     os << "ex(";
184     bp->printraw(os);
185     os << ")";
186 }
187
188 void ex::printtree(ostream & os, unsigned indent) const
189 {
190     debugmsg("ex printtree",LOGLEVEL_PRINT);
191     GINAC_ASSERT(bp!=0);
192     // os << "refcount=" << bp->refcount << " ";
193     bp->printtree(os,indent);
194 }
195
196 /** Print expression as a C++ statement. The output looks like
197  *  "<type> <var_name> = <expression>;". The "type" parameter has an effect
198  *  on how number literals are printed.
199  *
200  *  @param os output stream
201  *  @param type variable type (one of the csrc_types)
202  *  @param var_name variable name to be printed */
203 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
204 {
205     debugmsg("ex print csrc", LOGLEVEL_PRINT);
206     GINAC_ASSERT(bp!=0);
207     switch (type) {
208         case csrc_types::ctype_float:
209             os << "float ";
210             break;
211         case csrc_types::ctype_double:
212             os << "double ";
213             break;
214         case csrc_types::ctype_cl_N:
215             os << "cl_N ";
216             break;
217     }
218     os << var_name << " = ";
219     bp->printcsrc(os, type, 0);
220     os << ";\n";
221 }
222
223 /** Little wrapper arount print to be called within a debugger. */
224 void ex::dbgprint(void) const
225 {
226     debugmsg("ex dbgprint",LOGLEVEL_PRINT);
227     GINAC_ASSERT(bp!=0);
228     bp->dbgprint();
229 }
230
231 /** Little wrapper arount printtree to be called within a debugger. */
232 void ex::dbgprinttree(void) const
233 {
234     debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
235     GINAC_ASSERT(bp!=0);
236     bp->dbgprinttree();
237 }
238
239 bool ex::info(unsigned inf) const
240 {
241     if (inf == info_flags::normal_form) {
242
243     // Polynomials are in normal form
244     if (info(info_flags::polynomial))
245         return true;
246
247     // polynomial^(-int) is in normal form
248     if (is_ex_exactly_of_type(*this, power))
249         return op(1).info(info_flags::negint);
250
251     // polynomial^(int) * polynomial^(int) * ... is in normal form
252     if (!is_ex_exactly_of_type(*this, mul))
253         return false;
254     for (unsigned i=0; i<nops(); i++) {
255         if (is_ex_exactly_of_type(op(i), power)) {
256             if (!op(i).op(1).info(info_flags::integer))
257                 return false;
258             if (!op(i).op(0).info(info_flags::polynomial))
259                 return false;
260         } else
261             if (!op(i).info(info_flags::polynomial))
262                 return false;
263     }
264     return true;
265     } else {
266         return bp->info(inf);
267     }
268 }
269
270 unsigned ex::nops() const
271 {
272     GINAC_ASSERT(bp!=0);
273     return bp->nops();
274 }
275
276 ex ex::expand(unsigned options) const
277 {
278     GINAC_ASSERT(bp!=0);
279     return bp->expand(options);
280 }
281
282 bool ex::has(const ex & other) const
283 {
284     GINAC_ASSERT(bp!=0);
285     return bp->has(other);
286 }
287
288 int ex::degree(const symbol & s) const
289 {
290     GINAC_ASSERT(bp!=0);
291     return bp->degree(s);
292 }
293
294 int ex::ldegree(const symbol & s) const
295 {
296     GINAC_ASSERT(bp!=0);
297     return bp->ldegree(s);
298 }
299
300 ex ex::coeff(const symbol & s, int n) const
301 {
302     GINAC_ASSERT(bp!=0);
303     return bp->coeff(s,n);
304 }
305
306 ex ex::numer(bool normalize) const
307 {
308     ex n;
309     if (normalize && !info(info_flags::normal_form))
310         n = normal();
311     else
312         n = *this;
313
314     // polynomial
315     if (n.info(info_flags::polynomial))
316         return n;
317
318     // something^(-int)
319     if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
320         return _ex1();
321
322     // something^(int) * something^(int) * ...
323     if (!is_ex_exactly_of_type(n, mul))
324         return n;
325     ex res = _ex1();
326     for (unsigned i=0; i<n.nops(); i++) {
327         if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
328             res *= n.op(i);
329     }
330     return res;
331 }
332
333 ex ex::denom(bool normalize) const
334 {
335     ex n;
336     if (normalize && !info(info_flags::normal_form))
337         n = normal();
338     else
339         n = *this;
340
341     // polynomial
342     if (n.info(info_flags::polynomial))
343         return _ex1();
344
345     // something^(-int)
346     if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
347         return power(n.op(0), -(n.op(1)));
348
349     // something^(int) * something^(int) * ...
350     if (!is_ex_exactly_of_type(n, mul))
351         return _ex1();
352     ex res = _ex1();
353     for (unsigned i=0; i<n.nops(); i++) {
354         if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
355             res *= power(n.op(i), -1);
356     }
357     return res;
358 }
359
360 ex ex::collect(const symbol & s) const
361 {
362     GINAC_ASSERT(bp!=0);
363     return bp->collect(s);
364 }
365
366 ex ex::eval(int level) const
367 {
368     GINAC_ASSERT(bp!=0);
369     return bp->eval(level);
370 }
371
372 ex ex::evalf(int level) const
373 {
374     GINAC_ASSERT(bp!=0);
375     return bp->evalf(level);
376 }
377
378 /** Compute partial derivative of an expression.
379  *
380  *  @param s  symbol by which the expression is derived
381  *  @param nth  order of derivative (default 1)
382  *  @return partial derivative as a new expression */
383 ex ex::diff(const symbol & s, unsigned nth) const
384 {
385     GINAC_ASSERT(bp!=0);
386
387     if (!nth)
388         return *this;
389     else
390         return bp->diff(s, nth);
391 }
392
393 ex ex::subs(const lst & ls, const lst & lr) const
394 {
395     GINAC_ASSERT(bp!=0);
396     return bp->subs(ls,lr);
397 }
398
399 ex ex::subs(const ex & e) const
400 {
401     GINAC_ASSERT(bp!=0);
402     return bp->subs(e);
403 }
404
405 exvector ex::get_indices(void) const
406 {
407     GINAC_ASSERT(bp!=0);
408     return bp->get_indices();
409 }
410
411 ex ex::simplify_ncmul(const exvector & v) const
412 {
413     GINAC_ASSERT(bp!=0);
414     return bp->simplify_ncmul(v);
415 }
416
417 ex ex::operator[](const ex & index) const
418 {
419     debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
420     GINAC_ASSERT(bp!=0);
421     return (*bp)[index];
422 }
423
424 ex ex::operator[](int i) const
425 {
426     debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
427     GINAC_ASSERT(bp!=0);
428     return (*bp)[i];
429 }
430
431 /** Return operand/member at position i. */
432 ex ex::op(int i) const
433 {
434     debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
435     GINAC_ASSERT(bp!=0);
436     return bp->op(i);
437 }
438
439 /** Return modifyable operand/member at position i. */
440 ex & ex::let_op(int i)
441 {
442     debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
443     makewriteable();
444     GINAC_ASSERT(bp!=0);
445     return bp->let_op(i);
446 }
447
448 /** Left hand side of relational expression. */
449 ex ex::lhs(void) const
450 {
451     debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
452     GINAC_ASSERT(is_ex_of_type(*this,relational));
453     return (*static_cast<relational *>(bp)).lhs();
454 }
455
456 /** Right hand side of relational expression. */
457 ex ex::rhs(void) const
458 {
459     debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
460     GINAC_ASSERT(is_ex_of_type(*this,relational));
461     return (*static_cast<relational *>(bp)).rhs();
462 }
463
464 #ifndef INLINE_EX_CONSTRUCTORS
465 int ex::compare(const ex & other) const
466 {
467     GINAC_ASSERT(bp!=0);
468     GINAC_ASSERT(other.bp!=0);
469     if (bp==other.bp) {
470         // special case: both expression point to same basic, trivially equal
471         return 0; 
472     }
473     return bp->compare(*other.bp);
474 }
475 #endif // ndef INLINE_EX_CONSTRUCTORS
476
477 #ifndef INLINE_EX_CONSTRUCTORS
478 bool ex::is_equal(const ex & other) const
479 {
480     GINAC_ASSERT(bp!=0);
481     GINAC_ASSERT(other.bp!=0);
482     if (bp==other.bp) {
483         // special case: both expression point to same basic, trivially equal
484         return true; 
485     }
486     return bp->is_equal(*other.bp);
487 }
488 #endif // ndef INLINE_EX_CONSTRUCTORS
489
490 unsigned ex::return_type(void) const
491 {
492     GINAC_ASSERT(bp!=0);
493     return bp->return_type();
494 }
495
496 unsigned ex::return_type_tinfo(void) const
497 {
498     GINAC_ASSERT(bp!=0);
499     return bp->return_type_tinfo();
500 }
501
502 unsigned ex::gethash(void) const
503 {
504     GINAC_ASSERT(bp!=0);
505     return bp->gethash();
506 }
507
508 ex ex::exadd(const ex & rh) const
509 {
510     return (new add(*this,rh))->setflag(status_flags::dynallocated);
511 }
512
513 ex ex::exmul(const ex & rh) const
514 {
515     return (new mul(*this,rh))->setflag(status_flags::dynallocated);
516 }
517
518 ex ex::exncmul(const ex & rh) const
519 {
520     return (new ncmul(*this,rh))->setflag(status_flags::dynallocated);
521 }
522
523 // private
524
525 void ex::makewriteable()
526 {
527     debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
528     GINAC_ASSERT(bp!=0);
529     GINAC_ASSERT(bp->flags & status_flags::dynallocated);
530     if (bp->refcount > 1) {
531         basic * bp2 = bp->duplicate();
532         ++bp2->refcount;
533         bp2->setflag(status_flags::dynallocated);
534         --bp->refcount;
535         bp = bp2;
536     }
537     GINAC_ASSERT(bp->refcount == 1);
538 }
539
540 void ex::construct_from_basic(const basic & other)
541 {
542     if ((other.flags & status_flags::evaluated)==0) {
543         // cf. copy constructor
544         const ex & tmpex = other.eval(1); // evaluate only one (top) level
545         bp = tmpex.bp;
546         GINAC_ASSERT(bp!=0);
547         GINAC_ASSERT(bp->flags & status_flags::dynallocated);
548         ++bp->refcount;
549         if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
550             delete &const_cast<basic &>(other);
551         }
552     } else {
553         if (other.flags & status_flags::dynallocated) {
554             bp = &const_cast<basic &>(other);
555         } else {
556             bp = other.duplicate();
557             bp->setflag(status_flags::dynallocated);
558         }
559         GINAC_ASSERT(bp!=0);
560         // bp->clearflag(status_flags::evaluated);
561         ++bp->refcount;
562     }
563     GINAC_ASSERT(bp!=0);
564     GINAC_ASSERT(bp->flags & status_flags::dynallocated);
565 }
566
567 void ex::construct_from_int(int i)
568 {
569     switch (i) {  // some tiny efficiency-hack
570     case -2:
571         bp = _ex_2().bp;
572         ++bp->refcount;
573         break;
574     case -1:
575         bp = _ex_1().bp;
576         ++bp->refcount;
577         break;
578     case 0:
579         bp = _ex0().bp;
580         ++bp->refcount;
581         break;
582     case 1:
583         bp = _ex1().bp;
584         ++bp->refcount;
585         break;
586     case 2:
587         bp = _ex2().bp;
588         ++bp->refcount;
589         break;
590     default:
591         bp = new numeric(i);
592         bp->setflag(status_flags::dynallocated);
593         ++bp->refcount;
594         GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
595         GINAC_ASSERT(bp->refcount=1);
596     }
597 }
598     
599 void ex::construct_from_uint(unsigned int i)
600 {
601     switch (i) {  // some tiny efficiency-hack
602     case -2:
603         bp = _ex_2().bp;
604         ++bp->refcount;
605         break;
606     case -1:
607         bp = _ex_1().bp;
608         ++bp->refcount;
609         break;
610     case 0:
611         bp = _ex0().bp;
612         ++bp->refcount;
613         break;
614     case 1:
615         bp = _ex1().bp;
616         ++bp->refcount;
617         break;
618     case 2:
619         bp = _ex2().bp;
620         ++bp->refcount;
621         break;
622     default:
623         bp = new numeric(i);
624         bp->setflag(status_flags::dynallocated);
625         ++bp->refcount;
626         GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
627         GINAC_ASSERT(bp->refcount=1);
628     }
629 }
630     
631 void ex::construct_from_long(long i)
632 {
633     switch (i) {  // some tiny efficiency-hack
634     case -2:
635         bp = _ex_2().bp;
636         ++bp->refcount;
637         break;
638     case -1:
639         bp = _ex_1().bp;
640         ++bp->refcount;
641         break;
642     case 0:
643         bp = _ex0().bp;
644         ++bp->refcount;
645         break;
646     case 1:
647         bp = _ex1().bp;
648         ++bp->refcount;
649         break;
650     case 2:
651         bp = _ex2().bp;
652         ++bp->refcount;
653         break;
654     default:
655         bp = new numeric(i);
656         bp->setflag(status_flags::dynallocated);
657         ++bp->refcount;
658         GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
659         GINAC_ASSERT(bp->refcount=1);
660     }
661 }
662     
663 void ex::construct_from_ulong(unsigned long i)
664 {
665     switch (i) {  // some tiny efficiency-hack
666     case -2:
667         bp = _ex_2().bp;
668         ++bp->refcount;
669         break;
670     case -1:
671         bp = _ex_1().bp;
672         ++bp->refcount;
673         break;
674     case 0:
675         bp = _ex0().bp;
676         ++bp->refcount;
677         break;
678     case 1:
679         bp = _ex1().bp;
680         ++bp->refcount;
681         break;
682     case 2:
683         bp = _ex2().bp;
684         ++bp->refcount;
685         break;
686     default:
687         bp = new numeric(i);
688         bp->setflag(status_flags::dynallocated);
689         ++bp->refcount;
690         GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
691         GINAC_ASSERT(bp->refcount=1);
692     }
693 }
694     
695 void ex::construct_from_double(double d)
696 {
697     bp = new numeric(d);
698     bp->setflag(status_flags::dynallocated);
699     ++bp->refcount;
700     GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
701     GINAC_ASSERT(bp->refcount=1);
702 }
703     
704 //////////
705 // static member variables
706 //////////
707
708 // none
709
710 //////////
711 // functions which are not member functions
712 //////////
713
714 // none
715
716 //////////
717 // global functions
718 //////////
719
720 // none
721
722
723 #ifndef NO_NAMESPACE_GINAC
724 } // namespace GiNaC
725 #endif // ndef NO_NAMESPACE_GINAC