@@ -466,6 +466,56 @@ impl<T: Zero> Zero for ~T {
466
466
fn is_zero ( & self ) -> bool { ( * * self ) . is_zero ( ) }
467
467
}
468
468
469
+ /// Saturating math operations
470
+ pub trait Saturating : Int {
471
+ /// Saturating addition operator.
472
+ /// Returns a+b, saturating at the numeric bounds instead of overflowing.
473
+ #[ inline]
474
+ fn saturating_add ( self , v : Self ) -> Self {
475
+ let x = self + v;
476
+ if v >= Zero :: zero ( ) {
477
+ if x < self {
478
+ // overflow
479
+ Bounded :: max_value :: < Self > ( )
480
+ } else { x }
481
+ } else {
482
+ if x > self {
483
+ // underflow
484
+ Bounded :: min_value :: < Self > ( )
485
+ } else { x }
486
+ }
487
+ }
488
+
489
+ /// Saturating subtraction operator.
490
+ /// Returns a-b, saturating at the numeric bounds instead of overflowing.
491
+ #[ inline]
492
+ fn saturating_sub ( self , v : Self ) -> Self {
493
+ let x = self - v;
494
+ if v >= Zero :: zero ( ) {
495
+ if x > self {
496
+ // underflow
497
+ Bounded :: min_value :: < Self > ( )
498
+ } else { x }
499
+ } else {
500
+ if x < self {
501
+ // overflow
502
+ Bounded :: max_value :: < Self > ( )
503
+ } else { x }
504
+ }
505
+ }
506
+ }
507
+
508
+ impl Saturating for int { }
509
+ impl Saturating for i8 { }
510
+ impl Saturating for i16 { }
511
+ impl Saturating for i32 { }
512
+ impl Saturating for i64 { }
513
+ impl Saturating for uint { }
514
+ impl Saturating for u8 { }
515
+ impl Saturating for u16 { }
516
+ impl Saturating for u32 { }
517
+ impl Saturating for u64 { }
518
+
469
519
/// Helper function for testing numeric operations
470
520
#[ cfg( test) ]
471
521
pub fn test_num < T : Num + NumCast > ( ten : T , two : T ) {
@@ -482,64 +532,111 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
482
532
assert_eq ! ( ten. rem( & two) , ten % two) ;
483
533
}
484
534
485
- macro_rules! test_cast_20(
486
- ( $_20: expr) => ( {
487
- let _20 = $_20;
488
-
489
- assert_eq!( 20 u, _20. to_uint( ) ) ;
490
- assert_eq!( 20u8 , _20. to_u8( ) ) ;
491
- assert_eq!( 20u16 , _20. to_u16( ) ) ;
492
- assert_eq!( 20u32 , _20. to_u32( ) ) ;
493
- assert_eq!( 20u64 , _20. to_u64( ) ) ;
494
- assert_eq!( 20 i, _20. to_int( ) ) ;
495
- assert_eq!( 20i8 , _20. to_i8( ) ) ;
496
- assert_eq!( 20i16 , _20. to_i16( ) ) ;
497
- assert_eq!( 20i32 , _20. to_i32( ) ) ;
498
- assert_eq!( 20i64 , _20. to_i64( ) ) ;
499
- assert_eq!( 20 f, _20. to_float( ) ) ;
500
- assert_eq!( 20f32 , _20. to_f32( ) ) ;
501
- assert_eq!( 20f64 , _20. to_f64( ) ) ;
502
-
503
- assert_eq!( _20, NumCast :: from( 20 u) ) ;
504
- assert_eq!( _20, NumCast :: from( 20u8 ) ) ;
505
- assert_eq!( _20, NumCast :: from( 20u16 ) ) ;
506
- assert_eq!( _20, NumCast :: from( 20u32 ) ) ;
507
- assert_eq!( _20, NumCast :: from( 20u64 ) ) ;
508
- assert_eq!( _20, NumCast :: from( 20 i) ) ;
509
- assert_eq!( _20, NumCast :: from( 20i8 ) ) ;
510
- assert_eq!( _20, NumCast :: from( 20i16 ) ) ;
511
- assert_eq!( _20, NumCast :: from( 20i32 ) ) ;
512
- assert_eq!( _20, NumCast :: from( 20i64 ) ) ;
513
- assert_eq!( _20, NumCast :: from( 20 f) ) ;
514
- assert_eq!( _20, NumCast :: from( 20f32 ) ) ;
515
- assert_eq!( _20, NumCast :: from( 20f64 ) ) ;
516
-
517
- assert_eq!( _20, cast( 20 u) ) ;
518
- assert_eq!( _20, cast( 20u8 ) ) ;
519
- assert_eq!( _20, cast( 20u16 ) ) ;
520
- assert_eq!( _20, cast( 20u32 ) ) ;
521
- assert_eq!( _20, cast( 20u64 ) ) ;
522
- assert_eq!( _20, cast( 20 i) ) ;
523
- assert_eq!( _20, cast( 20i8 ) ) ;
524
- assert_eq!( _20, cast( 20i16 ) ) ;
525
- assert_eq!( _20, cast( 20i32 ) ) ;
526
- assert_eq!( _20, cast( 20i64 ) ) ;
527
- assert_eq!( _20, cast( 20 f) ) ;
528
- assert_eq!( _20, cast( 20f32 ) ) ;
529
- assert_eq!( _20, cast( 20f64 ) ) ;
530
- } )
531
- )
535
+ #[ cfg( test) ]
536
+ mod tests {
537
+ use super :: * ;
538
+
539
+ macro_rules! test_cast_20(
540
+ ( $_20: expr) => ( {
541
+ let _20 = $_20;
542
+
543
+ assert_eq!( 20 u, _20. to_uint( ) ) ;
544
+ assert_eq!( 20u8 , _20. to_u8( ) ) ;
545
+ assert_eq!( 20u16 , _20. to_u16( ) ) ;
546
+ assert_eq!( 20u32 , _20. to_u32( ) ) ;
547
+ assert_eq!( 20u64 , _20. to_u64( ) ) ;
548
+ assert_eq!( 20 i, _20. to_int( ) ) ;
549
+ assert_eq!( 20i8 , _20. to_i8( ) ) ;
550
+ assert_eq!( 20i16 , _20. to_i16( ) ) ;
551
+ assert_eq!( 20i32 , _20. to_i32( ) ) ;
552
+ assert_eq!( 20i64 , _20. to_i64( ) ) ;
553
+ assert_eq!( 20 f, _20. to_float( ) ) ;
554
+ assert_eq!( 20f32 , _20. to_f32( ) ) ;
555
+ assert_eq!( 20f64 , _20. to_f64( ) ) ;
556
+
557
+ assert_eq!( _20, NumCast :: from( 20 u) ) ;
558
+ assert_eq!( _20, NumCast :: from( 20u8 ) ) ;
559
+ assert_eq!( _20, NumCast :: from( 20u16 ) ) ;
560
+ assert_eq!( _20, NumCast :: from( 20u32 ) ) ;
561
+ assert_eq!( _20, NumCast :: from( 20u64 ) ) ;
562
+ assert_eq!( _20, NumCast :: from( 20 i) ) ;
563
+ assert_eq!( _20, NumCast :: from( 20i8 ) ) ;
564
+ assert_eq!( _20, NumCast :: from( 20i16 ) ) ;
565
+ assert_eq!( _20, NumCast :: from( 20i32 ) ) ;
566
+ assert_eq!( _20, NumCast :: from( 20i64 ) ) ;
567
+ assert_eq!( _20, NumCast :: from( 20 f) ) ;
568
+ assert_eq!( _20, NumCast :: from( 20f32 ) ) ;
569
+ assert_eq!( _20, NumCast :: from( 20f64 ) ) ;
570
+
571
+ assert_eq!( _20, cast( 20 u) ) ;
572
+ assert_eq!( _20, cast( 20u8 ) ) ;
573
+ assert_eq!( _20, cast( 20u16 ) ) ;
574
+ assert_eq!( _20, cast( 20u32 ) ) ;
575
+ assert_eq!( _20, cast( 20u64 ) ) ;
576
+ assert_eq!( _20, cast( 20 i) ) ;
577
+ assert_eq!( _20, cast( 20i8 ) ) ;
578
+ assert_eq!( _20, cast( 20i16 ) ) ;
579
+ assert_eq!( _20, cast( 20i32 ) ) ;
580
+ assert_eq!( _20, cast( 20i64 ) ) ;
581
+ assert_eq!( _20, cast( 20 f) ) ;
582
+ assert_eq!( _20, cast( 20f32 ) ) ;
583
+ assert_eq!( _20, cast( 20f64 ) ) ;
584
+ } )
585
+ )
586
+
587
+ #[ test] fn test_u8_cast ( ) { test_cast_20 ! ( 20u8 ) }
588
+ #[ test] fn test_u16_cast ( ) { test_cast_20 ! ( 20u16 ) }
589
+ #[ test] fn test_u32_cast ( ) { test_cast_20 ! ( 20u32 ) }
590
+ #[ test] fn test_u64_cast ( ) { test_cast_20 ! ( 20u64 ) }
591
+ #[ test] fn test_uint_cast ( ) { test_cast_20 ! ( 20 u) }
592
+ #[ test] fn test_i8_cast ( ) { test_cast_20 ! ( 20i8 ) }
593
+ #[ test] fn test_i16_cast ( ) { test_cast_20 ! ( 20i16 ) }
594
+ #[ test] fn test_i32_cast ( ) { test_cast_20 ! ( 20i32 ) }
595
+ #[ test] fn test_i64_cast ( ) { test_cast_20 ! ( 20i64 ) }
596
+ #[ test] fn test_int_cast ( ) { test_cast_20 ! ( 20 i) }
597
+ #[ test] fn test_f32_cast ( ) { test_cast_20 ! ( 20f32 ) }
598
+ #[ test] fn test_f64_cast ( ) { test_cast_20 ! ( 20f64 ) }
599
+ #[ test] fn test_float_cast ( ) { test_cast_20 ! ( 20 f) }
600
+
601
+ #[ test]
602
+ fn test_saturating_add_uint ( ) {
603
+ use uint:: max_value;
604
+ assert_eq ! ( 3 u. saturating_add( 5 u) , 8 u) ;
605
+ assert_eq ! ( 3 u. saturating_add( max_value-1 ) , max_value) ;
606
+ assert_eq ! ( max_value. saturating_add( max_value) , max_value) ;
607
+ assert_eq ! ( ( max_value-2 ) . saturating_add( 1 ) , max_value-1 ) ;
608
+ }
609
+
610
+ #[ test]
611
+ fn test_saturating_sub_uint ( ) {
612
+ use uint:: max_value;
613
+ assert_eq ! ( 5 u. saturating_sub( 3 u) , 2 u) ;
614
+ assert_eq ! ( 3 u. saturating_sub( 5 u) , 0 u) ;
615
+ assert_eq ! ( 0 u. saturating_sub( 1 u) , 0 u) ;
616
+ assert_eq ! ( ( max_value-1 ) . saturating_sub( max_value) , 0 ) ;
617
+ }
532
618
533
- #[ test] fn test_u8_cast ( ) { test_cast_20 ! ( 20u8 ) }
534
- #[ test] fn test_u16_cast ( ) { test_cast_20 ! ( 20u16 ) }
535
- #[ test] fn test_u32_cast ( ) { test_cast_20 ! ( 20u32 ) }
536
- #[ test] fn test_u64_cast ( ) { test_cast_20 ! ( 20u64 ) }
537
- #[ test] fn test_uint_cast ( ) { test_cast_20 ! ( 20 u) }
538
- #[ test] fn test_i8_cast ( ) { test_cast_20 ! ( 20i8 ) }
539
- #[ test] fn test_i16_cast ( ) { test_cast_20 ! ( 20i16 ) }
540
- #[ test] fn test_i32_cast ( ) { test_cast_20 ! ( 20i32 ) }
541
- #[ test] fn test_i64_cast ( ) { test_cast_20 ! ( 20i64 ) }
542
- #[ test] fn test_int_cast ( ) { test_cast_20 ! ( 20 i) }
543
- #[ test] fn test_f32_cast ( ) { test_cast_20 ! ( 20f32 ) }
544
- #[ test] fn test_f64_cast ( ) { test_cast_20 ! ( 20f64 ) }
545
- #[ test] fn test_float_cast ( ) { test_cast_20 ! ( 20 f) }
619
+ #[ test]
620
+ fn test_saturating_add_int ( ) {
621
+ use int:: { min_value, max_value} ;
622
+ assert_eq ! ( 3 i. saturating_add( 5 i) , 8 i) ;
623
+ assert_eq ! ( 3 i. saturating_add( max_value-1 ) , max_value) ;
624
+ assert_eq ! ( max_value. saturating_add( max_value) , max_value) ;
625
+ assert_eq ! ( ( max_value-2 ) . saturating_add( 1 ) , max_value-1 ) ;
626
+ assert_eq ! ( 3 i. saturating_add( -5 i) , -2 i) ;
627
+ assert_eq ! ( min_value. saturating_add( -1 i) , min_value) ;
628
+ assert_eq ! ( ( -2 i) . saturating_add( -max_value) , min_value) ;
629
+ }
630
+
631
+ #[ test]
632
+ fn test_saturating_sub_int ( ) {
633
+ use int:: { min_value, max_value} ;
634
+ assert_eq ! ( 3 i. saturating_sub( 5 i) , -2 i) ;
635
+ assert_eq ! ( min_value. saturating_sub( 1 i) , min_value) ;
636
+ assert_eq ! ( ( -2 i) . saturating_sub( max_value) , min_value) ;
637
+ assert_eq ! ( 3 i. saturating_sub( -5 i) , 8 i) ;
638
+ assert_eq ! ( 3 i. saturating_sub( -( max_value-1 ) ) , max_value) ;
639
+ assert_eq ! ( max_value. saturating_sub( -max_value) , max_value) ;
640
+ assert_eq ! ( ( max_value-2 ) . saturating_sub( -1 ) , max_value-1 ) ;
641
+ }
642
+ }
0 commit comments