]> www.ginac.de Git - ginac.git/blob - ginac/printcsrc.cpp
34056400c7c60fe0ce613f417657368a88ad6f2f
[ginac.git] / ginac / printcsrc.cpp
1 /** @file printcsrc.cpp
2  *
3  *  The methods .printcsrc() are responsible for C-source output of
4  *  objects.  All related helper-functions go in here as well.
5  *
6  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include <iostream>
24
25 #include "ginac.h"
26
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.
30  *
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
35 {
36     debugmsg("ex print csrc", LOGLEVEL_PRINT);
37     ASSERT(bp!=0);
38         switch (type) {
39                 case csrc_types::ctype_float:
40                         os << "float ";
41                         break;
42                 case csrc_types::ctype_double:
43                         os << "double ";
44                         break;
45                 case csrc_types::ctype_cl_N:
46                         os << "cl_N ";
47                         break;
48         }
49     os << var_name << " = ";
50     bp->printcsrc(os, type, 0);
51     os << ";\n";
52 }
53
54 void basic::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
55 {
56     debugmsg("basic print csrc", LOGLEVEL_PRINT);
57 }
58
59 void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
60 {
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) {
66             os << "(";
67                         if (type == csrc_types::ctype_cl_N)
68                                 os << "cl_F(\"" << numer().evalf() << "\")";
69                         else
70                     os << numer().to_double();
71         } else {
72             os << "-(";
73                         if (type == csrc_types::ctype_cl_N)
74                                 os << "cl_F(\"" << -numer().evalf() << "\")";
75                         else
76                     os << -numer().to_double();
77         }
78         os << "/";
79                 if (type == csrc_types::ctype_cl_N)
80                         os << "cl_F(\"" << denom().evalf() << "\")";
81                 else
82                 os << denom().to_double();
83         os << ")";
84     } else {
85                 if (type == csrc_types::ctype_cl_N)
86                         os << "cl_F(\"" << evalf() << "\")";
87                 else
88                 os << to_double();
89         }
90         os.flags(oldflags);
91 }
92
93 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
94 {
95     debugmsg("symbol print csrc", LOGLEVEL_PRINT);
96     os << name;
97 }
98
99 void constant::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
100 {
101     debugmsg("constant print csrc",LOGLEVEL_PRINT);
102     os << name;
103 }
104
105 static void print_sym_pow(ostream & os, unsigned type, const symbol &x, int exp)
106 {
107     // Optimal output of integer powers of symbols to aid compiler CSE
108     if (exp == 1) {
109         x.printcsrc(os, type, 0);
110     } else if (exp == 2) {
111         x.printcsrc(os, type, 0);
112         os << "*";
113         x.printcsrc(os, type, 0);
114     } else if (exp & 1) {
115         x.printcsrc(os, 0);
116         os << "*";
117         print_sym_pow(os, type, x, exp-1);
118     } else {
119         os << "(";
120         print_sym_pow(os, type, x, exp >> 1);
121         os << ")*(";
122         print_sym_pow(os, type, x, exp >> 1);
123         os << ")";
124     }
125 }
126
127 void power::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
128 {
129     debugmsg("power print csrc", LOGLEVEL_PRINT);
130
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();
136         if (exp > 0)
137             os << "(";
138         else {
139             exp = -exp;
140                         if (type == csrc_types::ctype_cl_N)
141                                 os << "recip(";
142                         else
143                     os << "1.0/(";
144         }
145         print_sym_pow(os, type, static_cast<const symbol &>(*basis.bp), exp);
146         os << ")";
147
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)
151                         os << "recip(";
152                 else
153                 os << "1.0/(";
154         basis.bp->printcsrc(os, type, 0);
155                 os << ")";
156
157         // Otherwise, use the pow() or expt() (CLN) functions
158     } else {
159                 if (type == csrc_types::ctype_cl_N)
160                         os << "expt(";
161                 else
162                 os << "pow(";
163         basis.bp->printcsrc(os, type, 0);
164         os << ",";
165         exponent.bp->printcsrc(os, type, 0);
166         os << ")";
167     }
168 }
169
170 void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
171 {
172     debugmsg("add print csrc", LOGLEVEL_PRINT);
173     if (precedence <= upper_precedence)
174         os << "(";
175
176         // Print arguments, separated by "+"
177     epvector::const_iterator it = seq.begin();
178     epvector::const_iterator itend = seq.end();
179     while (it != itend) {
180
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) {
185             os << "-";
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);
189                         os << "/";
190             ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
191                 } else if (ex_to_numeric(it->coeff).numer().compare(numMINUSONE()) == 0) {
192                         os << "-";
193                 it->rest.bp->printcsrc(os, type, precedence);
194                         os << "/";
195             ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
196                 } else {
197             it->coeff.bp->printcsrc(os, type, precedence);
198             os << "*";
199                 it->rest.bp->printcsrc(os, type, precedence);
200         }
201
202                 // Separator is "+", except it the following expression would have a leading minus sign
203         it++;
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)))
205             os << "+";
206     }
207     
208     if (!overall_coeff.is_equal(exZERO())) {
209         if (overall_coeff > 0) os << '+';
210         overall_coeff.bp->printcsrc(os,type,precedence);
211     }
212     
213     if (precedence <= upper_precedence)
214         os << ")";
215 }
216
217 void mul::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
218 {
219     debugmsg("mul print csrc", LOGLEVEL_PRINT);
220     if (precedence <= upper_precedence)
221         os << "(";
222
223     if (!overall_coeff.is_equal(exONE())) {
224         overall_coeff.bp->printcsrc(os,type,precedence);
225         os << "*";
226     }
227     
228         // Print arguments, separated by "*" or "/"
229     epvector::const_iterator it = seq.begin();
230     epvector::const_iterator itend = seq.end();
231     while (it != itend) {
232
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)
236                                 os << "recip(";
237                         else
238                     os << "1.0/";
239                 }
240
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);
244         else
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);
247
248                 // Separator is "/" for negative integer powers, "*" otherwise
249         it++;
250         if (it != itend) {
251             if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(numZERO()) < 0)
252                 os << "/";
253             else
254                 os << "*";
255         }
256     }
257     if (precedence <= upper_precedence)
258         os << ")";
259 }
260
261 void ncmul::printcsrc(ostream & os, unsigned upper_precedence) const
262 {
263     debugmsg("ncmul print csrc",LOGLEVEL_PRINT);
264     exvector::const_iterator it;
265     exvector::const_iterator itend = seq.end()-1;
266     os << "ncmul(";
267     for (it=seq.begin(); it!=itend; ++it) {
268         (*it).bp->printcsrc(os,precedence);
269         os << ",";
270     }
271     (*it).bp->printcsrc(os,precedence);
272     os << ")";
273 }
274
275 void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
276 {
277     debugmsg("relational print csrc", LOGLEVEL_PRINT);
278     if (precedence<=upper_precedence)
279                 os << "(";
280
281         // Print left-hand expression
282     lh.bp->printcsrc(os, type, precedence);
283
284         // Print relational operator
285     switch (o) {
286             case equal:
287                 os << "==";
288                 break;
289             case not_equal:
290                 os << "!=";
291                 break;
292             case less:
293                 os << "<";
294                 break;
295             case less_or_equal:
296                 os << "<=";
297                 break;
298             case greater:
299                 os << ">";
300                 break;
301             case greater_or_equal:
302                 os << ">=";
303                 break;
304             default:
305                 os << "(INVALID RELATIONAL OPERATOR)";
306                         break;
307     }
308
309         // Print right-hand operator
310     rh.bp->printcsrc(os, type, precedence);
311
312     if (precedence <= upper_precedence)
313                 os << ")";
314 }