From: Christian Bauer Date: Fri, 6 Apr 2001 23:02:58 +0000 (+0000) Subject: - replaced the various print*() member functions by a single print() that X-Git-Tag: release_0-8-1~24 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=06eb6b761f4b9d9eed4decd8ed50d94b40b94a0e - replaced the various print*() member functions by a single print() that takes a print_context object that determines the output formatting; this should make it easier to add more output types - print_tree output of indexed objects looks better --- diff --git a/ginac/Makefile.am b/ginac/Makefile.am index 45fe8611..faaa66e3 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -16,7 +16,7 @@ ginacinclude_HEADERS = ginac.h add.h archive.h basic.h constant.h ex.h \ expair.h expairseq.h exprseq.h fail.h flags.h function.h inifcns.h \ lst.h matrix.h mul.h ncmul.h normal.h numeric.h operators.h power.h \ registrar.h relational.h pseries.h structure.h symbol.h tinfos.h assertion.h \ - version.h idx.h indexed.h tensor.h color.h clifford.h + version.h idx.h indexed.h tensor.h color.h clifford.h print.h LFLAGS = -Pginac_yy -olex.yy.c YFLAGS = -p ginac_yy -d EXTRA_DIST = container.pl function.pl structure.pl input_parser.h version.h.in diff --git a/ginac/add.cpp b/ginac/add.cpp index 7d73c306..0dd7dc9c 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -111,107 +111,105 @@ DEFAULT_ARCHIVING(add) // public -void add::print(std::ostream & os, unsigned upper_precedence) const +void add::print(const print_context & c, unsigned level) const { - debugmsg("add print",LOGLEVEL_PRINT); - if (precedence<=upper_precedence) os << "("; - numeric coeff; - bool first = true; - // first print the overall numeric coefficient, if present: - if (!overall_coeff.is_zero()) { - os << overall_coeff; - first = false; - } - // then proceed with the remaining factors: - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - coeff = ex_to_numeric(cit->coeff); - if (!first) { - if (coeff.csgn()==-1) os << '-'; else os << '+'; - } else { - if (coeff.csgn()==-1) os << '-'; - first = false; - } - if (!coeff.is_equal(_num1()) && - !coeff.is_equal(_num_1())) { - if (coeff.is_rational()) { - if (coeff.is_negative()) - os << -coeff; - else - os << coeff; - } else { - if (coeff.csgn()==-1) - (-coeff).print(os, precedence); - else - coeff.print(os, precedence); - } - os << '*'; - } - cit->rest.print(os, precedence); - } - if (precedence<=upper_precedence) os << ")"; -} + debugmsg("add print", LOGLEVEL_PRINT); -void add::printraw(std::ostream & os) const -{ - debugmsg("add printraw",LOGLEVEL_PRINT); - - os << "+("; - for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - os << "("; - (*it).rest.bp->printraw(os); - os << ","; - (*it).coeff.bp->printraw(os); - os << "),"; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; -} + if (is_of_type(c, print_tree)) { -void add::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("add print csrc", LOGLEVEL_PRINT); - if (precedence <= upper_precedence) - os << "("; + inherited::print(c, level); + + } else if (is_of_type(c, print_csrc)) { + + if (precedence <= level) + c.s << "("; - // Print arguments, separated by "+" - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { + // Print arguments, separated by "+" + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { - // If the coefficient is -1, it is replaced by a single minus sign - if (it->coeff.compare(_num1()) == 0) { - it->rest.bp->printcsrc(os, type, precedence); - } else if (it->coeff.compare(_num_1()) == 0) { - os << "-"; - it->rest.bp->printcsrc(os, type, precedence); - } else if (ex_to_numeric(it->coeff).numer().compare(_num1()) == 0) { - it->rest.bp->printcsrc(os, type, precedence); - os << "/"; - ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); - } else if (ex_to_numeric(it->coeff).numer().compare(_num_1()) == 0) { - os << "-"; - it->rest.bp->printcsrc(os, type, precedence); - os << "/"; - ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); - } else { - it->coeff.bp->printcsrc(os, type, precedence); - os << "*"; - it->rest.bp->printcsrc(os, type, precedence); - } + // If the coefficient is -1, it is replaced by a single minus sign + if (it->coeff.compare(_num1()) == 0) { + it->rest.bp->print(c, precedence); + } else if (it->coeff.compare(_num_1()) == 0) { + c.s << "-"; + it->rest.bp->print(c, precedence); + } else if (ex_to_numeric(it->coeff).numer().compare(_num1()) == 0) { + it->rest.bp->print(c, precedence); + c.s << "/"; + ex_to_numeric(it->coeff).denom().print(c, precedence); + } else if (ex_to_numeric(it->coeff).numer().compare(_num_1()) == 0) { + c.s << "-"; + it->rest.bp->print(c, precedence); + c.s << "/"; + ex_to_numeric(it->coeff).denom().print(c, precedence); + } else { + it->coeff.bp->print(c, precedence); + c.s << "*"; + it->rest.bp->print(c, precedence); + } - // Separator is "+", except if the following expression would have a leading minus sign - it++; - if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(_num0()) < 0))) - os << "+"; - } + // Separator is "+", except if the following expression would have a leading minus sign + it++; + if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(_num0()) < 0))) + c.s << "+"; + } - if (!overall_coeff.is_zero()) { - if (overall_coeff.info(info_flags::positive)) os << '+'; - overall_coeff.bp->printcsrc(os,type,precedence); - } + if (!overall_coeff.is_zero()) { + if (overall_coeff.info(info_flags::positive)) + c.s << '+'; + overall_coeff.bp->print(c, precedence); + } - if (precedence <= upper_precedence) - os << ")"; + if (precedence <= level) + c.s << ")"; + + } else { + + if (precedence <= level) + c.s << "("; + + numeric coeff; + bool first = true; + + // First print the overall numeric coefficient, if present + if (!overall_coeff.is_zero()) { + overall_coeff.print(c, precedence); + first = false; + } + + // Then proceed with the remaining factors + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + coeff = ex_to_numeric(it->coeff); + if (!first) { + if (coeff.csgn() == -1) c.s << '-'; else c.s << '+'; + } else { + if (coeff.csgn() == -1) c.s << '-'; + first = false; + } + if (!coeff.is_equal(_num1()) && + !coeff.is_equal(_num_1())) { + if (coeff.is_rational()) { + if (coeff.is_negative()) + (-coeff).print(c, precedence); + else + coeff.print(c, precedence); + } else { + if (coeff.csgn() == -1) + (-coeff).print(c, precedence); + else + coeff.print(c, precedence); + } + c.s << '*'; + } + it->rest.print(c, precedence); + it++; + } + + if (precedence <= level) + c.s << ")"; + } } bool add::info(unsigned inf) const diff --git a/ginac/add.h b/ginac/add.h index 738d09b3..c6d04d08 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -46,9 +46,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; int degree(const ex & s) const; int ldegree(const ex & s) const; diff --git a/ginac/basic.cpp b/ginac/basic.cpp index c4e17cd5..8040e4a0 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -21,7 +21,6 @@ */ #include -#include #include #include "basic.h" @@ -31,6 +30,7 @@ #include "symbol.h" #include "lst.h" #include "ncmul.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" @@ -109,46 +109,25 @@ void basic::archive(archive_node &n) const // public -/** Output to ostream formatted as parsable (as in ginsh) input. - * Generally, superfluous parenthesis should be avoided as far as possible. */ -void basic::print(std::ostream & os, unsigned upper_precedence) const +/** Output to stream. + * @param c print context object that describes the output formatting + * @param level value that is used to identify the precedence or indentation + * level for placing parentheses and formatting */ +void basic::print(const print_context & c, unsigned level) const { - debugmsg("basic print",LOGLEVEL_PRINT); - os << "[" << class_name() << " object]"; -} + debugmsg("basic print", LOGLEVEL_PRINT); -/** Output to ostream in ugly raw format, so brave developers can have a look - * at the underlying structure. */ -void basic::printraw(std::ostream & os) const -{ - debugmsg("basic printraw",LOGLEVEL_PRINT); - os << "[" << class_name() << " object]"; -} + if (is_of_type(c, print_tree)) { -/** Output to ostream formatted in tree- (indented-) form, so developers can - * have a look at the underlying structure. */ -void basic::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("basic printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "type=" << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags - << ", nops=" << nops() << std::endl; - for (unsigned i=0; iprint(std::cerr); @@ -169,7 +148,7 @@ void basic::dbgprint(void) const * @see basic::printtree */ void basic::dbgprinttree(void) const { - this->printtree(std::cerr,0); + this->print(print_tree(std::cerr)); } /** Create a new copy of this on the heap. One can think of this as simulating @@ -512,18 +491,18 @@ int basic::compare(const basic & other) const if (typeid_thisprintraw(std::cout); +// this->print(print_tree(std::cout)); // std::cout << " and "; -// other.printraw(std::cout); +// other.print(print_tree(std::cout)); // std::cout << std::endl; return -1; } if (typeid_this>typeid_other) { // std::cout << "hash collision, different types: " // << *this << " and " << other << std::endl; -// this->printraw(std::cout); +// this->print(print_tree(std::cout)); // std::cout << " and "; -// other.printraw(std::cout); +// other.print(print_tree(std::cout)); // std::cout << std::endl; return 1; } @@ -534,9 +513,9 @@ int basic::compare(const basic & other) const // if ((cmpval!=0) && (hash_this<0x80000000U)) { // std::cout << "hash collision, same type: " // << *this << " and " << other << std::endl; -// this->printraw(std::cout); +// this->print(print_tree(std::cout)); // std::cout << " and "; -// other.printraw(std::cout); +// other.print(print_tree(std::cout)); // std::cout << std::endl; // } // return cmpval; @@ -587,7 +566,6 @@ void basic::ensure_if_modifiable(void) const // protected unsigned basic::precedence = 70; -unsigned basic::delta_indent = 4; ////////// // global variables diff --git a/ginac/basic.h b/ginac/basic.h index 1f4a4fdc..a37e84dc 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -24,7 +24,6 @@ #define __GINAC_BASIC_H__ #include -#include #include // CINT needs to work properly with @@ -44,6 +43,7 @@ class lst; class numeric; class relational; class archive_node; +class print_context; // Cint doesn't like vector<..,default_alloc> but malloc_alloc is // unstandardized and not supported by newer GCCs. @@ -61,8 +61,6 @@ class basic friend class ex; -// member functions - // default ctor, dtor, copy ctor assignment operator and helpers public: basic() : tinfo_key(TINFO_basic), flags(0), refcount(0) @@ -101,10 +99,7 @@ protected: // new virtual functions which can be overridden by derived classes public: // only const functions please (may break reference counting) virtual basic * duplicate() const; - virtual void print(std::ostream & os,unsigned upper_precedence = 0) const; - virtual void printraw(std::ostream & os) const; - virtual void printtree(std::ostream & os, unsigned indent) const; - virtual void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + virtual void print(const print_context & c, unsigned level = 0) const; virtual void dbgprint(void) const; virtual void dbgprinttree(void) const; virtual bool info(unsigned inf) const; @@ -158,14 +153,12 @@ public: protected: void ensure_if_modifiable(void) const; -// member variables - + // member variables protected: unsigned tinfo_key; ///< typeinfo mutable unsigned flags; ///< of type status_flags mutable unsigned hashvalue; ///< hash value static unsigned precedence; ///< precedence for printing parens - static unsigned delta_indent; ///< precedence for printtree private: unsigned refcount; ///< Number of reference counts }; diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index c1c069dc..ecd95b7e 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -24,6 +24,7 @@ #include "ex.h" #include "idx.h" #include "ncmul.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" diff --git a/ginac/clifford.h b/ginac/clifford.h index 0feef3f0..50893c81 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -62,7 +62,7 @@ class diracone : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; }; @@ -73,7 +73,7 @@ class diracgamma : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; diff --git a/ginac/color.cpp b/ginac/color.cpp index 675d3274..c31a83c9 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -29,6 +29,7 @@ #include "ncmul.h" #include "numeric.h" #include "power.h" // for sqrt() +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" diff --git a/ginac/color.h b/ginac/color.h index c5c57c55..e5baa856 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -71,7 +71,7 @@ class su3one : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; }; /** This class represents an su(3) generator. */ @@ -81,7 +81,7 @@ class su3t : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; }; /** This class represents the tensor of antisymmetric su(3) structure @@ -92,7 +92,7 @@ class su3f : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; @@ -104,7 +104,7 @@ class su3d : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; diff --git a/ginac/constant.cpp b/ginac/constant.cpp index 5aad78d0..7afc35be 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -26,6 +26,7 @@ #include "constant.h" #include "numeric.h" #include "ex.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -126,32 +127,18 @@ void constant::archive(archive_node &n) const // public -void constant::print(std::ostream & os, unsigned upper_precedence) const +void constant::print(const print_context & c, unsigned level) const { - debugmsg("constant print",LOGLEVEL_PRINT); - os << name; -} + debugmsg("constant print", LOGLEVEL_PRINT); -void constant::printraw(std::ostream & os) const -{ - debugmsg("constant printraw",LOGLEVEL_PRINT); - os << class_name() << "(" << name << ")"; -} + if (is_of_type(c, print_tree)) { -void constant::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("constant printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << name - << ", type=" << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; -} + c.s << std::string(level, ' ') << name << " (" << class_name() << ")" + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; -void constant::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("constant print csrc",LOGLEVEL_PRINT); - os << name; + } else + c.s << name; } int constant::degree(const ex & s) const diff --git a/ginac/constant.h b/ginac/constant.h index d56f2bc8..fdf06615 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -48,10 +48,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence = 0) const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + void print(const print_context & c, unsigned level = 0) const; int degree(const ex & s) const; int ldegree(const ex & s) const; ex coeff(const ex & s, int n = 1) const; diff --git a/ginac/container.pl b/ginac/container.pl index 1a591ab3..55da47c0 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -204,9 +204,7 @@ public: ${constructors_interface} public: - void printraw(std::ostream & os) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printtree(std::ostream & os, unsigned indent) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; unsigned nops() const; ex & let_op(int i); @@ -226,9 +224,9 @@ public: virtual ${CONTAINER} & append(const ex & b); ${PREPEND_INTERFACE} protected: - virtual void printseq(std::ostream & os, char openbracket, char delim, + virtual void printseq(const print_context & c, char openbracket, char delim, char closebracket, unsigned this_precedence, - unsigned upper_precedence=0) const; + unsigned upper_precedence = 0) const; virtual ex this${CONTAINER}(${STLT} const & v) const; virtual ex this${CONTAINER}(${STLT} * vp) const; @@ -245,11 +243,6 @@ protected: static unsigned precedence; }; -// global constants - -extern const ${CONTAINER} some_${CONTAINER}; -extern const std::type_info & typeid_${CONTAINER}; - // utility functions inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e) { @@ -306,6 +299,7 @@ $implementation=<printraw(os); - os << ","; - } - os << ")"; -} + debugmsg("${CONTAINER} print", LOGLEVEL_PRINT); -void ${CONTAINER}::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("${CONTAINER} print",LOGLEVEL_PRINT); - // always print brackets around seq, ignore upper_precedence - printseq(os,'${open_bracket}',',','${close_bracket}',precedence,precedence+1); -} + if (is_of_type(c, print_tree)) { -void ${CONTAINER}::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT); + 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; + for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) + cit->print(c, level + delta_indent); + c.s << std::string(level + delta_indent,' ') << "=====" << std::endl; - os << std::string(indent,' ') << "type=" << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags - << ", nops=" << nops() << std::endl; - for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - (*cit).printtree(os,indent+delta_indent); + } else { + // always print brackets around seq, ignore upper_precedence + printseq(c, '${open_bracket}', ',', '${close_bracket}', precedence, precedence+1); } - os << std::string(indent+delta_indent,' ') << "=====" << std::endl; } // ${CONTAINER}::info() will be implemented by user elsewhere"; @@ -570,23 +551,26 @@ ${PREPEND_IMPLEMENTATION} // protected -void ${CONTAINER}::printseq(std::ostream & os, char openbracket, char delim, +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) os << openbracket; - if (seq.size()!=0) { - ${STLT}::const_iterator it,it_last; - it=seq.begin(); - it_last=seq.end(); - --it_last; - for (; it!=it_last; ++it) { - (*it).bp->print(os,this_precedence); - os << delim; + if (this_precedence <= upper_precedence) + c.s << openbracket; + + if (seq.size() != 0) { + ${STLT}::const_iterator it = seq.begin(), itend = seq.end(); + --itend; + while (it != itend) { + it->print(c, this_precedence); + c.s << delim; + it++; } - (*it).bp->print(os,this_precedence); + it->print(c, this_precedence); } - if (this_precedence<=upper_precedence) os << closebracket; + + if (this_precedence <= upper_precedence) + c.s << closebracket; } ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const @@ -749,13 +733,6 @@ ${STLT} * ${CONTAINER}::subschildren(const lst & ls, const lst & lr) const unsigned ${CONTAINER}::precedence = 10; -////////// -// global constants -////////// - -const ${CONTAINER} some_${CONTAINER}; -const std::type_info & typeid_${CONTAINER} = typeid(some_${CONTAINER}); - } // namespace GiNaC END_OF_IMPLEMENTATION diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 521ee1e1..42cde03a 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -76,64 +76,30 @@ void ex::swap(ex & other) other.bp = tmpbp; } -/** Output formatted to be useful as ginsh input. */ -void ex::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("ex print",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - bp->print(os,upper_precedence); -} - -/** Unreadable output with detailed type information. */ -void ex::printraw(std::ostream & os) const -{ - debugmsg("ex printraw",LOGLEVEL_PRINT); +/** Print expression to stream. The formatting of the output is determined + * by the kind of print_context object that is passed. Possible formattings + * include ginsh-parsable output (the default), tree-like output for + * debugging, and C++ source. + * @see print_context */ +void ex::print(const print_context & c, unsigned level) const +{ + debugmsg("ex print", LOGLEVEL_PRINT); GINAC_ASSERT(bp!=0); - os << "ex("; - bp->printraw(os); - os << ")"; + bp->print(c, level); } -/** Very detailed and unreadable output with type information and all this. */ -void ex::printtree(std::ostream & os, unsigned indent) const +/** Print expression to stream in a tree-like format suitable for debugging. */ +void ex::printtree(std::ostream & os) const { - debugmsg("ex printtree",LOGLEVEL_PRINT); + debugmsg("ex printtree", LOGLEVEL_PRINT); GINAC_ASSERT(bp!=0); - // os << "refcount=" << bp->refcount << " "; - bp->printtree(os,indent); -} - -/** Print expression as a C++ statement. The output looks like - * " = ;". The "type" parameter has an effect - * on how number literals are printed. - * - * @param os output stream - * @param type variable type (one of the csrc_types) - * @param var_name variable name to be printed */ -void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const -{ - debugmsg("ex print csrc", LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - switch (type) { - case csrc_types::ctype_float: - os << "float "; - break; - case csrc_types::ctype_double: - os << "double "; - break; - case csrc_types::ctype_cl_N: - os << "cl_N "; - break; - } - os << var_name << " = "; - bp->printcsrc(os, type, 0); - os << ";\n"; + bp->print(print_tree(os)); } /** Little wrapper arount print to be called within a debugger. */ void ex::dbgprint(void) const { - debugmsg("ex dbgprint",LOGLEVEL_PRINT); + debugmsg("ex dbgprint", LOGLEVEL_PRINT); GINAC_ASSERT(bp!=0); bp->dbgprint(); } @@ -141,7 +107,7 @@ void ex::dbgprint(void) const /** Little wrapper arount printtree to be called within a debugger. */ void ex::dbgprinttree(void) const { - debugmsg("ex dbgprinttree",LOGLEVEL_PRINT); + debugmsg("ex dbgprinttree", LOGLEVEL_PRINT); GINAC_ASSERT(bp!=0); bp->dbgprinttree(); } diff --git a/ginac/ex.h b/ginac/ex.h index 3358c280..accac216 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -76,10 +76,8 @@ public: // non-virtual functions in this class public: void swap(ex & other); - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent=0) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, const char *var_name) const; + void print(const print_context & c, unsigned level = 0) const; + void printtree(std::ostream & os) const; void dbgprint(void) const; void dbgprinttree(void) const; bool info(unsigned inf) const; diff --git a/ginac/expair.h b/ginac/expair.h index 2f34b4b8..74744e02 100644 --- a/ginac/expair.h +++ b/ginac/expair.h @@ -25,6 +25,7 @@ #include "ex.h" #include "numeric.h" +#include "print.h" namespace GiNaC { @@ -81,14 +82,12 @@ public: return coeff.compare(other.coeff); } - /** Output to ostream in ugly raw format. */ - void printraw(std::ostream & os) const + void print(std::ostream & os) const { - os << "expair("; - rest.printraw(os); - os << ","; - coeff.printraw(os); - os << ")"; + os << "expair:"; + print_tree c(os); + rest.print(c, c.delta_indent); + coeff.print(c, c.delta_indent); } /** True if this is of the form (numeric,ex(1)). */ diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 09a38af5..997fabd4 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -26,6 +26,7 @@ #include "expairseq.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -186,102 +187,89 @@ basic *expairseq::duplicate() const return new expairseq(*this); } -void expairseq::print(std::ostream &os, unsigned upper_precedence) const +void expairseq::print(const print_context & c, unsigned level) const { debugmsg("expairseq print",LOGLEVEL_PRINT); - os << "[["; - printseq(os,',',precedence,upper_precedence); - os << "]]"; -} -void expairseq::printraw(std::ostream &os) const -{ - debugmsg("expairseq printraw",LOGLEVEL_PRINT); - os << class_name() << "("; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - os << "("; - (*cit).rest.printraw(os); - os << ","; - (*cit).coeff.printraw(os); - os << "),"; - } - os << ")"; -} + if (is_of_type(c, print_tree)) { -void expairseq::printtree(std::ostream &os, unsigned indent) const -{ - debugmsg("expairseq printtree",LOGLEVEL_PRINT); + unsigned delta_indent = static_cast(c).delta_indent; - os << std::string(indent,' ') << "type=" << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags - << ", nops=" << nops() << std::endl; - for (unsigned i=0; i0) { - os << std::string(indent+delta_indent,' ') - << "bin " << i << " with entries "; - for (epplist::const_iterator it=hashtab[i].begin(); - it!=hashtab[i].end(); ++it) { - os << *it-seq.begin() << " "; - ++this_bin_fill; + unsigned count[MAXCOUNT+1]; + for (int i=0; i 0) { + c.s << std::string(level + delta_indent, ' ') + << "bin " << i << " with entries "; + for (epplist::const_iterator it=hashtab[i].begin(); + it!=hashtab[i].end(); ++it) { + c.s << *it-seq.begin() << " "; + ++this_bin_fill; + } + os << std::endl; + cum_fill += this_bin_fill; + cum_fill_sq += this_bin_fill*this_bin_fill; } - os << std::endl; - cum_fill += this_bin_fill; - cum_fill_sq += this_bin_fill*this_bin_fill; + if (this_bin_fill0) - fact *= k; - double prob = std::pow(lambda,k)/fact * std::exp(-lambda); - cum_prob += prob; - os << std::string(indent+delta_indent,' ') << "bins with " << k << " entries: " - << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: " - << int(prob*1000)/10.0 << ")" << std::endl; - } - os << std::string(indent+delta_indent,' ') << "bins with more entries: " - << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: " - << int((1-cum_prob)*1000)/10.0 << ")" << std::endl; - - os << std::string(indent+delta_indent,' ') << "variance: " - << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill) - << std::endl; - os << std::string(indent+delta_indent,' ') << "average fill: " - << (1.0*cum_fill)/hashtabsize - << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << std::endl; + unsigned fact = 1; + double cum_prob = 0; + double lambda = (1.0*seq.size()) / hashtabsize; + for (int k=0; k0) + fact *= k; + double prob = std::pow(lambda,k)/fact * std::exp(-lambda); + cum_prob += prob; + c.s << std::string(level + delta_indent, ' ') << "bins with " << k << " entries: " + << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: " + << int(prob*1000)/10.0 << ")" << std::endl; + } + c.s << std::string(level + delta_indent, ' ') << "bins with more entries: " + << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: " + << int((1-cum_prob)*1000)/10.0 << ")" << std::endl; + + c.s << std::string(level + delta_indent, ' ') << "variance: " + << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill) + << std::endl; + c.s << std::string(level + delta_indent, ' ') << "average fill: " + << (1.0*cum_fill)/hashtabsize + << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << std::endl; #endif // EXPAIRSEQ_USE_HASHTAB + + } else { + c.s << "[["; + printseq(c, ',', precedence, level); + c.s << "]]"; + } } bool expairseq::info(unsigned inf) const @@ -434,9 +422,9 @@ bool expairseq::is_equal_same_type(const basic &other) const // compare number of elements in each hashtab entry if (hashtabsize!=o.hashtabsize) { std::cout << "this:" << std::endl; - printtree(std::cout,0); + print(print_tree(std::cout)); std::cout << "other:" << std::endl; - other.printtree(std::cout,0); + other.print(print_tree(std::cout)); } GINAC_ASSERT(hashtabsize==o.hashtabsize); @@ -549,34 +537,34 @@ ex expairseq::thisexpairseq(epvector *vp, const ex &oc) const return expairseq(vp,oc); } -void expairseq::printpair(std::ostream &os, const expair &p, unsigned upper_precedence) const +void expairseq::printpair(const print_context & c, const expair & p, unsigned upper_precedence) const { - os << "[["; - p.rest.bp->print(os,precedence); - os << ","; - p.coeff.bp->print(os,precedence); - os << "]]"; + c.s << "[["; + p.rest.bp->print(c, precedence); + c.s << ","; + p.coeff.bp->print(c, precedence); + c.s << "]]"; } -void expairseq::printseq(std::ostream &os, char delim, +void expairseq::printseq(const print_context & c, char delim, unsigned this_precedence, unsigned upper_precedence) const { - if (this_precedence<=upper_precedence) - os << "("; - epvector::const_iterator it,it_last; - it_last=seq.end(); - --it_last; + if (this_precedence <= upper_precedence) + c.s << "("; + epvector::const_iterator it, it_last = seq.end() - 1; for (it=seq.begin(); it!=it_last; ++it) { - printpair(os,*it,this_precedence); - os << delim; + printpair(c, *it, this_precedence); + c.s << delim; + } + printpair(c, *it, this_precedence); + if (!overall_coeff.is_equal(default_overall_coeff())) { + c.s << delim; + overall_coeff.print(c, this_precedence); } - printpair(os,*it,this_precedence); - if (!overall_coeff.is_equal(default_overall_coeff())) - os << delim << overall_coeff; - if (this_precedence<=upper_precedence) - os << ")"; + if (this_precedence <= upper_precedence) + c.s << ")"; } @@ -1399,32 +1387,32 @@ void expairseq::combine_same_terms(void) * debugging or in assertions since being sorted is an invariance. */ bool expairseq::is_canonical() const { - if (seq.size()<=1) + if (seq.size() <= 1) return 1; #if EXPAIRSEQ_USE_HASHTAB - if (hashtabsize>0) return 1; // not canoncalized + if (hashtabsize > 0) return 1; // not canoncalized #endif // EXPAIRSEQ_USE_HASHTAB epvector::const_iterator it = seq.begin(); epvector::const_iterator it_last = it; for (++it; it!=seq.end(); it_last=it, ++it) { - if (!((*it_last).is_less(*it)||(*it_last).is_equal(*it))) { - if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| + if (!((*it_last).is_less(*it) || (*it_last).is_equal(*it))) { + if (!is_ex_exactly_of_type((*it_last).rest,numeric) || !is_ex_exactly_of_type((*it).rest,numeric)) { // double test makes it easier to set a breakpoint... - if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| + if (!is_ex_exactly_of_type((*it_last).rest,numeric) || !is_ex_exactly_of_type((*it).rest,numeric)) { - printpair(std::clog,*it_last,0); + printpair(std::clog, *it_last, 0); std::clog << ">"; - printpair(std::clog,*it,0); + printpair(std::clog, *it, 0); std::clog << "\n"; std::clog << "pair1:" << std::endl; - (*it_last).rest.printtree(std::clog); - (*it_last).coeff.printtree(std::clog); + (*it_last).rest.print(print_tree(std::clog)); + (*it_last).coeff.print(print_tree(std::clog)); std::clog << "pair2:" << std::endl; - (*it).rest.printtree(std::clog); - (*it).coeff.printtree(std::clog); + (*it).rest.print(print_tree(std::clog)); + (*it).coeff.print(print_tree(std::clog)); return 0; } } diff --git a/ginac/expairseq.h b/ginac/expairseq.h index 665daed8..e4e34653 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -87,9 +87,7 @@ public: // functions overriding virtual functions from bases classes public: basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; unsigned nops() const; ex op(int i) const; @@ -111,10 +109,10 @@ protected: protected: virtual ex thisexpairseq(const epvector & v, const ex & oc) const; virtual ex thisexpairseq(epvector * vp, const ex & oc) const; - virtual void printseq(std::ostream & os, char delim, + virtual void printseq(const print_context & c, char delim, unsigned this_precedence, unsigned upper_precedence) const; - virtual void printpair(std::ostream & os, const expair & p, + virtual void printpair(const print_context & c, const expair & p, unsigned upper_precedence) const; virtual expair split_ex_to_pair(const ex & e) const; virtual expair combine_ex_with_coeff_to_pair(const ex & e, diff --git a/ginac/fail.cpp b/ginac/fail.cpp index 7de656a5..3818538f 100644 --- a/ginac/fail.cpp +++ b/ginac/fail.cpp @@ -22,6 +22,7 @@ */ #include "fail.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" diff --git a/ginac/fail.h b/ginac/fail.h index 415aba59..fdab60c7 100644 --- a/ginac/fail.h +++ b/ginac/fail.h @@ -34,7 +34,7 @@ class fail : public basic // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; protected: unsigned return_type(void) const { return return_types::noncommutative_composite; }; }; diff --git a/ginac/flags.h b/ginac/flags.h index 987a4df0..96838cec 100644 --- a/ginac/flags.h +++ b/ginac/flags.h @@ -142,15 +142,6 @@ public: }; }; -class csrc_types { -public: - enum { - ctype_float, - ctype_double, - ctype_cl_N - }; -}; - /** Strategies how to clean up the function remember cache. * @see remember_table */ class remember_strategies { diff --git a/ginac/function.pl b/ginac/function.pl index b36df872..947830c4 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -333,10 +333,7 @@ $constructors_interface // functions overriding virtual functions from bases classes public: - void printraw(std::ostream & os) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; int degree(const ex & s) const; int ldegree(const ex & s) const; ex coeff(const ex & s, int n = 1) const; @@ -382,11 +379,6 @@ inline const function &ex_to_function(const ex &e) #define is_ex_the_function(OBJ, FUNCNAME) \\ (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->getserial() == function_index_##FUNCNAME) -// global constants - -extern const function some_function; -extern const std::type_info & typeid_function; - } // namespace GiNaC #endif // ndef __GINAC_FUNCTION_H__ @@ -427,6 +419,7 @@ $implementation=<print(os); - } - os << ")"; -} - -void function::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("function print",LOGLEVEL_PRINT); - - GINAC_ASSERT(serialprint(c); + it++; + if (it != itend) + c.s << ","; + } + c.s << ")"; - // Print function name in lowercase - std::string lname; - lname=registered_functions()[serial].name; - for (unsigned i=0; ibp->printcsrc(os, type, 0); - it++; - if (it != itend) - os << ","; + } else { + c.s << registered_functions()[serial].name; + printseq(c, '(', ',', ')', exprseq::precedence, function::precedence); } - os << ")"; } ex function::expand(unsigned options) const @@ -989,19 +957,6 @@ unsigned function::find_function(const std::string &name, unsigned nparams) throw (std::runtime_error("no function '" + name + "' with " + ToString(nparams) + " parameters defined")); } -////////// -// static member variables -////////// - -// none - -////////// -// global constants -////////// - -const function some_function; -const std::type_info & typeid_function=typeid(some_function); - } // namespace GiNaC END_OF_IMPLEMENTATION diff --git a/ginac/ginac.h b/ginac/ginac.h index a21eb1c9..1dc48fe0 100644 --- a/ginac/ginac.h +++ b/ginac/ginac.h @@ -30,6 +30,7 @@ #include "ex.h" #include "normal.h" #include "archive.h" +#include "print.h" #include "constant.h" #include "fail.h" diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 0a8686de..9f31a9ad 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -25,12 +25,11 @@ #include "idx.h" #include "symbol.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" -#include "exprseq.h" // !! - namespace GiNaC { GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic) @@ -122,59 +121,58 @@ DEFAULT_UNARCHIVE(varidx) // functions overriding virtual functions from bases classes ////////// -void idx::printraw(std::ostream & os) const +void idx::print(const print_context & c, unsigned level) const { - debugmsg("idx printraw", LOGLEVEL_PRINT); - - os << class_name() << "("; - value.printraw(os); - os << ",dim="; - dim.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; -} + debugmsg("idx print", LOGLEVEL_PRINT); -void idx::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("idx printtree",LOGLEVEL_PRINT); - - os << std::string(indent, ' ') << "type=" << class_name(); - value.printtree(os, indent + delta_indent); - os << std::string(indent, ' '); - os << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; -} + if (is_of_type(c, print_tree)) { -void idx::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("idx print", LOGLEVEL_PRINT); + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); - os << "."; + } else { - bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); - if (need_parens) - os << "("; - os << value; - if (need_parens) - os << ")"; + c.s << "."; + bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); + if (need_parens) + c.s << "("; + c.s << value; + if (need_parens) + c.s << ")"; + } } -void varidx::print(std::ostream & os, unsigned upper_precedence) const +void varidx::print(const print_context & c, unsigned level) const { debugmsg("varidx print", LOGLEVEL_PRINT); - if (covariant) - os << "."; - else - os << "~"; - - bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); - if (need_parens) - os << "("; - os << value; - if (need_parens) - os << ")"; + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << (covariant ? ", covariant" : ", contravariant") + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); + + } else { + + if (covariant) + c.s << "."; + else + c.s << "~"; + bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); + if (need_parens) + c.s << "("; + c.s << value; + if (need_parens) + c.s << ")"; + } } bool idx::info(unsigned inf) const diff --git a/ginac/idx.h b/ginac/idx.h index a54ad7c3..4981fefc 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -47,9 +47,7 @@ public: // functions overriding virtual functions from bases classes public: - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; unsigned nops() const; ex & let_op(int i); @@ -106,7 +104,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool is_dummy_pair_same_type(const basic & other) const; // non-virtual functions in this class diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 5277bf89..6fbe40b9 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -29,6 +29,7 @@ #include "ncmul.h" #include "power.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" @@ -176,42 +177,38 @@ DEFAULT_UNARCHIVE(indexed) // functions overriding virtual functions from bases classes ////////// -void indexed::printraw(std::ostream & os) const +void indexed::print(const print_context & c, unsigned level) const { - debugmsg("indexed printraw", LOGLEVEL_PRINT); + debugmsg("indexed print", LOGLEVEL_PRINT); GINAC_ASSERT(seq.size() > 0); - os << class_name() << "("; - seq[0].printraw(os); - os << ",indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; -} - -void indexed::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("indexed printtree", LOGLEVEL_PRINT); - GINAC_ASSERT(seq.size() > 0); + if (is_of_type(c, print_tree)) { - os << std::string(indent, ' ') << class_name() << ", " << seq.size()-1 << " indices"; - os << ",hash=" << hashvalue << ",flags=" << flags << std::endl; - printtreeindices(os, indent); -} + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << ", " << seq.size()-1 << " indices"; + switch (symmetry) { + case symmetric: c.s << ", symmetric"; break; + case antisymmetric: c.s << ", antisymmetric"; break; + default: break; + } + c.s << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + seq[0].print(c, level + delta_indent); + printindices(c, level + delta_indent); -void indexed::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("indexed print", LOGLEVEL_PRINT); - GINAC_ASSERT(seq.size() > 0); + } else { - const ex & base = seq[0]; - bool need_parens = is_ex_exactly_of_type(base, add) || is_ex_exactly_of_type(base, mul) - || is_ex_exactly_of_type(base, ncmul) || is_ex_exactly_of_type(base, power); - if (need_parens) - os << "("; - os << base; - if (need_parens) - os << ")"; - printindices(os); + const ex & base = seq[0]; + bool need_parens = is_ex_exactly_of_type(base, add) || is_ex_exactly_of_type(base, mul) + || is_ex_exactly_of_type(base, ncmul) || is_ex_exactly_of_type(base, power); + if (need_parens) + c.s << "("; + base.print(c); + if (need_parens) + c.s << ")"; + printindices(c, level); + } } bool indexed::info(unsigned inf) const @@ -409,38 +406,12 @@ ex indexed::expand(unsigned options) const // non-virtual functions in this class ////////// -void indexed::printrawindices(std::ostream & os) const -{ - if (seq.size() > 1) { - exvector::const_iterator it=seq.begin() + 1, itend = seq.end(); - while (it != itend) { - it->printraw(os); - it++; - if (it != itend) - os << ","; - } - } -} - -void indexed::printtreeindices(std::ostream & os, unsigned indent) const -{ - if (seq.size() > 1) { - exvector::const_iterator it=seq.begin() + 1, itend = seq.end(); - while (it != itend) { - os << std::string(indent + delta_indent, ' '); - it->printraw(os); - os << std::endl; - it++; - } - } -} - -void indexed::printindices(std::ostream & os) const +void indexed::printindices(const print_context & c, unsigned level) const { if (seq.size() > 1) { exvector::const_iterator it=seq.begin() + 1, itend = seq.end(); while (it != itend) { - it->print(os); + it->print(c, level); it++; } } diff --git a/ginac/indexed.h b/ginac/indexed.h index e98375d3..cba48c88 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -151,9 +151,7 @@ public: // functions overriding virtual functions from base classes public: - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; ex eval(int level = 0) const; int degree(const ex & s) const; @@ -187,9 +185,7 @@ public: exvector get_dummy_indices(const indexed & other) const; protected: - void printrawindices(std::ostream & os) const; - void printtreeindices(std::ostream & os, unsigned indent) const; - void printindices(std::ostream & os) const; + void printindices(const print_context & c, unsigned level) const; void assert_all_indices_of_type_idx(void) const; // member variables diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 380a45e7..25de42bf 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -25,16 +25,17 @@ #include #include "matrix.h" -#include "archive.h" #include "numeric.h" #include "lst.h" #include "idx.h" #include "indexed.h" -#include "utils.h" -#include "debugmsg.h" #include "power.h" #include "symbol.h" #include "normal.h" +#include "print.h" +#include "archive.h" +#include "utils.h" +#include "debugmsg.h" namespace GiNaC { @@ -145,36 +146,35 @@ DEFAULT_UNARCHIVE(matrix) // public -void matrix::print(std::ostream & os, unsigned upper_precedence) const +void matrix::print(const print_context & c, unsigned level) const { - debugmsg("matrix print",LOGLEVEL_PRINT); - os << "[[ "; - for (unsigned r=0; rprintraw(os); - os << ","; - (*it).coeff.bp->printraw(os); - os << "),"; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; -} + if (is_of_type(c, print_tree)) { -void mul::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("mul print csrc", LOGLEVEL_PRINT); - if (precedence <= upper_precedence) - os << "("; + inherited::print(c, level); - if (!overall_coeff.is_equal(_ex1())) { - overall_coeff.bp->printcsrc(os,type,precedence); - os << "*"; - } + } else if (is_of_type(c, print_csrc)) { + + if (precedence <= level) + c.s << "("; + + if (!overall_coeff.is_equal(_ex1())) { + overall_coeff.bp->print(c, precedence); + c.s << "*"; + } - // Print arguments, separated by "*" or "/" - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - - // If the first argument is a negative integer power, it gets printed as "1.0/" - if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) { - if (type == csrc_types::ctype_cl_N) - os << "recip("; - else - os << "1.0/"; + // Print arguments, separated by "*" or "/" + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + + // If the first argument is a negative integer power, it gets printed as "1.0/" + if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) { + if (is_of_type(c, print_csrc_cl_N)) + c.s << "recip("; + else + c.s << "1.0/"; + } + + // If the exponent is 1 or -1, it is left out + if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0) + it->rest.print(c, precedence); + else { + // Outer parens around ex needed for broken gcc-2.95 parser: + (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).print(c, level); + } + + // Separator is "/" for negative integer powers, "*" otherwise + ++it; + if (it != itend) { + if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) + c.s << "/"; + else + c.s << "*"; + } } - // If the exponent is 1 or -1, it is left out - if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0) - it->rest.bp->printcsrc(os, type, precedence); - else - // outer parens around ex needed for broken gcc-2.95 parser: - (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence); + if (precedence <= level) + c.s << ")"; - // Separator is "/" for negative integer powers, "*" otherwise - ++it; - if (it != itend) { - if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) - os << "/"; - else - os << "*"; + } else { + + if (precedence <= level) + c.s << "("; + + bool first = true; + + // First print the overall numeric coefficient + numeric coeff = ex_to_numeric(overall_coeff); + if (coeff.csgn() == -1) + c.s << '-'; + if (!coeff.is_equal(_num1()) && + !coeff.is_equal(_num_1())) { + if (coeff.is_rational()) { + if (coeff.is_negative()) + (-coeff).print(c, precedence); + else + coeff.print(c, precedence); + } else { + if (coeff.csgn() == -1) + (-coeff).print(c, precedence); + else + coeff.print(c, precedence); + } + c.s << '*'; + } + + // Then proceed with the remaining factors + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + if (!first) { + c.s << '*'; + } else { + first = false; + } + recombine_pair_to_ex(*it).print(c, precedence); + it++; } + + if (precedence <= level) + c.s << ")"; } - if (precedence <= upper_precedence) - os << ")"; } bool mul::info(unsigned inf) const @@ -327,7 +327,7 @@ ex mul::eval(int level) const (!(ex_to_numeric((*cit).coeff).is_integer()))); GINAC_ASSERT(!(cit->is_canonical_numeric())); if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) - printtree(std::cerr,0); + print(print_tree(std::cerr)); GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)); /* for paranoia */ expair p = split_ex_to_pair(recombine_pair_to_ex(*cit)); diff --git a/ginac/mul.h b/ginac/mul.h index 81459a44..affef3ba 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -47,9 +47,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const; + void print(const print_context & c, unsigned level) const; bool info(unsigned inf) const; int degree(const ex & s) const; int ldegree(const ex & s) const; diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index 9892670f..e775d82e 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -28,6 +28,7 @@ #include "ex.h" #include "add.h" #include "mul.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -112,36 +113,28 @@ DEFAULT_ARCHIVING(ncmul) // public -void ncmul::print(std::ostream & os, unsigned upper_precedence) const +void ncmul::print(const print_context & c, unsigned level) const { - debugmsg("ncmul print",LOGLEVEL_PRINT); - printseq(os,'(','*',')',precedence,upper_precedence); -} + debugmsg("ncmul print", LOGLEVEL_PRINT); -void ncmul::printraw(std::ostream & os) const -{ - debugmsg("ncmul printraw",LOGLEVEL_PRINT); - os << "ncmul("; - for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - (*it).bp->printraw(os); - os << ","; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; -} + if (is_of_type(c, print_tree)) { -void ncmul::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("ncmul print csrc",LOGLEVEL_PRINT); - exvector::const_iterator it; - exvector::const_iterator itend = seq.end()-1; - os << "ncmul("; - for (it=seq.begin(); it!=itend; ++it) { - (*it).bp->printcsrc(os,precedence); - os << ","; - } - (*it).bp->printcsrc(os,precedence); - os << ")"; + inherited::print(c, level); + + } else if (is_of_type(c, print_csrc)) { + + c.s << "ncmul("; + exvector::const_iterator it = seq.begin(), itend = seq.end()-1; + while (it != itend) { + it->print(c, precedence); + c.s << ","; + it++; + } + it->print(c, precedence); + c.s << ")"; + + } else + printseq(c, '(', '*', ')', precedence, level); } bool ncmul::info(unsigned inf) const diff --git a/ginac/ncmul.h b/ginac/ncmul.h index ec8e5612..05f99949 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -53,9 +53,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; int degree(const ex & s) const; int ldegree(const ex & s) const; diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index a4a40c8c..1308c9e1 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -40,6 +40,7 @@ #include "numeric.h" #include "ex.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -365,126 +366,113 @@ static void print_real_number(std::ostream &os, const cln::cl_R &num) * with the other routines and produces something compatible to ginsh input. * * @see print_real_number() */ -void numeric::print(std::ostream &os, unsigned upper_precedence) const +void numeric::print(const print_context & c, unsigned level) const { debugmsg("numeric print", LOGLEVEL_PRINT); - cln::cl_R r = cln::realpart(cln::the(value)); - cln::cl_R i = cln::imagpart(cln::the(value)); - if (cln::zerop(i)) { - // case 1, real: x or -x - if ((precedence<=upper_precedence) && (!this->is_nonneg_integer())) { - os << "("; - print_real_number(os, r); - os << ")"; + + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << cln::the(value) + << " (" << class_name() << ")" + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; + + } else if (is_of_type(c, print_csrc)) { + + std::ios::fmtflags oldflags = c.s.flags(); + c.s.setf(std::ios::scientific); + if (this->is_rational() && !this->is_integer()) { + if (compare(_num0()) > 0) { + c.s << "("; + if (is_of_type(c, print_csrc_cl_N)) + c.s << "cln::cl_F(\"" << numer().evalf() << "\")"; + else + c.s << numer().to_double(); + } else { + c.s << "-("; + if (is_of_type(c, print_csrc_cl_N)) + c.s << "cln::cl_F(\"" << -numer().evalf() << "\")"; + else + c.s << -numer().to_double(); + } + c.s << "/"; + if (is_of_type(c, print_csrc_cl_N)) + c.s << "cln::cl_F(\"" << denom().evalf() << "\")"; + else + c.s << denom().to_double(); + c.s << ")"; } else { - print_real_number(os, r); + if (is_of_type(c, print_csrc_cl_N)) + c.s << "cln::cl_F(\"" << evalf() << "\")"; + else + c.s << to_double(); } + c.s.flags(oldflags); + } else { - if (cln::zerop(r)) { - // case 2, imaginary: y*I or -y*I - if ((precedence<=upper_precedence) && (i < 0)) { - if (i == -1) { - os << "(-I)"; - } else { - os << "("; - print_real_number(os, i); - os << "*I)"; - } + + cln::cl_R r = cln::realpart(cln::the(value)); + cln::cl_R i = cln::imagpart(cln::the(value)); + if (cln::zerop(i)) { + // case 1, real: x or -x + if ((precedence <= level) && (!this->is_nonneg_integer())) { + c.s << "("; + print_real_number(c.s, r); + c.s << ")"; } else { - if (i == 1) { - os << "I"; - } else { + print_real_number(c.s, r); + } + } else { + if (cln::zerop(r)) { + // case 2, imaginary: y*I or -y*I + if ((precedence <= level) && (i < 0)) { if (i == -1) { - os << "-I"; + c.s << "(-I)"; } else { - print_real_number(os, i); - os << "*I"; + c.s << "("; + print_real_number(c.s, i); + c.s << "*I)"; } - } - } - } else { - // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I - if (precedence <= upper_precedence) - os << "("; - print_real_number(os, r); - if (i < 0) { - if (i == -1) { - os << "-I"; } else { - print_real_number(os, i); - os << "*I"; + if (i == 1) { + c.s << "I"; + } else { + if (i == -1) { + c.s << "-I"; + } else { + print_real_number(c.s, i); + c.s << "*I"; + } + } } } else { - if (i == 1) { - os << "+I"; + // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I + if (precedence <= level) + c.s << "("; + print_real_number(c.s, r); + if (i < 0) { + if (i == -1) { + c.s << "-I"; + } else { + print_real_number(c.s, i); + c.s << "*I"; + } } else { - os << "+"; - print_real_number(os, i); - os << "*I"; + if (i == 1) { + c.s << "+I"; + } else { + c.s << "+"; + print_real_number(c.s, i); + c.s << "*I"; + } } + if (precedence <= level) + c.s << ")"; } - if (precedence <= upper_precedence) - os << ")"; } } } - -void numeric::printraw(std::ostream &os) const -{ - // The method printraw doesn't do much, it simply uses CLN's operator<<() - // for output, which is ugly but reliable. e.g: 2+2i - debugmsg("numeric printraw", LOGLEVEL_PRINT); - os << class_name() << "(" << cln::the(value) << ")"; -} - - -void numeric::printtree(std::ostream &os, unsigned indent) const -{ - debugmsg("numeric printtree", LOGLEVEL_PRINT); - os << std::string(indent,' ') << cln::the(value) - << " (numeric): " - << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; -} - - -void numeric::printcsrc(std::ostream &os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("numeric print csrc", LOGLEVEL_PRINT); - std::ios::fmtflags oldflags = os.flags(); - os.setf(std::ios::scientific); - if (this->is_rational() && !this->is_integer()) { - if (compare(_num0()) > 0) { - os << "("; - if (type == csrc_types::ctype_cl_N) - os << "cln::cl_F(\"" << numer().evalf() << "\")"; - else - os << numer().to_double(); - } else { - os << "-("; - if (type == csrc_types::ctype_cl_N) - os << "cln::cl_F(\"" << -numer().evalf() << "\")"; - else - os << -numer().to_double(); - } - os << "/"; - if (type == csrc_types::ctype_cl_N) - os << "cln::cl_F(\"" << denom().evalf() << "\")"; - else - os << denom().to_double(); - os << ")"; - } else { - if (type == csrc_types::ctype_cl_N) - os << "cln::cl_F(\"" << evalf() << "\")"; - else - os << to_double(); - } - os.flags(oldflags); -} - - bool numeric::info(unsigned inf) const { switch (inf) { diff --git a/ginac/numeric.h b/ginac/numeric.h index ce50406f..2d856aaa 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -85,10 +85,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream &os, unsigned precedence = 0) const; - void printraw(std::ostream &os) const; - void printtree(std::ostream &os, unsigned indent) const; - void printcsrc(std::ostream &os, unsigned type, unsigned precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; bool has(const ex &other) const; ex eval(int level = 0) const; diff --git a/ginac/operators.cpp b/ginac/operators.cpp index bd9a4425..ee240174 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -24,6 +24,7 @@ #include "numeric.h" #include "power.h" #include "relational.h" +#include "print.h" #include "debugmsg.h" #include "utils.h" @@ -240,7 +241,7 @@ relational operator>=(const ex & lh, const ex & rh) std::ostream & operator<<(std::ostream & os, const ex & e) { - e.print(os); + e.print(print_context(os)); return os; } diff --git a/ginac/power.cpp b/ginac/power.cpp index c2885565..109eacfe 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -32,6 +32,7 @@ #include "inifcns.h" #include "relational.h" #include "symbol.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -102,106 +103,92 @@ DEFAULT_UNARCHIVE(power) // public -void power::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("power print",LOGLEVEL_PRINT); - if (exponent.is_equal(_ex1_2())) { - os << "sqrt(" << basis << ")"; - } else { - if (precedence<=upper_precedence) os << "("; - basis.print(os,precedence); - os << "^"; - exponent.print(os,precedence); - if (precedence<=upper_precedence) os << ")"; - } -} - -void power::printraw(std::ostream & os) const -{ - debugmsg("power printraw",LOGLEVEL_PRINT); - - os << class_name() << "("; - basis.printraw(os); - os << ","; - exponent.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; -} - -void power::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("power printtree",LOGLEVEL_PRINT); - - os << std::string(indent,' ') << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; - basis.printtree(os, indent+delta_indent); - exponent.printtree(os, indent+delta_indent); -} - -static void print_sym_pow(std::ostream & os, unsigned type, const symbol &x, int exp) +static void print_sym_pow(const print_context & c, const symbol &x, int exp) { // Optimal output of integer powers of symbols to aid compiler CSE. // C.f. ISO/IEC 14882:1998, section 1.9 [intro execution], paragraph 15 // to learn why such a hack is really necessary. if (exp == 1) { - x.printcsrc(os, type, 0); + x.print(c); } else if (exp == 2) { - x.printcsrc(os, type, 0); - os << "*"; - x.printcsrc(os, type, 0); + x.print(c); + c.s << "*"; + x.print(c); } else if (exp & 1) { - x.printcsrc(os, 0); - os << "*"; - print_sym_pow(os, type, x, exp-1); + x.print(c); + c.s << "*"; + print_sym_pow(c, x, exp-1); } else { - os << "("; - print_sym_pow(os, type, x, exp >> 1); - os << ")*("; - print_sym_pow(os, type, x, exp >> 1); - os << ")"; + c.s << "("; + print_sym_pow(c, x, exp >> 1); + c.s << ")*("; + print_sym_pow(c, x, exp >> 1); + c.s << ")"; } } -void power::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const +void power::print(const print_context & c, unsigned level) const { - debugmsg("power print csrc", LOGLEVEL_PRINT); - - // Integer powers of symbols are printed in a special, optimized way - if (exponent.info(info_flags::integer) - && (is_ex_exactly_of_type(basis, symbol) || is_ex_exactly_of_type(basis, constant))) { - int exp = ex_to_numeric(exponent).to_int(); - if (exp > 0) - os << "("; - else { - exp = -exp; - if (type == csrc_types::ctype_cl_N) - os << "recip("; + debugmsg("power print", LOGLEVEL_PRINT); + + if (is_of_type(c, print_tree)) { + + inherited::print(c, level); + + } else if (is_of_type(c, print_csrc)) { + + // Integer powers of symbols are printed in a special, optimized way + if (exponent.info(info_flags::integer) + && (is_ex_exactly_of_type(basis, symbol) || is_ex_exactly_of_type(basis, constant))) { + int exp = ex_to_numeric(exponent).to_int(); + if (exp > 0) + c.s << "("; + else { + exp = -exp; + if (is_of_type(c, print_csrc_cl_N)) + c.s << "recip("; + else + c.s << "1.0/("; + } + print_sym_pow(c, ex_to_symbol(basis), exp); + c.s << ")"; + + // ^-1 is printed as "1.0/" or with the recip() function of CLN + } else if (exponent.compare(_num_1()) == 0) { + if (is_of_type(c, print_csrc_cl_N)) + c.s << "recip("; else - os << "1.0/("; - } - print_sym_pow(os, type, static_cast(*basis.bp), exp); - os << ")"; + c.s << "1.0/("; + basis.print(c); + c.s << ")"; - // ^-1 is printed as "1.0/" or with the recip() function of CLN - } else if (exponent.compare(_num_1()) == 0) { - if (type == csrc_types::ctype_cl_N) - os << "recip("; - else - os << "1.0/("; - basis.bp->printcsrc(os, type, 0); - os << ")"; + // Otherwise, use the pow() or expt() (CLN) functions + } else { + if (is_of_type(c, print_csrc_cl_N)) + c.s << "expt("; + else + c.s << "pow("; + basis.print(c); + c.s << ","; + exponent.print(c); + c.s << ")"; + } - // Otherwise, use the pow() or expt() (CLN) functions } else { - if (type == csrc_types::ctype_cl_N) - os << "expt("; - else - os << "pow("; - basis.bp->printcsrc(os, type, 0); - os << ","; - exponent.bp->printcsrc(os, type, 0); - os << ")"; + + if (exponent.is_equal(_ex1_2())) { + c.s << "sqrt("; + basis.print(c); + c.s << ")"; + } else { + if (precedence <= level) + c.s << "("; + basis.print(c, precedence); + c.s << "^"; + exponent.print(c, precedence); + if (precedence <= level) + c.s << ")"; + } } } diff --git a/ginac/power.h b/ginac/power.h index 94602911..d9748ef9 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -48,10 +48,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence = 0) const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; unsigned nops() const; ex & let_op(int i); diff --git a/ginac/print.h b/ginac/print.h new file mode 100644 index 00000000..4fdbeb83 --- /dev/null +++ b/ginac/print.h @@ -0,0 +1,85 @@ +/** @file print.h + * + * Helper classes for expression output. */ + +/* + * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GINAC_PRINT_H__ +#define __GINAC_PRINT_H__ + +#include +#include + +namespace GiNaC { + +/** Context for default (ginsh-parsable) output. */ +class print_context +{ +public: + print_context(std::ostream & os = std::cout) : s(os) {} + std::ostream & s; /**< stream to output to */ + + // dummy virtual function to make the class polymorphic + virtual void dummy(void) {} +}; + +/** Context for tree-like output for debugging. */ +class print_tree : public print_context +{ +public: + print_tree(std::ostream & os = std::cout, unsigned d = 4) + : print_context(os), delta_indent(d) {} + unsigned delta_indent; /**< size of indentation step */ +}; + +/** Base context for C source output. */ +class print_csrc : public print_context +{ +public: + print_csrc(std::ostream & os = std::cout) + : print_context(os) {} +}; + +/** Context for C source output using float numbers. */ +class print_csrc_float : public print_csrc +{ +public: + print_csrc_float(std::ostream & os = std::cout) + : print_csrc(os) {} +}; + +/** Context for C source output using double numbers. */ +class print_csrc_double : public print_csrc +{ +public: + print_csrc_double(std::ostream & os = std::cout) + : print_csrc(os) {} +}; + +/** Context for C source output using CLN numbers. */ +class print_csrc_cl_N : public print_csrc +{ +public: + print_csrc_cl_N(std::ostream & os = std::cout) + : print_csrc(os) {} +}; + +} // namespace GiNaC + +#endif // ndef __GINAC_BASIC_H__ diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 7264d933..a4f96d97 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -31,6 +31,7 @@ #include "power.h" #include "relational.h" #include "symbol.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" @@ -121,73 +122,73 @@ DEFAULT_UNARCHIVE(pseries) // functions overriding virtual functions from bases classes ////////// -void pseries::print(std::ostream &os, unsigned upper_precedence) const +void pseries::print(const print_context & c, unsigned level) const { debugmsg("pseries print", LOGLEVEL_PRINT); - if (precedence<=upper_precedence) os << "("; - // objects of type pseries must not have any zero entries, so the - // trivial (zero) pseries needs a special treatment here: - if (seq.size()==0) - os << '0'; - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - // print a sign, if needed - if (i!=seq.begin()) - os << '+'; - if (!is_order_function(i->rest)) { - // print 'rest', i.e. the expansion coefficient - if (i->rest.info(info_flags::numeric) && - i->rest.info(info_flags::positive)) { - os << i->rest; - } else - os << "(" << i->rest << ')'; - // print 'coeff', something like (x-1)^42 - if (!i->coeff.is_zero()) { - os << '*'; - if (!point.is_zero()) - os << '(' << var-point << ')'; - else - os << var; - if (i->coeff.compare(_ex1())) { - os << '^'; - if (i->coeff.info(info_flags::negative)) - os << '(' << i->coeff << ')'; - else - os << i->coeff; - } - } - } else { - os << Order(power(var-point,i->coeff)); + + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + for (unsigned i=0; irest)) { + // print 'rest', i.e. the expansion coefficient + if (i->rest.info(info_flags::numeric) && + i->rest.info(info_flags::positive)) { + i->rest.print(c); + } else { + c.s << '('; + i->rest.print(c); + c.s << ')'; + } + // print 'coeff', something like (x-1)^42 + if (!i->coeff.is_zero()) { + c.s << '*'; + if (!point.is_zero()) { + c.s << '('; + (var-point).print(c); + c.s << ')'; + } else + var.print(c); + if (i->coeff.compare(_ex1())) { + c.s << '^'; + if (i->coeff.info(info_flags::negative)) { + c.s << '('; + i->coeff.print(c); + c.s << ')'; + } else + i->coeff.print(c); + } + } + } else + Order(power(var-point,i->coeff)).print(c); + } -void pseries::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("pseries printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << class_name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; - for (unsigned i=0; i"; - break; - case greater_or_equal: - os << ">="; - break; - default: - os << "(INVALID RELATIONAL OPERATOR)"; - } - rh.print(os,precedence); - if (precedence<=upper_precedence) os << ")"; -} -void relational::printraw(std::ostream & os) const -{ - debugmsg("relational printraw",LOGLEVEL_PRINT); - os << class_name() << "("; - lh.printraw(os); - os << ","; - rh.printraw(os); - os << ","; - switch (o) { - case equal: - os << "=="; - break; - case not_equal: - os << "!="; - break; - case less: - os << "<"; - break; - case less_or_equal: - os << "<="; - break; - case greater: - os << ">"; - break; - case greater_or_equal: - os << ">="; - break; - default: - os << "(INVALID RELATIONAL OPERATOR)"; - } - os << ")"; -} + if (is_of_type(c, print_tree)) { -void relational::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("relational print csrc", LOGLEVEL_PRINT); - if (precedence<=upper_precedence) - os << "("; + inherited::print(c, level); - // Print left-hand expression - lh.bp->printcsrc(os, type, precedence); + } else { - // Print relational operator - switch (o) { + if (precedence <= level) + c.s << "("; + lh.print(c, precedence); + switch (o) { case equal: - os << "=="; + c.s << "=="; break; case not_equal: - os << "!="; + c.s << "!="; break; case less: - os << "<"; + c.s << "<"; break; case less_or_equal: - os << "<="; + c.s << "<="; break; case greater: - os << ">"; + c.s << ">"; break; case greater_or_equal: - os << ">="; + c.s << ">="; break; default: - os << "(INVALID RELATIONAL OPERATOR)"; - break; + c.s << "(INVALID RELATIONAL OPERATOR)"; + } + rh.print(c, precedence); + if (precedence <= level) + c.s << ")"; } - - // Print right-hand operator - rh.bp->printcsrc(os, type, precedence); - - if (precedence <= upper_precedence) - os << ")"; } bool relational::info(unsigned inf) const diff --git a/ginac/relational.h b/ginac/relational.h index 15bda586..dcbcacc5 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -51,9 +51,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; unsigned nops() const; ex & let_op(int i); diff --git a/ginac/structure.cpp b/ginac/structure.cpp index 0bd1d4fb..c084096c 100644 --- a/ginac/structure.cpp +++ b/ginac/structure.cpp @@ -65,10 +65,8 @@ void structure::printtree(std::ostream & os, unsigned indent) const { debugmsg("structure printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "structure " - << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + os << std::string(indent,' ') << class_name() << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; } void structure::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const diff --git a/ginac/structure.pl b/ginac/structure.pl index 9a734c90..1455825c 100755 --- a/ginac/structure.pl +++ b/ginac/structure.pl @@ -173,9 +173,7 @@ public: // functions overriding virtual functions from bases classes public: basic * duplicate() const; - void printraw(ostream & os) const; - void print(ostream & os, unsigned upper_precedence=0) const; - void printtree(ostream & os, unsigned indent) const; + void print(const print_context & c, unsigned level = 0) const; int nops() const; ex & let_op(int i); ex expand(unsigned options=0) const; @@ -253,6 +251,7 @@ ${input_structure} #include #include "${STRUCTURE}.h" +#include "print.h" namespace GiNaC { @@ -328,22 +327,10 @@ basic * ${STRUCTURE}::duplicate() const return new ${STRUCTURE}(*this); } -void ${STRUCTURE}::printraw(ostream & os) const +void ${STRUCTURE}::print(const print_context & c, unsigned level) const { - debugmsg("${STRUCTURE} printraw",LOGLEVEL_PRINT); - os << class_name() << "()"; -} - -void ${STRUCTURE}::print(ostream & os, unsigned upper_precedence) const -{ - debugmsg("${STRUCTURE} print",LOGLEVEL_PRINT); - os << class_name() << "()"; -} - -void ${STRUCTURE}::printtree(ostream & os, unsigned indent) const -{ - debugmsg("${STRUCTURE} printtree",LOGLEVEL_PRINT); - os << "${STRUCTURE}()"; + debugmsg("${STRUCTURE} print", LOGLEVEL_PRINT); + c.s << class_name() << "()"; } int ${STRUCTURE}::nops() const diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index 09e4192b..e093e6c7 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -25,6 +25,7 @@ #include "symbol.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" @@ -131,33 +132,19 @@ basic *symbol::duplicate() const return new symbol(*this); } -void symbol::print(std::ostream & os, unsigned upper_precedence) const +void symbol::print(const print_context & c, unsigned level) const { - debugmsg("symbol print",LOGLEVEL_PRINT); - os << name; -} + debugmsg("symbol print", LOGLEVEL_PRINT); -void symbol::printraw(std::ostream & os) const -{ - debugmsg("symbol printraw",LOGLEVEL_PRINT); - os << class_name() << "(" << "name=" << name << ",serial=" << serial - << ",hash=" << hashvalue << ",flags=" << flags << ")"; -} + if (is_of_type(c, print_tree)) { -void symbol::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("symbol printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << name << " (symbol): " - << "serial=" << serial - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; -} + c.s << std::string(level, ' ') << name << " (" << class_name() << ")" + << ", serial=" << serial + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; -void symbol::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const -{ - debugmsg("symbol print csrc", LOGLEVEL_PRINT); - os << name; + } else + c.s << name; } bool symbol::info(unsigned inf) const diff --git a/ginac/symbol.h b/ginac/symbol.h index c147c89f..cda3e736 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -72,10 +72,7 @@ public: // functions overriding virtual functions from base classes public: basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence = 0) const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + void print(const print_context & c, unsigned level = 0) const; bool info(unsigned inf) const; ex expand(unsigned options = 0) const; bool has(const ex & other) const; diff --git a/ginac/tensor.cpp b/ginac/tensor.cpp index c7a68bf2..c14b50d7 100644 --- a/ginac/tensor.cpp +++ b/ginac/tensor.cpp @@ -29,6 +29,7 @@ #include "relational.h" #include "lst.h" #include "numeric.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" diff --git a/ginac/tensor.h b/ginac/tensor.h index 65c86c45..7396aca1 100644 --- a/ginac/tensor.h +++ b/ginac/tensor.h @@ -53,7 +53,7 @@ class tensdelta : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; @@ -68,7 +68,7 @@ class tensmetric : public tensor // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; }; @@ -88,7 +88,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; // member variables @@ -110,7 +110,7 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(const print_context & c, unsigned level = 0) const; ex eval_indexed(const basic & i) const; // member variables diff --git a/ginac/utils.h b/ginac/utils.h index 6e1d3ae8..c2a5f232 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -292,10 +292,13 @@ int classname::compare_same_type(const basic & other) const \ } #define DEFAULT_PRINT(classname, text) \ -void classname::print(std::ostream & os, unsigned upper_precedence) const \ +void classname::print(const print_context & c, unsigned level) const \ { \ debugmsg(#classname " print", LOGLEVEL_PRINT); \ - os << text; \ + if (is_of_type(c, print_tree)) \ + inherited::print(c, level); \ + else \ + c.s << text; \ } } // namespace GiNaC