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