From 7cad9b41c97f0b042ba4af8080e82c8ad4804560 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Sun, 15 Apr 2001 00:28:18 +0000 Subject: [PATCH] * basic::collec() never worked correctly on non-polynomials till now. We simply correct for the missing terms, which makes it at least algebraically correct (suggested by Pearu Peterson). * Added support to print out LaTeX-style, based on some work by Stefan Weinzierl: - print.h: added a class print_latex(). - function.pl: added function_options::latex_name() because there was no good way of setting that name before. - inifncs*.cpp: use it. - *.cpp: switch to see if print_context is actually print_latex and then change the style. * Fixed some stupid bugs in sections that were #define'd away for gcc-2.95. --- ginac/add.cpp | 21 ++++++++++++++++----- ginac/archive.cpp | 2 +- ginac/archive.h | 2 +- ginac/basic.cpp | 5 +++-- ginac/constant.cpp | 11 +++++++++-- ginac/flags.h | 2 +- ginac/function.pl | 14 ++++++++++++-- ginac/inifcns.cpp | 12 ++++++++---- ginac/inifcns_gamma.cpp | 10 +++++++--- ginac/inifcns_trans.cpp | 34 ++++++++++++++++++++++------------ ginac/inifcns_zeta.cpp | 1 + ginac/mul.cpp | 29 +++++++++++++++++++++-------- ginac/numeric.cpp | 37 ++++++++++++++++++++----------------- ginac/power.cpp | 26 ++++++++++++++++++++------ ginac/print.h | 8 ++++++++ ginac/pseries.cpp | 27 ++++++++++++++++++--------- ginac/symbol.cpp | 18 ++++++++++++++++++ 17 files changed, 186 insertions(+), 73 deletions(-) diff --git a/ginac/add.cpp b/ginac/add.cpp index 802c2372..1b7b2719 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -166,8 +166,12 @@ void add::print(const print_context & c, unsigned level) const } else { - if (precedence <= level) - c.s << "("; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << "{("; + else + c.s << "("; + } numeric coeff; bool first = true; @@ -204,14 +208,21 @@ void add::print(const print_context & c, unsigned level) const else coeff.print(c, precedence); } - c.s << '*'; + if (is_of_type(c, print_latex)) + c.s << ' '; + else + c.s << '*'; } it->rest.print(c, precedence); it++; } - if (precedence <= level) - c.s << ")"; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << ")}"; + else + c.s << ")"; + } } } diff --git a/ginac/archive.cpp b/ginac/archive.cpp index 3ce4ec65..cdd76192 100644 --- a/ginac/archive.cpp +++ b/ginac/archive.cpp @@ -463,7 +463,7 @@ void archive_node::get_properties(propinfovector &v) const std::vector::const_iterator i = props.begin(), iend = props.end(); while (i != iend) { property_type type = i->type; - string name = a.unatomize(i->name); + std::string name = a.unatomize(i->name); propinfovector::iterator a = v.begin(), aend = v.end(); bool found = false; diff --git a/ginac/archive.h b/ginac/archive.h index 96a6ea1c..53204398 100644 --- a/ginac/archive.h +++ b/ginac/archive.h @@ -79,7 +79,7 @@ public: #if defined(__GNUC__) && ((__GNUC__ == 2) && (__GNUC_MINOR__ < 97)) typedef std::vector propinfovector; #else - typedef std::vector propinfovector; + typedef std::vector propinfovector; #endif archive_node() : a(*dummy_ar_creator()), has_expression(false) {} // hack for cint which always requires a default constructor diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 8040e4a0..c649f64b 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -243,10 +243,11 @@ ex basic::coeff(const ex & s, int n) const ex basic::collect(const ex & s) const { ex x; - for (int n=this->ldegree(s); n<=this->degree(s); n++) + for (int n=this->ldegree(s); n<=this->degree(s); ++n) x += this->coeff(s,n)*power(s,n); - return x; + // correct for lost fractional arguments and return + return x + (*this - x).expand(); } /** Perform automatic non-interruptive symbolic evaluation on expression. */ diff --git a/ginac/constant.cpp b/ginac/constant.cpp index 7afc35be..c056a96a 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -132,11 +132,18 @@ void constant::print(const print_context & c, unsigned level) const debugmsg("constant print", LOGLEVEL_PRINT); if (is_of_type(c, print_tree)) { - c.s << std::string(level, ' ') << name << " (" << class_name() << ")" << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec << std::endl; - + } else if (is_of_type(c, print_latex)) { + if (name=="Pi") + c.s << "\\pi"; + else if (name=="Euler") + c.s << "\\gamma_E"; + else if (name=="Catalan") + c.s << "G"; + else + c.s << "\\mbox{"+name+"}"; } else c.s << name; } diff --git a/ginac/flags.h b/ginac/flags.h index 96838cec..9c11862e 100644 --- a/ginac/flags.h +++ b/ginac/flags.h @@ -69,7 +69,7 @@ public: class status_flags { public: enum { - dynallocated = 0x0001, ///< Heap-allocated (i.e. created by new if we want to be clever and bypass the stack) + dynallocated = 0x0001, ///< Heap-allocated (i.e. created by new if we want to be clever and bypass the stack, @see ex::construct_from_basic() ) evaluated = 0x0002, ///< .eval() has already done its job expanded = 0x0004, ///< .expand() has already done its job hash_calculated = 0x0008 ///< .calchash() has already done its job diff --git a/ginac/function.pl b/ginac/function.pl index d381ea69..9e303d07 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -264,6 +264,7 @@ public: ~function_options(); void initialize(void); function_options & set_name(std::string const & n, std::string const & tn=std::string()); + function_options & latex_name(std::string const & tn); // the following lines have been generated for max. ${maxargs} parameters $eval_func_interface $evalf_func_interface @@ -451,7 +452,7 @@ function_options::~function_options() void function_options::initialize(void) { - set_name("unnamed_function","\\\\operatorname{unnamed}"); + set_name("unnamed_function","\\\\mbox{unnamed}"); nparams=0; eval_f=evalf_f=derivative_f=series_f=0; evalf_params_first=true; @@ -465,13 +466,19 @@ function_options & function_options::set_name(std::string const & n, { name=n; if (tn==std::string()) { - TeX_name="\\\\operatorname{"+name+"}"; + TeX_name="\\\\mbox{"+name+"}"; } else { TeX_name=tn; } return *this; } +function_options & function_options::latex_name(std::string const & tn) +{ + TeX_name=tn; + return *this; +} + // the following lines have been generated for max. ${maxargs} parameters $eval_func_implementation $evalf_func_implementation @@ -669,6 +676,9 @@ void function::print(const print_context & c, unsigned level) const } c.s << ")"; + } else if is_of_type(c, print_latex) { + c.s << registered_functions()[serial].TeX_name; + printseq(c, '(', ',', ')', exprseq::precedence, function::precedence); } else { c.s << registered_functions()[serial].name; printseq(c, '(', ',', ')', exprseq::precedence, function::precedence); diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index fbdceb70..0daa9798 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -177,7 +177,8 @@ static ex eta_series(const ex & arg1, REGISTER_FUNCTION(eta, eval_func(eta_eval). evalf_func(eta_evalf). - series_func(eta_series)); + series_func(eta_series). + latex_name("\\eta")); ////////// @@ -315,7 +316,8 @@ static ex Li2_series(const ex &x, const relational &rel, int order, unsigned opt REGISTER_FUNCTION(Li2, eval_func(Li2_eval). evalf_func(Li2_evalf). derivative_func(Li2_deriv). - series_func(Li2_series)); + series_func(Li2_series). + latex_name("\\mbox{Li}_2")); ////////// // trilogarithm @@ -328,7 +330,8 @@ static ex Li3_eval(const ex & x) return Li3(x).hold(); } -REGISTER_FUNCTION(Li3, eval_func(Li3_eval)); +REGISTER_FUNCTION(Li3, eval_func(Li3_eval). + latex_name("\\mbox{Li}_3")); ////////// // factorial @@ -404,7 +407,8 @@ static ex Order_series(const ex & x, const relational & r, int order, unsigned o // Differentiation is handled in function::derivative because of its special requirements REGISTER_FUNCTION(Order, eval_func(Order_eval). - series_func(Order_series)); + series_func(Order_series). + latex_name("\\mathcal{O}")); ////////// // Inert partial differentiation operator diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index 57dbeb3d..014ae939 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -109,7 +109,8 @@ static ex lgamma_series(const ex & arg, REGISTER_FUNCTION(lgamma, eval_func(lgamma_eval). evalf_func(lgamma_evalf). derivative_func(lgamma_deriv). - series_func(lgamma_series)); + series_func(lgamma_series). + latex_name("\\log \\Gamma")); ////////// @@ -205,7 +206,8 @@ static ex tgamma_series(const ex & arg, REGISTER_FUNCTION(tgamma, eval_func(tgamma_eval). evalf_func(tgamma_evalf). derivative_func(tgamma_deriv). - series_func(tgamma_series)); + series_func(tgamma_series). + latex_name("\\Gamma")); ////////// @@ -316,7 +318,8 @@ static ex beta_series(const ex & arg1, REGISTER_FUNCTION(beta, eval_func(beta_eval). evalf_func(beta_evalf). derivative_func(beta_deriv). - series_func(beta_series)); + series_func(beta_series). + latex_name("\\mbox{B}")); ////////// @@ -541,6 +544,7 @@ const unsigned function_index_psi2 = evalf_func(psi2_evalf). derivative_func(psi2_deriv). series_func(psi2_series). + latex_name("\\psi"). overloaded(2)); diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index dbbb122c..3bda254a 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -89,7 +89,8 @@ static ex exp_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(exp, eval_func(exp_eval). evalf_func(exp_evalf). - derivative_func(exp_deriv)); + derivative_func(exp_deriv). + latex_name("\\exp")); ////////// // natural logarithm @@ -210,7 +211,8 @@ static ex log_series(const ex &arg, REGISTER_FUNCTION(log, eval_func(log_eval). evalf_func(log_evalf). derivative_func(log_deriv). - series_func(log_series)); + series_func(log_series). + latex_name("\\ln")); ////////// // sine (trigonometric function) @@ -291,7 +293,8 @@ static ex sin_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(sin, eval_func(sin_eval). evalf_func(sin_evalf). - derivative_func(sin_deriv)); + derivative_func(sin_deriv). + latex_name("\\sin")); ////////// // cosine (trigonometric function) @@ -372,7 +375,8 @@ static ex cos_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(cos, eval_func(cos_eval). evalf_func(cos_evalf). - derivative_func(cos_deriv)); + derivative_func(cos_deriv). + latex_name("\\cos")); ////////// // tangent (trigonometric function) @@ -467,7 +471,8 @@ static ex tan_series(const ex &x, REGISTER_FUNCTION(tan, eval_func(tan_eval). evalf_func(tan_evalf). derivative_func(tan_deriv). - series_func(tan_series)); + series_func(tan_series). + latex_name("\\tan")); ////////// // inverse sine (arc sine) @@ -518,7 +523,8 @@ static ex asin_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(asin, eval_func(asin_eval). evalf_func(asin_evalf). - derivative_func(asin_deriv)); + derivative_func(asin_deriv). + latex_name("\\arcsin")); ////////// // inverse cosine (arc cosine) @@ -569,7 +575,8 @@ static ex acos_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(acos, eval_func(acos_eval). evalf_func(acos_evalf). - derivative_func(acos_deriv)); + derivative_func(acos_deriv). + latex_name("\\arccos")); ////////// // inverse tangent (arc tangent) @@ -660,7 +667,8 @@ static ex atan_series(const ex &arg, REGISTER_FUNCTION(atan, eval_func(atan_eval). evalf_func(atan_evalf). derivative_func(atan_deriv). - series_func(atan_series)); + series_func(atan_series). + latex_name("\\arctan")); ////////// // inverse tangent (atan2(y,x)) @@ -754,7 +762,8 @@ static ex sinh_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(sinh, eval_func(sinh_eval). evalf_func(sinh_evalf). - derivative_func(sinh_deriv)); + derivative_func(sinh_deriv). + latex_name("\\sinh")); ////////// // hyperbolic cosine (trigonometric function) @@ -808,8 +817,8 @@ static ex cosh_deriv(const ex & x, unsigned deriv_param) REGISTER_FUNCTION(cosh, eval_func(cosh_eval). evalf_func(cosh_evalf). - derivative_func(cosh_deriv)); - + derivative_func(cosh_deriv). + latex_name("\\cosh")); ////////// // hyperbolic tangent (trigonometric function) @@ -880,7 +889,8 @@ static ex tanh_series(const ex &x, REGISTER_FUNCTION(tanh, eval_func(tanh_eval). evalf_func(tanh_evalf). derivative_func(tanh_deriv). - series_func(tanh_series)); + series_func(tanh_series). + latex_name("\\tanh")); ////////// // inverse hyperbolic sine (trigonometric function) diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index 0f069089..0b3046e1 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -83,6 +83,7 @@ const unsigned function_index_zeta1 = eval_func(zeta1_eval). evalf_func(zeta1_evalf). derivative_func(zeta1_deriv). + latex_name("\\zeta"). overloaded(2)); ////////// diff --git a/ginac/mul.cpp b/ginac/mul.cpp index b42fcfe4..27451f6b 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -136,8 +136,7 @@ void mul::print(const print_context & c, unsigned level) const } else if (is_of_type(c, print_csrc)) { - if (precedence <= level) - c.s << "("; + c.s << "("; if (!overall_coeff.is_equal(_ex1())) { overall_coeff.bp->print(c, precedence); @@ -179,8 +178,12 @@ void mul::print(const print_context & c, unsigned level) const } else { - if (precedence <= level) - c.s << "("; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << "{("; + else + c.s << "("; + } bool first = true; @@ -201,14 +204,20 @@ void mul::print(const print_context & c, unsigned level) const else coeff.print(c, precedence); } - c.s << '*'; + if (is_of_type(c, print_latex)) + c.s << ' '; + else + c.s << '*'; } // Then proceed with the remaining factors epvector::const_iterator it = seq.begin(), itend = seq.end(); while (it != itend) { if (!first) { - c.s << '*'; + if (is_of_type(c, print_latex)) + c.s << ' '; + else + c.s << '*'; } else { first = false; } @@ -216,8 +225,12 @@ void mul::print(const print_context & c, unsigned level) const it++; } - if (precedence <= level) - c.s << ")"; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << ")}"; + else + c.s << ")"; + } } } diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 1308c9e1..3af060d0 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -410,15 +410,18 @@ void numeric::print(const print_context & c, unsigned level) const c.s.flags(oldflags); } else { - - cln::cl_R r = cln::realpart(cln::the(value)); - cln::cl_R i = cln::imagpart(cln::the(value)); + const std::string par_open = is_of_type(c, print_latex) ? "{(" : "("; + const std::string par_close = is_of_type(c, print_latex) ? ")}" : ")"; + const std::string imag_sym = is_of_type(c, print_latex) ? "i" : "I"; + const std::string mul_sym = is_of_type(c, print_latex) ? " " : "*"; + const cln::cl_R r = cln::realpart(cln::the(value)); + const 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 << "("; + c.s << par_open; print_real_number(c.s, r); - c.s << ")"; + c.s << par_close; } else { print_real_number(c.s, r); } @@ -427,47 +430,47 @@ void numeric::print(const print_context & c, unsigned level) const // case 2, imaginary: y*I or -y*I if ((precedence <= level) && (i < 0)) { if (i == -1) { - c.s << "(-I)"; + c.s << par_open+imag_sym+par_close; } else { - c.s << "("; + c.s << par_open; print_real_number(c.s, i); - c.s << "*I)"; + c.s << mul_sym+imag_sym+par_close; } } else { if (i == 1) { - c.s << "I"; + c.s << imag_sym; } else { if (i == -1) { - c.s << "-I"; + c.s << "-" << imag_sym; } else { print_real_number(c.s, i); - c.s << "*I"; + c.s << mul_sym+imag_sym; } } } } else { // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I if (precedence <= level) - c.s << "("; + c.s << par_open; print_real_number(c.s, r); if (i < 0) { if (i == -1) { - c.s << "-I"; + c.s << "-"+imag_sym; } else { print_real_number(c.s, i); - c.s << "*I"; + c.s << mul_sym+imag_sym; } } else { if (i == 1) { - c.s << "+I"; + c.s << "+"+imag_sym; } else { c.s << "+"; print_real_number(c.s, i); - c.s << "*I"; + c.s << mul_sym+imag_sym; } } if (precedence <= level) - c.s << ")"; + c.s << par_close; } } } diff --git a/ginac/power.cpp b/ginac/power.cpp index 109eacfe..6b8c184e 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -177,17 +177,31 @@ void power::print(const print_context & c, unsigned level) const } else { if (exponent.is_equal(_ex1_2())) { - c.s << "sqrt("; + if (is_of_type(c, print_latex)) + c.s << "\\sqrt{"; + else + c.s << "sqrt("; basis.print(c); - c.s << ")"; + if (is_of_type(c, print_latex)) + c.s << "}"; + else + c.s << ")"; } else { - if (precedence <= level) - c.s << "("; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << "{("; + else + c.s << "("; + } basis.print(c, precedence); c.s << "^"; exponent.print(c, precedence); - if (precedence <= level) - c.s << ")"; + if (precedence <= level) { + if (is_of_type(c, print_latex)) + c.s << ")}"; + else + c.s << ")"; + } } } } diff --git a/ginac/print.h b/ginac/print.h index 4fdbeb83..c8bd9b66 100644 --- a/ginac/print.h +++ b/ginac/print.h @@ -39,6 +39,14 @@ public: virtual void dummy(void) {} }; +/** Context for latex-parsable output. */ +class print_latex : public print_context +{ +public: + print_latex(std::ostream & os = std::cout) + : print_context(os) {} +}; + /** Context for tree-like output for debugging. */ class print_tree : public print_context { diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 789d7671..5f15a2e3 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -144,7 +144,10 @@ void pseries::print(const print_context & c, unsigned level) const if (precedence <= level) c.s << "("; - + + std::string par_open = is_of_type(c, print_latex) ? "{(" : "("; + std::string par_close = is_of_type(c, print_latex) ? ")}" : ")"; + // objects of type pseries must not have any zero entries, so the // trivial (zero) pseries needs a special treatment here: if (seq.size() == 0) @@ -159,27 +162,33 @@ void pseries::print(const print_context & c, unsigned level) const i->rest.info(info_flags::positive)) { i->rest.print(c); } else { - c.s << '('; + c.s << par_open; i->rest.print(c); - c.s << ')'; + c.s << par_close; } // print 'coeff', something like (x-1)^42 if (!i->coeff.is_zero()) { c.s << '*'; if (!point.is_zero()) { - c.s << '('; + c.s << par_open; (var-point).print(c); - c.s << ')'; + c.s << par_close; } 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 + c.s << par_open; i->coeff.print(c); + c.s << par_close; + } else { + if (is_of_type(c, print_latex)) { + c.s << '{'; + i->coeff.print(c); + c.s << '}'; + } else + i->coeff.print(c); + } } } } else diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index e093e6c7..bebb8776 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -143,6 +143,24 @@ void symbol::print(const print_context & c, unsigned level) const << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec << std::endl; + } else if (is_of_type(c, print_latex)) { + if (name=="alpha" || name=="beta" || name=="gamma" + || name=="delta" || name=="epsilon" || name=="varepsilon" + || name=="zeta" || name=="eta" || name=="theta" + || name=="vartheta" || name=="iota" || name=="kappa" + || name=="lambda" || name=="mu" || name=="nu" + || name=="xi" || name=="omicron" || name=="pi" + || name=="varpi" || name=="rho" || name=="varrho" + || name=="sigma" || name=="varsigma" || name=="tau" + || name=="upsilon" || name=="phi" || name=="varphix" + || name=="chi" || name=="psi" || name=="omega" + || name=="Gamma" || name=="Delta" || name=="Theta" + || name=="Lambda" || name=="Xi" || name=="Pi" + || name=="Sigma" || name=="Upsilon" || name=="Phi" + || name=="Psi" || name=="Omega") + c.s << "\\" << name; + else + c.s << name; } else c.s << name; } -- 2.44.0