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)
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}.
93 * This file was generated automatically by container.pl.
94 * Please do not modify it directly, edit the perl script instead!
95 * container.pl options: \$CONTAINER=${CONTAINER}
96 * \$STLHEADER=${STLHEADER}
97 * \$reserve=${reserve}
98 * \$prepend=${prepend}
100 * \$open_bracket=${open_bracket}
101 * \$close_bracket=${close_bracket}
103 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
105 * This program is free software; you can redistribute it and/or modify
106 * it under the terms of the GNU General Public License as published by
107 * the Free Software Foundation; either version 2 of the License, or
108 * (at your option) any later version.
110 * This program is distributed in the hope that it will be useful,
111 * but WITHOUT ANY WARRANTY; without even the implied warranty of
112 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113 * GNU General Public License for more details.
115 * You should have received a copy of the GNU General Public License
116 * along with this program; if not, write to the Free Software
117 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
120 #ifndef __GINAC_${CONTAINER_UC}_H__
121 #define __GINAC_${CONTAINER_UC}_H__
123 #include <${STLHEADER}>
124 #include <ginac/basic.h>
126 typedef ${STLHEADER}<ex> ${STLT};
128 class ${CONTAINER} : public basic
134 ${CONTAINER}(${CONTAINER} const & other);
135 ${CONTAINER} const & operator=(${CONTAINER} const & other);
137 void copy(${CONTAINER} const & other);
138 void destroy(bool call_parent);
141 ${CONTAINER}(${STLT} const & s, bool discardable=0);
142 ${CONTAINER}(${STLT} * vp); // vp will be deleted
143 explicit ${CONTAINER}(ex const & e1);
144 explicit ${CONTAINER}(ex const & e1, ex const & e2);
145 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3);
146 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
148 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
149 ex const & e4, ex const & e5);
150 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
151 ex const & e4, ex const & e5, ex const & e6);
152 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
153 ex const & e4, ex const & e5, ex const & e6,
155 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
156 ex const & e4, ex const & e5, ex const & e6,
157 ex const & e7, ex const & e8);
158 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
159 ex const & e4, ex const & e5, ex const & e6,
160 ex const & e7, ex const & e8, ex const & e9);
161 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
162 ex const & e4, ex const & e5, ex const & e6,
163 ex const & e7, ex const & e8, ex const & e9,
167 basic * duplicate() const;
168 void printraw(ostream & os) const;
169 void print(ostream & os, unsigned upper_precedence=0) const;
170 void printtree(ostream & os, unsigned indent) const;
171 bool info(unsigned inf) const;
173 ex & let_op(int const i);
174 ex expand(unsigned options=0) const;
175 bool has(ex const & other) const;
176 ex eval(int level=0) const;
177 ex evalf(int level=0) const;
178 ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
179 ex diff(symbol const & s) const;
180 ex subs(lst const & ls, lst const & lr) const;
182 int compare_same_type(basic const & other) const;
183 bool is_equal_same_type(basic const & other) const;
184 unsigned return_type(void) const;
186 // new virtual functions which can be overridden by derived classes
188 virtual ${CONTAINER} & append(ex const & b);
191 virtual void printseq(ostream & os, char openbracket, char delim,
192 char closebracket, unsigned this_precedence,
193 unsigned upper_precedence=0) const;
194 virtual ex this${CONTAINER}(${STLT} const & v) const;
195 virtual ex this${CONTAINER}(${STLT} * vp) const;
198 bool is_canonical() const;
199 ${STLT} evalchildren(int level) const;
200 ${STLT} evalfchildren(int level) const;
201 ${STLT} normalchildren(int level) const;
202 ${STLT} diffchildren(symbol const & s) const;
203 ${STLT} * subschildren(lst const & ls, lst const & lr) const;
207 static unsigned precedence;
212 extern const ${CONTAINER} some_${CONTAINER};
213 extern type_info const & typeid_${CONTAINER};
217 #define ex_to_${CONTAINER}(X) (static_cast<${CONTAINER} const &>(*(X).bp))
219 #endif // ndef __GINAC_${CONTAINER_UC}_H__
223 $implementation=<<END_OF_IMPLEMENTATION;
224 /** \@file ${CONTAINER}.cpp
226 * Implementation of GiNaC's ${CONTAINER}.
227 * This file was generated automatically by container.pl.
228 * Please do not modify it directly, edit the perl script instead!
229 * container.pl options: \$CONTAINER=${CONTAINER}
230 * \$STLHEADER=${STLHEADER}
231 * \$reserve=${reserve}
232 * \$prepend=${prepend}
234 * \$open_bracket=${open_bracket}
235 * \$close_bracket=${close_bracket}
237 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
239 * This program is free software; you can redistribute it and/or modify
240 * it under the terms of the GNU General Public License as published by
241 * the Free Software Foundation; either version 2 of the License, or
242 * (at your option) any later version.
244 * This program is distributed in the hope that it will be useful,
245 * but WITHOUT ANY WARRANTY; without even the implied warranty of
246 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
247 * GNU General Public License for more details.
249 * You should have received a copy of the GNU General Public License
250 * along with this program; if not, write to the Free Software
251 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
257 #include "${CONTAINER}.h"
260 ${RESERVE_IMPLEMENTATION}
263 // default constructor, destructor, copy constructor assignment operator and helpers
268 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER})
270 debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
273 ${CONTAINER}::~${CONTAINER}()
275 debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
279 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
281 debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
285 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
287 debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
288 if (this != &other) {
297 void ${CONTAINER}::copy(${CONTAINER} const & other)
303 void ${CONTAINER}::destroy(bool call_parent)
306 if (call_parent) basic::destroy(call_parent);
310 // other constructors
315 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER})
317 debugmsg("${CONTAINER} constructor from ${STLT}",
320 seq.swap(const_cast<${STLT} &>(s));
326 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER})
328 debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
334 ${CONTAINER}::${CONTAINER}(ex const & e1) : basic(TINFO_${CONTAINER})
336 debugmsg("${CONTAINER} constructor from 1 ex",
342 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER})
344 debugmsg("${CONTAINER} constructor from 2 ex",
351 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
352 : basic(TINFO_${CONTAINER})
354 debugmsg("${CONTAINER} constructor from 3 ex",
362 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
363 ex const & e4) : basic(TINFO_${CONTAINER})
365 debugmsg("${CONTAINER} constructor from 4 ex",
374 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
375 ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER})
377 debugmsg("${CONTAINER} constructor from 5 ex",
387 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
388 ex const & e4, ex const & e5, ex const & e6)
389 : basic(TINFO_${CONTAINER})
391 debugmsg("${CONTAINER} constructor from 6 ex",
402 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
403 ex const & e4, ex const & e5, ex const & e6,
404 ex const & e7) : basic(TINFO_${CONTAINER})
406 debugmsg("${CONTAINER} constructor from 7 ex",
418 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
419 ex const & e4, ex const & e5, ex const & e6,
420 ex const & e7, ex const & e8) : basic(TINFO_${CONTAINER})
422 debugmsg("${CONTAINER} constructor from 8 ex",
435 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
436 ex const & e4, ex const & e5, ex const & e6,
437 ex const & e7, ex const & e8, ex const & e9)
438 : basic(TINFO_${CONTAINER})
440 debugmsg("${CONTAINER} constructor from 9 ex",
454 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
455 ex const & e4, ex const & e5, ex const & e6,
456 ex const & e7, ex const & e8, ex const & e9,
458 : basic(TINFO_${CONTAINER})
460 debugmsg("${CONTAINER} constructor from 10 ex",
476 // functions overriding virtual functions from bases classes
481 basic * ${CONTAINER}::duplicate() const
483 debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
484 return new ${CONTAINER}(*this);
487 void ${CONTAINER}::printraw(ostream & os) const
489 debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
491 os << "${CONTAINER}(";
492 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
493 (*cit).bp->printraw(os);
499 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
501 debugmsg("${CONTAINER} print",LOGLEVEL_PRINT);
502 // always print brackets around seq, ignore upper_precedence
503 printseq(os,'${open_bracket}',',','${close_bracket}',precedence,precedence+1);
506 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
508 debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
510 os << string(indent,' ') << "type=" << typeid(*this).name()
511 << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
512 << ", flags=" << flags
513 << ", nops=" << nops() << endl;
514 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
515 (*cit).printtree(os,indent+delta_indent);
517 os << string(indent+delta_indent,' ') << "=====" << endl;
520 // ${CONTAINER}::info() will be implemented by user elsewhere";
522 int ${CONTAINER}::nops() const
527 ${LET_OP_IMPLEMENTATION}
529 ex ${CONTAINER}::expand(unsigned options) const
532 RESERVE(s,seq.size());
533 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
534 s.push_back((*it).expand(options));
537 return this${CONTAINER}(s);
540 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
542 bool ${CONTAINER}::has(ex const & other) const
545 if (is_equal(*other.bp)) return true;
546 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
547 if ((*it).has(other)) return true;
552 ex ${CONTAINER}::eval(int level) const
557 return this${CONTAINER}(evalchildren(level));
560 ex ${CONTAINER}::evalf(int level) const
562 return this${CONTAINER}(evalfchildren(level));
565 /** Implementation of ex::normal() for ${CONTAINER}s. It normalizes the arguments
566 * and replaces the ${CONTAINER} by a temporary symbol.
567 * \@see ex::normal */
568 ex ${CONTAINER}::normal(lst &sym_lst, lst &repl_lst, int level) const
570 ex n=this${CONTAINER}(normalchildren(level));
571 return n.bp->basic::normal(sym_lst,repl_lst,level);
574 ex ${CONTAINER}::diff(symbol const & s) const
576 return this${CONTAINER}(diffchildren(s));
579 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
581 ${STLT} * vp=subschildren(ls,lr);
585 return this${CONTAINER}(vp);
590 int ${CONTAINER}::compare_same_type(basic const & other) const
592 ASSERT(is_of_type(other,${CONTAINER}));
593 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
594 (const_cast<basic &>(other));
596 ${STLT}::const_iterator it1=seq.begin();
597 ${STLT}::const_iterator it2=o.seq.begin();
599 for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
600 cmpval=(*it1).compare(*it2);
601 if (cmpval!=0) return cmpval;
604 if (it1==seq.end()) {
605 return (it2==o.seq.end() ? 0 : -1);
611 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
613 ASSERT(is_of_type(other,${CONTAINER}));
614 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
615 (const_cast<basic &>(other));
616 if (seq.size()!=o.seq.size()) return false;
618 ${STLT}::const_iterator it1=seq.begin();
619 ${STLT}::const_iterator it2=o.seq.begin();
621 for (; it1!=seq.end(); ++it1, ++it2) {
622 if (!(*it1).is_equal(*it2)) return false;
628 unsigned ${CONTAINER}::return_type(void) const
630 return return_types::noncommutative_composite;
634 // new virtual functions which can be overridden by derived classes
639 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
641 ensure_if_modifiable();
646 ${PREPEND_IMPLEMENTATION}
650 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
651 char closebracket, unsigned this_precedence,
652 unsigned upper_precedence) const
654 if (this_precedence<=upper_precedence) os << openbracket;
656 ${STLT}::const_iterator it,it_last;
660 for (; it!=it_last; ++it) {
661 (*it).bp->print(os,this_precedence);
664 (*it).bp->print(os,this_precedence);
666 if (this_precedence<=upper_precedence) os << closebracket;
669 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
671 return ${CONTAINER}(v);
674 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
676 return ${CONTAINER}(vp);
680 // non-virtual functions in this class
689 bool ${CONTAINER}::is_canonical() const
691 if (seq.size()<=1) { return 1; }
693 ${STLT}::const_iterator it=seq.begin();
694 ${STLT}::const_iterator it_last=it;
695 for (++it; it!=seq.end(); it_last=it, ++it) {
696 if ((*it_last).compare(*it)>0) {
697 if ((*it_last).compare(*it)>0) {
698 cout << *it_last << ">" << *it << "\\n";
707 ${STLT} ${CONTAINER}::evalchildren(int level) const
710 RESERVE(s,seq.size());
715 if (level == -max_recursion_level) {
716 throw(std::runtime_error("max recursion level reached"));
719 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
720 s.push_back((*it).eval(level));
725 ${STLT} ${CONTAINER}::evalfchildren(int level) const
728 RESERVE(s,seq.size());
733 if (level == -max_recursion_level) {
734 throw(std::runtime_error("max recursion level reached"));
737 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
738 s.push_back((*it).evalf(level));
743 ${STLT} ${CONTAINER}::normalchildren(int level) const
746 RESERVE(s,seq.size());
751 if (level == -max_recursion_level) {
752 throw(std::runtime_error("max recursion level reached"));
755 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
756 s.push_back((*it).normal(level));
761 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
764 RESERVE(s,seq.size());
765 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
766 s.push_back((*it).diff(y));
771 /* obsolete subschildren
772 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
775 RESERVE(s,seq.size());
776 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
777 s.push_back((*it).subs(ls,lr));
783 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
785 // returns a NULL pointer if nothing had to be substituted
786 // returns a pointer to a newly created epvector otherwise
787 // (which has to be deleted somewhere else)
789 ${STLT}::const_iterator last=seq.end();
790 ${STLT}::const_iterator cit=seq.begin();
792 ex const & subsed_ex=(*cit).subs(ls,lr);
793 if (!are_ex_trivially_equal(*cit,subsed_ex)) {
795 // something changed, copy seq, subs and return it
796 ${STLT} *s=new ${STLT};
797 RESERVE(*s,seq.size());
799 // copy parts of seq which are known not to have changed
800 ${STLT}::const_iterator cit2=seq.begin();
805 // copy first changed element
806 s->push_back(subsed_ex);
810 s->push_back((*cit2).subs(ls,lr));
818 return 0; // nothing has changed
822 // static member variables
827 unsigned ${CONTAINER}::precedence=10;
833 const ${CONTAINER} some_${CONTAINER};
834 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
836 END_OF_IMPLEMENTATION
838 print "Creating interface file ${CONTAINER}.h...";
839 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
840 print OUT $interface;
844 print "Creating implementation file ${CONTAINER}.cpp...";
845 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
846 print OUT $implementation;