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