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