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