- ASSERT macro renamed to GINAC_ASSERT
[ginac.git] / ginac / container.pl
1 #!/usr/bin/perl -w
2
3 if ($#ARGV!=0) {
4     die 'usage: container.pl type (type=lst or exprseq)';
5 }
6
7 if ($ARGV[0] eq 'lst') {
8     $type='lst';
9 } elsif ($ARGV[0] eq 'exprseq') {
10     $type='exprseq';
11 } else {
12     die 'only lst and exprseq supported';
13 }
14
15 #$type='lst';
16 #$type='exprseq';
17
18 if ($type eq 'exprseq') {
19
20     # settings for exprseq
21     $CONTAINER="exprseq";
22     $STLHEADER="vector";
23     $reserve=1;
24     $prepend=0;
25     $let_op=0;
26     $open_bracket='(';
27     $close_bracket=')';
28     
29 } elsif ($type eq 'lst') {
30  
31     # settings for lst
32     $CONTAINER="lst";
33     $STLHEADER="list";
34     $reserve=0;
35     $prepend=1;
36     $let_op=1;
37     $open_bracket='[';
38     $close_bracket=']';
39
40 } else {
41     die "invalid type $type";
42 }
43
44 $CONTAINER_UC=uc(${CONTAINER});
45 $STLT="ex".$STLHEADER;
46
47 if ($reserve) {
48     $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) (s).reserve(size)";
49 } else {
50     $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) // no reserve needed for ${STLHEADER}";
51 }
52
53 if ($prepend) {
54     $PREPEND_INTERFACE=<<END_OF_PREPEND_INTERFACE;
55     virtual ${CONTAINER} & prepend(ex const & b);
56 END_OF_PREPEND_INTERFACE
57
58     $PREPEND_IMPLEMENTATION=<<END_OF_PREPEND_IMPLEMENTATION;
59 ${CONTAINER} & ${CONTAINER}::prepend(ex const & b)
60 {
61     ensure_if_modifiable();
62     seq.push_front(b);
63     return *this;
64 }
65 END_OF_PREPEND_IMPLEMENTATION
66 } else {
67     $PREPEND_INTERFACE="    // no prepend possible for ${CONTAINER}";
68     $PREPEND_IMPLEMENTATION="";
69 }
70
71 if ($let_op) {
72     $LET_OP_IMPLEMENTATION=<<END_OF_LET_OP_IMPLEMENTATION
73 ex & ${CONTAINER}::let_op(int const i)
74 {
75     GINAC_ASSERT(i>=0);
76     GINAC_ASSERT(i<nops());
77
78     ${STLT}::iterator it=seq.begin();
79     for (int j=0; j<i; j++) {
80         ++it;
81     }
82     return *it;
83 }
84 END_OF_LET_OP_IMPLEMENTATION
85 } else {
86     $LET_OP_IMPLEMENTATION="// ${CONTAINER}::let_op() will be implemented by user elsewhere";
87 }
88
89 $interface=<<END_OF_INTERFACE;
90 /** \@file ${CONTAINER}.h
91  *
92  *  Definition of GiNaC's ${CONTAINER}. */
93
94 /*
95  *  This file was generated automatically by container.pl.
96  *  Please do not modify it directly, edit the perl script instead!
97  *  container.pl options: \$CONTAINER=${CONTAINER}
98  *                        \$STLHEADER=${STLHEADER}
99  *                        \$reserve=${reserve}
100  *                        \$prepend=${prepend}
101  *                        \$let_op=${let_op}
102  *                        \$open_bracket=${open_bracket}
103  *                        \$close_bracket=${close_bracket}
104  *
105  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
106  *
107  *  This program is free software; you can redistribute it and/or modify
108  *  it under the terms of the GNU General Public License as published by
109  *  the Free Software Foundation; either version 2 of the License, or
110  *  (at your option) any later version.
111  *
112  *  This program is distributed in the hope that it will be useful,
113  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
114  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
115  *  GNU General Public License for more details.
116  *
117  *  You should have received a copy of the GNU General Public License
118  *  along with this program; if not, write to the Free Software
119  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
120  */
121
122 #ifndef __GINAC_${CONTAINER_UC}_H__
123 #define __GINAC_${CONTAINER_UC}_H__
124
125 #include <${STLHEADER}>
126 #include <ginac/basic.h>
127 #include <ginac/ex.h>
128
129 namespace GiNaC {
130
131 typedef ${STLHEADER}<ex> ${STLT};
132
133 class ${CONTAINER} : public basic
134 {
135
136 public:
137     ${CONTAINER}();
138     ~${CONTAINER}();
139     ${CONTAINER}(${CONTAINER} const & other);
140     ${CONTAINER} const & operator=(${CONTAINER} const & other);
141 protected:
142     void copy(${CONTAINER} const & other);
143     void destroy(bool call_parent);
144
145 public:
146     ${CONTAINER}(${STLT} const & s, bool discardable=0);
147     ${CONTAINER}(${STLT} * vp); // vp will be deleted
148     explicit ${CONTAINER}(ex const & e1);
149     explicit ${CONTAINER}(ex const & e1, ex const & e2);
150     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3);
151     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
152              ex const & e4);
153     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
154              ex const & e4, ex const & e5);
155     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
156              ex const & e4, ex const & e5, ex const & e6);
157     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
158              ex const & e4, ex const & e5, ex const & e6,
159              ex const & e7);
160     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
161              ex const & e4, ex const & e5, ex const & e6,
162              ex const & e7, ex const & e8);
163     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
164              ex const & e4, ex const & e5, ex const & e6,
165              ex const & e7, ex const & e8, ex const & e9);
166     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
167              ex const & e4, ex const & e5, ex const & e6,
168              ex const & e7, ex const & e8, ex const & e9,
169              ex const &e10);
170
171 public:
172     basic * duplicate() const;
173     void printraw(ostream & os) const;
174     void print(ostream & os, unsigned upper_precedence=0) const;
175     void printtree(ostream & os, unsigned indent) const;
176     bool info(unsigned inf) const;
177     int nops() const;
178     ex & let_op(int const i);
179     ex expand(unsigned options=0) const;
180     bool has(ex const & other) const;
181     ex eval(int level=0) const;
182     ex evalf(int level=0) const;
183     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
184     ex diff(symbol const & s) const;
185     ex subs(lst const & ls, lst const & lr) const;
186 protected:
187     int compare_same_type(basic const & other) const;
188     bool is_equal_same_type(basic const & other) const;
189     unsigned return_type(void) const;
190
191     // new virtual functions which can be overridden by derived classes
192 public:
193     virtual ${CONTAINER} & append(ex const & b);
194 ${PREPEND_INTERFACE}
195 protected:
196     virtual void printseq(ostream & os, char openbracket, char delim,
197                           char closebracket, unsigned this_precedence,
198                           unsigned upper_precedence=0) const;
199     virtual ex this${CONTAINER}(${STLT} const & v) const;
200     virtual ex this${CONTAINER}(${STLT} * vp) const;
201
202 protected:
203     bool is_canonical() const;
204     ${STLT} evalchildren(int level) const;
205     ${STLT} evalfchildren(int level) const;
206     ${STLT} normalchildren(int level) const;
207     ${STLT} diffchildren(symbol const & s) const;
208     ${STLT} * subschildren(lst const & ls, lst const & lr) const;
209
210 protected:
211     ${STLT} seq;
212     static unsigned precedence;
213 };
214
215 // global constants
216
217 extern const ${CONTAINER} some_${CONTAINER};
218 extern type_info const & typeid_${CONTAINER};
219
220 // utility functions
221 inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e)
222 {
223     return static_cast<const ${CONTAINER} &>(*e.bp);
224 }
225
226 } // namespace GiNaC
227
228 #endif // ndef __GINAC_${CONTAINER_UC}_H__
229
230 END_OF_INTERFACE
231
232 $implementation=<<END_OF_IMPLEMENTATION;
233 /** \@file ${CONTAINER}.cpp
234  *
235  *  Implementation of GiNaC's ${CONTAINER}. */
236
237 /*
238  *  This file was generated automatically by container.pl.
239  *  Please do not modify it directly, edit the perl script instead!
240  *  container.pl options: \$CONTAINER=${CONTAINER}
241  *                        \$STLHEADER=${STLHEADER}
242  *                        \$reserve=${reserve}
243  *                        \$prepend=${prepend}
244  *                        \$let_op=${let_op}
245  *                        \$open_bracket=${open_bracket}
246  *                        \$close_bracket=${close_bracket}
247  *
248  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
249  *
250  *  This program is free software; you can redistribute it and/or modify
251  *  it under the terms of the GNU General Public License as published by
252  *  the Free Software Foundation; either version 2 of the License, or
253  *  (at your option) any later version.
254  *
255  *  This program is distributed in the hope that it will be useful,
256  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
257  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
258  *  GNU General Public License for more details.
259  *
260  *  You should have received a copy of the GNU General Public License
261  *  along with this program; if not, write to the Free Software
262  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
263  */
264
265 #include <iostream>
266 #include <stdexcept>
267
268 #include "${CONTAINER}.h"
269 #include "ex.h"
270 #include "debugmsg.h"
271
272 namespace GiNaC {
273
274 ${RESERVE_IMPLEMENTATION}
275
276 //////////
277 // default constructor, destructor, copy constructor assignment operator and helpers
278 //////////
279
280 // public
281
282 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER})
283 {
284     debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
285 }
286
287 ${CONTAINER}::~${CONTAINER}()
288 {
289     debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
290     destroy(0);
291 }
292
293 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
294 {
295     debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
296     copy(other);
297 }
298
299 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
300 {
301     debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
302     if (this != &other) {
303         destroy(1);
304         copy(other);
305     }
306     return *this;
307 }
308
309 // protected
310
311 void ${CONTAINER}::copy(${CONTAINER} const & other)
312 {
313     basic::copy(other);
314     seq=other.seq;
315 }
316
317 void ${CONTAINER}::destroy(bool call_parent)
318 {
319     seq.clear();
320     if (call_parent) basic::destroy(call_parent);
321 }
322
323 //////////
324 // other constructors
325 //////////
326
327 // public
328
329 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) :  basic(TINFO_${CONTAINER})
330 {
331     debugmsg("${CONTAINER} constructor from ${STLT}",
332              LOGLEVEL_CONSTRUCT);
333     if (discardable) {
334         seq.swap(const_cast<${STLT} &>(s));
335     } else {
336         seq=s;
337     }
338 }
339
340 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER})
341 {
342     debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
343     GINAC_ASSERT(vp!=0);
344     seq.swap(*vp);
345     delete vp;
346 }
347
348 ${CONTAINER}::${CONTAINER}(ex const & e1) :  basic(TINFO_${CONTAINER})
349 {
350     debugmsg("${CONTAINER} constructor from 1 ex",
351              LOGLEVEL_CONSTRUCT);
352     RESERVE(seq,1);
353     seq.push_back(e1);
354 }
355
356 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER})
357 {
358     debugmsg("${CONTAINER} constructor from 2 ex",
359              LOGLEVEL_CONSTRUCT);
360     RESERVE(seq,2);
361     seq.push_back(e1);
362     seq.push_back(e2);
363 }
364
365 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
366     : basic(TINFO_${CONTAINER})
367 {
368     debugmsg("${CONTAINER} constructor from 3 ex",
369              LOGLEVEL_CONSTRUCT);
370     RESERVE(seq,3);
371     seq.push_back(e1);
372     seq.push_back(e2);
373     seq.push_back(e3);
374 }
375
376 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
377                      ex const & e4) : basic(TINFO_${CONTAINER})
378 {
379     debugmsg("${CONTAINER} constructor from 4 ex",
380              LOGLEVEL_CONSTRUCT);
381     RESERVE(seq,4);
382     seq.push_back(e1);
383     seq.push_back(e2);
384     seq.push_back(e3);
385     seq.push_back(e4);
386 }
387
388 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
389                      ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER})
390 {
391     debugmsg("${CONTAINER} constructor from 5 ex",
392              LOGLEVEL_CONSTRUCT);
393     RESERVE(seq,5);
394     seq.push_back(e1);
395     seq.push_back(e2);
396     seq.push_back(e3);
397     seq.push_back(e4);
398     seq.push_back(e5);
399 }
400
401 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
402                      ex const & e4, ex const & e5, ex const & e6)
403     : basic(TINFO_${CONTAINER})
404 {
405     debugmsg("${CONTAINER} constructor from 6 ex",
406              LOGLEVEL_CONSTRUCT);
407     RESERVE(seq,6);
408     seq.push_back(e1);
409     seq.push_back(e2);
410     seq.push_back(e3);
411     seq.push_back(e4);
412     seq.push_back(e5);
413     seq.push_back(e6);
414 }
415
416 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
417                      ex const & e4, ex const & e5, ex const & e6,
418                      ex const & e7) : basic(TINFO_${CONTAINER})
419 {
420     debugmsg("${CONTAINER} constructor from 7 ex",
421              LOGLEVEL_CONSTRUCT);
422     RESERVE(seq,7);
423     seq.push_back(e1);
424     seq.push_back(e2);
425     seq.push_back(e3);
426     seq.push_back(e4);
427     seq.push_back(e5);
428     seq.push_back(e6);
429     seq.push_back(e7);
430 }
431
432 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
433                      ex const & e4, ex const & e5, ex const & e6,
434                      ex const & e7, ex const & e8) : basic(TINFO_${CONTAINER})
435 {
436     debugmsg("${CONTAINER} constructor from 8 ex",
437              LOGLEVEL_CONSTRUCT);
438     RESERVE(seq,8);
439     seq.push_back(e1);
440     seq.push_back(e2);
441     seq.push_back(e3);
442     seq.push_back(e4);
443     seq.push_back(e5);
444     seq.push_back(e6);
445     seq.push_back(e7);
446     seq.push_back(e8);
447 }
448
449 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
450                      ex const & e4, ex const & e5, ex const & e6,
451                      ex const & e7, ex const & e8, ex const & e9)
452     : basic(TINFO_${CONTAINER})
453 {
454     debugmsg("${CONTAINER} constructor from 9 ex",
455              LOGLEVEL_CONSTRUCT);
456     RESERVE(seq,9);
457     seq.push_back(e1);
458     seq.push_back(e2);
459     seq.push_back(e3);
460     seq.push_back(e4);
461     seq.push_back(e5);
462     seq.push_back(e6);
463     seq.push_back(e7);
464     seq.push_back(e8);
465     seq.push_back(e9);
466 }
467
468 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
469                      ex const & e4, ex const & e5, ex const & e6,
470                      ex const & e7, ex const & e8, ex const & e9,
471                      ex const &e10)
472     : basic(TINFO_${CONTAINER})
473 {
474     debugmsg("${CONTAINER} constructor from 10 ex",
475              LOGLEVEL_CONSTRUCT);
476     RESERVE(seq,10);
477     seq.push_back(e1);
478     seq.push_back(e2);
479     seq.push_back(e3);
480     seq.push_back(e4);
481     seq.push_back(e5);
482     seq.push_back(e6);
483     seq.push_back(e7);
484     seq.push_back(e8);
485     seq.push_back(e9);
486     seq.push_back(e10);
487 }
488
489 //////////
490 // functions overriding virtual functions from bases classes
491 //////////
492
493 // public
494
495 basic * ${CONTAINER}::duplicate() const
496 {
497     debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
498     return new ${CONTAINER}(*this);
499 }
500
501 void ${CONTAINER}::printraw(ostream & os) const
502 {
503     debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
504
505     os << "${CONTAINER}(";
506     for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
507         (*cit).bp->printraw(os);
508         os << ",";
509     }
510     os << ")";
511 }
512
513 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
514 {
515     debugmsg("${CONTAINER} print",LOGLEVEL_PRINT);
516     // always print brackets around seq, ignore upper_precedence
517     printseq(os,'${open_bracket}',',','${close_bracket}',precedence,precedence+1);
518 }
519
520 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
521 {
522     debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
523
524     os << string(indent,' ') << "type=" << typeid(*this).name()
525        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
526        << ", flags=" << flags
527        << ", nops=" << nops() << endl;
528     for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
529         (*cit).printtree(os,indent+delta_indent);
530     }
531     os << string(indent+delta_indent,' ') << "=====" << endl;
532 }
533
534 // ${CONTAINER}::info() will be implemented by user elsewhere";
535
536 int ${CONTAINER}::nops() const
537 {
538     return seq.size();
539 }
540
541 ${LET_OP_IMPLEMENTATION}
542
543 ex ${CONTAINER}::expand(unsigned options) const
544 {
545     ${STLT} s;
546     RESERVE(s,seq.size());
547     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
548         s.push_back((*it).expand(options));
549     }
550
551     return this${CONTAINER}(s);
552 }
553
554 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
555
556 bool ${CONTAINER}::has(ex const & other) const
557 {
558     GINAC_ASSERT(other.bp!=0);
559     if (is_equal(*other.bp)) return true;
560     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
561         if ((*it).has(other)) return true;
562     }
563     return false;
564 }
565
566 ex ${CONTAINER}::eval(int level) const
567 {
568     if (level==1) {
569         return this->hold();
570     }
571     return this${CONTAINER}(evalchildren(level));
572 }
573
574 ex ${CONTAINER}::evalf(int level) const
575 {
576     return this${CONTAINER}(evalfchildren(level));
577 }
578
579 /** Implementation of ex::normal() for ${CONTAINER}s. It normalizes the arguments
580  *  and replaces the ${CONTAINER} by a temporary symbol.
581  *  \@see ex::normal */
582 ex ${CONTAINER}::normal(lst &sym_lst, lst &repl_lst, int level) const
583 {
584     ex n=this${CONTAINER}(normalchildren(level));
585     return n.bp->basic::normal(sym_lst,repl_lst,level);
586 }
587
588 ex ${CONTAINER}::diff(symbol const & s) const
589 {
590     return this${CONTAINER}(diffchildren(s));
591 }
592
593 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
594 {
595     ${STLT} * vp=subschildren(ls,lr);
596     if (vp==0) {
597         return *this;
598     }
599     return this${CONTAINER}(vp);
600 }
601
602 // protected
603
604 int ${CONTAINER}::compare_same_type(basic const & other) const
605 {
606     GINAC_ASSERT(is_of_type(other,${CONTAINER}));
607     ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
608                                     (const_cast<basic &>(other));
609     int cmpval;
610     ${STLT}::const_iterator it1=seq.begin();
611     ${STLT}::const_iterator it2=o.seq.begin();
612
613     for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
614         cmpval=(*it1).compare(*it2);
615         if (cmpval!=0) return cmpval;
616     }
617
618     if (it1==seq.end()) {
619         return (it2==o.seq.end() ? 0 : -1);
620     }
621
622     return 1;
623 }
624
625 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
626 {
627     GINAC_ASSERT(is_of_type(other,${CONTAINER}));
628     ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
629                                     (const_cast<basic &>(other));
630     if (seq.size()!=o.seq.size()) return false;
631
632     ${STLT}::const_iterator it1=seq.begin();
633     ${STLT}::const_iterator it2=o.seq.begin();
634
635     for (; it1!=seq.end(); ++it1, ++it2) {
636         if (!(*it1).is_equal(*it2)) return false;
637     }
638
639     return true;
640 }
641
642 unsigned ${CONTAINER}::return_type(void) const
643 {
644     return return_types::noncommutative_composite;
645 }
646
647 //////////
648 // new virtual functions which can be overridden by derived classes
649 //////////
650
651 // public
652
653 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
654 {
655     ensure_if_modifiable();
656     seq.push_back(b);
657     return *this;
658 }
659
660 ${PREPEND_IMPLEMENTATION}
661
662 // protected
663
664 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
665                          char closebracket, unsigned this_precedence,
666                          unsigned upper_precedence) const
667 {
668     if (this_precedence<=upper_precedence) os << openbracket;
669     if (seq.size()!=0) {
670         ${STLT}::const_iterator it,it_last;
671         it=seq.begin();
672         it_last=seq.end();
673         --it_last;
674         for (; it!=it_last; ++it) {
675             (*it).bp->print(os,this_precedence);
676             os << delim;
677         }
678         (*it).bp->print(os,this_precedence);
679     }
680     if (this_precedence<=upper_precedence) os << closebracket;
681 }
682
683 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
684 {
685     return ${CONTAINER}(v);
686 }
687
688 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
689 {
690     return ${CONTAINER}(vp);
691 }
692
693 //////////
694 // non-virtual functions in this class
695 //////////
696
697 // public
698
699 // none
700
701 // protected
702
703 bool ${CONTAINER}::is_canonical() const
704 {
705     if (seq.size()<=1) { return 1; }
706
707     ${STLT}::const_iterator it=seq.begin();
708     ${STLT}::const_iterator it_last=it;
709     for (++it; it!=seq.end(); it_last=it, ++it) {
710         if ((*it_last).compare(*it)>0) {
711             if ((*it_last).compare(*it)>0) {
712                 cout << *it_last << ">" << *it << "\\n";
713                 return 0;
714                 }
715         }
716     }
717     return 1;
718 }
719
720
721 ${STLT} ${CONTAINER}::evalchildren(int level) const
722 {
723     ${STLT} s;
724     RESERVE(s,seq.size());
725
726     if (level==1) {
727         return seq;
728     }
729     if (level == -max_recursion_level) {
730         throw(std::runtime_error("max recursion level reached"));
731     }
732     --level;
733     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
734         s.push_back((*it).eval(level));
735     }
736     return s;
737 }
738
739 ${STLT} ${CONTAINER}::evalfchildren(int level) const
740 {
741     ${STLT} s;
742     RESERVE(s,seq.size());
743
744     if (level==1) {
745         return seq;
746     }
747     if (level == -max_recursion_level) {
748         throw(std::runtime_error("max recursion level reached"));
749     }
750     --level;
751     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
752         s.push_back((*it).evalf(level));
753     }
754     return s;
755 }
756
757 ${STLT} ${CONTAINER}::normalchildren(int level) const
758 {
759     ${STLT} s;
760     RESERVE(s,seq.size());
761
762     if (level==1) {
763         return seq;
764     }
765     if (level == -max_recursion_level) {
766         throw(std::runtime_error("max recursion level reached"));
767     }
768     --level;
769     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
770         s.push_back((*it).normal(level));
771     }
772     return s;
773 }
774
775 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
776 {
777     ${STLT} s;
778     RESERVE(s,seq.size());
779     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
780         s.push_back((*it).diff(y));
781     }
782     return s;
783 }
784
785 /* obsolete subschildren
786 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
787 {
788     ${STLT} s;
789     RESERVE(s,seq.size());
790     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
791         s.push_back((*it).subs(ls,lr));
792     }
793     return s;
794 }
795 */
796
797 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
798 {
799     // returns a NULL pointer if nothing had to be substituted
800     // returns a pointer to a newly created epvector otherwise
801     // (which has to be deleted somewhere else)
802
803     ${STLT}::const_iterator last=seq.end();
804     ${STLT}::const_iterator cit=seq.begin();
805     while (cit!=last) {
806         ex const & subsed_ex=(*cit).subs(ls,lr);
807         if (!are_ex_trivially_equal(*cit,subsed_ex)) {
808
809             // something changed, copy seq, subs and return it
810             ${STLT} *s=new ${STLT};
811             RESERVE(*s,seq.size());
812
813             // copy parts of seq which are known not to have changed
814             ${STLT}::const_iterator cit2=seq.begin();
815             while (cit2!=cit) {
816                 s->push_back(*cit2);
817                 ++cit2;
818             }
819             // copy first changed element
820             s->push_back(subsed_ex);
821             ++cit2;
822             // copy rest
823             while (cit2!=last) {
824                 s->push_back((*cit2).subs(ls,lr));
825                 ++cit2;
826             }
827             return s;
828         }
829         ++cit;
830     }
831     
832     return 0; // nothing has changed
833 }
834
835 //////////
836 // static member variables
837 //////////
838
839 // protected
840
841 unsigned ${CONTAINER}::precedence=10;
842
843 //////////
844 // global constants
845 //////////
846
847 const ${CONTAINER} some_${CONTAINER};
848 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
849
850 } // namespace GiNaC
851
852 END_OF_IMPLEMENTATION
853
854 print "Creating interface file ${CONTAINER}.h...";
855 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
856 print OUT $interface;
857 close OUT;
858 print "ok.\n";
859
860 print "Creating implementation file ${CONTAINER}.cpp...";
861 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
862 print OUT $implementation;
863 close OUT;
864 print "ok.\n";
865
866 print "done.\n";