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"
44 /** Print expression as a C++ statement. The output looks like
45 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
46 * on how number literals are printed.
48 * @param os output stream
49 * @param type variable type (one of the csrc_types)
50 * @param var_name variable name to be printed */
51 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
53 debugmsg("ex print csrc", LOGLEVEL_PRINT);
56 case csrc_types::ctype_float:
59 case csrc_types::ctype_double:
62 case csrc_types::ctype_cl_N:
66 os << var_name << " = ";
67 bp->printcsrc(os, type, 0);
71 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
73 debugmsg("basic print csrc", LOGLEVEL_PRINT);
76 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
78 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
79 ios::fmtflags oldflags = os.flags();
80 os.setf(ios::scientific);
81 if (is_rational() && !is_integer()) {
82 if (compare(numZERO()) > 0) {
84 if (type == csrc_types::ctype_cl_N)
85 os << "cl_F(\"" << numer().evalf() << "\")";
87 os << numer().to_double();
90 if (type == csrc_types::ctype_cl_N)
91 os << "cl_F(\"" << -numer().evalf() << "\")";
93 os << -numer().to_double();
96 if (type == csrc_types::ctype_cl_N)
97 os << "cl_F(\"" << denom().evalf() << "\")";
99 os << denom().to_double();
102 if (type == csrc_types::ctype_cl_N)
103 os << "cl_F(\"" << evalf() << "\")";
110 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
112 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
116 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
118 debugmsg("constant print csrc",LOGLEVEL_PRINT);
122 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
124 // Optimal output of integer powers of symbols to aid compiler CSE
126 x.printcsrc(os, type, 0);
127 } else if (exp == 2) {
128 x.printcsrc(os, type, 0);
130 x.printcsrc(os, type, 0);
131 } else if (exp & 1) {
134 print_sym_pow(os, type, x, exp-1);
137 print_sym_pow(os, type, x, exp >> 1);
139 print_sym_pow(os, type, x, exp >> 1);
144 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
146 debugmsg("power print csrc", LOGLEVEL_PRINT);
148 // Integer powers of symbols are printed in a special, optimized way
149 if (exponent.info(info_flags::integer) &&
150 (is_ex_exactly_of_type(basis, symbol) ||
151 is_ex_exactly_of_type(basis, constant))) {
152 int exp = ex_to_numeric(exponent).to_int();
157 if (type == csrc_types::ctype_cl_N)
162 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
165 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
166 } else if (exponent.compare(numMINUSONE()) == 0) {
167 if (type == csrc_types::ctype_cl_N)
171 basis.bp->printcsrc(os, type, 0);
174 // Otherwise, use the pow() or expt() (CLN) functions
176 if (type == csrc_types::ctype_cl_N)
180 basis.bp->printcsrc(os, type, 0);
182 exponent.bp->printcsrc(os, type, 0);
187 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
189 debugmsg("add print csrc", LOGLEVEL_PRINT);
190 if (precedence <= upper_precedence)
193 // Print arguments, separated by "+"
194 epvector::const_iterator it = seq.begin();
195 epvector::const_iterator itend = seq.end();
196 while (it != itend) {
198 // If the coefficient is -1, it is replaced by a single minus sign
199 if (it->coeff.compare(numONE()) == 0) {
200 it->rest.bp->printcsrc(os, type, precedence);
201 } else if (it->coeff.compare(numMINUSONE()) == 0) {
203 it->rest.bp->printcsrc(os, type, precedence);
204 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
205 it->rest.bp->printcsrc(os, type, precedence);
207 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
208 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
210 it->rest.bp->printcsrc(os, type, precedence);
212 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
214 it->coeff.bp->printcsrc(os, type, precedence);
216 it->rest.bp->printcsrc(os, type, precedence);
219 // Separator is "+", except it the following expression would have a leading minus sign
221 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)))
225 if (!overall_coeff.is_equal(exZERO())) {
226 if (overall_coeff > 0) os << '+';
227 overall_coeff.bp->printcsrc(os,type,precedence);
230 if (precedence <= upper_precedence)
234 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
236 debugmsg("mul print csrc", LOGLEVEL_PRINT);
237 if (precedence <= upper_precedence)
240 if (!overall_coeff.is_equal(exONE())) {
241 overall_coeff.bp->printcsrc(os,type,precedence);
245 // Print arguments, separated by "*" or "/"
246 epvector::const_iterator it = seq.begin();
247 epvector::const_iterator itend = seq.end();
248 while (it != itend) {
250 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
251 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
252 if (type == csrc_types::ctype_cl_N)
258 // If the exponent is 1 or -1, it is left out
259 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
260 it->rest.bp->printcsrc(os, type, precedence);
262 // outer parens around ex needed for broken gcc-2.95 parser:
263 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
265 // Separator is "/" for negative integer powers, "*" otherwise
268 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
274 if (precedence <= upper_precedence)
278 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
280 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
281 exvector::const_iterator it;
282 exvector::const_iterator itend = seq.end()-1;
284 for (it=seq.begin(); it!=itend; ++it) {
285 (*it).bp->printcsrc(os,precedence);
288 (*it).bp->printcsrc(os,precedence);
292 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
294 debugmsg("relational print csrc", LOGLEVEL_PRINT);
295 if (precedence<=upper_precedence)
298 // Print left-hand expression
299 lh.bp->printcsrc(os, type, precedence);
301 // Print relational operator
318 case greater_or_equal:
322 os << "(INVALID RELATIONAL OPERATOR)";
326 // Print right-hand operator
327 rh.bp->printcsrc(os, type, precedence);
329 if (precedence <= upper_precedence)