From 5b7525eb42f71063f46abf3b44ecec739553b57f Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Wed, 13 Aug 2003 18:51:09 +0000 Subject: [PATCH] synced to 1.1 --- NEWS | 2 +- ginac/container.pl | 689 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 690 insertions(+), 1 deletion(-) create mode 100755 ginac/container.pl diff --git a/NEWS b/NEWS index fe249ae2..7d82b163 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,7 @@ This file records noteworthy changes. * Fixed a bug in the unarchiving of sums and products: terms were not reordered in a canonical way. * Fixed a bug in normal()/numer_denom(): denominator was not made unit - normal if it was a simple number + normal if it was a simple number. 1.0.14 (1 March 2003) * Improved the C-source output: complex numbers are printed correctly (using diff --git a/ginac/container.pl b/ginac/container.pl new file mode 100755 index 00000000..7b00ba24 --- /dev/null +++ b/ginac/container.pl @@ -0,0 +1,689 @@ +if (($#ARGV!=0) and ($#ARGV!=1)) { + die 'usage: container.pl type [maxargs] (type=lst or exprseq)'; +} + +if ($ARGV[0] eq 'lst') { + $type='lst'; +} elsif ($ARGV[0] eq 'exprseq') { + $type='exprseq'; +} else { + die 'only lst and exprseq supported'; +} + +if ($#ARGV==1) { + $maxargs=$ARGV[1]; +} else { + $maxargs=16; # must be greater or equal than the value used in function.pl +} + +if ($type eq 'exprseq') { + + # settings for exprseq + $CONTAINER="exprseq"; + $STLHEADER="vector"; + $reserve=1; + $prepend=0; + $sort=0; + $let_op=0; + $open_bracket='('; + $close_bracket=')'; + +} elsif ($type eq 'lst') { + + # settings for lst + $CONTAINER="lst"; + $STLHEADER="list"; + $reserve=0; + $prepend=1; + $sort=1; + $let_op=1; + $open_bracket='{'; + $close_bracket='}'; + +} else { + die "invalid type $type"; +} + +$CONTAINER_UC=uc(${CONTAINER}); +$STLT="ex".$STLHEADER; + +if ($reserve) { + $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) (s).reserve(size)"; +} else { + $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) // no reserve needed for ${STLHEADER}"; +} + +if ($prepend) { + $PREPEND_INTERFACE=<=0); + GINAC_ASSERT(i + +// CINT needs to work properly with and +#include + +#include "basic.h" +#include "ex.h" + +namespace GiNaC { + + +typedef std::${STLHEADER} ${STLT}; + +class ${CONTAINER} : public basic +{ + GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic) + +public: + ${CONTAINER}(${STLT} const & s, bool discardable = false); + ${CONTAINER}(${STLT} * vp); // vp will be deleted +${constructors_interface} + +public: + void print(const print_context & c, unsigned level = 0) const; + unsigned precedence(void) const {return 10;} + bool info(unsigned inf) const; + unsigned nops() const; + ex & let_op(int i); + ex map(map_function & f) const; + ex eval(int level=0) const; + ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const; +protected: + bool is_equal_same_type(const basic & other) const; + + // new virtual functions which can be overridden by derived classes +public: + virtual ${CONTAINER} & append(const ex & b); + virtual ${CONTAINER} & remove_last(void); +${PREPEND_INTERFACE} +${SORT_INTERFACE} +protected: + virtual void printseq(const print_context & c, char openbracket, char delim, + char closebracket, unsigned this_precedence, + unsigned upper_precedence = 0) const; + virtual ex this${CONTAINER}(${STLT} const & v) const; + virtual ex this${CONTAINER}(${STLT} * vp) const; + +protected: + bool is_canonical() const; + ${STLT} evalchildren(int level) const; + ${STLT} * subschildren(const lst & ls, const lst & lr, bool no_pattern = false) const; + +protected: + ${STLT} seq; +}; + +// utility functions + +/** Specialization of is_exactly_a<${CONTAINER}>(obj) for ${CONTAINER} objects. */ +template<> inline bool is_exactly_a<${CONTAINER}>(const basic & obj) +{ + return obj.tinfo()==TINFO_${CONTAINER}; +} + +} // namespace GiNaC + +#endif // ndef __GINAC_${CONTAINER_UC}_H__ + +END_OF_INTERFACE + +$implementation=< +#include + +#include "${CONTAINER}.h" +#include "ex.h" +#include "print.h" +#include "archive.h" + +namespace GiNaC { + +GINAC_IMPLEMENT_REGISTERED_CLASS(${CONTAINER}, basic) + +${RESERVE_IMPLEMENTATION} + +////////// +// default ctor, dtor, copy ctor, assignment operator and helpers +////////// + +// public + +${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER}) {} + +// protected + +void ${CONTAINER}::copy(${CONTAINER} const & other) +{ + inherited::copy(other); + seq=other.seq; +} + +void ${CONTAINER}::destroy(bool call_parent) +{ + seq.clear(); + if (call_parent) inherited::destroy(call_parent); +} + +////////// +// other ctors +////////// + +// public + +${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER}) +{ + if (discardable) { + seq.swap(const_cast<${STLT} &>(s)); + } else { + seq=s; + } +} + +${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER}) +{ + if (vp == 0) { + // lst(0) ends up here + seq.push_back(0); + } else { + seq.swap(*vp); + delete vp; + } +} + +${constructors_implementation} + +////////// +// archiving +////////// + +/** Construct object from archive_node. */ +${CONTAINER}::${CONTAINER}(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +{ + for (unsigned int i=0; true; i++) { + ex e; + if (n.find_ex("seq", e, sym_lst, i)) + seq.push_back(e); + else + break; + } +} + +/** Unarchive the object. */ +ex ${CONTAINER}::unarchive(const archive_node &n, const lst &sym_lst) +{ + return (new ${CONTAINER}(n, sym_lst))->setflag(status_flags::dynallocated); +} + +/** Archive the object. */ +void ${CONTAINER}::archive(archive_node &n) const +{ + inherited::archive(n); + ${STLT}::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + n.add_ex("seq", *i); + ++i; + } +} + +////////// +// functions overriding virtual functions from base classes +////////// + +// public + +void ${CONTAINER}::print(const print_context & c, unsigned level) const +{ + if (is_a(c)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << ", nops=" << nops() + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + ${STLT}::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + i->print(c, level + delta_indent); + ++i; + } + c.s << std::string(level + delta_indent,' ') << "=====" << std::endl; + } else if (is_a(c)) { + printseq(c, '[', ',', ']', precedence(), precedence()+1); + } else if (is_a(c)) { + c.s << class_name (); + printseq(c, '(', ',', ')', precedence(), precedence()+1); + } else { + // always print brackets around seq, ignore upper_precedence + printseq(c, '${open_bracket}', ',', '${close_bracket}', precedence(), precedence()+1); + } +} + +// ${CONTAINER}::info() will be implemented by user elsewhere"; + +unsigned ${CONTAINER}::nops() const +{ + return seq.size(); +} + +${LET_OP_IMPLEMENTATION} + +ex ${CONTAINER}::map(map_function & f) const +{ + // This implementation is here because basic::map() uses let_op() + // which is not defined for all containers + ${STLT} s; + RESERVE(s,seq.size()); + ${STLT}::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + s.push_back(f(*i)); + ++i; + } + + return this${CONTAINER}(s); +} + +ex ${CONTAINER}::eval(int level) const +{ + if (level==1) { + return this->hold(); + } + return this${CONTAINER}(evalchildren(level)); +} + +ex ${CONTAINER}::subs(const lst & ls, const lst & lr, bool no_pattern) const +{ + ${STLT} *vp = subschildren(ls, lr, no_pattern); + if (vp) + return ex_to(this${CONTAINER}(vp)).basic::subs(ls, lr, no_pattern); + else + return basic::subs(ls, lr, no_pattern); +} + +// protected + +int ${CONTAINER}::compare_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a<${CONTAINER}>(other)); + ${CONTAINER} const & o = static_cast(other); + + ${STLT}::const_iterator it1 = seq.begin(), it1end = seq.end(), + it2 = o.seq.begin(), it2end = o.seq.end(); + + while (it1 != it1end && it2 != it2end) { + int cmpval = it1->compare(*it2); + if (cmpval) + return cmpval; + ++it1; ++it2; + } + + return (it1 == it1end) ? (it2 == it2end ? 0 : -1) : 1; +} + +bool ${CONTAINER}::is_equal_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a<${CONTAINER}>(other)); + ${CONTAINER} const &o = static_cast(other); + + if (seq.size() != o.seq.size()) + return false; + + ${STLT}::const_iterator it1 = seq.begin(), it1end = seq.end(), + it2 = o.seq.begin(); + + while (it1 != it1end) { + if (!it1->is_equal(*it2)) + return false; + ++it1; ++it2; + } + + return true; +} + +////////// +// new virtual functions which can be overridden by derived classes +////////// + +// public + +${CONTAINER} & ${CONTAINER}::append(const ex & b) +{ + ensure_if_modifiable(); + seq.push_back(b); + return *this; +} + +${CONTAINER} & ${CONTAINER}::remove_last(void) +{ + ensure_if_modifiable(); + seq.pop_back(); + return *this; +} + +${PREPEND_IMPLEMENTATION} + +${SORT_IMPLEMENTATION} + +// protected + +void ${CONTAINER}::printseq(const print_context & c, char openbracket, char delim, + char closebracket, unsigned this_precedence, + unsigned upper_precedence) const +{ + if (this_precedence <= upper_precedence) + c.s << openbracket; + + if (!seq.empty()) { + ${STLT}::const_iterator it = seq.begin(), itend = seq.end(); + --itend; + while (it != itend) { + it->print(c, this_precedence); + c.s << delim; + ++it; + } + it->print(c, this_precedence); + } + + if (this_precedence <= upper_precedence) + c.s << closebracket; +} + +ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const +{ + return ${CONTAINER}(v); +} + +ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const +{ + return ${CONTAINER}(vp); +} + +////////// +// non-virtual functions in this class +////////// + +// public + +// none + +// protected + +bool ${CONTAINER}::is_canonical() const +{ + if (seq.size()<=1) { return 1; } + + ${STLT}::const_iterator it = seq.begin(), itend = seq.end(); + ${STLT}::const_iterator it_last=it; + for (++it; it!=itend; it_last=it, ++it) { + if (it_last->compare(*it)>0) { + if (it_last->compare(*it)>0) { + std::cout << *it_last << ">" << *it << "\\n"; + return 0; + } + } + } + return 1; +} + + +${STLT} ${CONTAINER}::evalchildren(int level) const +{ + ${STLT} s; + RESERVE(s,seq.size()); + + if (level==1) { + return seq; + } + if (level == -max_recursion_level) { + throw(std::runtime_error("max recursion level reached")); + } + --level; + ${STLT}::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + s.push_back(it->eval(level)); + ++it; + } + return s; +} + +${STLT} * ${CONTAINER}::subschildren(const lst & ls, const lst & lr, bool no_pattern) const +{ + // returns a NULL pointer if nothing had to be substituted + // returns a pointer to a newly created epvector otherwise + // (which has to be deleted somewhere else) + + ${STLT}::const_iterator cit = seq.begin(), end = seq.end(); + while (cit != end) { + const ex & subsed_ex = cit->subs(ls, lr, no_pattern); + if (!are_ex_trivially_equal(*cit, subsed_ex)) { + + // something changed, copy seq, subs and return it + ${STLT} *s=new ${STLT}; + RESERVE(*s, seq.size()); + + // copy parts of seq which are known not to have changed + ${STLT}::const_iterator cit2 = seq.begin(); + while (cit2 != cit) { + s->push_back(*cit2); + ++cit2; + } + + // copy first changed element + s->push_back(subsed_ex); + ++cit2; + + // copy rest + while (cit2 != end) { + s->push_back(cit2->subs(ls, lr, no_pattern)); + ++cit2; + } + return s; + } + ++cit; + } + + return 0; // nothing has changed +} + +} // namespace GiNaC + +END_OF_IMPLEMENTATION + +print "Creating interface file ${CONTAINER}.h..."; +open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h"; +print OUT $interface; +close OUT; +print "ok.\n"; + +print "Creating implementation file ${CONTAINER}.cpp..."; +open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp"; +print OUT $implementation; +close OUT; +print "ok.\n"; + +print "done.\n"; -- 2.44.0