use new-style print methods
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 14 Aug 2003 18:41:58 +0000 (18:41 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 14 Aug 2003 18:41:58 +0000 (18:41 +0000)
12 files changed:
ginac/add.cpp
ginac/add.h
ginac/container.h
ginac/exprseq.cpp
ginac/indexed.cpp
ginac/indexed.h
ginac/lst.cpp
ginac/mul.cpp
ginac/mul.h
ginac/power.cpp
ginac/pseries.cpp
ginac/pseries.h

index 511f3b3..3dcdf2c 100644 (file)
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq,
+  print_func<print_context>(&add::do_print).
+  print_func<print_latex>(&add::do_print_latex).
+  print_func<print_csrc>(&add::do_print_csrc).
+  print_func<print_tree>(&inherited::do_print_tree).
+  print_func<print_python_repr>(&add::do_print_python_repr))
 
 //////////
 // default constructor
@@ -103,130 +108,121 @@ DEFAULT_ARCHIVING(add)
 
 // public
 
-void add::print(const print_context & c, unsigned level) const
+void add::print_add(const print_context & c, const char *openbrace, const char *closebrace, const char *mul_sym, unsigned level) const
 {
-       if (is_a<print_tree>(c)) {
+       if (precedence() <= level)
+               c.s << openbrace << '(';
 
-               inherited::print(c, level);
+       numeric coeff;
+       bool first = true;
 
-       } else if (is_a<print_csrc>(c)) {
+       // First print the overall numeric coefficient, if present
+       if (!overall_coeff.is_zero()) {
+               overall_coeff.print(c, 0);
+               first = false;
+       }
 
-               if (precedence() <= level)
-                       c.s << "(";
-       
-               // 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.is_equal(_ex1)) {
-                               it->rest.print(c, precedence());
-                       } else if (it->coeff.is_equal(_ex_1)) {
-                               c.s << "-";
-                               it->rest.print(c, precedence());
-                       } else if (ex_to<numeric>(it->coeff).numer().is_equal(_num1)) {
-                               it->rest.print(c, precedence());
-                               c.s << "/";
-                               ex_to<numeric>(it->coeff).denom().print(c, precedence());
-                       } else if (ex_to<numeric>(it->coeff).numer().is_equal(_num_1)) {
-                               c.s << "-";
-                               it->rest.print(c, precedence());
-                               c.s << "/";
-                               ex_to<numeric>(it->coeff).denom().print(c, precedence());
+       // 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);
+                               else
+                                       coeff.print(c);
                        } else {
-                               it->coeff.print(c, precedence());
-                               c.s << "*";
-                               it->rest.print(c, precedence());
+                               if (coeff.csgn() == -1)
+                                       (-coeff).print(c, precedence());
+                               else
+                                       coeff.print(c, precedence());
                        }
-               
-                       // Separator is "+", except if the following expression would have a leading minus sign or the sign is sitting in parenthesis (as in a ctor)
-                       ++it;
-                       if (it != itend
-                        && (is_a<print_csrc_cl_N>(c) || !it->coeff.info(info_flags::real)  // sign inside ctor arguments
-                         || !(it->coeff.info(info_flags::negative) || (it->coeff.is_equal(_num1) && is_exactly_a<numeric>(it->rest) && it->rest.info(info_flags::negative)))))
-                               c.s << "+";
+                       c.s << mul_sym;
                }
-       
-               if (!overall_coeff.is_zero()) {
-                       if (overall_coeff.info(info_flags::positive)
-                        || is_a<print_csrc_cl_N>(c) || !overall_coeff.info(info_flags::real))  // sign inside ctor argument
-                               c.s << '+';
-                       overall_coeff.print(c, precedence());
-               }
-               
-               if (precedence() <= level)
-                       c.s << ")";
-
-       } else if (is_a<print_python_repr>(c)) {
-
-               c.s << class_name() << '(';
-               op(0).print(c);
-               for (size_t i=1; i<nops(); ++i) {
-                       c.s << ',';
-                       op(i).print(c);
-               }
-               c.s << ')';
-
-       } else {
+               it->rest.print(c, precedence());
+               ++it;
+       }
 
-               if (precedence() <= level) {
-                       if (is_a<print_latex>(c))
-                               c.s << "{(";
-                       else
-                               c.s << "(";
-               }
+       if (precedence() <= level)
+               c.s << ')' << closebrace;
+}
 
-               numeric coeff;
-               bool first = true;
+void add::do_print(const print_context & c, unsigned level) const
+{
+       print_add(c, "", "", "*", level);
+}
 
-               // First print the overall numeric coefficient, if present
-               if (!overall_coeff.is_zero()) {
-                       if (!is_a<print_tree>(c))
-                               overall_coeff.print(c, 0);
-                       else
-                               overall_coeff.print(c, precedence());
-                       first = false;
-               }
+void add::do_print_latex(const print_latex & c, unsigned level) const
+{
+       print_add(c, "{", "}", " ", level);
+}
 
-               // 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);
-                                       else
-                                               coeff.print(c);
-                               } else {
-                                       if (coeff.csgn() == -1)
-                                               (-coeff).print(c, precedence());
-                                       else
-                                               coeff.print(c, precedence());
-                               }
-                               if (is_a<print_latex>(c))
-                                       c.s << ' ';
-                               else
-                                       c.s << '*';
-                       }
+void add::do_print_csrc(const print_csrc & c, unsigned level) const
+{
+       if (precedence() <= level)
+               c.s << "(";
+       
+       // 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.is_equal(_ex1)) {
+                       it->rest.print(c, precedence());
+               } else if (it->coeff.is_equal(_ex_1)) {
+                       c.s << "-";
+                       it->rest.print(c, precedence());
+               } else if (ex_to<numeric>(it->coeff).numer().is_equal(_num1)) {
+                       it->rest.print(c, precedence());
+                       c.s << "/";
+                       ex_to<numeric>(it->coeff).denom().print(c, precedence());
+               } else if (ex_to<numeric>(it->coeff).numer().is_equal(_num_1)) {
+                       c.s << "-";
+                       it->rest.print(c, precedence());
+                       c.s << "/";
+                       ex_to<numeric>(it->coeff).denom().print(c, precedence());
+               } else {
+                       it->coeff.print(c, precedence());
+                       c.s << "*";
                        it->rest.print(c, precedence());
-                       ++it;
                }
+               
+               // Separator is "+", except if the following expression would have a leading minus sign or the sign is sitting in parenthesis (as in a ctor)
+               ++it;
+               if (it != itend
+                && (is_a<print_csrc_cl_N>(c) || !it->coeff.info(info_flags::real)  // sign inside ctor arguments
+                 || !(it->coeff.info(info_flags::negative) || (it->coeff.is_equal(_num1) && is_exactly_a<numeric>(it->rest) && it->rest.info(info_flags::negative)))))
+                       c.s << "+";
+       }
+       
+       if (!overall_coeff.is_zero()) {
+               if (overall_coeff.info(info_flags::positive)
+                || is_a<print_csrc_cl_N>(c) || !overall_coeff.info(info_flags::real))  // sign inside ctor argument
+                       c.s << '+';
+               overall_coeff.print(c, precedence());
+       }
+               
+       if (precedence() <= level)
+               c.s << ")";
+}
 
-               if (precedence() <= level) {
-                       if (is_a<print_latex>(c))
-                               c.s << ")}";
-                       else
-                               c.s << ")";
-               }
+void add::do_print_python_repr(const print_python_repr & c, unsigned level) const
+{
+       c.s << class_name() << '(';
+       op(0).print(c);
+       for (size_t i=1; i<nops(); ++i) {
+               c.s << ',';
+               op(i).print(c);
        }
+       c.s << ')';
 }
 
 bool add::info(unsigned inf) const
index 02969f0..d636d0a 100644 (file)
@@ -45,7 +45,6 @@ public:
        
        // functions overriding virtual functions from base classes
 public:
-       void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence() const {return 40;}
        bool info(unsigned inf) const;
        int degree(const ex & s) const;
@@ -73,6 +72,14 @@ protected:
                                               const ex & c) const;
        ex recombine_pair_to_ex(const expair & p) const;
        ex expand(unsigned options=0) const;
+
+       // non-virtual functions in this class
+protected:
+       void print_add(const print_context & c, const char *openbrace, const char *closebrace, const char *mul_sym, unsigned level) const;
+       void do_print(const print_context & c, unsigned level) const;
+       void do_print_latex(const print_latex & c, unsigned level) const;
+       void do_print_csrc(const print_csrc & c, unsigned level) const;
+       void do_print_python_repr(const print_python_repr & c, unsigned level) const;
 };
 
 // utility functions
index a6dea4a..c6a72e2 100644 (file)
@@ -272,7 +272,6 @@ public:
 
        // functions overriding virtual functions from base classes
 public:
-       void print(const print_context & c, unsigned level = 0) const;
        bool info(unsigned inf) const { return inherited::info(inf); }
        unsigned precedence() const { return 10; }
        size_t nops() const { return this->seq.size(); }
@@ -331,6 +330,10 @@ public:
        const_reverse_iterator rend() const {return this->seq.rend();}
 
 protected:
+       void do_print(const print_context & c, unsigned level) const;
+       void do_print_tree(const print_tree & c, unsigned level) const;
+       void do_print_python(const print_python & c, unsigned level) const;
+       void do_print_python_repr(const print_python_repr & c, unsigned level) const;
        STLT evalchildren(int level) const;
        STLT *subschildren(const exmap & m, unsigned options = 0) const;
 };
@@ -372,29 +375,38 @@ void container<C>::archive(archive_node &n) const
 }
 
 template <template <class> class C>
-void container<C>::print(const print_context & c, unsigned level) const
+void container<C>::do_print(const print_context & c, unsigned level) const
 {
-       if (is_a<print_tree>(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<const print_tree &>(c).delta_indent;
-               const_iterator i = this->seq.begin(), end = this->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<print_python>(c)) {
-               printseq(c, '[', ',', ']', precedence(), precedence()+1);
-       } else if (is_a<print_python_repr>(c)) {
-               c.s << class_name ();
-               printseq(c, '(', ',', ')', precedence(), precedence()+1);
-       } else {
-               // always print brackets around seq, ignore upper_precedence
-               printseq(c, get_open_delim(), ',', get_close_delim(), precedence(), precedence()+1);
+       // always print brackets around seq, ignore upper_precedence
+       printseq(c, get_open_delim(), ',', get_close_delim(), precedence(), precedence()+1);
+}
+
+template <template <class> class C>
+void container<C>::do_print_tree(const print_tree & c, unsigned level) const
+{
+       c.s << std::string(level, ' ') << class_name()
+           << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
+           << ", nops=" << nops()
+           << std::endl;
+       const_iterator i = this->seq.begin(), end = this->seq.end();
+       while (i != end) {
+               i->print(c, level + c.delta_indent);
+               ++i;
        }
+       c.s << std::string(level + c.delta_indent,' ') << "=====" << std::endl;
+}
+
+template <template <class> class C>
+void container<C>::do_print_python(const print_python & c, unsigned level) const
+{
+       printseq(c, '[', ',', ']', precedence(), precedence()+1);
+}
+
+template <template <class> class C>
+void container<C>::do_print_python_repr(const print_python_repr & c, unsigned level) const
+{
+       c.s << class_name();
+       printseq(c, '(', ',', ')', precedence(), precedence()+1);
 }
 
 template <template <class> class C>
index 828682f..1c28d96 100644 (file)
@@ -24,7 +24,9 @@
 
 namespace GiNaC {
 
-template <> GINAC_IMPLEMENT_REGISTERED_CLASS(exprseq, basic)
+template <> GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(exprseq, basic,
+  print_func<print_context>(&exprseq::do_print).
+  print_func<print_tree>(&exprseq::do_print_tree))
 
 /** Specialization of container::info() for exprseq. */
 bool exprseq::info(unsigned inf) const
index 412aad5..3fad73f 100644 (file)
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS(indexed, exprseq)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(indexed, exprseq,
+  print_func<print_context>(&indexed::do_print).
+  print_func<print_latex>(&indexed::do_print_latex).
+  print_func<print_tree>(&indexed::do_print_tree))
 
 //////////
 // default constructor
@@ -168,38 +171,80 @@ DEFAULT_UNARCHIVE(indexed)
 // functions overriding virtual functions from base classes
 //////////
 
-void indexed::print(const print_context & c, unsigned level) const
+void indexed::printindices(const print_context & c, unsigned level) const
 {
-       GINAC_ASSERT(seq.size() > 0);
-
-       if (is_a<print_tree>(c)) {
+       if (seq.size() > 1) {
 
-               c.s << std::string(level, ' ') << class_name()
-                   << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
-                   << ", " << seq.size()-1 << " indices"
-                   << ", symmetry=" << symtree << std::endl;
-               unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
-               seq[0].print(c, level + delta_indent);
-               printindices(c, level + delta_indent);
+               exvector::const_iterator it=seq.begin() + 1, itend = seq.end();
 
-       } else {
+               if (is_a<print_latex>(c)) {
 
-               bool is_tex = is_a<print_latex>(c);
-               const ex & base = seq[0];
+                       // TeX output: group by variance
+                       bool first = true;
+                       bool covariant = true;
 
-               if (precedence() <= level)
-                       c.s << (is_tex ? "{(" : "(");
-               if (is_tex)
-                       c.s << "{";
-               base.print(c, precedence());
-               if (is_tex)
+                       while (it != itend) {
+                               bool cur_covariant = (is_a<varidx>(*it) ? ex_to<varidx>(*it).is_covariant() : true);
+                               if (first || cur_covariant != covariant) { // Variance changed
+                                       // The empty {} prevents indices from ending up on top of each other
+                                       if (!first)
+                                               c.s << "}{}";
+                                       covariant = cur_covariant;
+                                       if (covariant)
+                                               c.s << "_{";
+                                       else
+                                               c.s << "^{";
+                               }
+                               it->print(c, level);
+                               c.s << " ";
+                               first = false;
+                               it++;
+                       }
                        c.s << "}";
-               printindices(c, level);
-               if (precedence() <= level)
-                       c.s << (is_tex ? ")}" : ")");
+
+               } else {
+
+                       // Ordinary output
+                       while (it != itend) {
+                               it->print(c, level);
+                               it++;
+                       }
+               }
        }
 }
 
+void indexed::print_indexed(const print_context & c, const char *openbrace, const char *closebrace, unsigned level) const
+{
+       if (precedence() <= level)
+               c.s << openbrace << '(';
+       c.s << openbrace;
+       seq[0].print(c, precedence());
+       c.s << closebrace;
+       printindices(c, level);
+       if (precedence() <= level)
+               c.s << ')' << closebrace;
+}
+
+void indexed::do_print(const print_context & c, unsigned level) const
+{
+       print_indexed(c, "", "", level);
+}
+
+void indexed::do_print_latex(const print_latex & c, unsigned level) const
+{
+       print_indexed(c, "{", "}", level);
+}
+
+void indexed::do_print_tree(const print_tree & c, unsigned level) const
+{
+       c.s << std::string(level, ' ') << class_name()
+           << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
+           << ", " << seq.size()-1 << " indices"
+           << ", symmetry=" << symtree << std::endl;
+       seq[0].print(c, level + c.delta_indent);
+       printindices(c, level + c.delta_indent);
+}
+
 bool indexed::info(unsigned inf) const
 {
        if (inf == info_flags::indexed) return true;
@@ -306,48 +351,6 @@ ex indexed::expand(unsigned options) const
 // non-virtual functions in this class
 //////////
 
-void indexed::printindices(const print_context & c, unsigned level) const
-{
-       if (seq.size() > 1) {
-
-               exvector::const_iterator it=seq.begin() + 1, itend = seq.end();
-
-               if (is_a<print_latex>(c)) {
-
-                       // TeX output: group by variance
-                       bool first = true;
-                       bool covariant = true;
-
-                       while (it != itend) {
-                               bool cur_covariant = (is_a<varidx>(*it) ? ex_to<varidx>(*it).is_covariant() : true);
-                               if (first || cur_covariant != covariant) { // Variance changed
-                                       // The empty {} prevents indices from ending up on top of each other
-                                       if (!first)
-                                               c.s << "}{}";
-                                       covariant = cur_covariant;
-                                       if (covariant)
-                                               c.s << "_{";
-                                       else
-                                               c.s << "^{";
-                               }
-                               it->print(c, level);
-                               c.s << " ";
-                               first = false;
-                               it++;
-                       }
-                       c.s << "}";
-
-               } else {
-
-                       // Ordinary output
-                       while (it != itend) {
-                               it->print(c, level);
-                               it++;
-                       }
-               }
-       }
-}
-
 /** Check whether all indices are of class idx and validate the symmetry
  *  tree. This function is used internally to make sure that all constructed
  *  indexed objects really carry indices and not some other classes. */
index 21947ff..d798107 100644 (file)
@@ -144,7 +144,6 @@ public:
 
        // functions overriding virtual functions from base classes
 public:
-       void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence() const {return 55;}
        bool info(unsigned inf) const;
        ex eval(int level = 0) const;
@@ -185,6 +184,10 @@ public:
 
 protected:
        void printindices(const print_context & c, unsigned level) const;
+       void print_indexed(const print_context & c, const char *openbrace, const char *closebrace, unsigned level) const;
+       void do_print(const print_context & c, unsigned level) const;
+       void do_print_latex(const print_latex & c, unsigned level) const;
+       void do_print_tree(const print_tree & c, unsigned level) const;
        void validate() const;
 
        // member variables
index 97e793e..954182b 100644 (file)
@@ -24,7 +24,9 @@
 
 namespace GiNaC {
 
-template <> GINAC_IMPLEMENT_REGISTERED_CLASS(lst, basic)
+template <> GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(lst, basic,
+  print_func<print_context>(&lst::do_print).
+  print_func<print_tree>(&lst::do_print_tree))
 
 /** Specialization of container::info() for lst. */
 bool lst::info(unsigned inf) const
index 9d2aac1..f283413 100644 (file)
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(mul, expairseq,
+  print_func<print_context>(&mul::do_print).
+  print_func<print_latex>(&mul::do_print_latex).
+  print_func<print_csrc>(&mul::do_print_csrc).
+  print_func<print_tree>(&inherited::do_print_tree).
+  print_func<print_python_repr>(&mul::do_print_python_repr))
+
 
 //////////
 // default constructor
@@ -118,159 +124,154 @@ DEFAULT_ARCHIVING(mul)
 // functions overriding virtual functions from base classes
 //////////
 
-// public
-void mul::print(const print_context & c, unsigned level) const
+void mul::print_overall_coeff(const print_context & c, const char *mul_sym) const
 {
-       if (is_a<print_tree>(c)) {
+       const 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);
+                       else
+                               coeff.print(c);
+               } else {
+                       if (coeff.csgn() == -1)
+                               (-coeff).print(c, precedence());
+                       else
+                               coeff.print(c, precedence());
+               }
+               c.s << mul_sym;
+       }
+}
 
-               inherited::print(c, level);
+void mul::do_print(const print_context & c, unsigned level) const
+{
+       if (precedence() <= level)
+               c.s << '(';
 
-       } else if (is_a<print_csrc>(c)) {
+       print_overall_coeff(c, "*");
 
-               if (precedence() <= level)
-                       c.s << "(";
+       epvector::const_iterator it = seq.begin(), itend = seq.end();
+       bool first = true;
+       while (it != itend) {
+               if (!first)
+                       c.s << '*';
+               else
+                       first = false;
+               recombine_pair_to_ex(*it).print(c, precedence());
+               ++it;
+       }
 
-               if (!overall_coeff.is_equal(_ex1)) {
-                       overall_coeff.print(c, precedence());
-                       c.s << "*";
-               }
+       if (precedence() <= level)
+               c.s << ')';
+}
 
-               // 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/<expr>"
-                       bool needclosingparenthesis = false;
-                       if (it == seq.begin() && it->coeff.info(info_flags::negint)) {
-                               if (is_a<print_csrc_cl_N>(c)) {
-                                       c.s << "recip(";
-                                       needclosingparenthesis = true;
-                               } else
-                                       c.s << "1.0/";
-                       }
+void mul::do_print_latex(const print_latex & c, unsigned level) const
+{
+       if (precedence() <= level)
+               c.s << "{(";
 
-                       // If the exponent is 1 or -1, it is left out
-                       if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1))
-                               it->rest.print(c, precedence());
-                       else if (it->coeff.info(info_flags::negint))
-                               // Outer parens around ex needed for broken GCC parser:
-                               (ex(power(it->rest, -ex_to<numeric>(it->coeff)))).print(c, level);
-                       else
-                               // Outer parens around ex needed for broken GCC parser:
-                               (ex(power(it->rest, ex_to<numeric>(it->coeff)))).print(c, level);
-
-                       if (needclosingparenthesis)
-                               c.s << ")";
-
-                       // Separator is "/" for negative integer powers, "*" otherwise
-                       ++it;
-                       if (it != itend) {
-                               if (it->coeff.info(info_flags::negint))
-                                       c.s << "/";
-                               else
-                                       c.s << "*";
-                       }
-               }
+       print_overall_coeff(c, " ");
 
-               if (precedence() <= level)
-                       c.s << ")";
+       // Separate factors into those with negative numeric exponent
+       // and all others
+       epvector::const_iterator it = seq.begin(), itend = seq.end();
+       exvector neg_powers, others;
+       while (it != itend) {
+               GINAC_ASSERT(is_exactly_a<numeric>(it->coeff));
+               if (ex_to<numeric>(it->coeff).is_negative())
+                       neg_powers.push_back(recombine_pair_to_ex(expair(it->rest, -(it->coeff))));
+               else
+                       others.push_back(recombine_pair_to_ex(*it));
+               ++it;
+       }
 
-       } else if (is_a<print_python_repr>(c)) {
-               c.s << class_name() << '(';
-               op(0).print(c);
-               for (size_t i=1; i<nops(); ++i) {
-                       c.s << ',';
-                       op(i).print(c);
-               }
-               c.s << ')';
-       } else {
+       if (!neg_powers.empty()) {
 
-               if (precedence() <= level) {
-                       if (is_a<print_latex>(c))
-                               c.s << "{(";
-                       else
-                               c.s << "(";
-               }
+               // Factors with negative exponent are printed as a fraction
+               c.s << "\\frac{";
+               mul(others).eval().print(c);
+               c.s << "}{";
+               mul(neg_powers).eval().print(c);
+               c.s << "}";
 
-               // First print the overall numeric coefficient
-               const 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);
-                               else
-                                       coeff.print(c);
-                       } else {
-                               if (coeff.csgn() == -1)
-                                       (-coeff).print(c, precedence());
-                               else
-                                       coeff.print(c, precedence());
-                       }
-                       if (is_a<print_latex>(c))
-                               c.s << ' ';
-                       else
-                               c.s << '*';
-               }
+       } else {
 
-               // Then proceed with the remaining factors
-               epvector::const_iterator it = seq.begin(), itend = seq.end();
-               if (is_a<print_latex>(c)) {
-
-                       // Separate factors into those with negative numeric exponent
-                       // and all others
-                       exvector neg_powers, others;
-                       while (it != itend) {
-                               GINAC_ASSERT(is_exactly_a<numeric>(it->coeff));
-                               if (ex_to<numeric>(it->coeff).is_negative())
-                                       neg_powers.push_back(recombine_pair_to_ex(expair(it->rest, -(it->coeff))));
-                               else
-                                       others.push_back(recombine_pair_to_ex(*it));
-                               ++it;
-                       }
+               // All other factors are printed in the ordinary way
+               exvector::const_iterator vit = others.begin(), vitend = others.end();
+               while (vit != vitend) {
+                       c.s << ' ';
+                       vit->print(c, precedence());
+                       ++vit;
+               }
+       }
 
-                       if (!neg_powers.empty()) {
+       if (precedence() <= level)
+               c.s << ")}";
+}
 
-                               // Factors with negative exponent are printed as a fraction
-                               c.s << "\\frac{";
-                               mul(others).eval().print(c);
-                               c.s << "}{";
-                               mul(neg_powers).eval().print(c);
-                               c.s << "}";
+void mul::do_print_csrc(const print_csrc & c, unsigned level) const
+{
+       if (precedence() <= level)
+               c.s << "(";
 
-                       } else {
+       if (!overall_coeff.is_equal(_ex1)) {
+               overall_coeff.print(c, precedence());
+               c.s << "*";
+       }
 
-                               // All other factors are printed in the ordinary way
-                               exvector::const_iterator vit = others.begin(), vitend = others.end();
-                               while (vit != vitend) {
-                                       c.s << ' ';
-                                       vit->print(c, precedence());
-                                       ++vit;
-                               }
-                       }
+       // 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/<expr>"
+               bool needclosingparenthesis = false;
+               if (it == seq.begin() && it->coeff.info(info_flags::negint)) {
+                       if (is_a<print_csrc_cl_N>(c)) {
+                               c.s << "recip(";
+                               needclosingparenthesis = true;
+                       } else
+                               c.s << "1.0/";
+               }
 
-               } else {
+               // If the exponent is 1 or -1, it is left out
+               if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1))
+                       it->rest.print(c, precedence());
+               else if (it->coeff.info(info_flags::negint))
+                       // Outer parens around ex needed for broken GCC parser:
+                       (ex(power(it->rest, -ex_to<numeric>(it->coeff)))).print(c, level);
+               else
+                       // Outer parens around ex needed for broken GCC parser:
+                       (ex(power(it->rest, ex_to<numeric>(it->coeff)))).print(c, level);
 
-                       bool first = true;
-                       while (it != itend) {
-                               if (!first)
-                                       c.s << '*';
-                               else
-                                       first = false;
-                               recombine_pair_to_ex(*it).print(c, precedence());
-                               ++it;
-                       }
-               }
+               if (needclosingparenthesis)
+                       c.s << ")";
 
-               if (precedence() <= level) {
-                       if (is_a<print_latex>(c))
-                               c.s << ")}";
+               // Separator is "/" for negative integer powers, "*" otherwise
+               ++it;
+               if (it != itend) {
+                       if (it->coeff.info(info_flags::negint))
+                               c.s << "/";
                        else
-                               c.s << ")";
+                               c.s << "*";
                }
        }
+
+       if (precedence() <= level)
+               c.s << ")";
+}
+
+void mul::do_print_python_repr(const print_python_repr & c, unsigned level) const
+{
+       c.s << class_name() << '(';
+       op(0).print(c);
+       for (size_t i=1; i<nops(); ++i) {
+               c.s << ',';
+               op(i).print(c);
+       }
+       c.s << ')';
 }
 
 bool mul::info(unsigned inf) const
index 12e7e48..e6aa161 100644 (file)
@@ -47,7 +47,6 @@ public:
        
        // functions overriding virtual functions from base classes
 public:
-       void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence() const {return 50;}
        bool info(unsigned inf) const;
        int degree(const ex & s) const;
@@ -87,6 +86,11 @@ protected:
 public:
        ex algebraic_subs_mul(const exmap & m, unsigned options) const;
 protected:
+       void print_overall_coeff(const print_context & c, const char *mul_sym) const;
+       void do_print(const print_context & c, unsigned level) const;
+       void do_print_latex(const print_latex & c, unsigned level) const;
+       void do_print_csrc(const print_csrc & c, unsigned level) const;
+       void do_print_python_repr(const print_python_repr & c, unsigned level) const;
        epvector * expandchildren(unsigned options) const;
 };
 
index 1aade2e..b38b733 100644 (file)
@@ -100,7 +100,7 @@ void power::print_power(const print_context & c, const char *powersymbol, const
        exponent.print(c, precedence());
        c.s << closebrace;
        if (precedence() <= level)
-               c.s << closebrace << ')';
+               c.s << ')' << closebrace;
 }
 
 void power::do_print_dflt(const print_dflt & c, unsigned level) const
index 224d28d..8820e4e 100644 (file)
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(pseries, basic,
+  print_func<print_context>(&pseries::do_print).
+  print_func<print_latex>(&pseries::do_print_latex).
+  print_func<print_tree>(&pseries::do_print_tree).
+  print_func<print_python>(&pseries::do_print_python).
+  print_func<print_python_repr>(&pseries::do_print_python_repr))
 
 
 /*
@@ -107,106 +112,113 @@ DEFAULT_UNARCHIVE(pseries)
 // functions overriding virtual functions from base classes
 //////////
 
-void pseries::print(const print_context & c, unsigned level) const
+void pseries::print_series(const print_context & c, const char *openbrace, const char *closebrace, const char *mul_sym, const char *pow_sym, unsigned level) const
 {
-       if (is_a<print_tree>(c)) {
+       if (precedence() <= level)
+               c.s << '(';
+               
+       // objects of type pseries must not have any zero entries, so the
+       // trivial (zero) pseries needs a special treatment here:
+       if (seq.empty())
+               c.s << '0';
 
-               c.s << std::string(level, ' ') << class_name()
-                   << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
-                   << std::endl;
-               unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
-               size_t num = seq.size();
-               for (size_t i=0; i<num; ++i) {
-                       seq[i].rest.print(c, level + delta_indent);
-                       seq[i].coeff.print(c, level + delta_indent);
-                       c.s << std::string(level + delta_indent, ' ') << "-----" << std::endl;
-               }
-               var.print(c, level + delta_indent);
-               point.print(c, level + delta_indent);
+       epvector::const_iterator i = seq.begin(), end = seq.end();
+       while (i != end) {
 
-       } else if (is_a<print_python_repr>(c)) {
-               c.s << class_name() << "(relational(";
-               var.print(c);
-               c.s << ',';
-               point.print(c);
-               c.s << "),[";
-               size_t num = seq.size();
-               for (size_t i=0; i<num; ++i) {
-                       if (i)
-                               c.s << ',';
-                       c.s << '(';
-                       seq[i].rest.print(c);
-                       c.s << ',';
-                       seq[i].coeff.print(c);
-                       c.s << ')';
-               }
-               c.s << "])";
-       } else {
+               // print a sign, if needed
+               if (i != seq.begin())
+                       c.s << '+';
 
-               if (precedence() <= level)
-                       c.s << "(";
-               
-               std::string par_open = is_a<print_latex>(c) ? "{(" : "(";
-               std::string par_close = is_a<print_latex>(c) ? ")}" : ")";
-               
-               // objects of type pseries must not have any zero entries, so the
-               // trivial (zero) pseries needs a special treatment here:
-               if (seq.empty())
-                       c.s << '0';
-               epvector::const_iterator i = seq.begin(), end = seq.end();
-               while (i != end) {
-                       // print a sign, if needed
-                       if (i != seq.begin())
-                               c.s << '+';
-                       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)) {
-                                       i->rest.print(c);
-                               } else {
-                                       c.s << par_open;
-                                       i->rest.print(c);
-                                       c.s << par_close;
-                               }
-                               // print 'coeff', something like (x-1)^42
-                               if (!i->coeff.is_zero()) {
-                                       if (is_a<print_latex>(c))
-                                               c.s << ' ';
-                                       else
-                                               c.s << '*';
-                                       if (!point.is_zero()) {
-                                               c.s << par_open;
-                                               (var-point).print(c);
-                                               c.s << par_close;
+               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)) {
+                               i->rest.print(c);
+                       } else {
+                               c.s << openbrace << '(';
+                               i->rest.print(c);
+                               c.s << ')' << closebrace;
+                       }
+
+                       // print 'coeff', something like (x-1)^42
+                       if (!i->coeff.is_zero()) {
+                               c.s << mul_sym;
+                               if (!point.is_zero()) {
+                                       c.s << openbrace << '(';
+                                       (var-point).print(c);
+                                       c.s << ')' << closebrace;
+                               } else
+                                       var.print(c);
+                               if (i->coeff.compare(_ex1)) {
+                                       c.s << pow_sym;
+                                       c.s << openbrace;
+                                       if (i->coeff.info(info_flags::negative)) {
+                                               c.s << '(';
+                                               i->coeff.print(c);
+                                               c.s << ')';
                                        } else
-                                               var.print(c);
-                                       if (i->coeff.compare(_ex1)) {
-                                               if (is_a<print_python>(c))
-                                                       c.s << "**";
-                                               else
-                                                       c.s << '^';
-                                               if (i->coeff.info(info_flags::negative)) {
-                                                       c.s << par_open;
-                                                       i->coeff.print(c);
-                                                       c.s << par_close;
-                                               } else {
-                                                       if (is_a<print_latex>(c)) {
-                                                               c.s << '{';
-                                                               i->coeff.print(c);
-                                                               c.s << '}';
-                                                       } else
-                                                               i->coeff.print(c);
-                                               }
-                                       }
+                                               i->coeff.print(c);
+                                       c.s << closebrace;
                                }
-                       } else
-                               Order(power(var-point,i->coeff)).print(c);
-                       ++i;
-               }
+                       }
+               } else
+                       Order(power(var-point,i->coeff)).print(c);
+               ++i;
+       }
+
+       if (precedence() <= level)
+               c.s << ')';
+}
+
+void pseries::do_print(const print_context & c, unsigned level) const
+{
+       print_series(c, "", "", "*", "^", level);
+}
+
+void pseries::do_print_latex(const print_latex & c, unsigned level) const
+{
+       print_series(c, "{", "}", " ", "^", level);
+}
 
-               if (precedence() <= level)
-                       c.s << ")";
+void pseries::do_print_python(const print_python & c, unsigned level) const
+{
+       print_series(c, "", "", "*", "**", level);
+}
+
+void pseries::do_print_tree(const print_tree & c, unsigned level) const
+{
+       c.s << std::string(level, ' ') << class_name()
+           << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
+           << std::endl;
+       size_t num = seq.size();
+       for (size_t i=0; i<num; ++i) {
+               seq[i].rest.print(c, level + c.delta_indent);
+               seq[i].coeff.print(c, level + c.delta_indent);
+               c.s << std::string(level + c.delta_indent, ' ') << "-----" << std::endl;
+       }
+       var.print(c, level + c.delta_indent);
+       point.print(c, level + c.delta_indent);
+}
+
+void pseries::do_print_python_repr(const print_python_repr & c, unsigned level) const
+{
+       c.s << class_name() << "(relational(";
+       var.print(c);
+       c.s << ',';
+       point.print(c);
+       c.s << "),[";
+       size_t num = seq.size();
+       for (size_t i=0; i<num; ++i) {
+               if (i)
+                       c.s << ',';
+               c.s << '(';
+               seq[i].rest.print(c);
+               c.s << ',';
+               seq[i].coeff.print(c);
+               c.s << ')';
        }
+       c.s << "])";
 }
 
 int pseries::compare_same_type(const basic & other) const
index 370c1f9..823c5ba 100644 (file)
@@ -42,7 +42,6 @@ public:
 
        // functions overriding virtual functions from base classes
 public:
-       void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence() const {return 38;} // for clarity just below add::precedence
        size_t nops() const;
        ex op(size_t i) const;
@@ -89,6 +88,14 @@ public:
        ex power_const(const numeric &p, int deg) const;
        pseries shift_exponents(int deg) const;
 
+protected:
+       void print_series(const print_context & c, const char *openbrace, const char *closebrace, const char *mul_sym, const char *pow_sym, unsigned level) const;
+       void do_print(const print_context & c, unsigned level) const;
+       void do_print_latex(const print_latex & c, unsigned level) const;
+       void do_print_tree(const print_tree & c, unsigned level) const;
+       void do_print_python(const print_python & c, unsigned level) const;
+       void do_print_python_repr(const print_python_repr & c, unsigned level) const;
+
 protected:
        /** Vector of {coefficient, power} pairs */
        epvector seq;