[GiNaC-devel] [PATCH] improved CLN C++ code output
Alexei Sheplyakov
varg at theor.jinr.ru
Wed Sep 5 09:30:32 CEST 2007
* small integers are printed as int (not as cl_I)
* no more ugly x+-y output
* powers always printed using cln::expt function.
Please note: this patch is for development branch only, since it breaks
binary compatibility (due to power::do_print_csrc_cl_N). I'll post
patches for GiNaC 1.[34] later.
---
ginac/add.cpp | 34 +++++++++++++++-------------------
ginac/numeric.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
ginac/power.cpp | 35 +++++++++++++++++++++--------------
ginac/power.h | 1 +
4 files changed, 83 insertions(+), 38 deletions(-)
diff --git a/ginac/add.cpp b/ginac/add.cpp
index b37ab79..98e8c79 100644
--- a/ginac/add.cpp
+++ b/ginac/add.cpp
@@ -23,6 +23,7 @@
#include <iostream>
#include <stdexcept>
#include <limits>
+#include <string>
#include "add.h"
#include "mul.h"
@@ -172,37 +173,32 @@ void add::do_print_csrc(const print_csrc & c, unsigned level) const
if (precedence() <= level)
c.s << "(";
- // Print arguments, separated by "+"
+ // Print arguments, separated by "+" or "-"
epvector::const_iterator it = seq.begin(), itend = seq.end();
+ char separator = ' ';
while (it != itend) {
- // If the coefficient is -1, it is replaced by a single minus sign
- if (it->coeff.is_equal(_ex1)) {
+ // If the coefficient is negative, separator is "-"
+ if (it->coeff.is_equal(_ex_1) ||
+ ex_to<numeric>(it->coeff).numer().is_equal(*_num_1_p))
+ separator = '-';
+ c.s << separator;
+ if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1)) {
it->rest.print(c, precedence());
- } else if (it->coeff.is_equal(_ex_1)) {
- c.s << "-";
+ } else if (ex_to<numeric>(it->coeff).numer().is_equal(*_num1_p) ||
+ ex_to<numeric>(it->coeff).numer().is_equal(*_num_1_p))
+ {
it->rest.print(c, precedence());
- } else if (ex_to<numeric>(it->coeff).numer().is_equal(*_num1_p)) {
- 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_p)) {
- c.s << "-";
- it->rest.print(c, precedence());
- c.s << "/";
+ c.s << '/';
ex_to<numeric>(it->coeff).denom().print(c, precedence());
} else {
it->coeff.print(c, precedence());
- c.s << "*";
+ c.s << '*';
it->rest.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_p) && is_exactly_a<numeric>(it->rest) && it->rest.info(info_flags::negative)))))
- c.s << "+";
+ separator = '+';
}
if (!overall_coeff.is_zero()) {
diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
index ef61ce7..74f0e50 100644
--- a/ginac/numeric.cpp
+++ b/ginac/numeric.cpp
@@ -399,6 +399,38 @@ static void print_real_csrc(const print_context & c, const cln::cl_R & x)
}
}
+template<typename T1, typename T2>
+static inline bool coerce(T1& dst, const T2& arg);
+
+/**
+ * @brief Check if CLN integer can be converted into int
+ *
+ * @sa http://www.ginac.de/pipermail/cln-list/2006-October/000248.html
+ */
+template<> static inline bool
+coerce<int, cln::cl_I>(int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_int =
+ (cln::cl_I)(long)(std::numeric_limits<int>::max());
+ static const cln::cl_I cl_min_int =
+ (cln::cl_I)(long)(std::numeric_limits<int>::min());
+ if ((arg >= cl_min_int) && (arg <= cl_max_int)) {
+ dst = cl_I_to_int(arg);
+ return true;
+ }
+ return false;
+}
+
+template<> static inline bool
+coerce<unsigned int, cln::cl_I>(unsigned int& dst, const cln::cl_I& arg) {
+ static const cln::cl_I cl_max_uint =
+ (cln::cl_I)(unsigned long)(std::numeric_limits<unsigned int>::max());
+ if ((! minusp(arg)) && (arg <= cl_max_uint)) {
+ dst = cl_I_to_uint(arg);
+ return true;
+ }
+ return false;
+}
+
/** Helper function to print real number in C++ source format using cl_N types.
*
* @see numeric::print() */
@@ -406,11 +438,20 @@ 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 << "\")";
-
+ int dst;
+ // fixnum
+ if (coerce(dst, cln::the<cln::cl_I>(x))) {
+ // can be converted to native int
+ if (dst < 0)
+ c.s << "(-" << dst << ")";
+ else
+ c.s << dst;
+ } else {
+ // bignum
+ c.s << "cln::cl_I(\"";
+ print_real_number(c, x);
+ c.s << "\")";
+ }
} else if (cln::instanceof(x, cln::cl_RA_ring)) {
// Rational number
diff --git a/ginac/power.cpp b/ginac/power.cpp
index faa0d05..68bec71 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -50,7 +50,8 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(power, basic,
print_func<print_latex>(&power::do_print_latex).
print_func<print_csrc>(&power::do_print_csrc).
print_func<print_python>(&power::do_print_python).
- print_func<print_python_repr>(&power::do_print_python_repr))
+ print_func<print_python_repr>(&power::do_print_python_repr).
+ print_func<print_csrc_cl_N>(&power::do_print_csrc_cl_N))
typedef std::vector<int> intvector;
@@ -162,6 +163,21 @@ static void print_sym_pow(const print_context & c, const symbol &x, int exp)
}
}
+void power::do_print_csrc_cl_N(const print_csrc_cl_N& c, unsigned level) const
+{
+ if (exponent.is_equal(_ex_1)) {
+ c.s << "recip(";
+ basis.print(c);
+ c.s << ')';
+ return;
+ }
+ c.s << "expt(";
+ basis.print(c);
+ c.s << ", ";
+ exponent.print(c);
+ c.s << ')';
+}
+
void power::do_print_csrc(const print_csrc & c, unsigned level) const
{
// Integer powers of symbols are printed in a special, optimized way
@@ -172,29 +188,20 @@ void power::do_print_csrc(const print_csrc & c, unsigned level) const
c.s << '(';
else {
exp = -exp;
- if (is_a<print_csrc_cl_N>(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
}
print_sym_pow(c, ex_to<symbol>(basis), exp);
c.s << ')';
// <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
} else if (exponent.is_equal(_ex_1)) {
- if (is_a<print_csrc_cl_N>(c))
- c.s << "recip(";
- else
- c.s << "1.0/(";
+ c.s << "1.0/(";
basis.print(c);
c.s << ')';
- // Otherwise, use the pow() or expt() (CLN) functions
+ // Otherwise, use the pow() function
} else {
- if (is_a<print_csrc_cl_N>(c))
- c.s << "expt(";
- else
- c.s << "pow(";
+ c.s << "pow(";
basis.print(c);
c.s << ',';
exponent.print(c);
diff --git a/ginac/power.h b/ginac/power.h
index f5e65d6..3375040 100644
--- a/ginac/power.h
+++ b/ginac/power.h
@@ -88,6 +88,7 @@ protected:
void do_print_csrc(const print_csrc & 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;
+ void do_print_csrc_cl_N(const print_csrc_cl_N & c, unsigned level) const;
ex expand_add(const add & a, int n, unsigned options) const;
ex expand_add_2(const add & a, unsigned options) const;
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20070905/1258af4a/attachment-0001.pgp
More information about the GiNaC-devel
mailing list