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