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
27 /** Print expression as a C++ statement. The output looks like
28 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
29 * on how number literals are printed.
31 * @param os output stream
32 * @param type variable type (one of the csrc_types)
33 * @param var_name variable name to be printed */
34 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
36 debugmsg("ex print csrc", LOGLEVEL_PRINT);
39 case csrc_types::ctype_float:
42 case csrc_types::ctype_double:
45 case csrc_types::ctype_cl_N:
49 os << var_name << " = ";
50 bp->printcsrc(os, type, 0);
54 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
56 debugmsg("basic print csrc", LOGLEVEL_PRINT);
59 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
61 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
62 ios::fmtflags oldflags = os.flags();
63 os.setf(ios::scientific);
64 if (is_rational() && !is_integer()) {
65 if (compare(numZERO()) > 0) {
67 if (type == csrc_types::ctype_cl_N)
68 os << "cl_F(\"" << numer().evalf() << "\")";
70 os << numer().to_double();
73 if (type == csrc_types::ctype_cl_N)
74 os << "cl_F(\"" << -numer().evalf() << "\")";
76 os << -numer().to_double();
79 if (type == csrc_types::ctype_cl_N)
80 os << "cl_F(\"" << denom().evalf() << "\")";
82 os << denom().to_double();
85 if (type == csrc_types::ctype_cl_N)
86 os << "cl_F(\"" << evalf() << "\")";
93 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
95 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
99 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
101 debugmsg("constant print csrc",LOGLEVEL_PRINT);
105 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
107 // Optimal output of integer powers of symbols to aid compiler CSE
109 x.printcsrc(os, type, 0);
110 } else if (exp == 2) {
111 x.printcsrc(os, type, 0);
113 x.printcsrc(os, type, 0);
114 } else if (exp & 1) {
117 print_sym_pow(os, type, x, exp-1);
120 print_sym_pow(os, type, x, exp >> 1);
122 print_sym_pow(os, type, x, exp >> 1);
127 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
129 debugmsg("power print csrc", LOGLEVEL_PRINT);
131 // Integer powers of symbols are printed in a special, optimized way
132 if (exponent.info(info_flags::integer) &&
133 (is_ex_exactly_of_type(basis, symbol) ||
134 is_ex_exactly_of_type(basis, constant))) {
135 int exp = ex_to_numeric(exponent).to_int();
140 if (type == csrc_types::ctype_cl_N)
145 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
148 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
149 } else if (exponent.compare(numMINUSONE()) == 0) {
150 if (type == csrc_types::ctype_cl_N)
154 basis.bp->printcsrc(os, type, 0);
157 // Otherwise, use the pow() or expt() (CLN) functions
159 if (type == csrc_types::ctype_cl_N)
163 basis.bp->printcsrc(os, type, 0);
165 exponent.bp->printcsrc(os, type, 0);
170 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
172 debugmsg("add print csrc", LOGLEVEL_PRINT);
173 if (precedence <= upper_precedence)
176 // Print arguments, separated by "+"
177 epvector::const_iterator it = seq.begin();
178 epvector::const_iterator itend = seq.end();
179 while (it != itend) {
181 // If the coefficient is -1, it is replaced by a single minus sign
182 if (it->coeff.compare(numONE()) == 0) {
183 it->rest.bp->printcsrc(os, type, precedence);
184 } else if (it->coeff.compare(numMINUSONE()) == 0) {
186 it->rest.bp->printcsrc(os, type, precedence);
187 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
188 it->rest.bp->printcsrc(os, type, precedence);
190 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
191 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
193 it->rest.bp->printcsrc(os, type, precedence);
195 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
197 it->coeff.bp->printcsrc(os, type, precedence);
199 it->rest.bp->printcsrc(os, type, precedence);
202 // Separator is "+", except it the following expression would have a leading minus sign
204 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)))
208 if (!overall_coeff.is_equal(exZERO())) {
209 if (overall_coeff > 0) os << '+';
210 overall_coeff.bp->printcsrc(os,type,precedence);
213 if (precedence <= upper_precedence)
217 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
219 debugmsg("mul print csrc", LOGLEVEL_PRINT);
220 if (precedence <= upper_precedence)
223 if (!overall_coeff.is_equal(exONE())) {
224 overall_coeff.bp->printcsrc(os,type,precedence);
228 // Print arguments, separated by "*" or "/"
229 epvector::const_iterator it = seq.begin();
230 epvector::const_iterator itend = seq.end();
231 while (it != itend) {
233 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
234 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
235 if (type == csrc_types::ctype_cl_N)
241 // If the exponent is 1 or -1, it is left out
242 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
243 it->rest.bp->printcsrc(os, type, precedence);
245 // outer parens around ex needed for broken gcc-2.95 parser:
246 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
248 // Separator is "/" for negative integer powers, "*" otherwise
251 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
257 if (precedence <= upper_precedence)
261 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
263 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
264 exvector::const_iterator it;
265 exvector::const_iterator itend = seq.end()-1;
267 for (it=seq.begin(); it!=itend; ++it) {
268 (*it).bp->printcsrc(os,precedence);
271 (*it).bp->printcsrc(os,precedence);
275 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
277 debugmsg("relational print csrc", LOGLEVEL_PRINT);
278 if (precedence<=upper_precedence)
281 // Print left-hand expression
282 lh.bp->printcsrc(os, type, precedence);
284 // Print relational operator
301 case greater_or_equal:
305 os << "(INVALID RELATIONAL OPERATOR)";
309 // Print right-hand operator
310 rh.bp->printcsrc(os, type, precedence);
312 if (precedence <= upper_precedence)