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