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-2000 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}>
127 // CINT needs <algorithm> to work properly with <vector> and <list>
130 #include <ginac/basic.h>
131 #include <ginac/ex.h>
133 #ifndef NO_GINAC_NAMESPACE
135 #endif // ndef NO_GINAC_NAMESPACE
137 // typedef ${STLHEADER}<ex> ${STLT};
138 typedef ${STLHEADER}<ex,malloc_alloc> ${STLT}; // CINT does not like ${STLHEADER}<...,default_alloc>
140 class ${CONTAINER} : public basic
142 GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic)
147 ${CONTAINER}(${CONTAINER} const & other);
148 ${CONTAINER} const & operator=(${CONTAINER} const & other);
150 void copy(${CONTAINER} const & other);
151 void destroy(bool call_parent);
154 ${CONTAINER}(${STLT} const & s, bool discardable=0);
155 ${CONTAINER}(${STLT} * vp); // vp will be deleted
156 explicit ${CONTAINER}(ex const & e1);
157 explicit ${CONTAINER}(ex const & e1, ex const & e2);
158 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3);
159 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
161 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
162 ex const & e4, ex const & e5);
163 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
164 ex const & e4, ex const & e5, ex const & e6);
165 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
166 ex const & e4, ex const & e5, ex const & e6,
168 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
169 ex const & e4, ex const & e5, ex const & e6,
170 ex const & e7, ex const & e8);
171 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
172 ex const & e4, ex const & e5, ex const & e6,
173 ex const & e7, ex const & e8, ex const & e9);
174 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
175 ex const & e4, ex const & e5, ex const & e6,
176 ex const & e7, ex const & e8, ex const & e9,
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 const i);
187 ex expand(unsigned options=0) const;
188 bool has(ex const & 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(symbol const & s) const;
193 ex subs(lst const & ls, lst const & lr) const;
195 int compare_same_type(basic const & other) const;
196 bool is_equal_same_type(basic const & other) const;
197 unsigned return_type(void) const;
199 // new virtual functions which can be overridden by derived classes
201 virtual ${CONTAINER} & append(ex const & b);
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;
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(symbol const & s) const;
216 ${STLT} * subschildren(lst const & ls, lst const & lr) const;
220 static unsigned precedence;
225 extern const ${CONTAINER} some_${CONTAINER};
226 extern type_info const & typeid_${CONTAINER};
229 inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e)
231 return static_cast<const ${CONTAINER} &>(*e.bp);
234 #ifndef NO_GINAC_NAMESPACE
236 #endif // ndef NO_GINAC_NAMESPACE
238 #endif // ndef __GINAC_${CONTAINER_UC}_H__
242 $implementation=<<END_OF_IMPLEMENTATION;
243 /** \@file ${CONTAINER}.cpp
245 * Implementation of GiNaC's ${CONTAINER}. */
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}
255 * \$open_bracket=${open_bracket}
256 * \$close_bracket=${close_bracket}
258 * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
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.
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.
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
278 #include "${CONTAINER}.h"
281 #include "debugmsg.h"
283 #ifndef NO_GINAC_NAMESPACE
285 #endif // ndef NO_GINAC_NAMESPACE
287 GINAC_IMPLEMENT_REGISTERED_CLASS(${CONTAINER}, basic)
289 ${RESERVE_IMPLEMENTATION}
292 // default constructor, destructor, copy constructor assignment operator and helpers
297 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER})
299 debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
302 ${CONTAINER}::~${CONTAINER}()
304 debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
308 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
310 debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
314 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
316 debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
317 if (this != &other) {
326 void ${CONTAINER}::copy(${CONTAINER} const & other)
328 inherited::copy(other);
332 void ${CONTAINER}::destroy(bool call_parent)
335 if (call_parent) inherited::destroy(call_parent);
339 // other constructors
344 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER})
346 debugmsg("${CONTAINER} constructor from ${STLT}",
349 seq.swap(const_cast<${STLT} &>(s));
355 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER})
357 debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
363 ${CONTAINER}::${CONTAINER}(ex const & e1) : basic(TINFO_${CONTAINER})
365 debugmsg("${CONTAINER} constructor from 1 ex",
371 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER})
373 debugmsg("${CONTAINER} constructor from 2 ex",
380 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
381 : basic(TINFO_${CONTAINER})
383 debugmsg("${CONTAINER} constructor from 3 ex",
391 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
392 ex const & e4) : basic(TINFO_${CONTAINER})
394 debugmsg("${CONTAINER} constructor from 4 ex",
403 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
404 ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER})
406 debugmsg("${CONTAINER} constructor from 5 ex",
416 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
417 ex const & e4, ex const & e5, ex const & e6)
418 : basic(TINFO_${CONTAINER})
420 debugmsg("${CONTAINER} constructor from 6 ex",
431 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
432 ex const & e4, ex const & e5, ex const & e6,
433 ex const & e7) : basic(TINFO_${CONTAINER})
435 debugmsg("${CONTAINER} constructor from 7 ex",
447 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
448 ex const & e4, ex const & e5, ex const & e6,
449 ex const & e7, ex const & e8) : basic(TINFO_${CONTAINER})
451 debugmsg("${CONTAINER} constructor from 8 ex",
464 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
465 ex const & e4, ex const & e5, ex const & e6,
466 ex const & e7, ex const & e8, ex const & e9)
467 : basic(TINFO_${CONTAINER})
469 debugmsg("${CONTAINER} constructor from 9 ex",
483 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
484 ex const & e4, ex const & e5, ex const & e6,
485 ex const & e7, ex const & e8, ex const & e9,
487 : basic(TINFO_${CONTAINER})
489 debugmsg("${CONTAINER} constructor from 10 ex",
508 /** Construct object from archive_node. */
509 ${CONTAINER}::${CONTAINER}(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
511 debugmsg("${CONTAINER} constructor from archive_node", LOGLEVEL_CONSTRUCT);
512 for (unsigned int i=0; true; i++) {
514 if (n.find_ex("seq", e, sym_lst, i))
521 /** Unarchive the object. */
522 ex ${CONTAINER}::unarchive(const archive_node &n, const lst &sym_lst)
524 return (new ${CONTAINER}(n, sym_lst))->setflag(status_flags::dynallocated);
527 /** Archive the object. */
528 void ${CONTAINER}::archive(archive_node &n) const
530 inherited::archive(n);
531 ${STLT}::const_iterator i = seq.begin(), iend = seq.end();
539 // functions overriding virtual functions from bases classes
544 basic * ${CONTAINER}::duplicate() const
546 debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
547 return new ${CONTAINER}(*this);
550 void ${CONTAINER}::printraw(ostream & os) const
552 debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
554 os << "${CONTAINER}(";
555 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
556 (*cit).bp->printraw(os);
562 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
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);
569 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
571 debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
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);
580 os << string(indent+delta_indent,' ') << "=====" << endl;
583 // ${CONTAINER}::info() will be implemented by user elsewhere";
585 unsigned ${CONTAINER}::nops() const
590 ${LET_OP_IMPLEMENTATION}
592 ex ${CONTAINER}::expand(unsigned options) const
595 RESERVE(s,seq.size());
596 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
597 s.push_back((*it).expand(options));
600 return this${CONTAINER}(s);
603 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
605 bool ${CONTAINER}::has(ex const & other) const
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;
615 ex ${CONTAINER}::eval(int level) const
620 return this${CONTAINER}(evalchildren(level));
623 ex ${CONTAINER}::evalf(int level) const
625 return this${CONTAINER}(evalfchildren(level));
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
633 ex n=this${CONTAINER}(normalchildren(level));
634 return n.bp->basic::normal(sym_lst,repl_lst,level);
637 ex ${CONTAINER}::diff(symbol const & s) const
639 return this${CONTAINER}(diffchildren(s));
642 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
644 ${STLT} * vp=subschildren(ls,lr);
648 return this${CONTAINER}(vp);
653 int ${CONTAINER}::compare_same_type(basic const & other) const
655 GINAC_ASSERT(is_of_type(other,${CONTAINER}));
656 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
657 (const_cast<basic &>(other));
659 ${STLT}::const_iterator it1=seq.begin();
660 ${STLT}::const_iterator it2=o.seq.begin();
662 for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
663 cmpval=(*it1).compare(*it2);
664 if (cmpval!=0) return cmpval;
667 if (it1==seq.end()) {
668 return (it2==o.seq.end() ? 0 : -1);
674 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
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;
681 ${STLT}::const_iterator it1=seq.begin();
682 ${STLT}::const_iterator it2=o.seq.begin();
684 for (; it1!=seq.end(); ++it1, ++it2) {
685 if (!(*it1).is_equal(*it2)) return false;
691 unsigned ${CONTAINER}::return_type(void) const
693 return return_types::noncommutative_composite;
697 // new virtual functions which can be overridden by derived classes
702 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
704 ensure_if_modifiable();
709 ${PREPEND_IMPLEMENTATION}
713 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
714 char closebracket, unsigned this_precedence,
715 unsigned upper_precedence) const
717 if (this_precedence<=upper_precedence) os << openbracket;
719 ${STLT}::const_iterator it,it_last;
723 for (; it!=it_last; ++it) {
724 (*it).bp->print(os,this_precedence);
727 (*it).bp->print(os,this_precedence);
729 if (this_precedence<=upper_precedence) os << closebracket;
732 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
734 return ${CONTAINER}(v);
737 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
739 return ${CONTAINER}(vp);
743 // non-virtual functions in this class
752 bool ${CONTAINER}::is_canonical() const
754 if (seq.size()<=1) { return 1; }
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";
770 ${STLT} ${CONTAINER}::evalchildren(int level) const
773 RESERVE(s,seq.size());
778 if (level == -max_recursion_level) {
779 throw(std::runtime_error("max recursion level reached"));
782 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
783 s.push_back((*it).eval(level));
788 ${STLT} ${CONTAINER}::evalfchildren(int level) const
791 RESERVE(s,seq.size());
796 if (level == -max_recursion_level) {
797 throw(std::runtime_error("max recursion level reached"));
800 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
801 s.push_back((*it).evalf(level));
806 ${STLT} ${CONTAINER}::normalchildren(int level) const
809 RESERVE(s,seq.size());
814 if (level == -max_recursion_level) {
815 throw(std::runtime_error("max recursion level reached"));
818 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
819 s.push_back((*it).normal(level));
824 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
827 RESERVE(s,seq.size());
828 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
829 s.push_back((*it).diff(y));
834 /* obsolete subschildren
835 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
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));
846 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
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)
852 ${STLT}::const_iterator last=seq.end();
853 ${STLT}::const_iterator cit=seq.begin();
855 ex const & subsed_ex=(*cit).subs(ls,lr);
856 if (!are_ex_trivially_equal(*cit,subsed_ex)) {
858 // something changed, copy seq, subs and return it
859 ${STLT} *s=new ${STLT};
860 RESERVE(*s,seq.size());
862 // copy parts of seq which are known not to have changed
863 ${STLT}::const_iterator cit2=seq.begin();
868 // copy first changed element
869 s->push_back(subsed_ex);
873 s->push_back((*cit2).subs(ls,lr));
881 return 0; // nothing has changed
885 // static member variables
890 unsigned ${CONTAINER}::precedence=10;
896 const ${CONTAINER} some_${CONTAINER};
897 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
899 #ifndef NO_GINAC_NAMESPACE
901 #endif // ndef NO_GINAC_NAMESPACE
903 END_OF_IMPLEMENTATION
905 print "Creating interface file ${CONTAINER}.h...";
906 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
907 print OUT $interface;
911 print "Creating implementation file ${CONTAINER}.cpp...";
912 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
913 print OUT $implementation;