[GiNaC-devel] [PATCH] Improved CLN C++ code output (print_csrc_cln) for GiNaC 1.3

Alexei Sheplyakov varg at theor.jinr.ru
Wed Sep 5 10:43:06 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.

---
 ginac/add.cpp     |   34 +++++++++++++++-------------------
 ginac/numeric.cpp |   51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 ginac/power.cpp   |   32 +++++++++++++++++++-------------
 3 files changed, 80 insertions(+), 37 deletions(-)

diff --git a/ginac/add.cpp b/ginac/add.cpp
index 067f9bf..4fd10d9 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"
@@ -170,37 +171,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 208a89c..7640670 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 4ebf0ac..f243147 100644
--- a/ginac/power.cpp
+++ b/ginac/power.cpp
@@ -164,6 +164,21 @@ static void print_sym_pow(const print_context & c, const symbol &x, int exp)
 
 void power::do_print_csrc(const print_csrc & c, unsigned level) const
 {
+	if (is_a<print_csrc_cl_N>(c)) {
+		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 << ')';
+		return;
+	}
+
 	// Integer powers of symbols are printed in a special, optimized way
 	if (exponent.info(info_flags::integer)
 	 && (is_a<symbol>(basis) || is_a<constant>(basis))) {
@@ -172,29 +187,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);
-- 
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/3fa44cc3/attachment.pgp


More information about the GiNaC-devel mailing list