From: Christian Bauer Date: Wed, 5 Feb 2003 22:31:41 +0000 (+0000) Subject: - complex numbers are printed correctly (using the STL complex<> template or X-Git-Tag: release_1-0-14~12 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=a8617f6e1705e980b7a5f6500f6a2c42563d3f6c;hp=2e30a241f7439b18778b1fabaecb6c31385419c5 - complex numbers are printed correctly (using the STL complex<> template or cln::complex()) - in the CLN output, rational numbers use cl_RA() - small integers are printed in a more compact format (e.g. "2.0" instead of "2.0000000e+00"). --- diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 545d8742..e1156f06 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "numeric.h" #include "ex.h" @@ -313,7 +314,7 @@ DEFAULT_UNARCHIVE(numeric) * want to visibly distinguish from cl_LF. * * @see numeric::print() */ -static void print_real_number(const print_context & c, const cln::cl_R &x) +static void print_real_number(const print_context & c, const cln::cl_R & x) { cln::cl_print_flags ourflags; if (cln::instanceof(x, cln::cl_RA_ring)) { @@ -339,6 +340,82 @@ static void print_real_number(const print_context & c, const cln::cl_R &x) } } +/** Helper function to print integer number in C++ source format. + * + * @see numeric::print() */ +static void print_integer_csrc(const print_context & c, const cln::cl_I & x) +{ + // Print small numbers in compact float format, but larger numbers in + // scientific format + const int max_cln_int = 536870911; // 2^29-1 + if (x >= cln::cl_I(-max_cln_int) && x <= cln::cl_I(max_cln_int)) + c.s << cln::cl_I_to_int(x) << ".0"; + else + c.s << cln::double_approx(x); +} + +/** Helper function to print real number in C++ source format. + * + * @see numeric::print() */ +static void print_real_csrc(const print_context & c, const cln::cl_R & x) +{ + if (cln::instanceof(x, cln::cl_I_ring)) { + + // Integer number + print_integer_csrc(c, cln::the(x)); + + } else if (cln::instanceof(x, cln::cl_RA_ring)) { + + // Rational number + const cln::cl_I numer = cln::numerator(cln::the(x)); + const cln::cl_I denom = cln::denominator(cln::the(x)); + if (cln::plusp(x) > 0) { + c.s << "("; + print_integer_csrc(c, numer); + } else { + c.s << "-("; + print_integer_csrc(c, -numer); + } + c.s << "/"; + print_integer_csrc(c, denom); + c.s << ")"; + + } else { + + // Anything else + c.s << cln::double_approx(x); + } +} + +/** Helper function to print real number in C++ source format using cl_N types. + * + * @see numeric::print() */ +static void print_real_cl_N(const print_context & c, const cln::cl_R & x) +{ + if (cln::instanceof(x, cln::cl_I_ring)) { + + // Integer number + c.s << "cln::cl_I(\""; + print_real_number(c, x); + c.s << "\")"; + + } else if (cln::instanceof(x, cln::cl_RA_ring)) { + + // Rational number + cln::cl_print_flags ourflags; + c.s << "cln::cl_RA(\""; + cln::print_rational(c.s, ourflags, cln::the(x)); + c.s << "\")"; + + } else { + + // Anything else + c.s << "cln::cl_F(\""; + print_real_number(c, cln::cl_float(1.0, cln::default_float_format) * x); + c.s << "_" << Digits << "\")"; + } +} + /** This method adds to the output so it blends more consistently together * with the other routines and produces something compatible to ginsh input. * @@ -352,56 +429,69 @@ void numeric::print(const print_context & c, unsigned level) const << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec << std::endl; + } else if (is_a(c)) { + + // CLN output + if (this->is_real()) { + + // Real number + print_real_cl_N(c, cln::the(value)); + + } else { + + // Complex number + c.s << "cln::complex("; + print_real_cl_N(c, cln::realpart(cln::the(value))); + c.s << ","; + print_real_cl_N(c, cln::imagpart(cln::the(value))); + c.s << ")"; + } + } else if (is_a(c)) { + // C++ source output std::ios::fmtflags oldflags = c.s.flags(); c.s.setf(std::ios::scientific); int oldprec = c.s.precision(); + + // Set precision if (is_a(c)) - c.s.precision(16); + c.s.precision(std::numeric_limits::digits10 + 1); else - c.s.precision(7); - if (is_a(c) && this->is_integer()) { - c.s << "cln::cl_I(\""; - const cln::cl_R r = cln::realpart(cln::the(value)); - print_real_number(c,r); - c.s << "\")"; - } else if (this->is_rational() && !this->is_integer()) { - if (compare(_num0) > 0) { - c.s << "("; - if (is_a(c)) - c.s << "cln::cl_F(\"" << numer().evalf() << "\")"; - else - c.s << numer().to_double(); - } else { - c.s << "-("; - if (is_a(c)) - c.s << "cln::cl_F(\"" << -numer().evalf() << "\")"; - else - c.s << -numer().to_double(); - } - c.s << "/"; - if (is_a(c)) - c.s << "cln::cl_F(\"" << denom().evalf() << "\")"; - else - c.s << denom().to_double(); - c.s << ")"; + c.s.precision(std::numeric_limits::digits10 + 1); + + if (this->is_real()) { + + // Real number + print_real_csrc(c, cln::the(value)); + } else { - if (is_a(c)) - c.s << "cln::cl_F(\"" << evalf() << "_" << Digits << "\")"; + + // Complex number + c.s << "std::complex<"; + if (is_a(c)) + c.s << "double>("; else - c.s << to_double(); + c.s << "float>("; + + print_real_csrc(c, cln::realpart(cln::the(value))); + c.s << ","; + print_real_csrc(c, cln::imagpart(cln::the(value))); + c.s << ")"; } + c.s.flags(oldflags); c.s.precision(oldprec); } else { + const std::string par_open = is_a(c) ? "{(" : "("; const std::string par_close = is_a(c) ? ")}" : ")"; const std::string imag_sym = is_a(c) ? "i" : "I"; const std::string mul_sym = is_a(c) ? " " : "*"; const cln::cl_R r = cln::realpart(cln::the(value)); const cln::cl_R i = cln::imagpart(cln::the(value)); + if (is_a(c)) c.s << class_name() << "('"; if (cln::zerop(i)) { diff --git a/ginac/print.h b/ginac/print.h index 00ebcc91..007f1e40 100644 --- a/ginac/print.h +++ b/ginac/print.h @@ -82,7 +82,7 @@ public: print_csrc(std::ostream &); }; -/** Context for C source output using float numbers. */ +/** Context for C source output using float precision. */ class print_csrc_float : public print_csrc { public: @@ -90,7 +90,7 @@ public: print_csrc_float(std::ostream &); }; -/** Context for C source output using double numbers. */ +/** Context for C source output using double precision. */ class print_csrc_double : public print_csrc { public: