1
+ use crate :: Uint256 ;
2
+
1
3
/// A fraction `p`/`q` with integers `p` and `q`.
2
4
///
3
5
/// `p` is called the numerator and `q` is called the denominator.
@@ -13,17 +15,21 @@ pub trait Fraction<T>: Sized {
13
15
fn inv ( & self ) -> Option < Self > ;
14
16
}
15
17
16
- impl < T : Clone > Fraction < T > for ( T , T ) {
18
+ impl < T : Copy + Into < Uint256 > > Fraction < T > for ( T , T ) {
17
19
fn numerator ( & self ) -> T {
18
- self . 0 . clone ( )
20
+ self . 0
19
21
}
20
22
21
23
fn denominator ( & self ) -> T {
22
- self . 1 . clone ( )
24
+ self . 1
23
25
}
24
26
25
27
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
+ }
27
33
}
28
34
}
29
35
@@ -46,23 +52,42 @@ macro_rules! impl_mul_fraction {
46
52
self . checked_mul_floored( rhs) . unwrap( )
47
53
}
48
54
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>>(
50
56
self ,
51
57
rhs: F ,
52
58
) -> Result <Self , CheckedMultiplyFractionError > {
53
- let floor_result = self . checked_mul_floored( rhs. clone( ) ) ?;
54
59
let numerator = rhs. numerator( ) . into( ) ;
55
60
let denominator = rhs. denominator( ) . into( ) ;
61
+ let floor_result = self . checked_mul_floored( rhs) ?;
56
62
if !numerator. checked_rem( denominator) ?. is_zero( ) {
57
63
Ok ( $Uint:: one( ) . checked_add( floor_result) ?)
58
64
} else {
59
65
Ok ( floor_result)
60
66
}
61
67
}
62
68
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 {
64
70
self . checked_mul_ceil( rhs) . unwrap( )
65
71
}
66
72
}
67
73
} ;
68
74
}
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