use crate::error::SolMathError;
use crate::overflow::checked_mul_div_rem_u;
pub fn mul_div_floor(a: u64, b: u64, c: u64) -> Result<u64, SolMathError> {
if c == 0 {
return Err(SolMathError::DivisionByZero);
}
let product = (a as u128) * (b as u128);
let result = product / (c as u128);
if result > u64::MAX as u128 {
return Err(SolMathError::Overflow);
}
Ok(result as u64)
}
pub fn mul_div_ceil(a: u64, b: u64, c: u64) -> Result<u64, SolMathError> {
if c == 0 {
return Err(SolMathError::DivisionByZero);
}
let product = (a as u128) * (b as u128);
let result = (product + (c as u128) - 1) / (c as u128);
if result > u64::MAX as u128 {
return Err(SolMathError::Overflow);
}
Ok(result as u64)
}
pub fn mul_div_floor_u128(a: u128, b: u128, c: u128) -> Result<u128, SolMathError> {
if c == 0 {
return Err(SolMathError::DivisionByZero);
}
checked_mul_div_rem_u(a, b, c)
.map(|(q, _)| q)
.ok_or(SolMathError::Overflow)
}
pub fn mul_div_ceil_u128(a: u128, b: u128, c: u128) -> Result<u128, SolMathError> {
if c == 0 {
return Err(SolMathError::DivisionByZero);
}
let (q, rem) = checked_mul_div_rem_u(a, b, c).ok_or(SolMathError::Overflow)?;
if rem != 0 {
q.checked_add(1).ok_or(SolMathError::Overflow)
} else {
Ok(q)
}
}