Adding python support to GiNaC

Pearu Peterson pearu at cens.ioc.ee
Tue Dec 18 18:48:42 CET 2001


Hi!

I have been working on the python interface to GiNaC. It is quite usable
already and I have tested it in many problems. However, it would be great
if some python specific changes that I had to do in GiNaC, could be added
to GiNaC. These changes include mostly printing expressions. Earlier I
used hooks from GiNaC archive features to get desired output for python,
but it was _very_ slow compared to the native GiNaC print hooks.

So, please find a patch attached that adds two new print_context classes,
print_python and print_python_repr, with the corresponding additions to
print methods of the basic classes.
The patch includes also the following change in the idx::print method for
print_latex context: `a.b' becomes `a_{b}' if b is covariant, `a^{b}',
otherwise (you can ignore it if you don't like it).

This patch is against GiNaC-1.0.1. I can make it also against the
latest GiNaC in CVS. Let me know if needed.

Thanks,
	Pearu
-------------- next part --------------
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/add.cpp GiNaC-1.0.1-print_python/ginac/add.cpp
--- GiNaC/ginac/add.cpp	Thu Nov 22 19:15:03 2001
+++ GiNaC-1.0.1-print_python/ginac/add.cpp	Fri Nov 23 16:28:09 2001
@@ -155,7 +155,16 @@
 	
 		if (precedence() <= level)
 			c.s << ")";
-
+	} else if (is_a<print_python_repr>(c)) {
+		c.s << class_name() << '(';
+		unsigned end = nops();
+		if (end)
+		  op(0).print(c);
+		for (unsigned i=1; i<end; ++i) {
+		  c.s << ',';
+		  op(i).print(c);
+		}
+		c.s << ')';
 	} else {
 
 		if (precedence() <= level) {
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/constant.cpp GiNaC-1.0.1-print_python/ginac/constant.cpp
--- GiNaC/ginac/constant.cpp	Thu Nov 22 19:15:04 2001
+++ GiNaC-1.0.1-print_python/ginac/constant.cpp	Fri Nov 23 20:58:47 2001
@@ -136,7 +136,12 @@
 		    << std::endl;
 	} else if (is_a<print_latex>(c))
 		c.s << TeX_name;
-	else
+	else if (is_a<print_python_repr>(c)) {
+	  c.s << class_name() << "('" << name << "'";
+		if (TeX_name != "\\mbox{" + name + "}")
+		  c.s << ",TeX_name='" << TeX_name << "'";
+		c.s << ')';
+	} else
 		c.s << name;
 }
 
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/container.pl GiNaC-1.0.1-print_python/ginac/container.pl
--- GiNaC/ginac/container.pl	Fri Oct 26 17:08:24 2001
+++ GiNaC-1.0.1-print_python/ginac/container.pl	Fri Nov 23 17:41:39 2001
@@ -430,7 +430,11 @@
 			++i;
 		}
 		c.s << std::string(level + delta_indent,' ') << "=====" << std::endl;
-
+	} else if (is_a<print_python>(c)) {
+		printseq(c, '[', ',', ']', precedence(), precedence()+1);
+	} else if (is_a<print_python_repr>(c)) {
+		c.s << class_name ();
+		printseq(c, '(', ',', ')', precedence(), precedence()+1);
 	} else {
 		// always print brackets around seq, ignore upper_precedence
 		printseq(c, '${open_bracket}', ',', '${close_bracket}', precedence(), precedence()+1);
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/exprseq.cpp GiNaC-1.0.1-print_python/ginac/exprseq.cpp
--- GiNaC/ginac/exprseq.cpp	Tue Nov 20 11:00:11 2001
+++ GiNaC-1.0.1-print_python/ginac/exprseq.cpp	Fri Nov 23 18:11:55 2001
@@ -345,7 +345,11 @@
 			++i;
 		}
 		c.s << std::string(level + delta_indent,' ') << "=====" << std::endl;
-
+	} else if (is_a<print_python>(c)) {
+		printseq(c, '[', ',', ']', precedence(), precedence()+1);
+	} else if (is_a<print_python_repr>(c)) {
+		c.s << class_name ();
+		printseq(c, '(', ',', ')', precedence(), precedence()+1);
 	} else {
 		// always print brackets around seq, ignore upper_precedence
 		printseq(c, '(', ',', ')', precedence(), precedence()+1);
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/idx.cpp GiNaC-1.0.1-print_python/ginac/idx.cpp
--- GiNaC/ginac/idx.cpp	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/idx.cpp	Fri Nov 23 17:36:39 2001
@@ -156,7 +156,9 @@
 
 	} else {
 
-		if (!is_of_type(c, print_latex))
+		if (is_a<print_latex>(c))
+			c.s << "_{";
+		else
 			c.s << ".";
 		bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol));
 		if (need_parens)
@@ -164,6 +166,8 @@
 		value.print(c);
 		if (need_parens)
 			c.s << ")";
+		if (is_a<print_latex>(c))
+			c.s << "}";
 	}
 }
 
@@ -180,8 +184,13 @@
 		dim.print(c, level + delta_indent);
 
 	} else {
-
-		if (!is_of_type(c, print_latex)) {
+	  if (is_a<print_latex>(c)) {
+			if (covariant)
+				c.s << "_{";
+			else
+				c.s << "^{";
+	  }
+		else {
 			if (covariant)
 				c.s << ".";
 			else
@@ -193,6 +202,8 @@
 		value.print(c);
 		if (need_parens)
 			c.s << ")";
+		if (is_a<print_latex>(c))
+			c.s << "}";
 	}
 }
 
@@ -212,7 +223,12 @@
 	} else {
 
 		bool is_tex = is_of_type(c, print_latex);
-		if (!is_tex) {
+		if (is_tex) {
+			if (covariant)
+				c.s << "_{";
+			else
+				c.s << "^{";
+		} else {
 			if (covariant)
 				c.s << ".";
 			else
@@ -231,6 +247,8 @@
 		if (need_parens)
 			c.s << ")";
 		if (is_tex && dotted)
+			c.s << "}";
+		if (is_tex)
 			c.s << "}";
 	}
 }
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/lst.cpp GiNaC-1.0.1-print_python/ginac/lst.cpp
--- GiNaC/ginac/lst.cpp	Tue Nov 20 11:00:11 2001
+++ GiNaC-1.0.1-print_python/ginac/lst.cpp	Fri Nov 23 18:11:55 2001
@@ -345,7 +345,11 @@
 			++i;
 		}
 		c.s << std::string(level + delta_indent,' ') << "=====" << std::endl;
-
+	} else if (is_a<print_python>(c)) {
+		printseq(c, '[', ',', ']', precedence(), precedence()+1);
+	} else if (is_a<print_python_repr>(c)) {
+		c.s << class_name ();
+		printseq(c, '(', ',', ')', precedence(), precedence()+1);
 	} else {
 		// always print brackets around seq, ignore upper_precedence
 		printseq(c, '{', ',', '}', precedence(), precedence()+1);
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/matrix.cpp GiNaC-1.0.1-print_python/ginac/matrix.cpp
--- GiNaC/ginac/matrix.cpp	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/matrix.cpp	Fri Nov 23 17:44:47 2001
@@ -147,6 +147,9 @@
 
 	} else {
 
+		if (is_a<print_python_repr>(c))
+		  c.s << class_name() << '(';
+
 		c.s << "[";
 		for (unsigned y=0; y<row-1; ++y) {
 			c.s << "[";
@@ -164,6 +167,9 @@
 		}
 		m[row*col-1].print(c);
 		c.s << "]]";
+
+		if (is_a<print_python_repr>(c))
+		  c.s << ')';
 
 	}
 }
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/mul.cpp GiNaC-1.0.1-print_python/ginac/mul.cpp
--- GiNaC/ginac/mul.cpp	Thu Nov 22 19:15:04 2001
+++ GiNaC-1.0.1-print_python/ginac/mul.cpp	Fri Nov 23 16:28:32 2001
@@ -168,7 +168,16 @@
 
 		if (precedence() <= level)
 			c.s << ")";
-
+	} else if (is_a<print_python_repr>(c)) {
+		c.s << class_name() << '(';
+		unsigned end = nops();
+		if (end)
+		  op(0).print(c);
+		for (unsigned i=1; i<end; ++i) {
+		  c.s << ',';
+		  op(i).print(c);
+		}
+		c.s << ')';
 	} else {
 
 		if (precedence() <= level) {
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/ncmul.cpp GiNaC-1.0.1-print_python/ginac/ncmul.cpp
--- GiNaC/ginac/ncmul.cpp	Fri Oct 26 17:08:24 2001
+++ GiNaC-1.0.1-print_python/ginac/ncmul.cpp	Fri Nov 23 16:38:15 2001
@@ -111,9 +111,9 @@
 
 		inherited::print(c, level);
 
-	} else if (is_a<print_csrc>(c)) {
+	} else if (is_a<print_csrc>(c) || is_a<print_python_repr>(c)) {
 
-		c.s << "ncmul(";
+		c.s << class_name() << "(";
 		exvector::const_iterator it = seq.begin(), itend = seq.end()-1;
 		while (it != itend) {
 			it->print(c, precedence());
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/numeric.cpp GiNaC-1.0.1-print_python/ginac/numeric.cpp
--- GiNaC/ginac/numeric.cpp	Tue Nov  6 17:55:29 2001
+++ GiNaC-1.0.1-print_python/ginac/numeric.cpp	Fri Nov 23 17:46:43 2001
@@ -389,6 +389,8 @@
 		const std::string mul_sym   = is_a<print_latex>(c) ? " " : "*";
 		const cln::cl_R r = cln::realpart(cln::the<cln::cl_N>(value));
 		const cln::cl_R i = cln::imagpart(cln::the<cln::cl_N>(value));
+		if (is_a<print_python_repr>(c))
+		  c.s << class_name() << "('";  
 		if (cln::zerop(i)) {
 			// case 1, real:  x  or  -x
 			if ((precedence() <= level) && (!this->is_nonneg_integer())) {
@@ -446,6 +448,8 @@
 					c.s << par_close;
 			}
 		}
+		if (is_a<print_python_repr>(c))
+		  c.s << "')";  
 	}
 }
 
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/power.cpp GiNaC-1.0.1-print_python/ginac/power.cpp
--- GiNaC/ginac/power.cpp	Fri Oct 26 17:08:24 2001
+++ GiNaC-1.0.1-print_python/ginac/power.cpp	Fri Nov 23 21:30:11 2001
@@ -159,6 +159,14 @@
 			c.s << ')';
 		}
 
+	} else if (is_a<print_python_repr>(c)) {
+
+		c.s << class_name() << '(';
+		basis.print(c);
+		c.s << ',';
+		exponent.print(c);
+		c.s << ')';
+
 	} else {
 
 		if (exponent.is_equal(_ex1_2)) {
@@ -179,7 +187,10 @@
 					c.s << "(";
 			}
 			basis.print(c, precedence());
-			c.s << '^';
+			if (is_a<print_python>(c))
+				c.s << "**";
+			else
+				c.s << '^';
 			if (is_a<print_latex>(c))
 				c.s << '{';
 			exponent.print(c, precedence());
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/print.cpp GiNaC-1.0.1-print_python/ginac/print.cpp
--- GiNaC/ginac/print.cpp	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/print.cpp	Fri Nov 23 14:01:57 2001
@@ -36,6 +36,16 @@
 print_latex::print_latex(std::ostream & os)
 	: print_context(os) {}
 
+print_python::print_python()
+	: print_context(std::cout) {}
+print_python::print_python(std::ostream & os)
+	: print_context(os) {}
+
+print_python_repr::print_python_repr()
+	: print_context(std::cout) {}
+print_python_repr::print_python_repr(std::ostream & os)
+	: print_context(os) {}
+
 print_tree::print_tree(unsigned d)
 	: print_context(std::cout), delta_indent(d) {}
 print_tree::print_tree(std::ostream & os, unsigned d)
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/print.h GiNaC-1.0.1-print_python/ginac/print.h
--- GiNaC/ginac/print.h	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/print.h	Sat Nov 24 10:35:57 2001
@@ -49,6 +49,22 @@
 	print_latex(std::ostream &);
 };
 
+/** Context for python pretty-print output. */
+class print_python : public print_context
+{
+public:
+	print_python();
+	print_python(std::ostream &);
+};
+
+/** Context for python-parsable output. */
+class print_python_repr : public print_context
+{
+public:
+	print_python_repr();
+	print_python_repr(std::ostream &);
+};
+
 /** Context for tree-like output for debugging. */
 class print_tree : public print_context
 {
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/pseries.cpp GiNaC-1.0.1-print_python/ginac/pseries.cpp
--- GiNaC/ginac/pseries.cpp	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/pseries.cpp	Tue Nov 27 11:40:46 2001
@@ -133,7 +133,23 @@
 		}
 		var.print(c, level + delta_indent);
 		point.print(c, level + delta_indent);
-
+	} else if (is_a<print_python_repr>(c)) {
+	  c.s << class_name() << "(relational(";
+	  var.print(c);
+	  c.s << ',';
+	  point.print(c);
+	  c.s << "),[";
+	  unsigned num = seq.size();
+	  for (unsigned i=0; i<num; ++i) {
+	    if (i)
+	      c.s << ',';
+	    c.s << '(';
+	    seq[i].rest.print(c);
+	    c.s << ',';
+	    seq[i].coeff.print(c);
+	    c.s << ')';
+	  }
+	  c.s << "])";
 	} else {
 
 		if (precedence() <= level)
@@ -174,7 +190,10 @@
 					} else
 						var.print(c);
 					if (i->coeff.compare(_ex1)) {
-						c.s << '^';
+						if (is_a<print_python>(c))
+						  c.s << "**";
+						else
+						  c.s << '^';
 						if (i->coeff.info(info_flags::negative)) {
 							c.s << par_open;
 							i->coeff.print(c);
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/relational.cpp GiNaC-1.0.1-print_python/ginac/relational.cpp
--- GiNaC/ginac/relational.cpp	Thu Nov 22 19:15:15 2001
+++ GiNaC-1.0.1-print_python/ginac/relational.cpp	Fri Nov 23 20:36:26 2001
@@ -95,9 +95,17 @@
 
 	} else {
 
-		if (precedence() <= level)
-			c.s << "(";
-		lh.print(c, precedence());
+	        if (is_a<print_python_repr>(c)) {
+		  c.s << class_name() << '('; 
+		  lh.print(c);
+		  c.s << ',';
+		  rh.print(c);
+		  c.s << ",'";
+		} else {
+		  if (precedence() <= level)
+		    c.s << "(";
+		  lh.print(c, precedence());
+		}
 		switch (o) {
 			case equal:
 				c.s << "==";
@@ -120,9 +128,13 @@
 			default:
 				c.s << "(INVALID RELATIONAL OPERATOR)";
 		}
-		rh.print(c, precedence());
-		if (precedence() <= level)
-			c.s << ")";
+		if (is_a<print_python_repr>(c))
+		  c.s << "')";
+		else {
+		  rh.print(c, precedence());
+		  if (precedence() <= level)
+		    c.s << ")";
+		}
 	}
 }
 
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/symbol.cpp GiNaC-1.0.1-print_python/ginac/symbol.cpp
--- GiNaC/ginac/symbol.cpp	Fri Oct 26 17:08:25 2001
+++ GiNaC-1.0.1-print_python/ginac/symbol.cpp	Fri Nov 23 18:00:58 2001
@@ -153,7 +153,12 @@
 
 	} else if (is_a<print_latex>(c))
 		c.s << TeX_name;
-	else
+	else if (is_a<print_python_repr>(c)) {
+		c.s << class_name() << "('" << name;
+		if (TeX_name != default_TeX_name())
+			c.s << "','" << TeX_name;
+		c.s << "')";
+	} else
 		c.s << name;
 }
 
diff -Nau -x CVS -x .libs -x .deps -x *.o -x *.lo -x *.la -x *~ -x Makefile GiNaC/ginac/wildcard.cpp GiNaC-1.0.1-print_python/ginac/wildcard.cpp
--- GiNaC/ginac/wildcard.cpp	Sat Oct 27 18:18:57 2001
+++ GiNaC-1.0.1-print_python/ginac/wildcard.cpp	Fri Nov 23 18:07:48 2001
@@ -95,6 +95,8 @@
 		c.s << std::string(level, ' ') << class_name() << " (" << label << ")"
 		    << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
 		    << std::endl;
+	} else if (is_a<print_python_repr>(c)) {
+	  c.s << class_name() << '(' << label << ')';
 	} else
 		c.s << "$" << label;
 }


More information about the GiNaC-devel mailing list