@@ -30,7 +30,7 @@ pub type Rational64 = Ratio<i64>;
30
30
/// Alias for arbitrary precision rationals.
31
31
pub type BigRational = Ratio < BigInt > ;
32
32
33
- impl < T : Copy + Num + Ord >
33
+ impl < T : Clone + Integer + Ord >
34
34
Ratio < T > {
35
35
/// Create a ratio representing the integer `t`.
36
36
#[ inline( always) ]
@@ -57,53 +57,30 @@ impl<T: Copy + Num + Ord>
57
57
58
58
/// Put self into lowest terms, with denom > 0.
59
59
fn reduce ( & mut self ) {
60
- let g : T = gcd ( self . numer , self . denom ) ;
60
+ let g : T = self . numer . gcd ( & self . denom ) ;
61
61
62
- self . numer /= g;
63
- self . denom /= g;
62
+ // FIXME(#6050): overloaded operators force moves with generic types
63
+ // self.numer /= g;
64
+ self . numer = self . numer / g;
65
+ // FIXME(#6050): overloaded operators force moves with generic types
66
+ // self.denom /= g;
67
+ self . denom = self . denom / g;
64
68
65
69
// keep denom positive!
66
70
if self . denom < Zero :: zero ( ) {
67
71
self . numer = -self . numer ;
68
72
self . denom = -self . denom ;
69
73
}
70
74
}
75
+
71
76
/// Return a `reduce`d copy of self.
72
77
fn reduced ( & self ) -> Ratio < T > {
73
- let mut ret = copy * self ;
78
+ let mut ret = self . clone ( ) ;
74
79
ret. reduce ( ) ;
75
80
ret
76
81
}
77
82
}
78
83
79
- /**
80
- Compute the greatest common divisor of two numbers, via Euclid's algorithm.
81
-
82
- The result can be negative.
83
- */
84
- #[ inline]
85
- pub fn gcd_raw < T : Num > ( n : T , m : T ) -> T {
86
- let mut m = m, n = n;
87
- while m != Zero :: zero ( ) {
88
- let temp = m;
89
- m = n % temp;
90
- n = temp;
91
- }
92
- n
93
- }
94
-
95
- /**
96
- Compute the greatest common divisor of two numbers, via Euclid's algorithm.
97
-
98
- The result is always positive.
99
- */
100
- #[ inline]
101
- pub fn gcd < T : Num + Ord > ( n : T , m : T ) -> T {
102
- let g = gcd_raw ( n, m) ;
103
- if g < Zero :: zero ( ) { -g }
104
- else { g }
105
- }
106
-
107
84
/* Comparisons */
108
85
109
86
// comparing a/b and c/d is the same as comparing a*d and b*c, so we
@@ -133,7 +110,7 @@ cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
133
110
134
111
/* Arithmetic */
135
112
// a/b * c/d = (a*c)/(b*d)
136
- impl < T : Copy + Num + Ord >
113
+ impl < T : Clone + Integer + Ord >
137
114
Mul < Ratio < T > , Ratio < T > > for Ratio < T > {
138
115
#[ inline]
139
116
fn mul ( & self , rhs : & Ratio < T > ) -> Ratio < T > {
@@ -142,7 +119,7 @@ impl<T: Copy + Num + Ord>
142
119
}
143
120
144
121
// (a/b) / (c/d) = (a*d)/(b*c)
145
- impl < T : Copy + Num + Ord >
122
+ impl < T : Clone + Integer + Ord >
146
123
Div < Ratio < T > , Ratio < T > > for Ratio < T > {
147
124
#[ inline]
148
125
fn div ( & self , rhs : & Ratio < T > ) -> Ratio < T > {
@@ -153,7 +130,7 @@ impl<T: Copy + Num + Ord>
153
130
// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
154
131
macro_rules! arith_impl {
155
132
( impl $imp: ident, $method: ident) => {
156
- impl <T : Copy + Num + Ord >
133
+ impl <T : Clone + Integer + Ord >
157
134
$imp<Ratio <T >, Ratio <T >> for Ratio <T > {
158
135
#[ inline]
159
136
fn $method( & self , rhs: & Ratio <T >) -> Ratio <T > {
@@ -173,16 +150,16 @@ arith_impl!(impl Sub, sub)
173
150
// a/b % c/d = (a*d % b*c)/(b*d)
174
151
arith_impl ! ( impl Rem , rem)
175
152
176
- impl < T : Copy + Num + Ord >
153
+ impl < T : Clone + Integer + Ord >
177
154
Neg < Ratio < T > > for Ratio < T > {
178
155
#[ inline]
179
156
fn neg ( & self ) -> Ratio < T > {
180
- Ratio :: new_raw ( -self . numer , self . denom )
157
+ Ratio :: new_raw ( -self . numer , self . denom . clone ( ) )
181
158
}
182
159
}
183
160
184
161
/* Constants */
185
- impl < T : Copy + Num + Ord >
162
+ impl < T : Clone + Integer + Ord >
186
163
Zero for Ratio < T > {
187
164
#[ inline]
188
165
fn zero ( ) -> Ratio < T > {
@@ -195,19 +172,19 @@ impl<T: Copy + Num + Ord>
195
172
}
196
173
}
197
174
198
- impl < T : Copy + Num + Ord >
175
+ impl < T : Clone + Integer + Ord >
199
176
One for Ratio < T > {
200
177
#[ inline]
201
178
fn one ( ) -> Ratio < T > {
202
179
Ratio :: new_raw ( One :: one ( ) , One :: one ( ) )
203
180
}
204
181
}
205
182
206
- impl < T : Copy + Num + Ord >
183
+ impl < T : Clone + Integer + Ord >
207
184
Num for Ratio < T > { }
208
185
209
186
/* Utils */
210
- impl < T : Copy + Num + Ord >
187
+ impl < T : Clone + Integer + Ord >
211
188
Round for Ratio < T > {
212
189
213
190
fn floor ( & self ) -> Ratio < T > {
@@ -241,14 +218,14 @@ impl<T: Copy + Num + Ord>
241
218
}
242
219
243
220
fn fract ( & self ) -> Ratio < T > {
244
- Ratio :: new_raw ( self . numer % self . denom , self . denom )
221
+ Ratio :: new_raw ( self . numer % self . denom , self . denom . clone ( ) )
245
222
}
246
223
}
247
224
248
- impl < T : Copy + Num + Ord > Fractional for Ratio < T > {
225
+ impl < T : Clone + Integer + Ord > Fractional for Ratio < T > {
249
226
#[ inline]
250
227
fn recip ( & self ) -> Ratio < T > {
251
- Ratio :: new_raw ( self . denom , self . numer )
228
+ Ratio :: new_raw ( self . denom . clone ( ) , self . numer . clone ( ) )
252
229
}
253
230
}
254
231
@@ -266,7 +243,7 @@ impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
266
243
}
267
244
}
268
245
269
- impl < T : FromStr + Copy + Num + Ord >
246
+ impl < T : FromStr + Clone + Integer + Ord >
270
247
FromStr for Ratio < T > {
271
248
/// Parses `numer/denom`.
272
249
fn from_str ( s : & str ) -> Option < Ratio < T > > {
@@ -276,14 +253,14 @@ impl<T: FromStr + Copy + Num + Ord>
276
253
}
277
254
} ) ;
278
255
if split. len ( ) < 2 { return None ; }
279
- do FromStr :: from_str ( split[ 0 ] ) . chain |a| {
280
- do FromStr :: from_str ( split[ 1 ] ) . chain |b| {
281
- Some ( Ratio :: new ( a, b ) )
256
+ do FromStr :: from_str :: < T > ( split[ 0 ] ) . chain |a| {
257
+ do FromStr :: from_str :: < T > ( split[ 1 ] ) . chain |b| {
258
+ Some ( Ratio :: new ( a. clone ( ) , b . clone ( ) ) )
282
259
}
283
260
}
284
261
}
285
262
}
286
- impl < T : FromStrRadix + Copy + Num + Ord >
263
+ impl < T : FromStrRadix + Clone + Integer + Ord >
287
264
FromStrRadix for Ratio < T > {
288
265
/// Parses `numer/denom` where the numbers are in base `radix`.
289
266
fn from_str_radix ( s : & str , radix : uint ) -> Option < Ratio < T > > {
@@ -294,9 +271,9 @@ impl<T: FromStrRadix + Copy + Num + Ord>
294
271
} ) ;
295
272
if split. len ( ) < 2 { None }
296
273
else {
297
- do FromStrRadix :: from_str_radix ( split[ 0 ] , radix) . chain |a| {
298
- do FromStrRadix :: from_str_radix ( split[ 1 ] , radix) . chain |b| {
299
- Some ( Ratio :: new ( a, b ) )
274
+ do FromStrRadix :: from_str_radix :: < T > ( split[ 0 ] , radix) . chain |a| {
275
+ do FromStrRadix :: from_str_radix :: < T > ( split[ 1 ] , radix) . chain |b| {
276
+ Some ( Ratio :: new ( a. clone ( ) , b . clone ( ) ) )
300
277
}
301
278
}
302
279
}
@@ -306,7 +283,7 @@ impl<T: FromStrRadix + Copy + Num + Ord>
306
283
#[ cfg( test) ]
307
284
mod test {
308
285
use super :: * ;
309
- use core:: num:: { Zero , One , FromStrRadix } ;
286
+ use core:: num:: { Zero , One , FromStrRadix , IntConvertible } ;
310
287
use core:: from_str:: FromStr ;
311
288
312
289
pub static _0 : Rational = Ratio { numer : 0 , denom : 1 } ;
@@ -316,16 +293,11 @@ mod test {
316
293
pub static _3_2: Rational = Ratio { numer : 3 , denom : 2 } ;
317
294
pub static _neg1_2: Rational = Ratio { numer : -1 , denom : 2 } ;
318
295
319
- #[ test]
320
- fn test_gcd ( ) {
321
- assert_eq ! ( gcd( 10 , 2 ) , 2 ) ;
322
- assert_eq ! ( gcd( 10 , 3 ) , 1 ) ;
323
- assert_eq ! ( gcd( 0 , 3 ) , 3 ) ;
324
- assert_eq ! ( gcd( 3 , 3 ) , 3 ) ;
325
-
326
- assert_eq ! ( gcd( 3 , -3 ) , 3 ) ;
327
- assert_eq ! ( gcd( -6 , 3 ) , 3 ) ;
328
- assert_eq ! ( gcd( -4 , -2 ) , 2 ) ;
296
+ pub fn to_big ( n : Rational ) -> BigRational {
297
+ Ratio :: new (
298
+ IntConvertible :: from_int ( n. numer ) ,
299
+ IntConvertible :: from_int ( n. denom )
300
+ )
329
301
}
330
302
331
303
#[ test]
@@ -374,45 +346,75 @@ mod test {
374
346
375
347
#[ test]
376
348
fn test_add ( ) {
377
- assert_eq ! ( _1 + _1_2, _3_2) ;
378
- assert_eq ! ( _1 + _1, _2) ;
379
- assert_eq ! ( _1_2 + _3_2, _2) ;
380
- assert_eq ! ( _1_2 + _neg1_2, _0) ;
349
+ fn test ( a : Rational , b : Rational , c : Rational ) {
350
+ assert_eq ! ( a + b, c) ;
351
+ assert_eq ! ( to_big( a) + to_big( b) , to_big( c) ) ;
352
+ }
353
+
354
+ test ( _1, _1_2, _3_2) ;
355
+ test ( _1, _1, _2) ;
356
+ test ( _1_2, _3_2, _2) ;
357
+ test ( _1_2, _neg1_2, _0) ;
381
358
}
382
359
383
360
#[ test]
384
361
fn test_sub ( ) {
385
- assert_eq ! ( _1 - _1_2, _1_2) ;
386
- assert_eq ! ( _3_2 - _1_2, _1) ;
387
- assert_eq ! ( _1 - _neg1_2, _3_2) ;
362
+ fn test ( a : Rational , b : Rational , c : Rational ) {
363
+ assert_eq ! ( a - b, c) ;
364
+ assert_eq ! ( to_big( a) - to_big( b) , to_big( c) )
365
+ }
366
+
367
+ test ( _1, _1_2, _1_2) ;
368
+ test ( _3_2, _1_2, _1) ;
369
+ test ( _1, _neg1_2, _3_2) ;
388
370
}
389
371
390
372
#[ test]
391
373
fn test_mul ( ) {
392
- assert_eq ! ( _1 * _1_2, _1_2) ;
393
- assert_eq ! ( _1_2 * _3_2, Ratio :: new( 3 , 4 ) ) ;
394
- assert_eq ! ( _1_2 * _neg1_2, Ratio :: new( -1 , 4 ) ) ;
374
+ fn test ( a : Rational , b : Rational , c : Rational ) {
375
+ assert_eq ! ( a * b, c) ;
376
+ assert_eq ! ( to_big( a) * to_big( b) , to_big( c) )
377
+ }
378
+
379
+ test ( _1, _1_2, _1_2) ;
380
+ test ( _1_2, _3_2, Ratio :: new ( 3 , 4 ) ) ;
381
+ test ( _1_2, _neg1_2, Ratio :: new ( -1 , 4 ) ) ;
395
382
}
396
383
397
384
#[ test]
398
385
fn test_div ( ) {
399
- assert_eq ! ( _1 / _1_2, _2) ;
400
- assert_eq ! ( _3_2 / _1_2, _1 + _2) ;
401
- assert_eq ! ( _1 / _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2) ;
386
+ fn test ( a : Rational , b : Rational , c : Rational ) {
387
+ assert_eq ! ( a / b, c) ;
388
+ assert_eq ! ( to_big( a) / to_big( b) , to_big( c) )
389
+ }
390
+
391
+ test ( _1, _1_2, _2) ;
392
+ test ( _3_2, _1_2, _1 + _2) ;
393
+ test ( _1, _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2) ;
402
394
}
403
395
404
396
#[ test]
405
397
fn test_rem ( ) {
406
- assert_eq ! ( _3_2 % _1, _1_2) ;
407
- assert_eq ! ( _2 % _neg1_2, _0) ;
408
- assert_eq ! ( _1_2 % _2, _1_2) ;
398
+ fn test ( a : Rational , b : Rational , c : Rational ) {
399
+ assert_eq ! ( a % b, c) ;
400
+ assert_eq ! ( to_big( a) % to_big( b) , to_big( c) )
401
+ }
402
+
403
+ test ( _3_2, _1, _1_2) ;
404
+ test ( _2, _neg1_2, _0) ;
405
+ test ( _1_2, _2, _1_2) ;
409
406
}
410
407
411
408
#[ test]
412
409
fn test_neg ( ) {
413
- assert_eq ! ( -_0, _0) ;
414
- assert_eq ! ( -_1_2, _neg1_2) ;
415
- assert_eq ! ( -( -_1) , _1) ;
410
+ fn test ( a : Rational , b : Rational ) {
411
+ assert_eq ! ( -a, b) ;
412
+ assert_eq ! ( -to_big( a) , to_big( b) )
413
+ }
414
+
415
+ test ( _0, _0) ;
416
+ test ( _1_2, _neg1_2) ;
417
+ test ( -_1, _1) ;
416
418
}
417
419
#[ test]
418
420
fn test_zero ( ) {
0 commit comments