* All operators are now strictly following the semantics we all know from
[ginac.git] / ginac / operators.cpp
1 /** @file operators.cpp
2  *
3  *  Implementation of GiNaC's overloaded operators. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2001 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 "operators.h"
24 #include "numeric.h"
25 #include "add.h"
26 #include "mul.h"
27 #include "power.h"
28 #include "ncmul.h"
29 #include "relational.h"
30 #include "print.h"
31 #include "debugmsg.h"
32 #include "utils.h"
33
34 namespace GiNaC {
35
36 /** Used internally by operator+() to add two ex objects together. */
37 static inline const ex exadd(const ex & lh, const ex & rh)
38 {
39         return (new add(lh,rh))->setflag(status_flags::dynallocated);
40 }
41
42 /** Used internally by operator*() to multiply two ex objects together. */
43 static inline const ex exmul(const ex & lh, const ex & rh)
44 {
45         // Check if we are constructing a mul object or a ncmul object.  Due to
46         // ncmul::eval()'s rule to pull out commutative elements we need to check
47         // only one of the elements.
48         if (rh.return_type()==return_types::commutative ||
49             lh.return_type()==return_types::commutative)
50                 return (new mul(lh,rh))->setflag(status_flags::dynallocated);
51         else
52                 return (new ncmul(lh,rh))->setflag(status_flags::dynallocated);
53 }
54
55 /** Used internally by operator-() and friends to change the sign of an argument. */
56 static inline const ex exminus(const ex & lh)
57 {
58         return (new mul(lh,_ex_1()))->setflag(status_flags::dynallocated);
59 }
60
61 // binary arithmetic operators ex with ex
62
63 const ex operator+(const ex & lh, const ex & rh)
64 {
65         debugmsg("operator+(ex,ex)",LOGLEVEL_OPERATOR);
66         return exadd(lh, rh);
67 }
68
69 const ex operator-(const ex & lh, const ex & rh)
70 {
71         debugmsg("operator-(ex,ex)",LOGLEVEL_OPERATOR);
72         return exadd(lh, exminus(rh));
73 }
74
75 const ex operator*(const ex & lh, const ex & rh)
76 {
77         debugmsg("operator*(ex,ex)",LOGLEVEL_OPERATOR);
78         return exmul(lh, rh);
79 }
80
81 const ex operator/(const ex & lh, const ex & rh)
82 {
83         debugmsg("operator/(ex,ex)",LOGLEVEL_OPERATOR);
84         return exmul(lh, power(rh,_ex_1()));
85 }
86
87
88 // binary arithmetic operators numeric with numeric
89
90 const numeric operator+(const numeric & lh, const numeric & rh)
91 {
92         debugmsg("operator+(numeric,numeric)",LOGLEVEL_OPERATOR);
93         return lh.add(rh);
94 }
95
96 const numeric operator-(const numeric & lh, const numeric & rh)
97 {
98         debugmsg("operator-(numeric,numeric)",LOGLEVEL_OPERATOR);
99         return lh.sub(rh);
100 }
101
102 const numeric operator*(const numeric & lh, const numeric & rh)
103 {
104         debugmsg("operator*(numeric,numeric)",LOGLEVEL_OPERATOR);
105         return lh.mul(rh);
106 }
107
108 const numeric operator/(const numeric & lh, const numeric & rh)
109 {
110         debugmsg("operator/(numeric,ex)",LOGLEVEL_OPERATOR);
111         return lh.div(rh);
112 }
113
114
115 // binary arithmetic assignment operators with ex
116
117 ex & operator+=(ex & lh, const ex & rh)
118 {
119         debugmsg("operator+=(ex,ex)",LOGLEVEL_OPERATOR);
120         return lh = exadd(lh, rh);
121 }
122
123 ex & operator-=(ex & lh, const ex & rh)
124 {
125         debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR);
126         return lh = exadd(lh, exminus(rh));
127 }
128
129 ex & operator*=(ex & lh, const ex & rh)
130 {
131         debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR);
132         return lh = exmul(lh, rh);
133 }
134
135 ex & operator/=(ex & lh, const ex & rh)
136 {
137         debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR);
138         return lh = exmul(lh, power(rh,_ex_1()));
139 }
140
141
142 // binary arithmetic assignment operators with numeric
143
144 numeric & operator+=(numeric & lh, const numeric & rh)
145 {
146         debugmsg("operator+=(numeric,numeric)",LOGLEVEL_OPERATOR);
147         lh = lh.add(rh);
148         return lh;
149 }
150
151 numeric & operator-=(numeric & lh, const numeric & rh)
152 {
153         debugmsg("operator-=(numeric,numeric)",LOGLEVEL_OPERATOR);
154         lh = lh.sub(rh);
155         return lh;
156 }
157
158 numeric & operator*=(numeric & lh, const numeric & rh)
159 {
160         debugmsg("operator*=(numeric,numeric)",LOGLEVEL_OPERATOR);
161         lh = lh.mul(rh);
162         return lh;
163 }
164
165 numeric & operator/=(numeric & lh, const numeric & rh)
166 {
167         debugmsg("operator/=(numeric,numeric)",LOGLEVEL_OPERATOR);
168         lh = lh.div(rh);
169         return lh;
170 }
171
172
173 // unary operators
174
175 const ex operator+(const ex & lh)
176 {
177         debugmsg("operator+(ex)",LOGLEVEL_OPERATOR);
178         return lh;
179 }
180
181 const ex operator-(const ex & lh)
182 {
183         debugmsg("operator-(ex)",LOGLEVEL_OPERATOR);
184         return exminus(lh);
185 }
186
187 const numeric operator+(const numeric & lh)
188 {
189         debugmsg("operator+(numeric)",LOGLEVEL_OPERATOR);
190         return lh;
191 }
192
193 const numeric operator-(const numeric & lh)
194 {
195         debugmsg("operator-(numeric)",LOGLEVEL_OPERATOR);
196         return _num_1().mul(lh);
197 }
198
199
200 // increment / decrement operators
201
202 /** Expression prefix increment.  Adds 1 and returns incremented ex. */
203 ex & operator++(ex & rh)
204 {
205         debugmsg("operator++(ex)",LOGLEVEL_OPERATOR);
206         return rh = exadd(rh, _ex1());
207 }
208
209 /** Expression prefix decrement.  Subtracts 1 and returns decremented ex. */
210 ex & operator--(ex & rh)
211 {
212         debugmsg("operator--(ex)",LOGLEVEL_OPERATOR);
213         return rh = exadd(rh, _ex_1());
214 }
215
216 /** Expression postfix increment.  Returns the ex and leaves the original
217  *  incremented by 1. */
218 const ex operator++(ex & lh, int)
219 {
220         debugmsg("operator++(ex,int)",LOGLEVEL_OPERATOR);
221         ex tmp(lh);
222         lh = exadd(lh, _ex1());
223         return tmp;
224 }
225
226 /** Expression Postfix decrement.  Returns the ex and leaves the original
227  *  decremented by 1. */
228 const ex operator--(ex & lh, int)
229 {
230         debugmsg("operator--(ex,int)",LOGLEVEL_OPERATOR);
231         ex tmp(lh);
232         lh = exadd(lh, _ex_1());
233         return tmp;
234 }
235
236 /** Numeric prefix increment.  Adds 1 and returns incremented number. */
237 numeric& operator++(numeric & rh)
238 {
239         debugmsg("operator++(numeric)",LOGLEVEL_OPERATOR);
240         rh = rh.add(_num1());
241         return rh;
242 }
243
244 /** Numeric prefix decrement.  Subtracts 1 and returns decremented number. */
245 numeric& operator--(numeric & rh)
246 {
247         debugmsg("operator--(numeric)",LOGLEVEL_OPERATOR);
248         rh = rh.add(_num_1());
249         return rh;
250 }
251
252 /** Numeric postfix increment.  Returns the number and leaves the original
253  *  incremented by 1. */
254 const numeric operator++(numeric & lh, int)
255 {
256         debugmsg("operator++(numeric,int)",LOGLEVEL_OPERATOR);
257         numeric tmp(lh);
258         lh = lh.add(_num1());
259         return tmp;
260 }
261
262 /** Numeric Postfix decrement.  Returns the number and leaves the original
263  *  decremented by 1. */
264 const numeric operator--(numeric & lh, int)
265 {
266         debugmsg("operator--(numeric,int)",LOGLEVEL_OPERATOR);
267         numeric tmp(lh);
268         lh = lh.add(_num_1());
269         return tmp;
270 }
271
272 // binary relational operators ex with ex
273
274 relational operator==(const ex & lh, const ex & rh)
275 {
276         debugmsg("operator==(ex,ex)",LOGLEVEL_OPERATOR);
277         return relational(lh,rh,relational::equal);
278 }
279
280 relational operator!=(const ex & lh, const ex & rh)
281 {
282         debugmsg("operator!=(ex,ex)",LOGLEVEL_OPERATOR);
283         return relational(lh,rh,relational::not_equal);
284 }
285
286 relational operator<(const ex & lh, const ex & rh)
287 {
288         debugmsg("operator<(ex,ex)",LOGLEVEL_OPERATOR);
289         return relational(lh,rh,relational::less);
290 }
291
292 relational operator<=(const ex & lh, const ex & rh)
293 {
294         debugmsg("operator<=(ex,ex)",LOGLEVEL_OPERATOR);
295         return relational(lh,rh,relational::less_or_equal);
296 }
297
298 relational operator>(const ex & lh, const ex & rh)
299 {
300         debugmsg("operator>(ex,ex)",LOGLEVEL_OPERATOR);
301         return relational(lh,rh,relational::greater);
302 }
303
304 relational operator>=(const ex & lh, const ex & rh)
305 {
306         debugmsg("operator>=(ex,ex)",LOGLEVEL_OPERATOR);
307         return relational(lh,rh,relational::greater_or_equal);
308 }
309
310 // input/output stream operators
311
312 std::ostream & operator<<(std::ostream & os, const ex & e)
313 {
314         e.print(print_context(os));
315         return os;
316 }
317
318 std::istream & operator>>(std::istream & is, ex & e)
319 {
320         throw (std::logic_error("expression input from streams not implemented"));
321 }
322
323 } // namespace GiNaC