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