- ASSERT macro renamed to GINAC_ASSERT
[ginac.git] / ginac / exprseq.cpp
1 /** @file exprseq.cpp
2  *
3  *  Implementation of GiNaC's exprseq. */
4
5 /*
6  *  This file was generated automatically by container.pl.
7  *  Please do not modify it directly, edit the perl script instead!
8  *  container.pl options: $CONTAINER=exprseq
9  *                        $STLHEADER=vector
10  *                        $reserve=1
11  *                        $prepend=0
12  *                        $let_op=0
13  *                        $open_bracket=(
14  *                        $close_bracket=)
15  *
16  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
17  *
18  *  This program is free software; you can redistribute it and/or modify
19  *  it under the terms of the GNU General Public License as published by
20  *  the Free Software Foundation; either version 2 of the License, or
21  *  (at your option) any later version.
22  *
23  *  This program is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with this program; if not, write to the Free Software
30  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31  */
32
33 #include <iostream>
34 #include <stdexcept>
35
36 #include "exprseq.h"
37 #include "ex.h"
38 #include "debugmsg.h"
39
40 namespace GiNaC {
41
42 #define RESERVE(s,size) (s).reserve(size)
43
44 //////////
45 // default constructor, destructor, copy constructor assignment operator and helpers
46 //////////
47
48 // public
49
50 exprseq::exprseq() : basic(TINFO_exprseq)
51 {
52     debugmsg("exprseq default constructor",LOGLEVEL_CONSTRUCT);
53 }
54
55 exprseq::~exprseq()
56 {
57     debugmsg("exprseq destructor",LOGLEVEL_DESTRUCT);
58     destroy(0);
59 }
60
61 exprseq::exprseq(exprseq const & other)
62 {
63     debugmsg("exprseq copy constructor",LOGLEVEL_CONSTRUCT);
64     copy(other);
65 }
66
67 exprseq const & exprseq::operator=(exprseq const & other)
68 {
69     debugmsg("exprseq operator=",LOGLEVEL_ASSIGNMENT);
70     if (this != &other) {
71         destroy(1);
72         copy(other);
73     }
74     return *this;
75 }
76
77 // protected
78
79 void exprseq::copy(exprseq const & other)
80 {
81     basic::copy(other);
82     seq=other.seq;
83 }
84
85 void exprseq::destroy(bool call_parent)
86 {
87     seq.clear();
88     if (call_parent) basic::destroy(call_parent);
89 }
90
91 //////////
92 // other constructors
93 //////////
94
95 // public
96
97 exprseq::exprseq(exvector const & s, bool discardable) :  basic(TINFO_exprseq)
98 {
99     debugmsg("exprseq constructor from exvector",
100              LOGLEVEL_CONSTRUCT);
101     if (discardable) {
102         seq.swap(const_cast<exvector &>(s));
103     } else {
104         seq=s;
105     }
106 }
107
108 exprseq::exprseq(exvector * vp) : basic(TINFO_exprseq)
109 {
110     debugmsg("exprseq constructor from exvector *",LOGLEVEL_CONSTRUCT);
111     GINAC_ASSERT(vp!=0);
112     seq.swap(*vp);
113     delete vp;
114 }
115
116 exprseq::exprseq(ex const & e1) :  basic(TINFO_exprseq)
117 {
118     debugmsg("exprseq constructor from 1 ex",
119              LOGLEVEL_CONSTRUCT);
120     RESERVE(seq,1);
121     seq.push_back(e1);
122 }
123
124 exprseq::exprseq(ex const & e1, ex const & e2) : basic(TINFO_exprseq)
125 {
126     debugmsg("exprseq constructor from 2 ex",
127              LOGLEVEL_CONSTRUCT);
128     RESERVE(seq,2);
129     seq.push_back(e1);
130     seq.push_back(e2);
131 }
132
133 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3)
134     : basic(TINFO_exprseq)
135 {
136     debugmsg("exprseq constructor from 3 ex",
137              LOGLEVEL_CONSTRUCT);
138     RESERVE(seq,3);
139     seq.push_back(e1);
140     seq.push_back(e2);
141     seq.push_back(e3);
142 }
143
144 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
145                      ex const & e4) : basic(TINFO_exprseq)
146 {
147     debugmsg("exprseq constructor from 4 ex",
148              LOGLEVEL_CONSTRUCT);
149     RESERVE(seq,4);
150     seq.push_back(e1);
151     seq.push_back(e2);
152     seq.push_back(e3);
153     seq.push_back(e4);
154 }
155
156 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
157                      ex const & e4, ex const & e5) : basic(TINFO_exprseq)
158 {
159     debugmsg("exprseq constructor from 5 ex",
160              LOGLEVEL_CONSTRUCT);
161     RESERVE(seq,5);
162     seq.push_back(e1);
163     seq.push_back(e2);
164     seq.push_back(e3);
165     seq.push_back(e4);
166     seq.push_back(e5);
167 }
168
169 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
170                      ex const & e4, ex const & e5, ex const & e6)
171     : basic(TINFO_exprseq)
172 {
173     debugmsg("exprseq constructor from 6 ex",
174              LOGLEVEL_CONSTRUCT);
175     RESERVE(seq,6);
176     seq.push_back(e1);
177     seq.push_back(e2);
178     seq.push_back(e3);
179     seq.push_back(e4);
180     seq.push_back(e5);
181     seq.push_back(e6);
182 }
183
184 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
185                      ex const & e4, ex const & e5, ex const & e6,
186                      ex const & e7) : basic(TINFO_exprseq)
187 {
188     debugmsg("exprseq constructor from 7 ex",
189              LOGLEVEL_CONSTRUCT);
190     RESERVE(seq,7);
191     seq.push_back(e1);
192     seq.push_back(e2);
193     seq.push_back(e3);
194     seq.push_back(e4);
195     seq.push_back(e5);
196     seq.push_back(e6);
197     seq.push_back(e7);
198 }
199
200 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
201                      ex const & e4, ex const & e5, ex const & e6,
202                      ex const & e7, ex const & e8) : basic(TINFO_exprseq)
203 {
204     debugmsg("exprseq constructor from 8 ex",
205              LOGLEVEL_CONSTRUCT);
206     RESERVE(seq,8);
207     seq.push_back(e1);
208     seq.push_back(e2);
209     seq.push_back(e3);
210     seq.push_back(e4);
211     seq.push_back(e5);
212     seq.push_back(e6);
213     seq.push_back(e7);
214     seq.push_back(e8);
215 }
216
217 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
218                      ex const & e4, ex const & e5, ex const & e6,
219                      ex const & e7, ex const & e8, ex const & e9)
220     : basic(TINFO_exprseq)
221 {
222     debugmsg("exprseq constructor from 9 ex",
223              LOGLEVEL_CONSTRUCT);
224     RESERVE(seq,9);
225     seq.push_back(e1);
226     seq.push_back(e2);
227     seq.push_back(e3);
228     seq.push_back(e4);
229     seq.push_back(e5);
230     seq.push_back(e6);
231     seq.push_back(e7);
232     seq.push_back(e8);
233     seq.push_back(e9);
234 }
235
236 exprseq::exprseq(ex const & e1, ex const & e2, ex const & e3,
237                      ex const & e4, ex const & e5, ex const & e6,
238                      ex const & e7, ex const & e8, ex const & e9,
239                      ex const &e10)
240     : basic(TINFO_exprseq)
241 {
242     debugmsg("exprseq constructor from 10 ex",
243              LOGLEVEL_CONSTRUCT);
244     RESERVE(seq,10);
245     seq.push_back(e1);
246     seq.push_back(e2);
247     seq.push_back(e3);
248     seq.push_back(e4);
249     seq.push_back(e5);
250     seq.push_back(e6);
251     seq.push_back(e7);
252     seq.push_back(e8);
253     seq.push_back(e9);
254     seq.push_back(e10);
255 }
256
257 //////////
258 // functions overriding virtual functions from bases classes
259 //////////
260
261 // public
262
263 basic * exprseq::duplicate() const
264 {
265     debugmsg("exprseq duplicate",LOGLEVEL_DUPLICATE);
266     return new exprseq(*this);
267 }
268
269 void exprseq::printraw(ostream & os) const
270 {
271     debugmsg("exprseq printraw",LOGLEVEL_PRINT);
272
273     os << "exprseq(";
274     for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
275         (*cit).bp->printraw(os);
276         os << ",";
277     }
278     os << ")";
279 }
280
281 void exprseq::print(ostream & os, unsigned upper_precedence) const
282 {
283     debugmsg("exprseq print",LOGLEVEL_PRINT);
284     // always print brackets around seq, ignore upper_precedence
285     printseq(os,'(',',',')',precedence,precedence+1);
286 }
287
288 void exprseq::printtree(ostream & os, unsigned indent) const
289 {
290     debugmsg("exprseq printtree",LOGLEVEL_PRINT);
291
292     os << string(indent,' ') << "type=" << typeid(*this).name()
293        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
294        << ", flags=" << flags
295        << ", nops=" << nops() << endl;
296     for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
297         (*cit).printtree(os,indent+delta_indent);
298     }
299     os << string(indent+delta_indent,' ') << "=====" << endl;
300 }
301
302 // exprseq::info() will be implemented by user elsewhere";
303
304 int exprseq::nops() const
305 {
306     return seq.size();
307 }
308
309 // exprseq::let_op() will be implemented by user elsewhere
310
311 ex exprseq::expand(unsigned options) const
312 {
313     exvector s;
314     RESERVE(s,seq.size());
315     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
316         s.push_back((*it).expand(options));
317     }
318
319     return thisexprseq(s);
320 }
321
322 // a exprseq 'has' an expression if it is this expression itself or a child 'has' it
323
324 bool exprseq::has(ex const & other) const
325 {
326     GINAC_ASSERT(other.bp!=0);
327     if (is_equal(*other.bp)) return true;
328     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
329         if ((*it).has(other)) return true;
330     }
331     return false;
332 }
333
334 ex exprseq::eval(int level) const
335 {
336     if (level==1) {
337         return this->hold();
338     }
339     return thisexprseq(evalchildren(level));
340 }
341
342 ex exprseq::evalf(int level) const
343 {
344     return thisexprseq(evalfchildren(level));
345 }
346
347 /** Implementation of ex::normal() for exprseqs. It normalizes the arguments
348  *  and replaces the exprseq by a temporary symbol.
349  *  @see ex::normal */
350 ex exprseq::normal(lst &sym_lst, lst &repl_lst, int level) const
351 {
352     ex n=thisexprseq(normalchildren(level));
353     return n.bp->basic::normal(sym_lst,repl_lst,level);
354 }
355
356 ex exprseq::diff(symbol const & s) const
357 {
358     return thisexprseq(diffchildren(s));
359 }
360
361 ex exprseq::subs(lst const & ls, lst const & lr) const
362 {
363     exvector * vp=subschildren(ls,lr);
364     if (vp==0) {
365         return *this;
366     }
367     return thisexprseq(vp);
368 }
369
370 // protected
371
372 int exprseq::compare_same_type(basic const & other) const
373 {
374     GINAC_ASSERT(is_of_type(other,exprseq));
375     exprseq const & o=static_cast<exprseq const &>
376                                     (const_cast<basic &>(other));
377     int cmpval;
378     exvector::const_iterator it1=seq.begin();
379     exvector::const_iterator it2=o.seq.begin();
380
381     for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
382         cmpval=(*it1).compare(*it2);
383         if (cmpval!=0) return cmpval;
384     }
385
386     if (it1==seq.end()) {
387         return (it2==o.seq.end() ? 0 : -1);
388     }
389
390     return 1;
391 }
392
393 bool exprseq::is_equal_same_type(basic const & other) const
394 {
395     GINAC_ASSERT(is_of_type(other,exprseq));
396     exprseq const & o=static_cast<exprseq const &>
397                                     (const_cast<basic &>(other));
398     if (seq.size()!=o.seq.size()) return false;
399
400     exvector::const_iterator it1=seq.begin();
401     exvector::const_iterator it2=o.seq.begin();
402
403     for (; it1!=seq.end(); ++it1, ++it2) {
404         if (!(*it1).is_equal(*it2)) return false;
405     }
406
407     return true;
408 }
409
410 unsigned exprseq::return_type(void) const
411 {
412     return return_types::noncommutative_composite;
413 }
414
415 //////////
416 // new virtual functions which can be overridden by derived classes
417 //////////
418
419 // public
420
421 exprseq & exprseq::append(ex const & b)
422 {
423     ensure_if_modifiable();
424     seq.push_back(b);
425     return *this;
426 }
427
428
429
430 // protected
431
432 void exprseq::printseq(ostream & os, char openbracket, char delim,
433                          char closebracket, unsigned this_precedence,
434                          unsigned upper_precedence) const
435 {
436     if (this_precedence<=upper_precedence) os << openbracket;
437     if (seq.size()!=0) {
438         exvector::const_iterator it,it_last;
439         it=seq.begin();
440         it_last=seq.end();
441         --it_last;
442         for (; it!=it_last; ++it) {
443             (*it).bp->print(os,this_precedence);
444             os << delim;
445         }
446         (*it).bp->print(os,this_precedence);
447     }
448     if (this_precedence<=upper_precedence) os << closebracket;
449 }
450
451 ex exprseq::thisexprseq(exvector const & v) const
452 {
453     return exprseq(v);
454 }
455
456 ex exprseq::thisexprseq(exvector * vp) const
457 {
458     return exprseq(vp);
459 }
460
461 //////////
462 // non-virtual functions in this class
463 //////////
464
465 // public
466
467 // none
468
469 // protected
470
471 bool exprseq::is_canonical() const
472 {
473     if (seq.size()<=1) { return 1; }
474
475     exvector::const_iterator it=seq.begin();
476     exvector::const_iterator it_last=it;
477     for (++it; it!=seq.end(); it_last=it, ++it) {
478         if ((*it_last).compare(*it)>0) {
479             if ((*it_last).compare(*it)>0) {
480                 cout << *it_last << ">" << *it << "\n";
481                 return 0;
482                 }
483         }
484     }
485     return 1;
486 }
487
488
489 exvector exprseq::evalchildren(int level) const
490 {
491     exvector s;
492     RESERVE(s,seq.size());
493
494     if (level==1) {
495         return seq;
496     }
497     if (level == -max_recursion_level) {
498         throw(std::runtime_error("max recursion level reached"));
499     }
500     --level;
501     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
502         s.push_back((*it).eval(level));
503     }
504     return s;
505 }
506
507 exvector exprseq::evalfchildren(int level) const
508 {
509     exvector s;
510     RESERVE(s,seq.size());
511
512     if (level==1) {
513         return seq;
514     }
515     if (level == -max_recursion_level) {
516         throw(std::runtime_error("max recursion level reached"));
517     }
518     --level;
519     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
520         s.push_back((*it).evalf(level));
521     }
522     return s;
523 }
524
525 exvector exprseq::normalchildren(int level) const
526 {
527     exvector s;
528     RESERVE(s,seq.size());
529
530     if (level==1) {
531         return seq;
532     }
533     if (level == -max_recursion_level) {
534         throw(std::runtime_error("max recursion level reached"));
535     }
536     --level;
537     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
538         s.push_back((*it).normal(level));
539     }
540     return s;
541 }
542
543 exvector exprseq::diffchildren(symbol const & y) const
544 {
545     exvector s;
546     RESERVE(s,seq.size());
547     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
548         s.push_back((*it).diff(y));
549     }
550     return s;
551 }
552
553 /* obsolete subschildren
554 exvector exprseq::subschildren(lst const & ls, lst const & lr) const
555 {
556     exvector s;
557     RESERVE(s,seq.size());
558     for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
559         s.push_back((*it).subs(ls,lr));
560     }
561     return s;
562 }
563 */
564
565 exvector * exprseq::subschildren(lst const & ls, lst const & lr) const
566 {
567     // returns a NULL pointer if nothing had to be substituted
568     // returns a pointer to a newly created epvector otherwise
569     // (which has to be deleted somewhere else)
570
571     exvector::const_iterator last=seq.end();
572     exvector::const_iterator cit=seq.begin();
573     while (cit!=last) {
574         ex const & subsed_ex=(*cit).subs(ls,lr);
575         if (!are_ex_trivially_equal(*cit,subsed_ex)) {
576
577             // something changed, copy seq, subs and return it
578             exvector *s=new exvector;
579             RESERVE(*s,seq.size());
580
581             // copy parts of seq which are known not to have changed
582             exvector::const_iterator cit2=seq.begin();
583             while (cit2!=cit) {
584                 s->push_back(*cit2);
585                 ++cit2;
586             }
587             // copy first changed element
588             s->push_back(subsed_ex);
589             ++cit2;
590             // copy rest
591             while (cit2!=last) {
592                 s->push_back((*cit2).subs(ls,lr));
593                 ++cit2;
594             }
595             return s;
596         }
597         ++cit;
598     }
599     
600     return 0; // nothing has changed
601 }
602
603 //////////
604 // static member variables
605 //////////
606
607 // protected
608
609 unsigned exprseq::precedence=10;
610
611 //////////
612 // global constants
613 //////////
614
615 const exprseq some_exprseq;
616 type_info const & typeid_exprseq=typeid(some_exprseq);
617
618 } // namespace GiNaC
619