4 die 'usage: container.pl type (type=lst or exprseq)';
7 if ($ARGV[0] eq 'lst') {
9 } elsif ($ARGV[0] eq 'exprseq') {
12 die 'only lst and exprseq supported';
18 if ($type eq 'exprseq') {
20 # settings for exprseq
29 } elsif ($type eq 'lst') {
41 die "invalid type $type";
44 $CONTAINER_UC=uc(${CONTAINER});
45 $STLT="ex".$STLHEADER;
48 $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) (s).reserve(size)";
50 $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) // no reserve needed for ${STLHEADER}";
54 $PREPEND_INTERFACE=<<END_OF_PREPEND_INTERFACE;
55 virtual ${CONTAINER} & prepend(ex const & b);
56 END_OF_PREPEND_INTERFACE
58 $PREPEND_IMPLEMENTATION=<<END_OF_PREPEND_IMPLEMENTATION;
59 ${CONTAINER} & ${CONTAINER}::prepend(ex const & b)
61 ensure_if_modifiable();
65 END_OF_PREPEND_IMPLEMENTATION
67 $PREPEND_INTERFACE=" // no prepend possible for ${CONTAINER}";
68 $PREPEND_IMPLEMENTATION="";
72 $LET_OP_IMPLEMENTATION=<<END_OF_LET_OP_IMPLEMENTATION
73 ex & ${CONTAINER}::let_op(int const i)
76 GINAC_ASSERT(i<nops());
78 ${STLT}::iterator it=seq.begin();
79 for (int j=0; j<i; j++) {
84 END_OF_LET_OP_IMPLEMENTATION
86 $LET_OP_IMPLEMENTATION="// ${CONTAINER}::let_op() will be implemented by user elsewhere";
89 $interface=<<END_OF_INTERFACE;
90 /** \@file ${CONTAINER}.h
92 * Definition of GiNaC's ${CONTAINER}. */
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}
102 * \$open_bracket=${open_bracket}
103 * \$close_bracket=${close_bracket}
105 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
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.
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.
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
122 #ifndef __GINAC_${CONTAINER_UC}_H__
123 #define __GINAC_${CONTAINER_UC}_H__
125 #include <${STLHEADER}>
126 #include <ginac/basic.h>
127 #include <ginac/ex.h>
131 typedef ${STLHEADER}<ex> ${STLT};
133 class ${CONTAINER} : public basic
139 ${CONTAINER}(${CONTAINER} const & other);
140 ${CONTAINER} const & operator=(${CONTAINER} const & other);
142 void copy(${CONTAINER} const & other);
143 void destroy(bool call_parent);
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,
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,
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,
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;
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;
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;
191 // new virtual functions which can be overridden by derived classes
193 virtual ${CONTAINER} & append(ex const & b);
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;
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;
212 static unsigned precedence;
217 extern const ${CONTAINER} some_${CONTAINER};
218 extern type_info const & typeid_${CONTAINER};
221 inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e)
223 return static_cast<const ${CONTAINER} &>(*e.bp);
228 #endif // ndef __GINAC_${CONTAINER_UC}_H__
232 $implementation=<<END_OF_IMPLEMENTATION;
233 /** \@file ${CONTAINER}.cpp
235 * Implementation of GiNaC's ${CONTAINER}. */
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}
245 * \$open_bracket=${open_bracket}
246 * \$close_bracket=${close_bracket}
248 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
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.
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.
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
268 #include "${CONTAINER}.h"
270 #include "debugmsg.h"
274 ${RESERVE_IMPLEMENTATION}
277 // default constructor, destructor, copy constructor assignment operator and helpers
282 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER})
284 debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
287 ${CONTAINER}::~${CONTAINER}()
289 debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
293 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
295 debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
299 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
301 debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
302 if (this != &other) {
311 void ${CONTAINER}::copy(${CONTAINER} const & other)
317 void ${CONTAINER}::destroy(bool call_parent)
320 if (call_parent) basic::destroy(call_parent);
324 // other constructors
329 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER})
331 debugmsg("${CONTAINER} constructor from ${STLT}",
334 seq.swap(const_cast<${STLT} &>(s));
340 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER})
342 debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
348 ${CONTAINER}::${CONTAINER}(ex const & e1) : basic(TINFO_${CONTAINER})
350 debugmsg("${CONTAINER} constructor from 1 ex",
356 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER})
358 debugmsg("${CONTAINER} constructor from 2 ex",
365 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
366 : basic(TINFO_${CONTAINER})
368 debugmsg("${CONTAINER} constructor from 3 ex",
376 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
377 ex const & e4) : basic(TINFO_${CONTAINER})
379 debugmsg("${CONTAINER} constructor from 4 ex",
388 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
389 ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER})
391 debugmsg("${CONTAINER} constructor from 5 ex",
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})
405 debugmsg("${CONTAINER} constructor from 6 ex",
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})
420 debugmsg("${CONTAINER} constructor from 7 ex",
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})
436 debugmsg("${CONTAINER} constructor from 8 ex",
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})
454 debugmsg("${CONTAINER} constructor from 9 ex",
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,
472 : basic(TINFO_${CONTAINER})
474 debugmsg("${CONTAINER} constructor from 10 ex",
490 // functions overriding virtual functions from bases classes
495 basic * ${CONTAINER}::duplicate() const
497 debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
498 return new ${CONTAINER}(*this);
501 void ${CONTAINER}::printraw(ostream & os) const
503 debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
505 os << "${CONTAINER}(";
506 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
507 (*cit).bp->printraw(os);
513 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
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);
520 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
522 debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
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);
531 os << string(indent+delta_indent,' ') << "=====" << endl;
534 // ${CONTAINER}::info() will be implemented by user elsewhere";
536 int ${CONTAINER}::nops() const
541 ${LET_OP_IMPLEMENTATION}
543 ex ${CONTAINER}::expand(unsigned options) const
546 RESERVE(s,seq.size());
547 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
548 s.push_back((*it).expand(options));
551 return this${CONTAINER}(s);
554 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
556 bool ${CONTAINER}::has(ex const & other) const
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;
566 ex ${CONTAINER}::eval(int level) const
571 return this${CONTAINER}(evalchildren(level));
574 ex ${CONTAINER}::evalf(int level) const
576 return this${CONTAINER}(evalfchildren(level));
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
584 ex n=this${CONTAINER}(normalchildren(level));
585 return n.bp->basic::normal(sym_lst,repl_lst,level);
588 ex ${CONTAINER}::diff(symbol const & s) const
590 return this${CONTAINER}(diffchildren(s));
593 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
595 ${STLT} * vp=subschildren(ls,lr);
599 return this${CONTAINER}(vp);
604 int ${CONTAINER}::compare_same_type(basic const & other) const
606 GINAC_ASSERT(is_of_type(other,${CONTAINER}));
607 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
608 (const_cast<basic &>(other));
610 ${STLT}::const_iterator it1=seq.begin();
611 ${STLT}::const_iterator it2=o.seq.begin();
613 for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
614 cmpval=(*it1).compare(*it2);
615 if (cmpval!=0) return cmpval;
618 if (it1==seq.end()) {
619 return (it2==o.seq.end() ? 0 : -1);
625 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
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;
632 ${STLT}::const_iterator it1=seq.begin();
633 ${STLT}::const_iterator it2=o.seq.begin();
635 for (; it1!=seq.end(); ++it1, ++it2) {
636 if (!(*it1).is_equal(*it2)) return false;
642 unsigned ${CONTAINER}::return_type(void) const
644 return return_types::noncommutative_composite;
648 // new virtual functions which can be overridden by derived classes
653 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
655 ensure_if_modifiable();
660 ${PREPEND_IMPLEMENTATION}
664 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
665 char closebracket, unsigned this_precedence,
666 unsigned upper_precedence) const
668 if (this_precedence<=upper_precedence) os << openbracket;
670 ${STLT}::const_iterator it,it_last;
674 for (; it!=it_last; ++it) {
675 (*it).bp->print(os,this_precedence);
678 (*it).bp->print(os,this_precedence);
680 if (this_precedence<=upper_precedence) os << closebracket;
683 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
685 return ${CONTAINER}(v);
688 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
690 return ${CONTAINER}(vp);
694 // non-virtual functions in this class
703 bool ${CONTAINER}::is_canonical() const
705 if (seq.size()<=1) { return 1; }
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";
721 ${STLT} ${CONTAINER}::evalchildren(int level) const
724 RESERVE(s,seq.size());
729 if (level == -max_recursion_level) {
730 throw(std::runtime_error("max recursion level reached"));
733 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
734 s.push_back((*it).eval(level));
739 ${STLT} ${CONTAINER}::evalfchildren(int level) const
742 RESERVE(s,seq.size());
747 if (level == -max_recursion_level) {
748 throw(std::runtime_error("max recursion level reached"));
751 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
752 s.push_back((*it).evalf(level));
757 ${STLT} ${CONTAINER}::normalchildren(int level) const
760 RESERVE(s,seq.size());
765 if (level == -max_recursion_level) {
766 throw(std::runtime_error("max recursion level reached"));
769 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
770 s.push_back((*it).normal(level));
775 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
778 RESERVE(s,seq.size());
779 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
780 s.push_back((*it).diff(y));
785 /* obsolete subschildren
786 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
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));
797 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
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)
803 ${STLT}::const_iterator last=seq.end();
804 ${STLT}::const_iterator cit=seq.begin();
806 ex const & subsed_ex=(*cit).subs(ls,lr);
807 if (!are_ex_trivially_equal(*cit,subsed_ex)) {
809 // something changed, copy seq, subs and return it
810 ${STLT} *s=new ${STLT};
811 RESERVE(*s,seq.size());
813 // copy parts of seq which are known not to have changed
814 ${STLT}::const_iterator cit2=seq.begin();
819 // copy first changed element
820 s->push_back(subsed_ex);
824 s->push_back((*cit2).subs(ls,lr));
832 return 0; // nothing has changed
836 // static member variables
841 unsigned ${CONTAINER}::precedence=10;
847 const ${CONTAINER} some_${CONTAINER};
848 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
852 END_OF_IMPLEMENTATION
854 print "Creating interface file ${CONTAINER}.h...";
855 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
856 print OUT $interface;
860 print "Creating implementation file ${CONTAINER}.cpp...";
861 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
862 print OUT $implementation;