- expressions can now be read from streams; the input expression can contain
[ginac.git] / ginac / operators.cpp
1 /** @file operators.cpp
2  *
3  *  Implementation of GiNaC's overloaded operators. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2000 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 #include <stdexcept>
25
26 #include "operators.h"
27 #include "basic.h"
28 #include "ex.h"
29 #include "numeric.h"
30 #include "power.h"
31 #include "relational.h"
32 #include "input_lexer.h"
33 #include "debugmsg.h"
34 #include "utils.h"
35
36 #ifndef NO_NAMESPACE_GINAC
37 namespace GiNaC {
38 #endif // ndef NO_NAMESPACE_GINAC
39
40 // binary arithmetic operators ex with ex
41
42 ex operator+(const ex & lh, const ex & rh)
43 {
44     debugmsg("operator+(ex,ex)",LOGLEVEL_OPERATOR);
45     return lh.exadd(rh);
46 }
47
48 ex operator-(const ex & lh, const ex & rh)
49 {
50     debugmsg("operator-(ex,ex)",LOGLEVEL_OPERATOR);
51     return lh.exadd(rh.exmul(_ex_1()));
52 }
53
54 ex operator*(const ex & lh, const ex & rh)
55 {
56     debugmsg("operator*(ex,ex)",LOGLEVEL_OPERATOR);
57     return lh.exmul(rh);
58 }
59
60 ex operator/(const ex & lh, const ex & rh)
61 {
62     debugmsg("operator*(ex,ex)",LOGLEVEL_OPERATOR);
63     return lh.exmul(power(rh,_ex_1()));
64 }
65
66 ex operator%(const ex & lh, const ex & rh)
67 {
68     debugmsg("operator%(ex,ex)",LOGLEVEL_OPERATOR);
69     return lh.exncmul(rh);
70 }
71
72
73 // binary arithmetic operators numeric with numeric
74
75 numeric operator+(const numeric & lh, const numeric & rh)
76 {
77     debugmsg("operator+(numeric,numeric)",LOGLEVEL_OPERATOR);
78     return lh.add(rh);
79 }
80
81 numeric operator-(const numeric & lh, const numeric & rh)
82 {
83     debugmsg("operator-(numeric,numeric)",LOGLEVEL_OPERATOR);
84     return lh.sub(rh);
85 }
86
87 numeric operator*(const numeric & lh, const numeric & rh)
88 {
89     debugmsg("operator*(numeric,numeric)",LOGLEVEL_OPERATOR);
90     return lh.mul(rh);
91 }
92
93 numeric operator/(const numeric & lh, const numeric & rh)
94 {
95     debugmsg("operator/(numeric,ex)",LOGLEVEL_OPERATOR);
96     return lh.div(rh);
97 }
98
99
100 // binary arithmetic assignment operators with ex
101
102 const ex & operator+=(ex & lh, const ex & rh)
103 {
104     debugmsg("operator+=(ex,ex)",LOGLEVEL_OPERATOR);
105     return (lh=lh+rh);
106 }
107
108 const ex & operator-=(ex & lh, const ex & rh)
109 {
110     debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR);
111     return (lh=lh-rh);
112 }
113
114 const ex & operator*=(ex & lh, const ex & rh)
115 {
116     debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR);
117     return (lh=lh*rh);
118 }
119
120 const ex & operator/=(ex & lh, const ex & rh)
121 {
122     debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR);
123     return (lh=lh/rh);
124 }
125
126 const ex & operator%=(ex & lh, const ex & rh)
127 {
128     debugmsg("operator%=(ex,ex)",LOGLEVEL_OPERATOR);
129     return (lh=lh%rh);
130 }
131
132
133 // binary arithmetic assignment operators with numeric
134
135 const numeric & operator+=(numeric & lh, const numeric & rh)
136 {
137     debugmsg("operator+=(numeric,numeric)",LOGLEVEL_OPERATOR);
138     return (lh=lh.add(rh));
139 }
140
141 const numeric & operator-=(numeric & lh, const numeric & rh)
142 {
143     debugmsg("operator-=(numeric,numeric)",LOGLEVEL_OPERATOR);
144     return (lh=lh.sub(rh));
145 }
146
147 const numeric & operator*=(numeric & lh, const numeric & rh)
148 {
149     debugmsg("operator*=(numeric,numeric)",LOGLEVEL_OPERATOR);
150     return (lh=lh.mul(rh));
151 }
152
153 const numeric & operator/=(numeric & lh, const numeric & rh)
154 {
155     debugmsg("operator/=(numeric,numeric)",LOGLEVEL_OPERATOR);
156     return (lh=lh.div(rh));
157 }
158
159 // unary operators
160
161 ex operator+(const ex & lh)
162 {
163     return lh;
164 }
165
166 ex operator-(const ex & lh)
167 {
168     return lh.exmul(_ex_1());
169 }
170
171 numeric operator+(const numeric & lh)
172 {
173     return lh;
174 }
175
176 numeric operator-(const numeric & lh)
177 {
178     return _num_1()*lh;
179 }
180
181 /** Numeric prefix increment.  Adds 1 and returns incremented number. */
182 numeric& operator++(numeric & rh)
183 {
184     rh = rh+_num1();
185     return rh;
186 }
187
188 /** Numeric prefix decrement.  Subtracts 1 and returns decremented number. */
189 numeric& operator--(numeric & rh)
190 {
191     rh = rh-_num1();
192     return rh;
193 }
194
195 /** Numeric postfix increment.  Returns the number and leaves the original
196  *  incremented by 1. */
197 numeric operator++(numeric & lh, int)
198 {
199     numeric tmp = lh;
200     lh = lh+_num1();
201     return tmp;
202 }
203
204 /** Numeric Postfix decrement.  Returns the number and leaves the original
205  *  decremented by 1. */
206 numeric operator--(numeric & lh, int)
207 {
208     numeric tmp = lh;
209     lh = lh-_num1();
210     return tmp;
211 }
212
213 // binary relational operators ex with ex
214
215 relational operator==(const ex & lh, const ex & rh)
216 {
217     debugmsg("operator==(ex,ex)",LOGLEVEL_OPERATOR);
218     return relational(lh,rh,relational::equal);
219 }
220
221 relational operator!=(const ex & lh, const ex & rh)
222 {
223     debugmsg("operator!=(ex,ex)",LOGLEVEL_OPERATOR);
224     return relational(lh,rh,relational::not_equal);
225 }
226
227 relational operator<(const ex & lh, const ex & rh)
228 {
229     debugmsg("operator<(ex,ex)",LOGLEVEL_OPERATOR);
230     return relational(lh,rh,relational::less);
231 }
232
233 relational operator<=(const ex & lh, const ex & rh)
234 {
235     debugmsg("operator<=(ex,ex)",LOGLEVEL_OPERATOR);
236     return relational(lh,rh,relational::less_or_equal);
237 }
238
239 relational operator>(const ex & lh, const ex & rh)
240 {
241     debugmsg("operator>(ex,ex)",LOGLEVEL_OPERATOR);
242     return relational(lh,rh,relational::greater);
243 }
244
245 relational operator>=(const ex & lh, const ex & rh)
246 {
247     debugmsg("operator>=(ex,ex)",LOGLEVEL_OPERATOR);
248     return relational(lh,rh,relational::greater_or_equal);
249 }
250
251 /*
252
253 // binary relational operators ex with numeric
254
255 relational operator==(const ex & lh, const numeric & rh)
256 {
257     debugmsg("operator==(ex,numeric)",LOGLEVEL_OPERATOR);
258     return relational(lh,rh,relational::equal);
259 }
260
261 relational operator!=(const ex & lh, const numeric & rh)
262 {
263     debugmsg("operator!=(ex,numeric)",LOGLEVEL_OPERATOR);
264     return relational(lh,rh,relational::not_equal);
265 }
266
267 relational operator<(const ex & lh, const numeric & rh)
268 {
269     debugmsg("operator<(ex,numeric)",LOGLEVEL_OPERATOR);
270     return relational(lh,rh,relational::less);
271 }
272
273 relational operator<=(const ex & lh, const numeric & rh)
274 {
275     debugmsg("operator<=(ex,numeric)",LOGLEVEL_OPERATOR);
276     return relational(lh,rh,relational::less_or_equal);
277 }
278
279 relational operator>(const ex & lh, const numeric & rh)
280 {
281     debugmsg("operator>(ex,numeric)",LOGLEVEL_OPERATOR);
282     return relational(lh,rh,relational::greater);
283 }
284
285 relational operator>=(const ex & lh, const numeric & rh)
286 {
287     debugmsg("operator>=(ex,numeric)",LOGLEVEL_OPERATOR);
288     return relational(lh,rh,relational::greater_or_equal);
289 }
290
291 // binary relational operators numeric with ex
292
293 relational operator==(const numeric & lh, const ex & rh)
294 {
295     debugmsg("operator==(numeric,ex)",LOGLEVEL_OPERATOR);
296     return relational(lh,rh,relational::equal);
297 }
298
299 relational operator!=(const numeric & lh, const ex & rh)
300 {
301     debugmsg("operator!=(numeric,ex)",LOGLEVEL_OPERATOR);
302     return relational(lh,rh,relational::not_equal);
303 }
304
305 relational operator<(const numeric & lh, const ex & rh)
306 {
307     debugmsg("operator<(numeric,ex)",LOGLEVEL_OPERATOR);
308     return relational(lh,rh,relational::less);
309 }
310
311 relational operator<=(const numeric & lh, const ex & rh)
312 {
313     debugmsg("operator<=(numeric,ex)",LOGLEVEL_OPERATOR);
314     return relational(lh,rh,relational::less_or_equal);
315 }
316
317 relational operator>(const numeric & lh, const ex & rh)
318 {
319     debugmsg("operator>(numeric,ex)",LOGLEVEL_OPERATOR);
320     return relational(lh,rh,relational::greater);
321 }
322
323 relational operator>=(const numeric & lh, const ex & rh)
324 {
325     debugmsg("operator>=(numeric,ex)",LOGLEVEL_OPERATOR);
326     return relational(lh,rh,relational::greater_or_equal);
327 }
328
329 */
330
331 // input/output stream operators
332
333 ostream & operator<<(ostream & os, const ex & e)
334 {
335     e.print(os);
336     return os;
337 }
338
339 /** Input (parse) expression from stream. The input grammar is similar to the
340  *  GiNaC output format. If 'e' contains a list of symbols upon entry, these
341  *  symbols are used in the parsed expression in all places where symbols with
342  *  the same names appear. All other encountered symbols will be newly created. */
343 istream & operator>>(istream & is, ex & e)
344 {
345         string s;
346         getline(is, s);
347         set_lexer_string(s);
348         set_lexer_symbols(e);
349         ginac_yyrestart(NULL);
350         if (yyparse())
351                 throw (std::runtime_error(get_parser_error()));
352         else
353                 e = parsed_ex;
354 }
355
356 #ifndef NO_NAMESPACE_GINAC
357 } // namespace GiNaC
358 #endif // ndef NO_NAMESPACE_GINAC