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"
41 /** Print expression as a C++ statement. The output looks like
42 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
43 * on how number literals are printed.
45 * @param os output stream
46 * @param type variable type (one of the csrc_types)
47 * @param var_name variable name to be printed */
48 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
50 debugmsg("ex print csrc", LOGLEVEL_PRINT);
53 case csrc_types::ctype_float:
56 case csrc_types::ctype_double:
59 case csrc_types::ctype_cl_N:
63 os << var_name << " = ";
64 bp->printcsrc(os, type, 0);
68 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
70 debugmsg("basic print csrc", LOGLEVEL_PRINT);
73 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
75 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
76 ios::fmtflags oldflags = os.flags();
77 os.setf(ios::scientific);
78 if (is_rational() && !is_integer()) {
79 if (compare(numZERO()) > 0) {
81 if (type == csrc_types::ctype_cl_N)
82 os << "cl_F(\"" << numer().evalf() << "\")";
84 os << numer().to_double();
87 if (type == csrc_types::ctype_cl_N)
88 os << "cl_F(\"" << -numer().evalf() << "\")";
90 os << -numer().to_double();
93 if (type == csrc_types::ctype_cl_N)
94 os << "cl_F(\"" << denom().evalf() << "\")";
96 os << denom().to_double();
99 if (type == csrc_types::ctype_cl_N)
100 os << "cl_F(\"" << evalf() << "\")";
107 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
109 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
113 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
115 debugmsg("constant print csrc",LOGLEVEL_PRINT);
119 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
121 // Optimal output of integer powers of symbols to aid compiler CSE
123 x.printcsrc(os, type, 0);
124 } else if (exp == 2) {
125 x.printcsrc(os, type, 0);
127 x.printcsrc(os, type, 0);
128 } else if (exp & 1) {
131 print_sym_pow(os, type, x, exp-1);
134 print_sym_pow(os, type, x, exp >> 1);
136 print_sym_pow(os, type, x, exp >> 1);
141 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
143 debugmsg("power print csrc", LOGLEVEL_PRINT);
145 // Integer powers of symbols are printed in a special, optimized way
146 if (exponent.info(info_flags::integer) &&
147 (is_ex_exactly_of_type(basis, symbol) ||
148 is_ex_exactly_of_type(basis, constant))) {
149 int exp = ex_to_numeric(exponent).to_int();
154 if (type == csrc_types::ctype_cl_N)
159 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
162 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
163 } else if (exponent.compare(numMINUSONE()) == 0) {
164 if (type == csrc_types::ctype_cl_N)
168 basis.bp->printcsrc(os, type, 0);
171 // Otherwise, use the pow() or expt() (CLN) functions
173 if (type == csrc_types::ctype_cl_N)
177 basis.bp->printcsrc(os, type, 0);
179 exponent.bp->printcsrc(os, type, 0);
184 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
186 debugmsg("add print csrc", LOGLEVEL_PRINT);
187 if (precedence <= upper_precedence)
190 // Print arguments, separated by "+"
191 epvector::const_iterator it = seq.begin();
192 epvector::const_iterator itend = seq.end();
193 while (it != itend) {
195 // If the coefficient is -1, it is replaced by a single minus sign
196 if (it->coeff.compare(numONE()) == 0) {
197 it->rest.bp->printcsrc(os, type, precedence);
198 } else if (it->coeff.compare(numMINUSONE()) == 0) {
200 it->rest.bp->printcsrc(os, type, precedence);
201 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
202 it->rest.bp->printcsrc(os, type, precedence);
204 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
205 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
207 it->rest.bp->printcsrc(os, type, precedence);
209 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
211 it->coeff.bp->printcsrc(os, type, precedence);
213 it->rest.bp->printcsrc(os, type, precedence);
216 // Separator is "+", except it the following expression would have a leading minus sign
218 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)))
222 if (!overall_coeff.is_equal(exZERO())) {
223 if (overall_coeff > 0) os << '+';
224 overall_coeff.bp->printcsrc(os,type,precedence);
227 if (precedence <= upper_precedence)
231 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
233 debugmsg("mul print csrc", LOGLEVEL_PRINT);
234 if (precedence <= upper_precedence)
237 if (!overall_coeff.is_equal(exONE())) {
238 overall_coeff.bp->printcsrc(os,type,precedence);
242 // Print arguments, separated by "*" or "/"
243 epvector::const_iterator it = seq.begin();
244 epvector::const_iterator itend = seq.end();
245 while (it != itend) {
247 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
248 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
249 if (type == csrc_types::ctype_cl_N)
255 // If the exponent is 1 or -1, it is left out
256 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
257 it->rest.bp->printcsrc(os, type, precedence);
259 // outer parens around ex needed for broken gcc-2.95 parser:
260 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
262 // Separator is "/" for negative integer powers, "*" otherwise
265 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
271 if (precedence <= upper_precedence)
275 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
277 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
278 exvector::const_iterator it;
279 exvector::const_iterator itend = seq.end()-1;
281 for (it=seq.begin(); it!=itend; ++it) {
282 (*it).bp->printcsrc(os,precedence);
285 (*it).bp->printcsrc(os,precedence);
289 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
291 debugmsg("relational print csrc", LOGLEVEL_PRINT);
292 if (precedence<=upper_precedence)
295 // Print left-hand expression
296 lh.bp->printcsrc(os, type, precedence);
298 // Print relational operator
315 case greater_or_equal:
319 os << "(INVALID RELATIONAL OPERATOR)";
323 // Print right-hand operator
324 rh.bp->printcsrc(os, type, precedence);
326 if (precedence <= upper_precedence)