a71f5dda9f00ab54a68e837b827e972e01c75a49
[ginac.git] / ginac / lst.cpp
1 /** @file lst.cpp
2  *
3  *  Implementation of GiNaC's lst. */
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=lst
9  *                        $STLHEADER=list
10  *                        $reserve=0
11  *                        $prepend=1
12  *                        $let_op=1
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 "lst.h"
37 #include "ex.h"
38 #include "debugmsg.h"
39
40 namespace GiNaC {
41
42 #define RESERVE(s,size) // no reserve needed for list
43
44 //////////
45 // default constructor, destructor, copy constructor assignment operator and helpers
46 //////////
47
48 // public
49
50 lst::lst() : basic(TINFO_lst)
51 {
52     debugmsg("lst default constructor",LOGLEVEL_CONSTRUCT);
53 }
54
55 lst::~lst()
56 {
57     debugmsg("lst destructor",LOGLEVEL_DESTRUCT);
58     destroy(0);
59 }
60
61 lst::lst(lst const & other)
62 {
63     debugmsg("lst copy constructor",LOGLEVEL_CONSTRUCT);
64     copy(other);
65 }
66
67 lst const & lst::operator=(lst const & other)
68 {
69     debugmsg("lst operator=",LOGLEVEL_ASSIGNMENT);
70     if (this != &other) {
71         destroy(1);
72         copy(other);
73     }
74     return *this;
75 }
76
77 // protected
78
79 void lst::copy(lst const & other)
80 {
81     basic::copy(other);
82     seq=other.seq;
83 }
84
85 void lst::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 lst::lst(exlist const & s, bool discardable) :  basic(TINFO_lst)
98 {
99     debugmsg("lst constructor from exlist",
100              LOGLEVEL_CONSTRUCT);
101     if (discardable) {
102         seq.swap(const_cast<exlist &>(s));
103     } else {
104         seq=s;
105     }
106 }
107
108 lst::lst(exlist * vp) : basic(TINFO_lst)
109 {
110     debugmsg("lst constructor from exlist *",LOGLEVEL_CONSTRUCT);
111     ASSERT(vp!=0);
112     seq.swap(*vp);
113     delete vp;
114 }
115
116 lst::lst(ex const & e1) :  basic(TINFO_lst)
117 {
118     debugmsg("lst constructor from 1 ex",
119              LOGLEVEL_CONSTRUCT);
120     RESERVE(seq,1);
121     seq.push_back(e1);
122 }
123
124 lst::lst(ex const & e1, ex const & e2) : basic(TINFO_lst)
125 {
126     debugmsg("lst constructor from 2 ex",
127              LOGLEVEL_CONSTRUCT);
128     RESERVE(seq,2);
129     seq.push_back(e1);
130     seq.push_back(e2);
131 }
132
133 lst::lst(ex const & e1, ex const & e2, ex const & e3)
134     : basic(TINFO_lst)
135 {
136     debugmsg("lst 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 lst::lst(ex const & e1, ex const & e2, ex const & e3,
145                      ex const & e4) : basic(TINFO_lst)
146 {
147     debugmsg("lst 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 lst::lst(ex const & e1, ex const & e2, ex const & e3,
157                      ex const & e4, ex const & e5) : basic(TINFO_lst)
158 {
159     debugmsg("lst 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 lst::lst(ex const & e1, ex const & e2, ex const & e3,
170                      ex const & e4, ex const & e5, ex const & e6)
171     : basic(TINFO_lst)
172 {
173     debugmsg("lst 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 lst::lst(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_lst)
187 {
188     debugmsg("lst 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 lst::lst(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_lst)
203 {
204     debugmsg("lst 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 lst::lst(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_lst)
221 {
222     debugmsg("lst 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 lst::lst(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_lst)
241 {
242     debugmsg("lst 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 * lst::duplicate() const
264 {
265     debugmsg("lst duplicate",LOGLEVEL_DUPLICATE);
266     return new lst(*this);
267 }
268
269 void lst::printraw(ostream & os) const
270 {
271     debugmsg("lst printraw",LOGLEVEL_PRINT);
272
273     os << "lst(";
274     for (exlist::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
275         (*cit).bp->printraw(os);
276         os << ",";
277     }
278     os << ")";
279 }
280
281 void lst::print(ostream & os, unsigned upper_precedence) const
282 {
283     debugmsg("lst print",LOGLEVEL_PRINT);
284     // always print brackets around seq, ignore upper_precedence
285     printseq(os,'[',',',']',precedence,precedence+1);
286 }
287
288 void lst::printtree(ostream & os, unsigned indent) const
289 {
290     debugmsg("lst 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 (exlist::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 // lst::info() will be implemented by user elsewhere";
303
304 int lst::nops() const
305 {
306     return seq.size();
307 }
308
309 ex & lst::let_op(int const i)
310 {
311     ASSERT(i>=0);
312     ASSERT(i<nops());
313
314     exlist::iterator it=seq.begin();
315     for (int j=0; j<i; j++) {
316         ++it;
317     }
318     return *it;
319 }
320
321
322 ex lst::expand(unsigned options) const
323 {
324     exlist s;
325     RESERVE(s,seq.size());
326     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
327         s.push_back((*it).expand(options));
328     }
329
330     return thislst(s);
331 }
332
333 // a lst 'has' an expression if it is this expression itself or a child 'has' it
334
335 bool lst::has(ex const & other) const
336 {
337     ASSERT(other.bp!=0);
338     if (is_equal(*other.bp)) return true;
339     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
340         if ((*it).has(other)) return true;
341     }
342     return false;
343 }
344
345 ex lst::eval(int level) const
346 {
347     if (level==1) {
348         return this->hold();
349     }
350     return thislst(evalchildren(level));
351 }
352
353 ex lst::evalf(int level) const
354 {
355     return thislst(evalfchildren(level));
356 }
357
358 /** Implementation of ex::normal() for lsts. It normalizes the arguments
359  *  and replaces the lst by a temporary symbol.
360  *  @see ex::normal */
361 ex lst::normal(lst &sym_lst, lst &repl_lst, int level) const
362 {
363     ex n=thislst(normalchildren(level));
364     return n.bp->basic::normal(sym_lst,repl_lst,level);
365 }
366
367 ex lst::diff(symbol const & s) const
368 {
369     return thislst(diffchildren(s));
370 }
371
372 ex lst::subs(lst const & ls, lst const & lr) const
373 {
374     exlist * vp=subschildren(ls,lr);
375     if (vp==0) {
376         return *this;
377     }
378     return thislst(vp);
379 }
380
381 // protected
382
383 int lst::compare_same_type(basic const & other) const
384 {
385     ASSERT(is_of_type(other,lst));
386     lst const & o=static_cast<lst const &>
387                                     (const_cast<basic &>(other));
388     int cmpval;
389     exlist::const_iterator it1=seq.begin();
390     exlist::const_iterator it2=o.seq.begin();
391
392     for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
393         cmpval=(*it1).compare(*it2);
394         if (cmpval!=0) return cmpval;
395     }
396
397     if (it1==seq.end()) {
398         return (it2==o.seq.end() ? 0 : -1);
399     }
400
401     return 1;
402 }
403
404 bool lst::is_equal_same_type(basic const & other) const
405 {
406     ASSERT(is_of_type(other,lst));
407     lst const & o=static_cast<lst const &>
408                                     (const_cast<basic &>(other));
409     if (seq.size()!=o.seq.size()) return false;
410
411     exlist::const_iterator it1=seq.begin();
412     exlist::const_iterator it2=o.seq.begin();
413
414     for (; it1!=seq.end(); ++it1, ++it2) {
415         if (!(*it1).is_equal(*it2)) return false;
416     }
417
418     return true;
419 }
420
421 unsigned lst::return_type(void) const
422 {
423     return return_types::noncommutative_composite;
424 }
425
426 //////////
427 // new virtual functions which can be overridden by derived classes
428 //////////
429
430 // public
431
432 lst & lst::append(ex const & b)
433 {
434     ensure_if_modifiable();
435     seq.push_back(b);
436     return *this;
437 }
438
439 lst & lst::prepend(ex const & b)
440 {
441     ensure_if_modifiable();
442     seq.push_front(b);
443     return *this;
444 }
445
446
447 // protected
448
449 void lst::printseq(ostream & os, char openbracket, char delim,
450                          char closebracket, unsigned this_precedence,
451                          unsigned upper_precedence) const
452 {
453     if (this_precedence<=upper_precedence) os << openbracket;
454     if (seq.size()!=0) {
455         exlist::const_iterator it,it_last;
456         it=seq.begin();
457         it_last=seq.end();
458         --it_last;
459         for (; it!=it_last; ++it) {
460             (*it).bp->print(os,this_precedence);
461             os << delim;
462         }
463         (*it).bp->print(os,this_precedence);
464     }
465     if (this_precedence<=upper_precedence) os << closebracket;
466 }
467
468 ex lst::thislst(exlist const & v) const
469 {
470     return lst(v);
471 }
472
473 ex lst::thislst(exlist * vp) const
474 {
475     return lst(vp);
476 }
477
478 //////////
479 // non-virtual functions in this class
480 //////////
481
482 // public
483
484 // none
485
486 // protected
487
488 bool lst::is_canonical() const
489 {
490     if (seq.size()<=1) { return 1; }
491
492     exlist::const_iterator it=seq.begin();
493     exlist::const_iterator it_last=it;
494     for (++it; it!=seq.end(); it_last=it, ++it) {
495         if ((*it_last).compare(*it)>0) {
496             if ((*it_last).compare(*it)>0) {
497                 cout << *it_last << ">" << *it << "\n";
498                 return 0;
499                 }
500         }
501     }
502     return 1;
503 }
504
505
506 exlist lst::evalchildren(int level) const
507 {
508     exlist s;
509     RESERVE(s,seq.size());
510
511     if (level==1) {
512         return seq;
513     }
514     if (level == -max_recursion_level) {
515         throw(std::runtime_error("max recursion level reached"));
516     }
517     --level;
518     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
519         s.push_back((*it).eval(level));
520     }
521     return s;
522 }
523
524 exlist lst::evalfchildren(int level) const
525 {
526     exlist s;
527     RESERVE(s,seq.size());
528
529     if (level==1) {
530         return seq;
531     }
532     if (level == -max_recursion_level) {
533         throw(std::runtime_error("max recursion level reached"));
534     }
535     --level;
536     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
537         s.push_back((*it).evalf(level));
538     }
539     return s;
540 }
541
542 exlist lst::normalchildren(int level) const
543 {
544     exlist s;
545     RESERVE(s,seq.size());
546
547     if (level==1) {
548         return seq;
549     }
550     if (level == -max_recursion_level) {
551         throw(std::runtime_error("max recursion level reached"));
552     }
553     --level;
554     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
555         s.push_back((*it).normal(level));
556     }
557     return s;
558 }
559
560 exlist lst::diffchildren(symbol const & y) const
561 {
562     exlist s;
563     RESERVE(s,seq.size());
564     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
565         s.push_back((*it).diff(y));
566     }
567     return s;
568 }
569
570 /* obsolete subschildren
571 exlist lst::subschildren(lst const & ls, lst const & lr) const
572 {
573     exlist s;
574     RESERVE(s,seq.size());
575     for (exlist::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
576         s.push_back((*it).subs(ls,lr));
577     }
578     return s;
579 }
580 */
581
582 exlist * lst::subschildren(lst const & ls, lst const & lr) const
583 {
584     // returns a NULL pointer if nothing had to be substituted
585     // returns a pointer to a newly created epvector otherwise
586     // (which has to be deleted somewhere else)
587
588     exlist::const_iterator last=seq.end();
589     exlist::const_iterator cit=seq.begin();
590     while (cit!=last) {
591         ex const & subsed_ex=(*cit).subs(ls,lr);
592         if (!are_ex_trivially_equal(*cit,subsed_ex)) {
593
594             // something changed, copy seq, subs and return it
595             exlist *s=new exlist;
596             RESERVE(*s,seq.size());
597
598             // copy parts of seq which are known not to have changed
599             exlist::const_iterator cit2=seq.begin();
600             while (cit2!=cit) {
601                 s->push_back(*cit2);
602                 ++cit2;
603             }
604             // copy first changed element
605             s->push_back(subsed_ex);
606             ++cit2;
607             // copy rest
608             while (cit2!=last) {
609                 s->push_back((*cit2).subs(ls,lr));
610                 ++cit2;
611             }
612             return s;
613         }
614         ++cit;
615     }
616     
617     return 0; // nothing has changed
618 }
619
620 //////////
621 // static member variables
622 //////////
623
624 // protected
625
626 unsigned lst::precedence=10;
627
628 //////////
629 // global constants
630 //////////
631
632 const lst some_lst;
633 type_info const & typeid_lst=typeid(some_lst);
634
635 } // namespace GiNaC
636