[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