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
// 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
// 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;
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
// 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(); }
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;
};
}
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>
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
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
// 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;
// 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. */
// 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;
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
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
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
// 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
// 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;
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;
};
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
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))
/*
// 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
// 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;
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;