@@ -7,8 +7,11 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, S
77use std:: str:: FromStr ;
88use thiserror:: Error ;
99
10- use crate :: errors:: { CheckedFromRatioError , CheckedMultiplyRatioError , StdError } ;
11- use crate :: { Decimal , OverflowError , Uint512 } ;
10+ use crate :: errors:: {
11+ CheckedFromRatioError , CheckedMultiplyRatioError , DivideByZeroError , OverflowError ,
12+ OverflowOperation , StdError ,
13+ } ;
14+ use crate :: { Decimal , Uint512 } ;
1215
1316use super :: Fraction ;
1417use super :: Isqrt ;
@@ -194,6 +197,20 @@ impl Decimal256 {
194197 Self :: DECIMAL_PLACES as u32
195198 }
196199
200+ pub fn checked_add ( self , other : Self ) -> Result < Self , OverflowError > {
201+ self . 0
202+ . checked_add ( other. 0 )
203+ . map ( Self )
204+ . map_err ( |_| OverflowError :: new ( OverflowOperation :: Add , self , other) )
205+ }
206+
207+ pub fn checked_sub ( self , other : Self ) -> Result < Self , OverflowError > {
208+ self . 0
209+ . checked_sub ( other. 0 )
210+ . map ( Self )
211+ . map_err ( |_| OverflowError :: new ( OverflowOperation :: Sub , self , other) )
212+ }
213+
197214 /// Multiplies one `Decimal256` by another, returning an `OverflowError` if an overflow occurred.
198215 pub fn checked_mul ( self , other : Self ) -> Result < Self , OverflowError > {
199216 let result_as_uint512 = self . numerator ( ) . full_mul ( other. numerator ( ) )
@@ -241,6 +258,17 @@ impl Decimal256 {
241258 } )
242259 }
243260
261+ pub fn checked_div ( self , other : Self ) -> Result < Self , CheckedFromRatioError > {
262+ Decimal256 :: checked_from_ratio ( self . numerator ( ) , other. numerator ( ) )
263+ }
264+
265+ pub fn checked_rem ( self , other : Self ) -> Result < Self , DivideByZeroError > {
266+ self . 0
267+ . checked_rem ( other. 0 )
268+ . map ( Self )
269+ . map_err ( |_| DivideByZeroError :: new ( self ) )
270+ }
271+
244272 /// Returns the approximate square root as a Decimal256.
245273 ///
246274 /// This should not overflow or panic.
@@ -1887,4 +1915,71 @@ mod tests {
18871915 fn decimal256_rem_panics_for_zero ( ) {
18881916 let _ = Decimal256 :: percent ( 777 ) % Decimal256 :: zero ( ) ;
18891917 }
1918+
1919+ #[ test]
1920+ fn decimal256_checked_methods ( ) {
1921+ // checked add
1922+ assert_eq ! (
1923+ Decimal256 :: percent( 402 )
1924+ . checked_add( Decimal256 :: percent( 111 ) )
1925+ . unwrap( ) ,
1926+ Decimal256 :: percent( 513 )
1927+ ) ;
1928+ assert ! ( matches!(
1929+ Decimal256 :: MAX . checked_add( Decimal256 :: percent( 1 ) ) ,
1930+ Err ( OverflowError { .. } )
1931+ ) ) ;
1932+
1933+ // checked sub
1934+ assert_eq ! (
1935+ Decimal256 :: percent( 1111 )
1936+ . checked_sub( Decimal256 :: percent( 111 ) )
1937+ . unwrap( ) ,
1938+ Decimal256 :: percent( 1000 )
1939+ ) ;
1940+ assert ! ( matches!(
1941+ Decimal256 :: zero( ) . checked_sub( Decimal256 :: percent( 1 ) ) ,
1942+ Err ( OverflowError { .. } )
1943+ ) ) ;
1944+
1945+ // checked div
1946+ assert_eq ! (
1947+ Decimal256 :: percent( 30 )
1948+ . checked_div( Decimal256 :: percent( 200 ) )
1949+ . unwrap( ) ,
1950+ Decimal256 :: percent( 15 )
1951+ ) ;
1952+ assert_eq ! (
1953+ Decimal256 :: percent( 88 )
1954+ . checked_div( Decimal256 :: percent( 20 ) )
1955+ . unwrap( ) ,
1956+ Decimal256 :: percent( 440 )
1957+ ) ;
1958+ assert ! ( matches!(
1959+ Decimal256 :: MAX . checked_div( Decimal256 :: zero( ) ) ,
1960+ Err ( CheckedFromRatioError :: DivideByZero { .. } )
1961+ ) ) ;
1962+ assert ! ( matches!(
1963+ Decimal256 :: MAX . checked_div( Decimal256 :: percent( 1 ) ) ,
1964+ Err ( CheckedFromRatioError :: Overflow { .. } )
1965+ ) ) ;
1966+
1967+ // checked rem
1968+ assert_eq ! (
1969+ Decimal256 :: percent( 402 )
1970+ . checked_rem( Decimal256 :: percent( 111 ) )
1971+ . unwrap( ) ,
1972+ Decimal256 :: percent( 69 )
1973+ ) ;
1974+ assert_eq ! (
1975+ Decimal256 :: percent( 1525 )
1976+ . checked_rem( Decimal256 :: percent( 400 ) )
1977+ . unwrap( ) ,
1978+ Decimal256 :: percent( 325 )
1979+ ) ;
1980+ assert ! ( matches!(
1981+ Decimal256 :: MAX . checked_rem( Decimal256 :: zero( ) ) ,
1982+ Err ( DivideByZeroError { .. } )
1983+ ) ) ;
1984+ }
18901985}
0 commit comments