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. */
7 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "expairseq.h"
37 #include "relational.h"
42 #ifndef NO_GINAC_NAMESPACE
44 #endif // ndef NO_GINAC_NAMESPACE
46 /** Print expression as a C++ statement. The output looks like
47 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
48 * on how number literals are printed.
50 * @param os output stream
51 * @param type variable type (one of the csrc_types)
52 * @param var_name variable name to be printed */
53 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
55 debugmsg("ex print csrc", LOGLEVEL_PRINT);
58 case csrc_types::ctype_float:
61 case csrc_types::ctype_double:
64 case csrc_types::ctype_cl_N:
68 os << var_name << " = ";
69 bp->printcsrc(os, type, 0);
73 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
75 debugmsg("basic print csrc", LOGLEVEL_PRINT);
78 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
80 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
81 ios::fmtflags oldflags = os.flags();
82 os.setf(ios::scientific);
83 if (is_rational() && !is_integer()) {
84 if (compare(numZERO()) > 0) {
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(\"" << -numer().evalf() << "\")";
95 os << -numer().to_double();
98 if (type == csrc_types::ctype_cl_N)
99 os << "cl_F(\"" << denom().evalf() << "\")";
101 os << denom().to_double();
104 if (type == csrc_types::ctype_cl_N)
105 os << "cl_F(\"" << evalf() << "\")";
112 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
114 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
118 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
120 debugmsg("constant print csrc",LOGLEVEL_PRINT);
124 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
126 // Optimal output of integer powers of symbols to aid compiler CSE
128 x.printcsrc(os, type, 0);
129 } else if (exp == 2) {
130 x.printcsrc(os, type, 0);
132 x.printcsrc(os, type, 0);
133 } else if (exp & 1) {
136 print_sym_pow(os, type, x, exp-1);
139 print_sym_pow(os, type, x, exp >> 1);
141 print_sym_pow(os, type, x, exp >> 1);
146 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
148 debugmsg("power print csrc", LOGLEVEL_PRINT);
150 // Integer powers of symbols are printed in a special, optimized way
151 if (exponent.info(info_flags::integer) &&
152 (is_ex_exactly_of_type(basis, symbol) ||
153 is_ex_exactly_of_type(basis, constant))) {
154 int exp = ex_to_numeric(exponent).to_int();
159 if (type == csrc_types::ctype_cl_N)
164 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
167 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
168 } else if (exponent.compare(numMINUSONE()) == 0) {
169 if (type == csrc_types::ctype_cl_N)
173 basis.bp->printcsrc(os, type, 0);
176 // Otherwise, use the pow() or expt() (CLN) functions
178 if (type == csrc_types::ctype_cl_N)
182 basis.bp->printcsrc(os, type, 0);
184 exponent.bp->printcsrc(os, type, 0);
189 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
191 debugmsg("add print csrc", LOGLEVEL_PRINT);
192 if (precedence <= upper_precedence)
195 // Print arguments, separated by "+"
196 epvector::const_iterator it = seq.begin();
197 epvector::const_iterator itend = seq.end();
198 while (it != itend) {
200 // If the coefficient is -1, it is replaced by a single minus sign
201 if (it->coeff.compare(numONE()) == 0) {
202 it->rest.bp->printcsrc(os, type, precedence);
203 } else if (it->coeff.compare(numMINUSONE()) == 0) {
205 it->rest.bp->printcsrc(os, type, precedence);
206 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
207 it->rest.bp->printcsrc(os, type, precedence);
209 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
210 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
212 it->rest.bp->printcsrc(os, type, precedence);
214 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
216 it->coeff.bp->printcsrc(os, type, precedence);
218 it->rest.bp->printcsrc(os, type, precedence);
221 // Separator is "+", except it the following expression would have a leading minus sign
223 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)))
227 if (!overall_coeff.is_equal(exZERO())) {
228 if (overall_coeff > 0) os << '+';
229 overall_coeff.bp->printcsrc(os,type,precedence);
232 if (precedence <= upper_precedence)
236 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
238 debugmsg("mul print csrc", LOGLEVEL_PRINT);
239 if (precedence <= upper_precedence)
242 if (!overall_coeff.is_equal(exONE())) {
243 overall_coeff.bp->printcsrc(os,type,precedence);
247 // Print arguments, separated by "*" or "/"
248 epvector::const_iterator it = seq.begin();
249 epvector::const_iterator itend = seq.end();
250 while (it != itend) {
252 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
253 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
254 if (type == csrc_types::ctype_cl_N)
260 // If the exponent is 1 or -1, it is left out
261 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
262 it->rest.bp->printcsrc(os, type, precedence);
264 // outer parens around ex needed for broken gcc-2.95 parser:
265 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
267 // Separator is "/" for negative integer powers, "*" otherwise
270 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
276 if (precedence <= upper_precedence)
280 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
282 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
283 exvector::const_iterator it;
284 exvector::const_iterator itend = seq.end()-1;
286 for (it=seq.begin(); it!=itend; ++it) {
287 (*it).bp->printcsrc(os,precedence);
290 (*it).bp->printcsrc(os,precedence);
294 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
296 debugmsg("relational print csrc", LOGLEVEL_PRINT);
297 if (precedence<=upper_precedence)
300 // Print left-hand expression
301 lh.bp->printcsrc(os, type, precedence);
303 // Print relational operator
320 case greater_or_equal:
324 os << "(INVALID RELATIONAL OPERATOR)";
328 // Print right-hand operator
329 rh.bp->printcsrc(os, type, precedence);
331 if (precedence <= upper_precedence)
335 #ifndef NO_GINAC_NAMESPACE
337 #endif // ndef NO_GINAC_NAMESPACE