1- use serde:: { Deserialize , Serialize } ;
2-
3- use crate :: errors:: CheckedMultiplyFractionalError ;
4- use crate :: Uint512 ;
5-
61/// A fraction `p`/`q` with integers `p` and `q`.
72///
83/// `p` is called the numerator and `q` is called the denominator.
9- pub trait Fractional < T > : Sized {
4+ pub trait Fraction < T > : Sized {
105 /// Returns the numerator `p`
116 fn numerator ( & self ) -> T ;
127 /// Returns the denominator `q`
@@ -18,16 +13,7 @@ pub trait Fractional<T>: Sized {
1813 fn inv ( & self ) -> Option < Self > ;
1914}
2015
21- #[ derive( Serialize , Deserialize , Clone , Debug , PartialEq , Eq ) ]
22- pub struct Fraction < T > ( T , T ) ;
23-
24- impl < T > Fraction < T > {
25- pub fn new ( numerator : T , denominator : T ) -> Self {
26- Self ( numerator, denominator)
27- }
28- }
29-
30- impl < T : Clone > Fractional < T > for Fraction < T > {
16+ impl < T : Clone > Fraction < T > for ( T , T ) {
3117 fn numerator ( & self ) -> T {
3218 self . 0 . clone ( )
3319 }
@@ -37,66 +23,46 @@ impl<T: Clone> Fractional<T> for Fraction<T> {
3723 }
3824
3925 fn inv ( & self ) -> Option < Self > {
40- unimplemented ! ( )
26+ Some ( ( self . 1 . clone ( ) , self . 0 . clone ( ) ) )
4127 }
4228}
4329
44- pub trait FractionMath {
45- fn checked_mul_floored < F : Fractional < T > , T : Into < Uint512 > > (
46- self ,
47- rhs : F ,
48- ) -> Result < Self , CheckedMultiplyFractionalError >
49- where
50- Self : Sized ;
51-
52- fn mul_floored < F : Fractional < T > , T : Into < Uint512 > > ( self , rhs : F ) -> Self ;
53-
54- fn checked_mul_ceil < F : Fractional < T > + Clone , T : Into < Uint512 > > (
55- self ,
56- rhs : F ,
57- ) -> Result < Self , CheckedMultiplyFractionalError >
58- where
59- Self : Sized ;
60-
61- fn mul_ceil < F : Fractional < T > + Clone , T : Into < Uint512 > > ( self , rhs : F ) -> Self ;
62- }
63-
6430#[ macro_export]
65- macro_rules! fraction_math {
66- ( $name : ident) => {
67- impl FractionMath for $name {
68- fn checked_mul_floored<F : Fractional <T >, T : Into <Uint512 >>(
31+ macro_rules! impl_mul_fraction {
32+ ( $UintBase : ident , $UintLarger : ident) => {
33+ impl $UintBase {
34+ pub fn checked_mul_floored<F : Fraction <T >, T : Into <$UintBase >>(
6935 self ,
7036 rhs: F ,
71- ) -> Result <Self , CheckedMultiplyFractionalError > {
72- let res = Uint512 :: from ( self )
73- . checked_mul ( rhs. numerator( ) . into( ) ) ?
74- . checked_div( rhs. denominator( ) . into( ) ) ?;
37+ ) -> Result <Self , CheckedMultiplyFractionError > {
38+ let res = self
39+ . full_mul ( rhs. numerator( ) . into( ) )
40+ . checked_div( $UintLarger :: from ( rhs. denominator( ) . into( ) ) ) ?;
7541 Ok ( res. try_into( ) ?)
7642 }
7743
78- fn mul_floored<F : Fractional <T >, T : Into <Uint512 >>( self , rhs: F ) -> Self {
44+ pub fn mul_floored<F : Fraction <T >, T : Into <$UintBase >>( self , rhs: F ) -> Self {
7945 self . checked_mul_floored( rhs) . unwrap( )
8046 }
8147
82- fn mul_ceil<F : Fractional <T > + Clone , T : Into <Uint512 >>( self , rhs: F ) -> Self {
83- self . checked_mul_ceil( rhs) . unwrap( )
84- }
85-
86- fn checked_mul_ceil<F : Fractional <T > + Clone , T : Into <Uint512 >>(
48+ pub fn checked_mul_ceil<F : Fraction <T > + Clone , T : Into <$UintBase>>(
8749 self ,
8850 rhs: F ,
89- ) -> Result <Self , CheckedMultiplyFractionalError > {
51+ ) -> Result <Self , CheckedMultiplyFractionError > {
9052 let floor_result = self . checked_mul_floored( rhs. clone( ) ) ?;
9153 let numerator = rhs. numerator( ) . into( ) ;
9254 let denominator = rhs. denominator( ) . into( ) ;
9355 if !numerator. checked_rem( denominator) ?. is_zero( ) {
94- let ceil_result = Uint512 :: one( ) . checked_add( floor_result. into( ) ) ?;
56+ let ceil_result = $UintLarger :: one( ) . checked_add( floor_result. into( ) ) ?;
9557 Ok ( ceil_result. try_into( ) ?)
9658 } else {
9759 Ok ( floor_result)
9860 }
9961 }
62+
63+ pub fn mul_ceil<F : Fraction <T > + Clone , T : Into <$UintBase>>( self , rhs: F ) -> Self {
64+ self . checked_mul_ceil( rhs) . unwrap( )
65+ }
10066 }
10167 } ;
10268}
0 commit comments