1 // bigrat.h: declaration of bigrational number class
2 //////////////////////////////////////////////////////////////////////////
3 //
4 // Copyright 1990-2012 John Cremona
5 //
6 // This file is part of the eclib package.
7 //
8 // eclib is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 2 of the License, or (at your
11 // option) any later version.
12 //
13 // eclib is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with eclib; if not, write to the Free Software Foundation,
20 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 //
22 //////////////////////////////////////////////////////////////////////////
23
24 #if !defined(_ECLIB_BIGRATIONAL_H)
25 #define _ECLIB_BIGRATIONAL_H 1 //flags that this file has been included
26
27 #include <eclib/rat.h>
28
29 class bigrational {
30
31 public:
32 // constructors
33 bigrational(bigint num_val=BIGINT(0), bigint den_val=BIGINT(1));
34 bigrational(const bigrational& q);
35 bigrational(const rational& q);
36 void operator=(const bigrational& q);
37 void operator=(const rational& q);
38
39 // bigrational manipulations
40 void cancel(); // cancel *this in situ
41 friend bigint num(const bigrational&); // the numerator
42 friend bigint den(const bigrational&); // the denominator
43 friend bigrational recip(const bigrational&); // reciprocal
44 friend bigint round(const bigrational&); // nearest integer
45
46 // Binary Operator Functions
47 friend bigrational operator+(const bigrational&, const bigrational&);
48 friend bigrational operator+(bigint, const bigrational&);
49 friend bigrational operator+(const bigrational&, bigint);
50 friend bigrational operator-(const bigrational&, const bigrational&);
51 friend bigrational operator-(bigint, const bigrational&);
52 friend bigrational operator-(const bigrational&, bigint);
53 friend bigrational operator*(const bigrational&, const bigrational&);
54 friend bigrational operator*(const bigrational&, bigint);
55 friend bigrational operator*(bigint, const bigrational&);
56 friend bigrational operator/(const bigrational&, const bigrational&);
57 friend bigrational operator/(const bigrational&, bigint);
58 friend bigrational operator/(bigint, const bigrational&);
59 friend int operator==(const bigrational&, const bigrational&);
60 friend int operator!=(const bigrational&, const bigrational&);
61 friend int operator<(const bigrational&, const bigrational&);
62 friend int operator>(const bigrational&, const bigrational&);
63 friend ostream& operator<< (ostream&s, const bigrational&);
64 friend istream& operator>> (istream& is, bigrational& r);
65 bigrational& operator+=(const bigrational&);
66 bigrational& operator+=(bigint);
67 bigrational& operator-=(const bigrational&);
68 bigrational& operator-=(bigint);
69 bigrational& operator*=(const bigrational&);
70 bigrational& operator*=(bigint);
71 bigrational& operator/=(const bigrational&);
72 bigrational& operator/=(bigint);
73 bigrational operator+();
74 bigrational operator-();
75 friend bigint floor(const bigrational& r);
76 friend bigint ceil(const bigrational& r);
77 operator bigfloat(); // conversion operator
78
79 // Implementation
80 private:
81 bigint n, d;
82 };
83
84
85 // Inline bigrational functions
86
cancel()87 inline void bigrational::cancel() // cancel *this in situ
88 {
89 bigint g = gcd(n,d);
90 if (g>1) {n/=g; d/=g;}
91 if (d<0) {n=-n; d=-d;}
92 }
93
bigrational(bigint num_val,bigint den_val)94 inline bigrational::bigrational(bigint num_val, bigint den_val)
95 {
96 n=num_val; d=den_val;
97 (*this).cancel();
98 }
99
bigrational(const bigrational & q)100 inline bigrational::bigrational(const bigrational& q) :n(q.n), d(q.d) {;}
bigrational(const rational & q)101 inline bigrational::bigrational(const rational& q) :n(BIGINT(q.n)), d(BIGINT(q.d)) {;}
102 inline void bigrational::operator=(const bigrational& q) {n=q.n; d=q.d;}
103 inline void bigrational::operator=(const rational& q) {n=BIGINT(q.n); d=BIGINT(q.d);}
104
105 inline bigrational bigrational::operator+()
106 {
107 return *this;
108 }
109
110 inline bigrational bigrational::operator-()
111 {
112 return bigrational(-n, d);
113 }
114
115
116 // Definitions of compound-assignment operator member functions
117
118 inline bigrational& bigrational::operator+=(const bigrational& q2)
119 {
120 n = n*q2.d+d*q2.n;
121 d *= q2.d;
122 (*this).cancel();
123 return *this;
124 }
125
126 inline bigrational& bigrational::operator+=(bigint num_val2)
127 {
128 n += d*num_val2;
129 return *this;
130 }
131
132 inline bigrational& bigrational::operator-=(const bigrational& q2)
133 {
134 n = n*q2.d-d*q2.n;
135 d *= q2.d;
136 (*this).cancel();
137 return *this;
138 }
139
140 inline bigrational& bigrational::operator-=(bigint num_val2)
141 {
142 n -= d*num_val2;
143 return *this;
144 }
145
146 inline bigrational& bigrational::operator*=(bigint num_val2)
147 {
148 n*=num_val2;
149 (*this).cancel();
150 return *this;
151 }
152
153 inline bigrational& bigrational::operator/=(bigint num_val2)
154 {
155 d*=num_val2;
156 (*this).cancel();
157 return *this;
158 }
159
bigfloat()160 inline bigrational::operator bigfloat() {return I2bigfloat(n)/I2bigfloat(d);}
161
162 // Definitions of non-member bigrational functions
163
num(const bigrational & q)164 inline bigint num(const bigrational& q)
165 {
166 return q.n;
167 }
168
den(const bigrational & q)169 inline bigint den(const bigrational& q)
170 {
171 return q.d;
172 }
173
recip(const bigrational & q)174 inline bigrational recip(const bigrational& q)
175 {
176 return bigrational(q.d, q.n);
177 }
178
round(const bigrational & q)179 inline bigint round(const bigrational& q)
180 {
181 return q.n / q.d; //provisional -- should fix rounding direction.
182 }
183
184 // Definitions of non-member binary operator functions
185
186 inline bigrational operator+(const bigrational& q1, const bigrational& q2)
187 {
188 return bigrational(q1.n*q2.d + q2.n*q1.d, q1.d * q2.d);
189 }
190
191 inline bigrational operator+(bigint num_val1, const bigrational& q2)
192 {
193 return bigrational(num_val1*q2.d + q2.n, q2.d);
194 }
195
196 inline bigrational operator+(const bigrational& q1, bigint num_val2)
197 {
198 return bigrational(q1.n + num_val2*q1.d, q1.d);
199 }
200
201 inline bigrational operator-(const bigrational& q1, const bigrational& q2)
202 {
203 return bigrational(q1.n*q2.d - q2.n*q1.d, q1.d * q2.d);
204 }
205
206 inline bigrational operator-(bigint num_val1, const bigrational& q2)
207 {
208 return bigrational(num_val1*q2.d - q2.n, q2.d);
209 }
210
211 inline bigrational operator-(const bigrational& q1, bigint num_val2)
212 {
213 return bigrational(q1.n - num_val2*q1.d, q1.d);
214 }
215
216 inline bigrational operator*(const bigrational& q1, bigint num_val2)
217 {
218 return bigrational(q1.n*num_val2, q1.d);
219 }
220
221 inline bigrational operator*(bigint num_val1, const bigrational& q2)
222 {
223 return bigrational(q2.n*num_val1, q2.d);
224 }
225
226 inline bigrational operator*(const bigrational& q1, const bigrational& q2)
227 {
228 return bigrational(q1.n*q2.n, q1.d*q2.d);
229 }
230
231 inline bigrational operator/(const bigrational& q1, bigint num_val2)
232 {
233 return bigrational(q1.n, q1.d*num_val2);
234 }
235
236 inline bigrational operator/(const bigrational& q1, const bigrational& q2)
237 {
238 return bigrational(q1.n*q2.d, q1.d*q2.n);
239 }
240
241 inline bigrational operator/(bigint num_val1, const bigrational& q2)
242 {
243 return bigrational(q2.d*num_val1, q2.n);
244 }
245
246 inline int operator==(const bigrational& q1, const bigrational& q2)
247 {
248 return q1.n*q2.d == q2.n*q1.d;
249 }
250
251 inline int operator!=(const bigrational& q1, const bigrational& q2)
252 {
253 return q1.n*q2.d != q2.n*q1.d;
254 }
255
256 inline int operator<(const bigrational& q1, const bigrational& q2)
257 {
258 return q1.n*q2.d < q2.n*q1.d;
259 }
260
261 inline int operator>(const bigrational& q1, const bigrational& q2)
262 {
263 return q1.n*q2.d > q2.n*q1.d;
264 }
265
266 inline ostream& operator<<(ostream& s, const bigrational& q)
267 {
268 if(q.d==0) s<<"oo";
269 else
270 {
271 s << q.n;
272 if (q.d!=1) {s << "/" << q.d;}
273 }
274 return s;
275 }
276
277
278 inline istream& operator>> (istream& is, bigrational& r)
279 {
280 char c=0;
281 bigint n,d=BIGINT(1);
282 is>>n;
283 if(!is.eof())
284 {
285 is.get(c);
286 if(c=='/')
287 {
288 is>>d;
289 }
290 else
291 {
292 is.putback(c);
293 }
294 }
295 r=bigrational(n,d);
296 return is;
297 }
298 // NB gcd(n,d)=1 and d>0:
299
floor(const bigrational & r)300 inline bigint floor(const bigrational& r)
301 {
302 return (r.n-(r.n%r.d))/r.d;
303 }
304
ceil(const bigrational & r)305 inline bigint ceil(const bigrational& r)
306 {
307 if(r.d==BIGINT(1)) return r.n;
308 return BIGINT(1) + (r.n-(r.n%r.d))/r.d;
309 }
310
311 #endif
312