1 /** @file printcsrc.cpp
3 * The methods .printcsrc() are responsible for C-source output of
4 * objects. All related helper-functions go in here as well.
6 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "expairseq.h"
36 #include "relational.h"
40 /** Print expression as a C++ statement. The output looks like
41 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
42 * on how number literals are printed.
44 * @param os output stream
45 * @param type variable type (one of the csrc_types)
46 * @param var_name variable name to be printed */
47 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
49 debugmsg("ex print csrc", LOGLEVEL_PRINT);
52 case csrc_types::ctype_float:
55 case csrc_types::ctype_double:
58 case csrc_types::ctype_cl_N:
62 os << var_name << " = ";
63 bp->printcsrc(os, type, 0);
67 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
69 debugmsg("basic print csrc", LOGLEVEL_PRINT);
72 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
74 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
75 ios::fmtflags oldflags = os.flags();
76 os.setf(ios::scientific);
77 if (is_rational() && !is_integer()) {
78 if (compare(numZERO()) > 0) {
80 if (type == csrc_types::ctype_cl_N)
81 os << "cl_F(\"" << numer().evalf() << "\")";
83 os << numer().to_double();
86 if (type == csrc_types::ctype_cl_N)
87 os << "cl_F(\"" << -numer().evalf() << "\")";
89 os << -numer().to_double();
92 if (type == csrc_types::ctype_cl_N)
93 os << "cl_F(\"" << denom().evalf() << "\")";
95 os << denom().to_double();
98 if (type == csrc_types::ctype_cl_N)
99 os << "cl_F(\"" << evalf() << "\")";
106 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
108 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
112 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
114 debugmsg("constant print csrc",LOGLEVEL_PRINT);
118 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
120 // Optimal output of integer powers of symbols to aid compiler CSE
122 x.printcsrc(os, type, 0);
123 } else if (exp == 2) {
124 x.printcsrc(os, type, 0);
126 x.printcsrc(os, type, 0);
127 } else if (exp & 1) {
130 print_sym_pow(os, type, x, exp-1);
133 print_sym_pow(os, type, x, exp >> 1);
135 print_sym_pow(os, type, x, exp >> 1);
140 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
142 debugmsg("power print csrc", LOGLEVEL_PRINT);
144 // Integer powers of symbols are printed in a special, optimized way
145 if (exponent.info(info_flags::integer) &&
146 (is_ex_exactly_of_type(basis, symbol) ||
147 is_ex_exactly_of_type(basis, constant))) {
148 int exp = ex_to_numeric(exponent).to_int();
153 if (type == csrc_types::ctype_cl_N)
158 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
161 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
162 } else if (exponent.compare(numMINUSONE()) == 0) {
163 if (type == csrc_types::ctype_cl_N)
167 basis.bp->printcsrc(os, type, 0);
170 // Otherwise, use the pow() or expt() (CLN) functions
172 if (type == csrc_types::ctype_cl_N)
176 basis.bp->printcsrc(os, type, 0);
178 exponent.bp->printcsrc(os, type, 0);
183 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
185 debugmsg("add print csrc", LOGLEVEL_PRINT);
186 if (precedence <= upper_precedence)
189 // Print arguments, separated by "+"
190 epvector::const_iterator it = seq.begin();
191 epvector::const_iterator itend = seq.end();
192 while (it != itend) {
194 // If the coefficient is -1, it is replaced by a single minus sign
195 if (it->coeff.compare(numONE()) == 0) {
196 it->rest.bp->printcsrc(os, type, precedence);
197 } else if (it->coeff.compare(numMINUSONE()) == 0) {
199 it->rest.bp->printcsrc(os, type, precedence);
200 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
201 it->rest.bp->printcsrc(os, type, precedence);
203 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
204 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
206 it->rest.bp->printcsrc(os, type, precedence);
208 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
210 it->coeff.bp->printcsrc(os, type, precedence);
212 it->rest.bp->printcsrc(os, type, precedence);
215 // Separator is "+", except it the following expression would have a leading minus sign
217 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)))
221 if (!overall_coeff.is_equal(exZERO())) {
222 if (overall_coeff > 0) os << '+';
223 overall_coeff.bp->printcsrc(os,type,precedence);
226 if (precedence <= upper_precedence)
230 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
232 debugmsg("mul print csrc", LOGLEVEL_PRINT);
233 if (precedence <= upper_precedence)
236 if (!overall_coeff.is_equal(exONE())) {
237 overall_coeff.bp->printcsrc(os,type,precedence);
241 // Print arguments, separated by "*" or "/"
242 epvector::const_iterator it = seq.begin();
243 epvector::const_iterator itend = seq.end();
244 while (it != itend) {
246 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
247 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
248 if (type == csrc_types::ctype_cl_N)
254 // If the exponent is 1 or -1, it is left out
255 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
256 it->rest.bp->printcsrc(os, type, precedence);
258 // outer parens around ex needed for broken gcc-2.95 parser:
259 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
261 // Separator is "/" for negative integer powers, "*" otherwise
264 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
270 if (precedence <= upper_precedence)
274 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
276 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
277 exvector::const_iterator it;
278 exvector::const_iterator itend = seq.end()-1;
280 for (it=seq.begin(); it!=itend; ++it) {
281 (*it).bp->printcsrc(os,precedence);
284 (*it).bp->printcsrc(os,precedence);
288 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
290 debugmsg("relational print csrc", LOGLEVEL_PRINT);
291 if (precedence<=upper_precedence)
294 // Print left-hand expression
295 lh.bp->printcsrc(os, type, precedence);
297 // Print relational operator
314 case greater_or_equal:
318 os << "(INVALID RELATIONAL OPERATOR)";
322 // Print right-hand operator
323 rh.bp->printcsrc(os, type, precedence);
325 if (precedence <= upper_precedence)