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