@@ -110,9 +110,11 @@ impl<T: Clone + Integer> Ratio<T> {
110
110
111
111
// FIXME(#5992): assignment operator overloads
112
112
// self.numer /= g;
113
+ // T: Clone + Integer != T: Clone + NumAssign
113
114
self . numer = self . numer . clone ( ) / g. clone ( ) ;
114
115
// FIXME(#5992): assignment operator overloads
115
116
// self.denom /= g;
117
+ // T: Clone + Integer != T: Clone + NumAssign
116
118
self . denom = self . denom . clone ( ) / g;
117
119
118
120
// keep denom positive!
@@ -265,7 +267,6 @@ impl<T> From<T> for Ratio<T> where T: Clone + Integer {
265
267
}
266
268
}
267
269
268
-
269
270
// From pair (through the `new` constructor)
270
271
impl < T > From < ( T , T ) > for Ratio < T > where T : Clone + Integer {
271
272
fn from ( pair : ( T , T ) ) -> Ratio < T > {
@@ -362,6 +363,114 @@ impl<T: Clone + Integer + Hash> Hash for Ratio<T> {
362
363
}
363
364
}
364
365
366
+ mod opassign {
367
+ use std:: ops:: { AddAssign , SubAssign , MulAssign , DivAssign , RemAssign } ;
368
+
369
+ use Ratio ;
370
+ use integer:: Integer ;
371
+ use traits:: NumAssign ;
372
+
373
+ impl < T : Clone + Integer + NumAssign > AddAssign for Ratio < T > {
374
+ fn add_assign ( & mut self , other : Ratio < T > ) {
375
+ self . numer = ( self . numer . clone ( ) * other. denom . clone ( ) ) . add ( self . denom . clone ( ) * other. numer ) ;
376
+ self . denom *= other. denom ;
377
+ self . reduce ( ) ;
378
+ }
379
+ }
380
+
381
+ impl < T : Clone + Integer + NumAssign > DivAssign for Ratio < T > {
382
+ fn div_assign ( & mut self , other : Ratio < T > ) {
383
+ self . numer *= other. denom ;
384
+ self . denom *= other. numer ;
385
+ self . reduce ( ) ;
386
+ }
387
+ }
388
+
389
+ impl < T : Clone + Integer + NumAssign > MulAssign for Ratio < T > {
390
+ fn mul_assign ( & mut self , other : Ratio < T > ) {
391
+ self . numer *= other. numer ;
392
+ self . denom *= other. denom ;
393
+ self . reduce ( ) ;
394
+ }
395
+ }
396
+
397
+ impl < T : Clone + Integer + NumAssign > RemAssign for Ratio < T > {
398
+ fn rem_assign ( & mut self , other : Ratio < T > ) {
399
+ self . numer = ( self . numer . clone ( ) * other. denom . clone ( ) ) . rem ( self . denom . clone ( ) * other. numer ) ;
400
+ self . denom *= other. denom ;
401
+ self . reduce ( ) ;
402
+ }
403
+ }
404
+
405
+ impl < T : Clone + Integer + NumAssign > SubAssign for Ratio < T > {
406
+ fn sub_assign ( & mut self , other : Ratio < T > ) {
407
+ self . numer = ( self . numer . clone ( ) * other. denom . clone ( ) ) . sub ( self . denom . clone ( ) * other. numer ) ;
408
+ self . denom *= other. denom ;
409
+ self . reduce ( ) ;
410
+ }
411
+ }
412
+
413
+ // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b
414
+ impl < T : Clone + Integer + NumAssign > AddAssign < T > for Ratio < T > {
415
+ fn add_assign ( & mut self , other : T ) {
416
+ self . numer += self . denom . clone ( ) * other;
417
+ self . reduce ( ) ;
418
+ }
419
+ }
420
+
421
+ impl < T : Clone + Integer + NumAssign > DivAssign < T > for Ratio < T > {
422
+ fn div_assign ( & mut self , other : T ) {
423
+ self . denom *= other;
424
+ self . reduce ( ) ;
425
+ }
426
+ }
427
+
428
+ impl < T : Clone + Integer + NumAssign > MulAssign < T > for Ratio < T > {
429
+ fn mul_assign ( & mut self , other : T ) {
430
+ self . numer *= other;
431
+ self . reduce ( ) ;
432
+ }
433
+ }
434
+
435
+ // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b
436
+ impl < T : Clone + Integer + NumAssign > RemAssign < T > for Ratio < T > {
437
+ fn rem_assign ( & mut self , other : T ) {
438
+ self . numer %= self . denom . clone ( ) * other;
439
+ self . reduce ( ) ;
440
+ }
441
+ }
442
+
443
+ // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b
444
+ impl < T : Clone + Integer + NumAssign > SubAssign < T > for Ratio < T > {
445
+ fn sub_assign ( & mut self , other : T ) {
446
+ self . numer -= self . denom . clone ( ) * other;
447
+ self . reduce ( ) ;
448
+ }
449
+ }
450
+
451
+ macro_rules! forward_op_assign {
452
+ ( impl $imp: ident, $method: ident) => {
453
+ impl <' a, T : Clone + Integer + NumAssign > $imp<& ' a Ratio <T >> for Ratio <T > {
454
+ #[ inline]
455
+ fn $method( & mut self , other: & Ratio <T >) {
456
+ self . $method( other. clone( ) )
457
+ }
458
+ }
459
+ impl <' a, T : Clone + Integer + NumAssign > $imp<& ' a T > for Ratio <T > {
460
+ #[ inline]
461
+ fn $method( & mut self , other: & T ) {
462
+ self . $method( other. clone( ) )
463
+ }
464
+ }
465
+ }
466
+ }
467
+
468
+ forward_op_assign ! ( impl AddAssign , add_assign) ;
469
+ forward_op_assign ! ( impl DivAssign , div_assign) ;
470
+ forward_op_assign ! ( impl MulAssign , mul_assign) ;
471
+ forward_op_assign ! ( impl RemAssign , rem_assign) ;
472
+ forward_op_assign ! ( impl SubAssign , sub_assign) ;
473
+ }
365
474
366
475
macro_rules! forward_val_val_binop {
367
476
( impl $imp: ident, $method: ident) => {
@@ -373,6 +482,14 @@ macro_rules! forward_val_val_binop {
373
482
( & self ) . $method( & other)
374
483
}
375
484
}
485
+ impl <T : Clone + Integer > $imp<T > for Ratio <T > {
486
+ type Output = Ratio <T >;
487
+
488
+ #[ inline]
489
+ fn $method( self , other: T ) -> Ratio <T > {
490
+ ( & self ) . $method( & other)
491
+ }
492
+ }
376
493
}
377
494
}
378
495
@@ -388,6 +505,16 @@ macro_rules! forward_ref_val_binop {
388
505
self . $method( & other)
389
506
}
390
507
}
508
+ impl <' a, T > $imp<T > for & ' a Ratio <T > where
509
+ T : Clone + Integer
510
+ {
511
+ type Output = Ratio <T >;
512
+
513
+ #[ inline]
514
+ fn $method( self , other: T ) -> Ratio <T > {
515
+ self . $method( & other)
516
+ }
517
+ }
391
518
}
392
519
}
393
520
@@ -403,6 +530,16 @@ macro_rules! forward_val_ref_binop {
403
530
( & self ) . $method( other)
404
531
}
405
532
}
533
+ impl <' a, T > $imp<& ' a T > for Ratio <T > where
534
+ T : Clone + Integer
535
+ {
536
+ type Output = Ratio <T >;
537
+
538
+ #[ inline]
539
+ fn $method( self , other: & T ) -> Ratio <T > {
540
+ ( & self ) . $method( other)
541
+ }
542
+ }
406
543
}
407
544
}
408
545
@@ -427,9 +564,20 @@ impl<'a, 'b, T> Mul<&'b Ratio<T>> for &'a Ratio<T>
427
564
self . denom . clone ( ) * rhs. denom . clone ( ) )
428
565
}
429
566
}
567
+ // a/b * c/1 = (a*c) / (b*1) = (a*c) / b
568
+ impl < ' a , ' b , T > Mul < & ' b T > for & ' a Ratio < T >
569
+ where T : Clone + Integer
570
+ {
571
+ type Output = Ratio < T > ;
572
+ #[ inline]
573
+ fn mul ( self , rhs : & T ) -> Ratio < T > {
574
+ Ratio :: new ( self . numer . clone ( ) * rhs. clone ( ) ,
575
+ self . denom . clone ( ) )
576
+ }
577
+ }
430
578
431
579
forward_all_binop ! ( impl Div , div) ;
432
- // (a/b) / (c/d) = (a*d)/ (b*c)
580
+ // (a/b) / (c/d) = (a*d) / (b*c)
433
581
impl < ' a , ' b , T > Div < & ' b Ratio < T > > for & ' a Ratio < T >
434
582
where T : Clone + Integer
435
583
{
@@ -441,11 +589,23 @@ impl<'a, 'b, T> Div<&'b Ratio<T>> for &'a Ratio<T>
441
589
self . denom . clone ( ) * rhs. numer . clone ( ) )
442
590
}
443
591
}
592
+ // (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c)
593
+ impl < ' a , ' b , T > Div < & ' b T > for & ' a Ratio < T >
594
+ where T : Clone + Integer
595
+ {
596
+ type Output = Ratio < T > ;
597
+
598
+ #[ inline]
599
+ fn div ( self , rhs : & T ) -> Ratio < T > {
600
+ Ratio :: new ( self . numer . clone ( ) ,
601
+ self . denom . clone ( ) * rhs. clone ( ) )
602
+ }
603
+ }
444
604
445
- // Abstracts the a/b `op` c/d = (a*d `op` b*c) / (b*d) pattern
446
605
macro_rules! arith_impl {
447
606
( impl $imp: ident, $method: ident) => {
448
607
forward_all_binop!( impl $imp, $method) ;
608
+ // Abstracts the a/b `op` c/d = (a*d `op` b*c) / (b*d) pattern
449
609
impl <' a, ' b, T : Clone + Integer >
450
610
$imp<& ' b Ratio <T >> for & ' a Ratio <T > {
451
611
type Output = Ratio <T >;
@@ -455,16 +615,21 @@ macro_rules! arith_impl {
455
615
self . denom. clone( ) * rhs. denom. clone( ) )
456
616
}
457
617
}
618
+ // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern
619
+ impl <' a, ' b, T : Clone + Integer >
620
+ $imp<& ' b T > for & ' a Ratio <T > {
621
+ type Output = Ratio <T >;
622
+ #[ inline]
623
+ fn $method( self , rhs: & ' b T ) -> Ratio <T > {
624
+ Ratio :: new( self . numer. clone( ) . $method( self . denom. clone( ) * rhs. clone( ) ) ,
625
+ self . denom. clone( ) )
626
+ }
627
+ }
458
628
}
459
629
}
460
630
461
- // a/b + c/d = (a*d + b*c)/(b*d)
462
631
arith_impl ! ( impl Add , add) ;
463
-
464
- // a/b - c/d = (a*d - b*c)/(b*d)
465
632
arith_impl ! ( impl Sub , sub) ;
466
-
467
- // a/b % c/d = (a*d % b*c)/(b*d)
468
633
arith_impl ! ( impl Rem , rem) ;
469
634
470
635
// Like `std::try!` for Option<T>, unwrap the value or early-return None.
@@ -1164,69 +1329,99 @@ mod test {
1164
1329
fn test_add ( ) {
1165
1330
fn test ( a : Rational , b : Rational , c : Rational ) {
1166
1331
assert_eq ! ( a + b, c) ;
1332
+ assert_eq ! ( { let mut x = a; x += b; x} , c) ;
1167
1333
assert_eq ! ( to_big( a) + to_big( b) , to_big( c) ) ;
1168
1334
assert_eq ! ( a. checked_add( & b) , Some ( c) ) ;
1169
1335
assert_eq ! ( to_big( a) . checked_add( & to_big( b) ) , Some ( to_big( c) ) ) ;
1170
1336
}
1337
+ fn test_assign ( a : Rational , b : isize , c : Rational ) {
1338
+ assert_eq ! ( a + b, c) ;
1339
+ assert_eq ! ( { let mut x = a; x += b; x} , c) ;
1340
+ }
1171
1341
1172
1342
test ( _1, _1_2, _3_2) ;
1173
1343
test ( _1, _1, _2) ;
1174
1344
test ( _1_2, _3_2, _2) ;
1175
1345
test ( _1_2, _NEG1_2, _0) ;
1346
+ test_assign ( _1_2, 1 , _3_2) ;
1176
1347
}
1177
1348
1178
1349
#[ test]
1179
1350
fn test_sub ( ) {
1180
1351
fn test ( a : Rational , b : Rational , c : Rational ) {
1181
1352
assert_eq ! ( a - b, c) ;
1353
+ assert_eq ! ( { let mut x = a; x -= b; x} , c) ;
1182
1354
assert_eq ! ( to_big( a) - to_big( b) , to_big( c) ) ;
1183
1355
assert_eq ! ( a. checked_sub( & b) , Some ( c) ) ;
1184
1356
assert_eq ! ( to_big( a) . checked_sub( & to_big( b) ) , Some ( to_big( c) ) ) ;
1185
1357
}
1358
+ fn test_assign ( a : Rational , b : isize , c : Rational ) {
1359
+ assert_eq ! ( a - b, c) ;
1360
+ assert_eq ! ( { let mut x = a; x -= b; x} , c) ;
1361
+ }
1186
1362
1187
1363
test ( _1, _1_2, _1_2) ;
1188
1364
test ( _3_2, _1_2, _1) ;
1189
1365
test ( _1, _NEG1_2, _3_2) ;
1366
+ test_assign ( _1_2, 1 , _NEG1_2) ;
1190
1367
}
1191
1368
1192
1369
#[ test]
1193
1370
fn test_mul ( ) {
1194
1371
fn test ( a : Rational , b : Rational , c : Rational ) {
1195
1372
assert_eq ! ( a * b, c) ;
1373
+ assert_eq ! ( { let mut x = a; x *= b; x} , c) ;
1196
1374
assert_eq ! ( to_big( a) * to_big( b) , to_big( c) ) ;
1197
1375
assert_eq ! ( a. checked_mul( & b) , Some ( c) ) ;
1198
1376
assert_eq ! ( to_big( a) . checked_mul( & to_big( b) ) , Some ( to_big( c) ) ) ;
1199
1377
}
1378
+ fn test_assign ( a : Rational , b : isize , c : Rational ) {
1379
+ assert_eq ! ( a * b, c) ;
1380
+ assert_eq ! ( { let mut x = a; x *= b; x} , c) ;
1381
+ }
1200
1382
1201
1383
test ( _1, _1_2, _1_2) ;
1202
1384
test ( _1_2, _3_2, Ratio :: new ( 3 , 4 ) ) ;
1203
1385
test ( _1_2, _NEG1_2, Ratio :: new ( -1 , 4 ) ) ;
1386
+ test_assign ( _1_2, 2 , _1) ;
1204
1387
}
1205
1388
1206
1389
#[ test]
1207
1390
fn test_div ( ) {
1208
1391
fn test ( a : Rational , b : Rational , c : Rational ) {
1209
1392
assert_eq ! ( a / b, c) ;
1393
+ assert_eq ! ( { let mut x = a; x /= b; x} , c) ;
1210
1394
assert_eq ! ( to_big( a) / to_big( b) , to_big( c) ) ;
1211
1395
assert_eq ! ( a. checked_div( & b) , Some ( c) ) ;
1212
1396
assert_eq ! ( to_big( a) . checked_div( & to_big( b) ) , Some ( to_big( c) ) ) ;
1213
1397
}
1398
+ fn test_assign ( a : Rational , b : isize , c : Rational ) {
1399
+ assert_eq ! ( a / b, c) ;
1400
+ assert_eq ! ( { let mut x = a; x /= b; x} , c) ;
1401
+ }
1214
1402
1215
1403
test ( _1, _1_2, _2) ;
1216
1404
test ( _3_2, _1_2, _1 + _2) ;
1217
1405
test ( _1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2) ;
1406
+ test_assign ( _1, 2 , _1_2) ;
1218
1407
}
1219
1408
1220
1409
#[ test]
1221
1410
fn test_rem ( ) {
1222
1411
fn test ( a : Rational , b : Rational , c : Rational ) {
1223
1412
assert_eq ! ( a % b, c) ;
1413
+ assert_eq ! ( { let mut x = a; x %= b; x} , c) ;
1224
1414
assert_eq ! ( to_big( a) % to_big( b) , to_big( c) )
1225
1415
}
1416
+ fn test_assign ( a : Rational , b : isize , c : Rational ) {
1417
+ assert_eq ! ( a % b, c) ;
1418
+ assert_eq ! ( { let mut x = a; x %= b; x} , c) ;
1419
+ }
1226
1420
1227
1421
test ( _3_2, _1, _1_2) ;
1228
1422
test ( _2, _NEG1_2, _0) ;
1229
1423
test ( _1_2, _2, _1_2) ;
1424
+ test_assign ( _3_2, 1 , _1_2) ;
1230
1425
}
1231
1426
1232
1427
#[ test]
0 commit comments