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