1+ use crate :: Uint256 ;
2+
13/// A fraction `p`/`q` with integers `p` and `q`.
24///
35/// `p` is called the numerator and `q` is called the denominator.
@@ -13,17 +15,21 @@ pub trait Fraction<T>: Sized {
1315 fn inv ( & self ) -> Option < Self > ;
1416}
1517
16- impl < T : Clone > Fraction < T > for ( T , T ) {
18+ impl < T : Copy + Into < Uint256 > > Fraction < T > for ( T , T ) {
1719 fn numerator ( & self ) -> T {
18- self . 0 . clone ( )
20+ self . 0
1921 }
2022
2123 fn denominator ( & self ) -> T {
22- self . 1 . clone ( )
24+ self . 1
2325 }
2426
2527 fn inv ( & self ) -> Option < Self > {
26- Some ( ( self . 1 . clone ( ) , self . 0 . clone ( ) ) )
28+ if self . numerator ( ) . into ( ) == Uint256 :: zero ( ) {
29+ None
30+ } else {
31+ Some ( ( self . 1 , self . 0 ) )
32+ }
2733 }
2834}
2935
@@ -46,23 +52,42 @@ macro_rules! impl_mul_fraction {
4652 self . checked_mul_floored( rhs) . unwrap( )
4753 }
4854
49- pub fn checked_mul_ceil<F : Fraction <T > + Clone , T : Into <$Uint>>(
55+ pub fn checked_mul_ceil<F : Fraction <T >, T : Into <$Uint>>(
5056 self ,
5157 rhs: F ,
5258 ) -> Result <Self , CheckedMultiplyFractionError > {
53- let floor_result = self . checked_mul_floored( rhs. clone( ) ) ?;
5459 let numerator = rhs. numerator( ) . into( ) ;
5560 let denominator = rhs. denominator( ) . into( ) ;
61+ let floor_result = self . checked_mul_floored( rhs) ?;
5662 if !numerator. checked_rem( denominator) ?. is_zero( ) {
5763 Ok ( $Uint:: one( ) . checked_add( floor_result) ?)
5864 } else {
5965 Ok ( floor_result)
6066 }
6167 }
6268
63- pub fn mul_ceil<F : Fraction <T > + Clone , T : Into <$Uint>>( self , rhs: F ) -> Self {
69+ pub fn mul_ceil<F : Fraction <T >, T : Into <$Uint>>( self , rhs: F ) -> Self {
6470 self . checked_mul_ceil( rhs) . unwrap( )
6571 }
6672 }
6773 } ;
6874}
75+
76+ #[ cfg( test) ]
77+ mod tests {
78+ use crate :: { Fraction , Uint128 , Uint64 } ;
79+
80+ #[ test]
81+ fn fraction_tuple_methods ( ) {
82+ let fraction = ( Uint64 :: one ( ) , Uint64 :: new ( 2 ) ) ;
83+ assert_eq ! ( Uint64 :: one( ) , fraction. numerator( ) ) ;
84+ assert_eq ! ( Uint64 :: new( 2 ) , fraction. denominator( ) ) ;
85+ assert_eq ! ( Some ( ( Uint64 :: new( 2 ) , Uint64 :: one( ) ) ) , fraction. inv( ) ) ;
86+ }
87+
88+ #[ test]
89+ fn inverse_with_zero_denominator ( ) {
90+ let fraction = ( Uint128 :: zero ( ) , Uint128 :: one ( ) ) ;
91+ assert_eq ! ( None , fraction. inv( ) ) ;
92+ }
93+ }
0 commit comments