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 #ifndef _${CONTAINER_UC}_H_
104 #define _${CONTAINER_UC}_H_
106 #include <${STLHEADER}>
108 #include <ginac/ginac.h>
110 typedef ${STLHEADER}<ex> ${STLT};
112 class ${CONTAINER} : public basic
118 ${CONTAINER}(${CONTAINER} const & other);
119 ${CONTAINER} const & operator=(${CONTAINER} const & other);
121 void copy(${CONTAINER} const & other);
122 void destroy(bool call_parent);
125 ${CONTAINER}(${STLT} const & s, bool discardable=0);
126 ${CONTAINER}(${STLT} * vp); // vp will be deleted
127 explicit ${CONTAINER}(ex const & e1);
128 explicit ${CONTAINER}(ex const & e1, ex const & e2);
129 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3);
130 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
132 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
133 ex const & e4, ex const & e5);
134 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
135 ex const & e4, ex const & e5, ex const & e6);
136 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
137 ex const & e4, ex const & e5, ex const & e6,
139 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
140 ex const & e4, ex const & e5, ex const & e6,
141 ex const & e7, ex const & e8);
142 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
143 ex const & e4, ex const & e5, ex const & e6,
144 ex const & e7, ex const & e8, ex const & e9);
145 explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
146 ex const & e4, ex const & e5, ex const & e6,
147 ex const & e7, ex const & e8, ex const & e9,
151 basic * duplicate() const;
152 void printraw(ostream & os) const;
153 void print(ostream & os, unsigned upper_precedence=0) const;
154 void printtree(ostream & os, unsigned indent) const;
155 bool info(unsigned inf) const;
157 ex & let_op(int const i);
158 ex expand(unsigned options=0) const;
159 bool has(ex const & other) const;
160 ex eval(int level=0) const;
161 ex evalf(int level=0) const;
162 ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
163 ex diff(symbol const & s) const;
164 ex subs(lst const & ls, lst const & lr) const;
166 int compare_same_type(basic const & other) const;
167 bool is_equal_same_type(basic const & other) const;
168 unsigned return_type(void) const;
170 // new virtual functions which can be overridden by derived classes
172 virtual ${CONTAINER} & append(ex const & b);
175 virtual void printseq(ostream & os, char openbracket, char delim,
176 char closebracket, unsigned this_precedence,
177 unsigned upper_precedence=0) const;
178 virtual ex this${CONTAINER}(${STLT} const & v) const;
179 virtual ex this${CONTAINER}(${STLT} * vp) const;
182 bool is_canonical() const;
183 ${STLT} evalchildren(int level) const;
184 ${STLT} evalfchildren(int level) const;
185 ${STLT} normalchildren(int level) const;
186 ${STLT} diffchildren(symbol const & s) const;
187 ${STLT} * subschildren(lst const & ls, lst const & lr) const;
191 static unsigned precedence;
196 extern const ${CONTAINER} some_${CONTAINER};
197 extern type_info const & typeid_${CONTAINER};
201 #define ex_to_${CONTAINER}(X) (static_cast<${CONTAINER} const &>(*(X).bp))
203 #endif // ndef _${CONTAINER_UC}_H_
207 $implementation=<<END_OF_IMPLEMENTATION;
208 /** \@file ${CONTAINER}.cpp
210 * Implementation of GiNaC's ${CONTAINER}.
211 * This file was generated automatically by container.pl.
212 * Please do not modify it directly, edit the perl script instead!
213 * container.pl options: \$CONTAINER=${CONTAINER}
214 * \$STLHEADER=${STLHEADER}
215 * \$reserve=${reserve}
216 * \$prepend=${prepend}
218 * \$open_bracket=${open_bracket}
219 * \$close_bracket=${close_bracket} */
226 ${RESERVE_IMPLEMENTATION}
229 // default constructor, destructor, copy constructor assignment operator and helpers
234 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER_UC})
236 debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
239 ${CONTAINER}::~${CONTAINER}()
241 debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
245 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
247 debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
251 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
253 debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
254 if (this != &other) {
263 void ${CONTAINER}::copy(${CONTAINER} const & other)
269 void ${CONTAINER}::destroy(bool call_parent)
272 if (call_parent) basic::destroy(call_parent);
276 // other constructors
281 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER_UC})
283 debugmsg("${CONTAINER} constructor from ${STLT}",
286 seq.swap(const_cast<${STLT} &>(s));
292 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER_UC})
294 debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
300 ${CONTAINER}::${CONTAINER}(ex const & e1) : basic(TINFO_${CONTAINER_UC})
302 debugmsg("${CONTAINER} constructor from 1 ex",
308 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER_UC})
310 debugmsg("${CONTAINER} constructor from 2 ex",
317 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
318 : basic(TINFO_${CONTAINER_UC})
320 debugmsg("${CONTAINER} constructor from 3 ex",
328 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
329 ex const & e4) : basic(TINFO_${CONTAINER_UC})
331 debugmsg("${CONTAINER} constructor from 4 ex",
340 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
341 ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER_UC})
343 debugmsg("${CONTAINER} constructor from 5 ex",
353 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
354 ex const & e4, ex const & e5, ex const & e6)
355 : basic(TINFO_${CONTAINER_UC})
357 debugmsg("${CONTAINER} constructor from 6 ex",
368 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
369 ex const & e4, ex const & e5, ex const & e6,
370 ex const & e7) : basic(TINFO_${CONTAINER_UC})
372 debugmsg("${CONTAINER} constructor from 7 ex",
384 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
385 ex const & e4, ex const & e5, ex const & e6,
386 ex const & e7, ex const & e8) : basic(TINFO_${CONTAINER_UC})
388 debugmsg("${CONTAINER} constructor from 8 ex",
401 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
402 ex const & e4, ex const & e5, ex const & e6,
403 ex const & e7, ex const & e8, ex const & e9)
404 : basic(TINFO_${CONTAINER_UC})
406 debugmsg("${CONTAINER} constructor from 9 ex",
420 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
421 ex const & e4, ex const & e5, ex const & e6,
422 ex const & e7, ex const & e8, ex const & e9,
424 : basic(TINFO_${CONTAINER_UC})
426 debugmsg("${CONTAINER} constructor from 10 ex",
442 // functions overriding virtual functions from bases classes
447 basic * ${CONTAINER}::duplicate() const
449 debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
450 return new ${CONTAINER}(*this);
453 void ${CONTAINER}::printraw(ostream & os) const
455 debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
457 os << "${CONTAINER}(";
458 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
459 (*cit).bp->printraw(os);
465 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
467 debugmsg("${CONTAINER} print",LOGLEVEL_PRINT);
468 // always print brackets around seq, ignore upper_precedence
469 printseq(os,'${open_bracket}',',','${close_bracket}',precedence,precedence+1);
472 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
474 debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
476 os << string(indent,' ') << "type=" << typeid(*this).name()
477 << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
478 << ", flags=" << flags
479 << ", nops=" << nops() << endl;
480 for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
481 (*cit).printtree(os,indent+delta_indent);
483 os << string(indent+delta_indent,' ') << "=====" << endl;
486 // ${CONTAINER}::info() will be implemented by user elsewhere";
488 int ${CONTAINER}::nops() const
493 ${LET_OP_IMPLEMENTATION}
495 ex ${CONTAINER}::expand(unsigned options) const
498 RESERVE(s,seq.size());
499 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
500 s.push_back((*it).expand(options));
503 return this${CONTAINER}(s);
506 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
508 bool ${CONTAINER}::has(ex const & other) const
511 if (is_equal(*other.bp)) return true;
512 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
513 if ((*it).has(other)) return true;
518 ex ${CONTAINER}::eval(int level) const
523 return this${CONTAINER}(evalchildren(level));
526 ex ${CONTAINER}::evalf(int level) const
528 return this${CONTAINER}(evalfchildren(level));
531 /** Implementation of ex::normal() for ${CONTAINER}s. It normalizes the arguments
532 * and replaces the ${CONTAINER} by a temporary symbol.
533 * \@see ex::normal */
534 ex ${CONTAINER}::normal(lst &sym_lst, lst &repl_lst, int level) const
536 ex n=this${CONTAINER}(normalchildren(level));
537 return n.bp->basic::normal(sym_lst,repl_lst,level);
540 ex ${CONTAINER}::diff(symbol const & s) const
542 return this${CONTAINER}(diffchildren(s));
545 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
547 ${STLT} * vp=subschildren(ls,lr);
551 return this${CONTAINER}(vp);
556 int ${CONTAINER}::compare_same_type(basic const & other) const
558 ASSERT(is_of_type(other,${CONTAINER}));
559 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
560 (const_cast<basic &>(other));
562 ${STLT}::const_iterator it1=seq.begin();
563 ${STLT}::const_iterator it2=o.seq.begin();
565 for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
566 cmpval=(*it1).compare(*it2);
567 if (cmpval!=0) return cmpval;
570 if (it1==seq.end()) {
571 return (it2==o.seq.end() ? 0 : -1);
577 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
579 ASSERT(is_of_type(other,${CONTAINER}));
580 ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
581 (const_cast<basic &>(other));
582 if (seq.size()!=o.seq.size()) return false;
584 ${STLT}::const_iterator it1=seq.begin();
585 ${STLT}::const_iterator it2=o.seq.begin();
587 for (; it1!=seq.end(); ++it1, ++it2) {
588 if (!(*it1).is_equal(*it2)) return false;
594 unsigned ${CONTAINER}::return_type(void) const
596 return return_types::noncommutative_composite;
600 // new virtual functions which can be overridden by derived classes
605 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
607 ensure_if_modifiable();
612 ${PREPEND_IMPLEMENTATION}
616 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
617 char closebracket, unsigned this_precedence,
618 unsigned upper_precedence) const
620 if (this_precedence<=upper_precedence) os << openbracket;
622 ${STLT}::const_iterator it,it_last;
626 for (; it!=it_last; ++it) {
627 (*it).bp->print(os,this_precedence);
630 (*it).bp->print(os,this_precedence);
632 if (this_precedence<=upper_precedence) os << closebracket;
635 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
637 return ${CONTAINER}(v);
640 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
642 return ${CONTAINER}(vp);
646 // non-virtual functions in this class
655 bool ${CONTAINER}::is_canonical() const
657 if (seq.size()<=1) { return 1; }
659 ${STLT}::const_iterator it=seq.begin();
660 ${STLT}::const_iterator it_last=it;
661 for (++it; it!=seq.end(); it_last=it, ++it) {
662 if ((*it_last).compare(*it)>0) {
663 if ((*it_last).compare(*it)>0) {
664 cout << *it_last << ">" << *it << "\\n";
673 ${STLT} ${CONTAINER}::evalchildren(int level) const
676 RESERVE(s,seq.size());
681 if (level == -max_recursion_level) {
682 throw(std::runtime_error("max recursion level reached"));
685 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
686 s.push_back((*it).eval(level));
691 ${STLT} ${CONTAINER}::evalfchildren(int level) const
694 RESERVE(s,seq.size());
699 if (level == -max_recursion_level) {
700 throw(std::runtime_error("max recursion level reached"));
703 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
704 s.push_back((*it).evalf(level));
709 ${STLT} ${CONTAINER}::normalchildren(int level) const
712 RESERVE(s,seq.size());
717 if (level == -max_recursion_level) {
718 throw(std::runtime_error("max recursion level reached"));
721 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
722 s.push_back((*it).normal(level));
727 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
730 RESERVE(s,seq.size());
731 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
732 s.push_back((*it).diff(y));
737 /* obsolete subschildren
738 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
741 RESERVE(s,seq.size());
742 for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
743 s.push_back((*it).subs(ls,lr));
749 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
751 // returns a NULL pointer if nothing had to be substituted
752 // returns a pointer to a newly created epvector otherwise
753 // (which has to be deleted somewhere else)
755 ${STLT}::const_iterator last=seq.end();
756 ${STLT}::const_iterator cit=seq.begin();
758 ex const & subsed_ex=(*cit).subs(ls,lr);
759 if (!are_ex_trivially_equal(*cit,subsed_ex)) {
761 // something changed, copy seq, subs and return it
762 ${STLT} *s=new ${STLT};
763 RESERVE(*s,seq.size());
765 // copy parts of seq which are known not to have changed
766 ${STLT}::const_iterator cit2=seq.begin();
771 // copy first changed element
772 s->push_back(subsed_ex);
776 s->push_back((*cit2).subs(ls,lr));
784 return 0; // nothing has changed
788 // static member variables
793 unsigned ${CONTAINER}::precedence=10;
799 const ${CONTAINER} some_${CONTAINER};
800 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
802 END_OF_IMPLEMENTATION
804 print "Creating interface file ${CONTAINER}.h...";
805 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
806 print OUT $interface;
810 print "Creating implementation file ${CONTAINER}.cpp...";
811 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
812 print OUT $implementation;