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