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