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