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. */
10 /** Print expression as a C++ statement. The output looks like
11 * "<type> <var_name> = <expression>;". The "type" parameter has an effect
12 * on how number literals are printed.
14 * @param os output stream
15 * @param type variable type (one of the csrc_types)
16 * @param var_name variable name to be printed */
17 void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
19 debugmsg("ex print csrc", LOGLEVEL_PRINT);
22 case csrc_types::ctype_float:
25 case csrc_types::ctype_double:
28 case csrc_types::ctype_cl_N:
32 os << var_name << " = ";
33 bp->printcsrc(os, type, 0);
37 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
39 debugmsg("basic print csrc", LOGLEVEL_PRINT);
42 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
44 debugmsg("numeric print csrc", LOGLEVEL_PRINT);
45 ios::fmtflags oldflags = os.flags();
46 os.setf(ios::scientific);
47 if (is_rational() && !is_integer()) {
48 if (compare(numZERO()) > 0) {
50 if (type == csrc_types::ctype_cl_N)
51 os << "cl_F(\"" << numer().evalf() << "\")";
53 os << numer().to_double();
56 if (type == csrc_types::ctype_cl_N)
57 os << "cl_F(\"" << -numer().evalf() << "\")";
59 os << -numer().to_double();
62 if (type == csrc_types::ctype_cl_N)
63 os << "cl_F(\"" << denom().evalf() << "\")";
65 os << denom().to_double();
68 if (type == csrc_types::ctype_cl_N)
69 os << "cl_F(\"" << evalf() << "\")";
76 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
78 debugmsg("symbol print csrc", LOGLEVEL_PRINT);
82 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
84 debugmsg("constant print csrc",LOGLEVEL_PRINT);
88 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
90 // Optimal output of integer powers of symbols to aid compiler CSE
92 x.printcsrc(os, type, 0);
93 } else if (exp == 2) {
94 x.printcsrc(os, type, 0);
96 x.printcsrc(os, type, 0);
100 print_sym_pow(os, type, x, exp-1);
103 print_sym_pow(os, type, x, exp >> 1);
105 print_sym_pow(os, type, x, exp >> 1);
110 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
112 debugmsg("power print csrc", LOGLEVEL_PRINT);
114 // Integer powers of symbols are printed in a special, optimized way
115 if (exponent.info(info_flags::integer) &&
116 (is_ex_exactly_of_type(basis, symbol) ||
117 is_ex_exactly_of_type(basis, constant))) {
118 int exp = ex_to_numeric(exponent).to_int();
123 if (type == csrc_types::ctype_cl_N)
128 print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
131 // <expr>^-1 is printed as "1.0/<expr>" or with the recip() function of CLN
132 } else if (exponent.compare(numMINUSONE()) == 0) {
133 if (type == csrc_types::ctype_cl_N)
137 basis.bp->printcsrc(os, type, 0);
140 // Otherwise, use the pow() or expt() (CLN) functions
142 if (type == csrc_types::ctype_cl_N)
146 basis.bp->printcsrc(os, type, 0);
148 exponent.bp->printcsrc(os, type, 0);
153 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
155 debugmsg("add print csrc", LOGLEVEL_PRINT);
156 if (precedence <= upper_precedence)
159 // Print arguments, separated by "+"
160 epvector::const_iterator it = seq.begin();
161 epvector::const_iterator itend = seq.end();
162 while (it != itend) {
164 // If the coefficient is -1, it is replaced by a single minus sign
165 if (it->coeff.compare(numONE()) == 0) {
166 it->rest.bp->printcsrc(os, type, precedence);
167 } else if (it->coeff.compare(numMINUSONE()) == 0) {
169 it->rest.bp->printcsrc(os, type, precedence);
170 } else if (ex_to_numeric(it->coeff).numer().compare(numONE()) == 0) {
171 it->rest.bp->printcsrc(os, type, precedence);
173 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
174 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
176 it->rest.bp->printcsrc(os, type, precedence);
178 ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
180 it->coeff.bp->printcsrc(os, type, precedence);
182 it->rest.bp->printcsrc(os, type, precedence);
185 // Separator is "+", except it the following expression would have a leading minus sign
187 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)))
191 if (!overall_coeff.is_equal(exZERO())) {
192 if (overall_coeff > 0) os << '+';
193 overall_coeff.bp->printcsrc(os,type,precedence);
196 if (precedence <= upper_precedence)
200 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
202 debugmsg("mul print csrc", LOGLEVEL_PRINT);
203 if (precedence <= upper_precedence)
206 if (!overall_coeff.is_equal(exONE())) {
207 overall_coeff.bp->printcsrc(os,type,precedence);
211 // Print arguments, separated by "*" or "/"
212 epvector::const_iterator it = seq.begin();
213 epvector::const_iterator itend = seq.end();
214 while (it != itend) {
216 // If the first argument is a negative integer power, it gets printed as "1.0/<expr>"
217 if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0) {
218 if (type == csrc_types::ctype_cl_N)
224 // If the exponent is 1 or -1, it is left out
225 if (it->coeff.compare(exONE()) == 0 || it->coeff.compare(numMINUSONE()) == 0)
226 it->rest.bp->printcsrc(os, type, precedence);
228 // outer parens around ex needed for broken gcc-2.95 parser:
229 (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence);
231 // Separator is "/" for negative integer powers, "*" otherwise
234 if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
240 if (precedence <= upper_precedence)
244 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
246 debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
247 exvector::const_iterator it;
248 exvector::const_iterator itend = seq.end()-1;
250 for (it=seq.begin(); it!=itend; ++it) {
251 (*it).bp->printcsrc(os,precedence);
254 (*it).bp->printcsrc(os,precedence);
258 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
260 debugmsg("relational print csrc", LOGLEVEL_PRINT);
261 if (precedence<=upper_precedence)
264 // Print left-hand expression
265 lh.bp->printcsrc(os, type, precedence);
267 // Print relational operator
284 case greater_or_equal:
288 os << "(INVALID RELATIONAL OPERATOR)";
292 // Print right-hand operator
293 rh.bp->printcsrc(os, type, precedence);
295 if (precedence <= upper_precedence)