--- /dev/null
+/** @file printcsrc.cpp
+ *
+ * The methods .printcsrc() are responsible for C-source output of
+ * objects. All related helper-functions go in here as well. */
+
+#include <iostream>
+
+#include "ginac.h"
+
+/** Print expression as a C++ statement. The output looks like
+ * "<type> <var_name> = <expression>;". The "type" parameter has an effect
+ * on how number literals are printed.
+ *
+ * @param os output stream
+ * @param type variable type (one of the csrc_types)
+ * @param var_name variable name to be printed */
+void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
+{
+ debugmsg("ex print csrc", LOGLEVEL_PRINT);
+ ASSERT(bp!=0);
+ switch (type) {
+ case csrc_types::ctype_float:
+ os << "float ";
+ break;
+ case csrc_types::ctype_double:
+ os << "double ";
+ break;
+ case csrc_types::ctype_cl_N:
+ os << "cl_N ";
+ break;
+ }
+ os << var_name << " = ";
+ bp->printcsrc(os, type, 0);
+ os << ";\n";
+}
+
+void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("basic print csrc", LOGLEVEL_PRINT);
+}
+
+void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("numeric print csrc", LOGLEVEL_PRINT);
+ ios::fmtflags oldflags = os.flags();
+ os.setf(ios::scientific);
+ if (is_rational() && !is_integer()) {
+ if (compare(numZERO()) > 0) {
+ os << "(";
+ if (type == csrc_types::ctype_cl_N)
+ os << "cl_F(\"" << numer().evalf() << "\")";
+ else
+ os << numer().to_double();
+ } else {
+ os << "-(";
+ if (type == csrc_types::ctype_cl_N)
+ os << "cl_F(\"" << -numer().evalf() << "\")";
+ else
+ os << -numer().to_double();
+ }
+ os << "/";
+ if (type == csrc_types::ctype_cl_N)
+ os << "cl_F(\"" << denom().evalf() << "\")";
+ else
+ os << denom().to_double();
+ os << ")";
+ } else {
+ if (type == csrc_types::ctype_cl_N)
+ os << "cl_F(\"" << evalf() << "\")";
+ else
+ os << to_double();
+ }
+ os.flags(oldflags);
+}
+
+void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("symbol print csrc", LOGLEVEL_PRINT);
+ os << name;
+}
+
+void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("constant print csrc",LOGLEVEL_PRINT);
+ os << name;
+}
+
+static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
+{
+ // Optimal output of integer powers of symbols to aid compiler CSE
+ if (exp == 1) {
+ x.printcsrc(os, type, 0);
+ } else if (exp == 2) {
+ x.printcsrc(os, type, 0);
+ os << "*";
+ x.printcsrc(os, type, 0);
+ } else if (exp & 1) {
+ x.printcsrc(os, 0);
+ os << "*";
+ print_sym_pow(os, type, x, exp-1);
+ } else {
+ os << "(";
+ print_sym_pow(os, type, x, exp >> 1);
+ os << ")*(";
+ print_sym_pow(os, type, x, exp >> 1);
+ os << ")";
+ }
+}
+
+void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("power print csrc", LOGLEVEL_PRINT);
+
+ // Integer powers of symbols are printed in a special, optimized way
+ if (exponent.info(info_flags::integer) &&
+ (is_ex_exactly_of_type(basis, symbol) ||
+ is_ex_exactly_of_type(basis, constant))) {
+ int exp = ex_to_numeric(exponent).to_int();
+ if (exp > 0)
+ os << "(";
+ else {
+ exp = -exp;
+ if (type == csrc_types::ctype_cl_N)
+ os << "recip(";
+ else
+ os << "1.0/(";
+ }
+ print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
+ os << ")";
+
+ // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
+ } else if (exponent.compare(numMINUSONE()) == 0) {
+ if (type == csrc_types::ctype_cl_N)
+ os << "recip(";
+ else
+ os << "1.0/(";
+ basis.bp->printcsrc(os, type, 0);
+ os << ")";
+
+ // Otherwise, use the pow() or expt() (CLN) functions
+ } else {
+ if (type == csrc_types::ctype_cl_N)
+ os << "expt(";
+ else
+ os << "pow(";
+ basis.bp->printcsrc(os, type, 0);
+ os << ",";
+ exponent.bp->printcsrc(os, type, 0);
+ os << ")";
+ }
+}
+
+void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("add print csrc", LOGLEVEL_PRINT);
+ if (precedence <= upper_precedence)
+ os << "(";
+
+ // Print arguments, separated by "+"
+ epvector::const_iterator it = seq.begin();
+ epvector::const_iterator itend = seq.end();
+ while (it != itend) {
+
+ // If the coefficient is -1, it is replaced by a single minus sign
+ if (it->coeff.compare(numONE()) == 0) {
+ it->rest.bp->printcsrc(os, type, precedence);
+ } else if (it->coeff.compare(numMINUSONE()) == 0) {
+ os << "-";
+ it->rest.bp->printcsrc(os, type, precedence);
+ } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
+ it->rest.bp->printcsrc(os, type, precedence);
+ os << "/";
+ ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
+ } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
+ os << "-";
+ it->rest.bp->printcsrc(os, type, precedence);
+ os << "/";
+ ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
+ } else {
+ it->coeff.bp->printcsrc(os, type, precedence);
+ os << "*";
+ it->rest.bp->printcsrc(os, type, precedence);
+ }
+
+ // Separator is "+", except it the following expression would have a leading minus sign
+ it++;
+ if (it != itend && !(it->coeff.compare(numZERO()) < 0 || (it->coeff.compare(numONE()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(numZERO()) < 0)))
+ os << "+";
+ }
+
+ if (!overall_coeff.is_equal(exZERO())) {
+ if (overall_coeff > 0) os << '+';
+ overall_coeff.bp->printcsrc(os,type,precedence);
+ }
+
+ if (precedence <= upper_precedence)
+ os << ")";
+}
+
+void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("mul print csrc", LOGLEVEL_PRINT);
+ if (precedence <= upper_precedence)
+ os << "(";
+
+ if (!overall_coeff.is_equal(exONE())) {
+ overall_coeff.bp->printcsrc(os,type,precedence);
+ os << "*";
+ }
+
+ // Print arguments, separated by "*" or "/"
+ epvector::const_iterator it = seq.begin();
+ epvector::const_iterator itend = seq.end();
+ while (it != itend) {
+
+ // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
+ if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
+ if (type == csrc_types::ctype_cl_N)
+ os << "recip(";
+ else
+ os << "1.0/";
+ }
+
+ // If the exponent is 1 or -1, it is left out
+ if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
+ it->rest.bp->printcsrc(os, type, precedence);
+ else
+ // outer parens around ex needed for broken gcc-2.95 parser:
+ (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
+
+ // Separator is "/" for negative integer powers, "*" otherwise
+ it++;
+ if (it != itend) {
+ if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
+ os << "/";
+ else
+ os << "*";
+ }
+ }
+ if (precedence <= upper_precedence)
+ os << ")";
+}
+
+void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
+{
+ debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
+ exvector::const_iterator it;
+ exvector::const_iterator itend = seq.end()-1;
+ os << "ncmul(";
+ for (it=seq.begin(); it!=itend; ++it) {
+ (*it).bp->printcsrc(os,precedence);
+ os << ",";
+ }
+ (*it).bp->printcsrc(os,precedence);
+ os << ")";
+}
+
+void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+ debugmsg("relational print csrc", LOGLEVEL_PRINT);
+ if (precedence<=upper_precedence)
+ os << "(";
+
+ // Print left-hand expression
+ lh.bp->printcsrc(os, type, precedence);
+
+ // Print relational operator
+ switch (o) {
+ case equal:
+ os << "==";
+ break;
+ case not_equal:
+ os << "!=";
+ break;
+ case less:
+ os << "<";
+ break;
+ case less_or_equal:
+ os << "<=";
+ break;
+ case greater:
+ os << ">";
+ break;
+ case greater_or_equal:
+ os << ">=";
+ break;
+ default:
+ os << "(INVALID RELATIONAL OPERATOR)";
+ break;
+ }
+
+ // Print right-hand operator
+ rh.bp->printcsrc(os, type, precedence);
+
+ if (precedence <= upper_precedence)
+ os << ")";
+}