899c21b0d02aacb85ce45e83056460a8f9f94606
[ginac.git] / ginac / print.cpp
1 /** @file print.cpp
2  *
3  *  The methods .print() are responsible for the nice default-output of
4  *  objects.  All related helper-functions go in here as well. */
5
6 /*
7  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
8  *
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.
13  *
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.
18  *
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
22  */
23
24 #include <iostream>
25
26 #include "basic.h"
27 #include "ex.h"
28 #include "add.h"
29 #include "constant.h"
30 #include "expairseq.h"
31 #include "fail.h"
32 #include "indexed.h"
33 #include "inifcns.h"
34 #include "matrix.h"
35 #include "mul.h"
36 #include "ncmul.h"
37 #include "numeric.h"
38 #include "power.h"
39 #include "relational.h"
40 #include "series.h"
41 #include "symbol.h"
42 #include "debugmsg.h"
43
44 namespace GiNaC {
45
46 void ex::print(ostream & os, unsigned upper_precedence) const
47 {
48     debugmsg("ex print",LOGLEVEL_PRINT);
49     ASSERT(bp!=0);
50     bp->print(os,upper_precedence);
51 }
52
53 void ex::dbgprint(void) const
54 {
55     debugmsg("ex dbgprint",LOGLEVEL_PRINT);
56     ASSERT(bp!=0);
57     bp->dbgprint();
58 }
59
60 void basic::print(ostream & os, unsigned upper_precedence) const
61 {
62     debugmsg("basic print",LOGLEVEL_PRINT);
63     os << "[basic object]";
64 }
65
66 void basic::dbgprint(void) const
67 {
68     print(cerr);
69     cerr << endl;
70 }
71
72 void symbol::print(ostream & os, unsigned upper_precedence) const
73 {
74     debugmsg("symbol print",LOGLEVEL_PRINT);
75     os << name;
76 }
77
78 void constant::print(ostream & os, unsigned upper_precedence) const
79 {
80     debugmsg("constant print",LOGLEVEL_PRINT);
81     os << name;
82 }
83
84 void power::print(ostream & os, unsigned upper_precedence) const
85 {
86     debugmsg("power print",LOGLEVEL_PRINT);
87 #if 1
88     if (precedence<=upper_precedence) os << "(";
89     basis.print(os,precedence);
90     os << "^";
91     exponent.print(os,precedence);
92     if (precedence<=upper_precedence) os << ")";
93 #else
94     os << "pow(" << basis << "," << exponent << ")";
95 #endif
96 }
97
98 void fail::print(ostream & os, unsigned upper_precedence) const
99 {
100     debugmsg("fail print",LOGLEVEL_PRINT);
101     os << "FAIL";
102 }
103
104 void expairseq::printpair(ostream & os, expair const & p, unsigned upper_precedence) const
105 {
106     os << "[[";
107     p.rest.bp->print(os,precedence);
108     os << ",";
109     p.coeff.bp->print(os,precedence);
110     os << "]]";
111 }
112
113 /*
114 void expairseq::printseq(ostream & os, char delim, unsigned this_precedence,
115                          unsigned upper_precedence) const
116 {
117     if (this_precedence<=upper_precedence) os << "(";
118     epvector::const_iterator itt,it,it_last,it_start;
119     it_last=seq.end();
120     --it_last;
121     it_start=seq.begin();
122
123     switch (delim) {
124     case '+':
125         for (it=seq.begin(); it!=it_last; ++it) {
126             itt = it +1;
127             expair const & k = *itt;
128             printpair(os,*it, this_precedence);
129             if (((is_ex_of_type(k.rest, numeric)) && (k.coeff*k.rest > 0) ) || ((!is_ex_of_type(k.rest, numeric)) && (k.coeff >0))){
130                 os << "+";
131             }
132         }
133         printpair(os,*it,this_precedence);
134         break;
135         
136     case '*':
137         for (it = it_last ; it!=it_start; --it) {
138             if ((*it).rest.is_equal(exMINUSONE()) &&
139                 (*it).coeff.is_equal(exONE())) {
140                 os << "-";
141             } else {
142                 printpair(os, *it,this_precedence);
143                 os << delim;
144             }
145         }
146         printpair(os,*it,this_precedence);
147         break;
148     default:
149         clog << "Nobody expects the Spanish Inquisition: "
150              << "deliminator unknown!" << endl;
151     }
152     if (this_precedence<=upper_precedence) os << ")";
153 }
154 */
155
156 void expairseq::printseq(ostream & os, char delim, unsigned this_precedence,
157                          unsigned upper_precedence) const
158 {
159     if (this_precedence<=upper_precedence) os << "(";
160     epvector::const_iterator it,it_last;
161     it_last=seq.end();
162     --it_last;
163     for (it=seq.begin(); it!=it_last; ++it) {
164         printpair(os,*it,this_precedence);
165         os << delim;
166     }
167     printpair(os,*it,this_precedence);
168     if (!overall_coeff.is_equal(default_overall_coeff())) {
169         os << delim << overall_coeff;
170     }
171     if (this_precedence<=upper_precedence) os << ")";
172 }
173     
174 void expairseq::print(ostream & os, unsigned upper_precedence) const
175 {
176     debugmsg("expairseq print",LOGLEVEL_PRINT);
177     os << "[[";
178     printseq(os,',',precedence,upper_precedence);
179     os << "]]";
180 }
181
182 void add::printpair(ostream & os, expair const & p, unsigned upper_precedence) const
183 {
184     os << "(";
185     if (p.coeff == -1) {
186         os << "-";
187     } else {
188         if (p.coeff != 1) {
189             os << p.coeff;
190             os << "*";
191         }
192     }
193     os << p.rest;
194     os << ")";
195 }
196     
197 void add::print(ostream & os, unsigned upper_precedence) const
198 {
199     debugmsg("add print",LOGLEVEL_PRINT);
200     if (precedence<=upper_precedence) os << "(";
201     bool first=true;
202     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
203         if (!first) {
204             if (cit->coeff > 0) os << '+';
205         } else {
206             first=false;
207         }
208         if (cit->coeff == -1) {
209             os << "-";
210         } else {
211             if (cit->coeff != 1) {
212                 (cit->coeff).print(os,precedence);
213                 os << "*";
214             }
215         }
216         os << cit->rest;
217     }
218     if (!overall_coeff.is_zero()) {
219         if (overall_coeff > 0) os << '+';
220         os << overall_coeff;
221     }
222     if (precedence<=upper_precedence) os << ")";
223 }
224
225 void mul::printpair(ostream & os, expair const & p, unsigned upper_precedence) const
226 {
227     os << "(";
228     if (p.coeff.compare(exONE())==0) {
229         p.rest.print(os,upper_precedence);
230     } else {
231         // outer parens around ex needed for broken gcc-2.95 parser:
232         (ex(power(p.rest,p.coeff))).print(os,upper_precedence);
233     }
234     os << ")";
235 }
236     
237 void mul::print(ostream & os, unsigned upper_precedence) const
238 {
239     debugmsg("mul print",LOGLEVEL_PRINT);
240     if (precedence<=upper_precedence) os << "(";
241     bool first=true;
242     if (!overall_coeff.is_equal(exONE())) {
243         overall_coeff.print(os,precedence);
244         first=false;
245     }
246     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
247         if (!first) {
248             os << '*';
249         } else {
250             first=false;
251         }
252         recombine_pair_to_ex(*cit).print(os,precedence);
253     }
254     if (precedence<=upper_precedence) os << ")";
255 }
256
257 void ncmul::print(ostream & os, unsigned upper_precedence) const
258 {
259     debugmsg("ncmul print",LOGLEVEL_PRINT);
260     printseq(os,'(','%',')',precedence,upper_precedence);
261 }
262
263 /*void function::print(ostream & os, unsigned upper_precedence) const
264  *{
265  *    debugmsg("function print",LOGLEVEL_PRINT);
266  *    os << name;
267  *    printseq(os,'(',',',')',exprseq::precedence,function::precedence);
268  *}*/
269
270 void series::print(ostream &os, unsigned upper_precedence) const
271 {
272         debugmsg("symbol print", LOGLEVEL_PRINT);
273         convert_to_poly().print(os, upper_precedence);
274 }
275
276 void relational::print(ostream & os, unsigned upper_precedence) const
277 {
278     debugmsg("relational print",LOGLEVEL_PRINT);
279     if (precedence<=upper_precedence) os << "(";
280     lh.print(os,precedence);
281     switch (o) {
282     case equal:
283         os << "==";
284         break;
285     case not_equal:
286         os << "!=";
287         break;
288     case less:
289         os << "<";
290         break;
291     case less_or_equal:
292         os << "<=";
293         break;
294     case greater:
295         os << ">";
296         break;
297     case greater_or_equal:
298         os << ">=";
299         break;
300     default:
301         os << "(INVALID RELATIONAL OPERATOR)";
302     }
303     rh.print(os,precedence);
304     if (precedence<=upper_precedence) os << ")";
305 }
306
307 void matrix::print(ostream & os, unsigned upper_precedence) const
308 {
309     debugmsg("matrix print",LOGLEVEL_PRINT);
310     os << "[[ ";
311     for (int r=0; r<row-1; ++r) {
312         os << "[[";
313         for (int c=0; c<col-1; ++c) {
314             os << m[r*col+c] << ",";
315         }
316         os << m[col*(r+1)-1] << "]], ";
317     }
318     os << "[[";
319     for (int c=0; c<col-1; ++c) {
320         os << m[(row-1)*col+c] << ",";
321     }
322     os << m[row*col-1] << "]] ]]";
323 }
324
325 } // namespace GiNaC