@@ -9,7 +9,7 @@ use thiserror::Error;
99
1010use crate :: errors:: {
1111 CheckedFromRatioError , CheckedMultiplyRatioError , DivideByZeroError , OverflowError ,
12- OverflowOperation , StdError ,
12+ OverflowOperation , RoundUpOverflowError , StdError ,
1313} ;
1414use crate :: { Decimal , Uint512 } ;
1515
@@ -197,6 +197,31 @@ impl Decimal256 {
197197 Self :: DECIMAL_PLACES as u32
198198 }
199199
200+ /// Rounds value down after decimal places.
201+ pub fn floor ( & self ) -> Self {
202+ Self ( ( self . 0 / Self :: DECIMAL_FRACTIONAL ) * Self :: DECIMAL_FRACTIONAL )
203+ }
204+
205+ /// Rounds value up after decimal places. Panics on overflow.
206+ pub fn ceil ( & self ) -> Self {
207+ match self . checked_ceil ( ) {
208+ Ok ( value) => value,
209+ Err ( _) => panic ! ( "attempt to ceil with overflow" ) ,
210+ }
211+ }
212+
213+ /// Rounds value up after decimal places. Returns OverflowError on overflow.
214+ pub fn checked_ceil ( & self ) -> Result < Self , RoundUpOverflowError > {
215+ let floor = self . floor ( ) ;
216+ if & floor == self {
217+ Ok ( floor)
218+ } else {
219+ floor
220+ . checked_add ( Decimal256 :: one ( ) )
221+ . map_err ( |_| RoundUpOverflowError )
222+ }
223+ }
224+
200225 pub fn checked_add ( self , other : Self ) -> Result < Self , OverflowError > {
201226 self . 0
202227 . checked_add ( other. 0 )
@@ -2022,4 +2047,34 @@ mod tests {
20222047 ) ;
20232048 assert_eq ! ( Decimal256 :: MAX . saturating_pow( 2u32 ) , Decimal256 :: MAX ) ;
20242049 }
2050+
2051+ #[ test]
2052+ fn decimal256_rounding ( ) {
2053+ assert_eq ! ( Decimal256 :: one( ) . floor( ) , Decimal256 :: one( ) ) ;
2054+ assert_eq ! ( Decimal256 :: percent( 150 ) . floor( ) , Decimal256 :: one( ) ) ;
2055+ assert_eq ! ( Decimal256 :: percent( 199 ) . floor( ) , Decimal256 :: one( ) ) ;
2056+ assert_eq ! ( Decimal256 :: percent( 200 ) . floor( ) , Decimal256 :: percent( 200 ) ) ;
2057+ assert_eq ! ( Decimal256 :: percent( 99 ) . floor( ) , Decimal256 :: zero( ) ) ;
2058+
2059+ assert_eq ! ( Decimal256 :: one( ) . ceil( ) , Decimal256 :: one( ) ) ;
2060+ assert_eq ! ( Decimal256 :: percent( 150 ) . ceil( ) , Decimal256 :: percent( 200 ) ) ;
2061+ assert_eq ! ( Decimal256 :: percent( 199 ) . ceil( ) , Decimal256 :: percent( 200 ) ) ;
2062+ assert_eq ! ( Decimal256 :: percent( 99 ) . ceil( ) , Decimal256 :: one( ) ) ;
2063+ assert_eq ! ( Decimal256 ( Uint256 :: from( 1u128 ) ) . ceil( ) , Decimal256 :: one( ) ) ;
2064+ }
2065+
2066+ #[ test]
2067+ #[ should_panic( expected = "attempt to ceil with overflow" ) ]
2068+ fn decimal256_ceil_panics ( ) {
2069+ let _ = Decimal256 :: MAX . ceil ( ) ;
2070+ }
2071+
2072+ #[ test]
2073+ fn decimal256_checked_ceil ( ) {
2074+ assert_eq ! (
2075+ Decimal256 :: percent( 199 ) . checked_ceil( ) ,
2076+ Ok ( Decimal256 :: percent( 200 ) )
2077+ ) ;
2078+ assert_eq ! ( Decimal256 :: MAX . checked_ceil( ) , Err ( RoundUpOverflowError ) ) ;
2079+ }
20252080}
0 commit comments