use parity_scale_codec::{alloc::string::ToString, CompactAs, Decode, Encode, MaxEncodedLen};
use scale_info::prelude::string::String;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sp_arithmetic::{
helpers_128bit::multiply_by_rational_with_rounding,
traits::{
Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Saturating,
UniqueSaturatedInto, Zero,
},
FixedPointNumber, FixedPointOperand, Rounding, SignedRounding,
};
use sp_std::{
ops::{self},
prelude::*,
};
struct I129 {
value: u128,
negative: bool,
}
impl<N: FixedPointOperand> From<N> for I129 {
fn from(n: N) -> I129 {
if n < N::zero() {
let value: u128 = n
.checked_neg()
.map(|n| n.unique_saturated_into())
.unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
I129 {
value,
negative: true,
}
} else {
I129 {
value: n.unique_saturated_into(),
negative: false,
}
}
}
}
fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
Some(N::min_value())
} else {
let unsigned_inner: N = n.value.try_into().ok()?;
let inner = if n.negative {
unsigned_inner.checked_neg()?
} else {
unsigned_inner
};
Some(inner)
}
}
fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
if (n < N::zero()) != (m < D::zero()) {
R::min_value()
} else {
R::max_value()
}
}
pub trait FixedPointNumberExtension: FixedPointNumber {
fn checked_mul_int_with_rounding<N: FixedPointOperand>(
self,
int: N,
r: SignedRounding,
) -> Option<N> {
let lhs: I129 = self.into_inner().into();
let rhs: I129 = int.into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational_with_rounding(
lhs.value,
rhs.value,
Self::DIV.unique_saturated_into(),
Rounding::from_signed(r, negative),
)
.and_then(|value| from_i129(I129 { value, negative }))
}
fn saturating_mul_int_with_rounding<N: FixedPointOperand>(
self,
int: N,
r: SignedRounding,
) -> N {
self.checked_mul_int_with_rounding(int, r)
.unwrap_or_else(|| to_bound(self.into_inner(), int))
}
fn checked_mul_int_floor<N: FixedPointOperand>(self, int: N) -> Option<N> {
self.checked_mul_int_with_rounding(int, SignedRounding::Minor)
}
fn checked_mul_int_ceil<N: FixedPointOperand>(self, int: N) -> Option<N> {
self.checked_mul_int_with_rounding(int, SignedRounding::Major)
}
fn checked_mul_with_rounding(&self, other: &Self, r: SignedRounding) -> Option<Self>;
fn checked_mul_floor(&self, other: &Self) -> Option<Self> {
self.checked_mul_with_rounding(other, SignedRounding::Minor)
}
fn checked_mul_ceil(&self, other: &Self) -> Option<Self> {
self.checked_mul_with_rounding(other, SignedRounding::Major)
}
fn saturating_mul_with_rounding(self, other: Self, r: SignedRounding) -> Self;
fn saturating_mul_floor(self, other: Self) -> Self {
self.saturating_mul_with_rounding(other, SignedRounding::Minor)
}
fn saturating_mul_ceil(self, other: Self) -> Self {
self.saturating_mul_with_rounding(other, SignedRounding::Major)
}
fn saturating_mul_int_floor<N: FixedPointOperand>(self, int: N) -> N {
self.saturating_mul_int_with_rounding(int, SignedRounding::Minor)
}
fn saturating_mul_int_ceil<N: FixedPointOperand>(self, int: N) -> N {
self.saturating_mul_int_with_rounding(int, SignedRounding::Major)
}
fn checked_from_rational_with_rounding<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
pref: SignedRounding,
) -> Option<Self> {
if d == D::zero() {
return None;
}
let n: I129 = n.into();
let d: I129 = d.into();
let negative = n.negative != d.negative;
multiply_by_rational_with_rounding(
n.value,
Self::DIV.unique_saturated_into(),
d.value,
Rounding::from_signed(pref, negative),
)
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self::from_inner)
}
fn checked_from_rational_ceil<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Option<Self> {
Self::checked_from_rational_with_rounding(n, d, SignedRounding::Major)
}
fn checked_from_rational_floor<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Option<Self> {
Self::checked_from_rational_with_rounding(n, d, SignedRounding::Minor)
}
fn saturating_from_rational_with_rounding<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
r: SignedRounding,
) -> Self {
if d == D::zero() {
panic!("attempted to create fixed point from rational with zero denominator")
}
Self::checked_from_rational_with_rounding(n, d, r).unwrap_or_else(|| to_bound(n, d))
}
fn saturating_from_rational_floor<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Self {
Self::saturating_from_rational_with_rounding(n, d, SignedRounding::Minor)
}
fn saturating_from_rational_ceil<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Self {
Self::saturating_from_rational_with_rounding(n, d, SignedRounding::Major)
}
fn checked_div_with_rounding(&self, other: &Self, r: SignedRounding) -> Option<Self>;
fn checked_div_floor(&self, other: &Self) -> Option<Self> {
self.checked_div_with_rounding(other, SignedRounding::Minor)
}
fn checked_div_ceil(&self, other: &Self) -> Option<Self> {
self.checked_div_with_rounding(other, SignedRounding::Major)
}
fn saturating_div_with_rounding(&self, other: &Self, r: SignedRounding) -> Self;
fn saturating_div_floor(&self, other: &Self) -> Self {
self.saturating_div_with_rounding(other, SignedRounding::Minor)
}
fn saturating_div_ceil(&self, other: &Self) -> Self {
self.saturating_div_with_rounding(other, SignedRounding::Major)
}
fn checked_div_int_with_rounding<N: FixedPointOperand>(
self,
int: N,
r: SignedRounding,
) -> Option<N>;
fn checked_div_int_floor<N: FixedPointOperand>(self, int: N) -> Option<N> {
self.checked_div_int_with_rounding(int, SignedRounding::Minor)
}
fn checked_div_int_ceil<N: FixedPointOperand>(self, int: N) -> Option<N> {
self.checked_div_int_with_rounding(int, SignedRounding::Major)
}
fn saturating_div_int_with_rounding<N: FixedPointOperand>(
self,
int: N,
r: SignedRounding,
) -> N {
if int == N::zero() {
panic!("attempt to divide by zero")
}
self.checked_div_int_with_rounding(int, r)
.unwrap_or_else(|| to_bound(self.into_inner(), int))
}
fn saturating_div_int_floor<N: FixedPointOperand>(self, int: N) -> N {
self.saturating_div_int_with_rounding(int, SignedRounding::Minor)
}
fn saturating_div_int_ceil<N: FixedPointOperand>(self, int: N) -> N {
self.saturating_div_int_with_rounding(int, SignedRounding::Major)
}
fn reciprocal_with_rounding(self, r: SignedRounding) -> Option<Self> {
Self::one().checked_div_with_rounding(&self, r)
}
fn reciprocal_floor(self) -> Option<Self> {
self.reciprocal_with_rounding(SignedRounding::Minor)
}
fn reciprocal_ceil(self) -> Option<Self> {
self.reciprocal_with_rounding(SignedRounding::Major)
}
fn saturating_pow_with_rounding(self, pow: usize, r: SignedRounding) -> Self {
if pow == 0 {
return Self::one();
}
let mut accum_a = Self::one();
let mut accum_b = self;
let exp = pow as u32;
let msb_pos = 32 - exp.leading_zeros();
for i in 0..msb_pos {
if ((1 << i) & exp) > 0 {
accum_a = accum_a.saturating_mul_with_rounding(accum_b, r)
}
accum_b = accum_b.saturating_mul_with_rounding(accum_b, r)
}
accum_a
}
fn saturating_pow_floor(self, pow: usize) -> Self {
self.saturating_pow_with_rounding(pow, SignedRounding::Minor)
}
fn saturating_pow_ceil(self, pow: usize) -> Self {
self.saturating_pow_with_rounding(pow, SignedRounding::Major)
}
}
const DECIMALS_18: u128 = 1_000_000_000_000_000_000u128;
const DECIMALS_27: u128 = 1_000_000_000_000_000_000_000_000_000u128;
#[doc = "_Fixed Point 128 bits unsigned with 27 decimals precision"]
pub type Rate = FixedU128<DECIMALS_27>;
#[doc = "_Fixed Point 128 bits unsigned with 18 decimals precision"]
pub type Ratio = FixedU128<DECIMALS_18>;
#[doc = "_Fixed Point 128 bits unsigned with 18 decimals precision"]
pub type Quantity = FixedU128<DECIMALS_18>;
#[doc = "_Fixed Point 128 bits unsigned with variable precision."]
#[derive(
Encode,
Decode,
CompactAs,
Default,
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
scale_info::TypeInfo,
MaxEncodedLen,
)]
pub struct FixedU128<const DIV: u128>(u128);
impl<const DIV: u128> From<u128> for FixedU128<DIV> {
fn from(int: u128) -> Self {
FixedU128::saturating_from_integer(int)
}
}
impl<N: FixedPointOperand, D: FixedPointOperand, const DIV: u128> From<(N, D)> for FixedU128<DIV> {
fn from(r: (N, D)) -> Self {
FixedU128::saturating_from_rational(r.0, r.1)
}
}
impl<const DIV: u128> FixedPointNumber for FixedU128<DIV> {
type Inner = u128;
const DIV: Self::Inner = DIV;
const SIGNED: bool = false;
fn from_inner(inner: Self::Inner) -> Self {
Self(inner)
}
fn into_inner(self) -> Self::Inner {
self.0
}
fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Option<Self> {
Self::checked_from_rational_with_rounding(n, d, SignedRounding::NearestPrefLow)
}
fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
self.checked_mul_int_with_rounding(n, SignedRounding::NearestPrefLow)
}
}
impl<const DIV: u128> FixedPointNumberExtension for FixedU128<DIV> {
fn checked_mul_with_rounding(&self, other: &Self, r: SignedRounding) -> Option<Self> {
let lhs: I129 = self.into_inner().into();
let rhs: I129 = other.into_inner().into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational_with_rounding(
lhs.value,
rhs.value,
Self::DIV.unique_saturated_into(),
Rounding::from_signed(r, negative),
)
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self)
}
fn checked_div_with_rounding(&self, other: &Self, r: SignedRounding) -> Option<Self> {
if other.0 == 0 {
return None;
}
let lhs: I129 = self.0.into();
let rhs: I129 = other.0.into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational_with_rounding(
lhs.value,
Self::DIV,
rhs.value,
Rounding::from_signed(r, negative),
)
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self)
}
fn saturating_mul_with_rounding(self, other: Self, r: SignedRounding) -> Self {
self.checked_mul_with_rounding(&other, r)
.unwrap_or_else(|| to_bound(self.0, other.0))
}
fn saturating_div_with_rounding(&self, other: &Self, r: SignedRounding) -> Self {
if other.is_zero() {
panic!("attempt to divide by zero")
}
self.checked_div_with_rounding(other, r)
.unwrap_or_else(|| to_bound(self.0, other.0))
}
fn checked_div_int_with_rounding<N: FixedPointOperand>(
self,
int: N,
r: SignedRounding,
) -> Option<N> {
let rhs: I129 = int.into();
self.checked_div_with_rounding(&Self::from_inner(rhs.value), r)
.and_then(|n| n.into_inner().into())
.and_then(|n| N::try_from(n).ok())
}
}
impl<const DIV: u128> FixedU128<DIV> {
pub const fn from_inner(inner: u128) -> Self {
Self(inner)
}
pub const fn from_integer(n: u128) -> Self {
Self::from_inner(n * DIV)
}
}
impl<const DIV: u128> Saturating for FixedU128<DIV> {
fn saturating_add(self, rhs: Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}
fn saturating_sub(self, rhs: Self) -> Self {
Self(self.0.saturating_sub(rhs.0))
}
fn saturating_mul(self, rhs: Self) -> Self {
self.saturating_mul_with_rounding(rhs, SignedRounding::NearestPrefLow)
}
fn saturating_pow(self, exp: usize) -> Self {
self.saturating_pow_with_rounding(exp, SignedRounding::NearestPrefLow)
}
}
impl<const DIV: u128> ops::Neg for FixedU128<DIV> {
type Output = Self;
fn neg(self) -> Self::Output {
Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
}
}
impl<const DIV: u128> ops::Add for FixedU128<DIV> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl<const DIV: u128> ops::Sub for FixedU128<DIV> {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}
impl<const DIV: u128> ops::Mul for FixedU128<DIV> {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self.checked_mul(&rhs)
.unwrap_or_else(|| panic!("attempt to multiply with overflow"))
}
}
impl<const DIV: u128> ops::Div for FixedU128<DIV> {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
if rhs.0 == 0 {
panic!("attempt to divide by zero")
}
self.checked_div(&rhs)
.unwrap_or_else(|| panic!("attempt to divide with overflow"))
}
}
impl<const DIV: u128> CheckedSub for FixedU128<DIV> {
fn checked_sub(&self, rhs: &Self) -> Option<Self> {
self.0.checked_sub(rhs.0).map(Self)
}
}
impl<const DIV: u128> CheckedAdd for FixedU128<DIV> {
fn checked_add(&self, rhs: &Self) -> Option<Self> {
self.0.checked_add(rhs.0).map(Self)
}
}
impl<const DIV: u128> CheckedDiv for FixedU128<DIV> {
fn checked_div(&self, other: &Self) -> Option<Self> {
self.checked_div_with_rounding(other, SignedRounding::NearestPrefLow)
}
}
impl<const DIV: u128> CheckedMul for FixedU128<DIV> {
fn checked_mul(&self, other: &Self) -> Option<Self> {
self.checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
}
}
impl<const DIV: u128> Bounded for FixedU128<DIV> {
fn min_value() -> Self {
Self(<Self as FixedPointNumber>::Inner::min_value())
}
fn max_value() -> Self {
Self(<Self as FixedPointNumber>::Inner::max_value())
}
}
impl<const DIV: u128> Zero for FixedU128<DIV> {
fn zero() -> Self {
Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
}
fn is_zero(&self) -> bool {
self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
}
}
impl<const DIV: u128> One for FixedU128<DIV> {
fn one() -> Self {
Self::from_inner(Self::DIV)
}
}
impl<const DIV: u128> sp_std::fmt::Debug for FixedU128<DIV> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
let integral = {
let int = self.0 / Self::accuracy();
let signum_for_zero = if int == 0 && self.is_negative() {
"-"
} else {
""
};
format!("{signum_for_zero}{int}")
};
let precision = (Self::accuracy() as f64).log10() as usize;
let fractional = format!(
"{:0>weight$}",
((self.0 % Self::accuracy()) as i128).abs(),
weight = precision
);
write!(f, "{}({}.{})", stringify!(FixedU128), integral, fractional)
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<const DIV: u128> sp_std::fmt::Display for FixedU128<DIV> {
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<const DIV: u128> sp_std::str::FromStr for FixedU128<DIV> {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let inner: <Self as FixedPointNumber>::Inner = s
.parse()
.map_err(|_| "invalid string input for fixed point number")?;
Ok(Self::from_inner(inner))
}
}
impl<const DIV: u128> Serialize for FixedU128<DIV> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de, const DIV: u128> Deserialize<'de> for FixedU128<DIV> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use sp_std::str::FromStr;
let s = String::deserialize(deserializer)?;
FixedU128::from_str(&s).map_err(de::Error::custom)
}
}
#[cfg(test)]
mod test_fixed_u128 {
use super::*;
fn max() -> FixedU128<DECIMALS_27> {
FixedU128::<DECIMALS_27>::max_value()
}
fn min() -> FixedU128<DECIMALS_27> {
FixedU128::<DECIMALS_27>::min_value()
}
fn precision() -> usize {
(FixedU128::<DECIMALS_27>::accuracy() as f64).log10() as usize
}
#[test]
fn macro_preconditions() {
assert!(FixedU128::<DECIMALS_27>::DIV > 0);
}
#[test]
fn from_i129_works() {
let a = I129 {
value: 1,
negative: true,
};
assert_eq!(from_i129::<u128>(a), None);
let a = I129 {
value: u128::MAX - 1,
negative: false,
};
assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
let a = I129 {
value: u128::MAX,
negative: false,
};
assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
let a = I129 {
value: i128::MAX as u128 + 1,
negative: true,
};
assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
let a = I129 {
value: i128::MAX as u128 + 1,
negative: false,
};
assert_eq!(from_i129::<i128>(a), None);
let a = I129 {
value: i128::MAX as u128,
negative: false,
};
assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
}
#[test]
fn to_bound_works() {
let a = 1i32;
let b = 1i32;
assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
let a = -1i32;
let b = -1i32;
assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
let a = 1i32;
let b = -1i32;
assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
let a = -1i32;
let b = 1i32;
assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
let a = 1i32;
let b = -1i32;
assert_eq!(to_bound::<_, _, u32>(a, b), 0);
}
#[test]
fn op_neg_works() {
let a = FixedU128::<DECIMALS_27>::zero();
let b = -a;
assert_eq!(a, b);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let b = -a;
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(-5), b);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(-5);
let b = -a;
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(5), b);
let a = FixedU128::<DECIMALS_27>::max_value();
let b = -a;
assert_eq!(
FixedU128::<DECIMALS_27>::min_value() + FixedU128::<DECIMALS_27>::from_inner(1),
b
);
let a = FixedU128::<DECIMALS_27>::min_value() + FixedU128::<DECIMALS_27>::from_inner(1);
let b = -a;
assert_eq!(FixedU128::<DECIMALS_27>::max_value(), b);
}
}
#[test]
fn op_checked_add_overflow_works() {
let a = FixedU128::<DECIMALS_27>::max_value();
let b = 1.into();
assert!(a.checked_add(&b).is_none());
}
#[test]
fn op_add_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(3), a + b);
if FixedU128::<DECIMALS_27>::SIGNED {
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, -2);
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(2), a + b);
}
}
#[test]
fn op_checked_sub_underflow_works() {
let a = FixedU128::<DECIMALS_27>::min_value();
let b = 1.into();
assert!(a.checked_sub(&b).is_none());
}
#[test]
fn op_sub_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(2), a - b);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-2),
b.saturating_sub(a)
);
}
#[test]
fn op_checked_mul_overflow_works() {
let a = FixedU128::<DECIMALS_27>::max_value();
let b = 2.into();
assert!(a.checked_mul(&b).is_none());
}
#[test]
fn op_mul_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(42);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(2);
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(84), a * b);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(42);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(-2);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-84),
a * b
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn op_div_panics_on_zero_divisor() {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(1);
let b = 0.into();
let _c = a / b;
}
#[test]
fn op_checked_div_overflow_works() {
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::min_value();
let b =
FixedU128::<DECIMALS_27>::zero().saturating_sub(FixedU128::<DECIMALS_27>::one());
assert!(a.checked_div(&b).is_none());
}
}
#[test]
fn op_div_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(42);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(2);
assert_eq!(FixedU128::<DECIMALS_27>::saturating_from_integer(21), a / b);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(42);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(-2);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-21),
a / b
);
}
}
#[test]
fn saturating_from_integer_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(42);
assert_eq!(a.into_inner(), 42 * accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(-42);
assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(inner_max / accuracy);
assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(inner_min / accuracy);
assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(inner_max / accuracy + 1);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(
(inner_min / accuracy).saturating_sub(1),
);
assert_eq!(a.into_inner(), inner_min);
}
#[test]
fn checked_from_integer_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::checked_from_integer(42u128)
.expect("42 * accuracy <= inner_max; qed");
assert_eq!(a.into_inner(), 42 * accuracy);
let a = FixedU128::<DECIMALS_27>::checked_from_integer(inner_max / accuracy)
.expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
let a = FixedU128::<DECIMALS_27>::checked_from_integer(inner_max / accuracy + 1);
assert_eq!(a, None);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::checked_from_integer(0.saturating_sub(4u128))
.expect("-42 * accuracy >= inner_min; qed");
assert_eq!(a.into_inner(), 0 - 42 * accuracy);
let a = FixedU128::<DECIMALS_27>::checked_from_integer(inner_min / accuracy)
.expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
let a = FixedU128::<DECIMALS_27>::checked_from_integer(inner_min / accuracy - 1);
assert_eq!(a, None);
}
}
#[test]
fn from_inner_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
assert_eq!(max(), FixedU128::<DECIMALS_27>::from_inner(inner_max));
assert_eq!(min(), FixedU128::<DECIMALS_27>::from_inner(inner_min));
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_from_rational_panics_on_zero_divisor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 0);
}
#[test]
fn saturating_from_rational_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
assert_eq!(a.into_inner(), 25 * accuracy / 10);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max - 1, accuracy);
assert_eq!(a.into_inner(), inner_max - 1);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min + 1, accuracy);
assert_eq!(a.into_inner(), inner_min + 1);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, accuracy);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, accuracy);
assert_eq!(a.into_inner(), inner_min);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(0, 1);
assert_eq!(a.into_inner(), 0);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2);
assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(5, -2);
assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, -2);
assert_eq!(a.into_inner(), 25 * accuracy / 10);
let a =
FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max as u128 + 1, accuracy);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
inner_max as u128 + 2,
0 - accuracy,
);
assert_eq!(a.into_inner(), inner_min);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 0 - accuracy);
assert_eq!(a.into_inner(), 0 - inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, 0 - accuracy);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min + 1, 0 - accuracy);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, 0 - 1);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 0 - 1);
assert_eq!(a.into_inner(), inner_min);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 0 - inner_max);
assert_eq!(a.into_inner(), 0 - accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(0 - inner_max, inner_max);
assert_eq!(a.into_inner(), 0 - accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 0 - 3 * accuracy);
assert_eq!(a.into_inner(), 0 - inner_max / 3);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, 0 - accuracy / 3);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 0 - accuracy);
assert_eq!(a.into_inner(), 0.saturating_sub(1));
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, inner_min);
assert_eq!(a.into_inner(), accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 0 - accuracy - 1);
assert_eq!(a.into_inner(), 0);
}
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max - 1, accuracy);
assert_eq!(a.into_inner(), inner_max - 1);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min + 1, accuracy);
assert_eq!(a.into_inner(), inner_min + 1);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 1);
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, 1);
assert_eq!(a.into_inner(), inner_min);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, inner_max);
assert_eq!(a.into_inner(), accuracy);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_max, 3 * accuracy);
assert_eq!(a.into_inner(), inner_max / 3);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, 2 * accuracy);
assert_eq!(a.into_inner(), inner_min / 2);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(inner_min, accuracy / 3);
assert_eq!(a.into_inner(), inner_min);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, accuracy);
assert_eq!(a.into_inner(), 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy).unwrap();
assert_eq!(a.into_inner(), 0);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy - 1).unwrap();
assert_eq!(a.into_inner(), 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy + 1).unwrap();
assert_eq!(a.into_inner(), 0);
}
#[test]
#[should_panic(
expected = "attempted to create fixed point from rational with zero denominator"
)]
fn saturating_from_rational_with_rounding_panics_on_zero_divisor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
0,
SignedRounding::NearestPrefLow,
);
}
#[test]
fn saturating_from_rational_with_rounding_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
0,
1,
SignedRounding::NearestPrefLow
),
FixedU128::<DECIMALS_27>::zero()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
5,
FixedU128::<DECIMALS_27>::accuracy() * 10,
SignedRounding::NearestPrefLow
)
.into_inner(),
0
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
6,
FixedU128::<DECIMALS_27>::accuracy() * 10,
SignedRounding::NearestPrefLow
)
.into_inner(),
1
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
3,
SignedRounding::Minor
)
.into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
3,
SignedRounding::Major
)
.into_inner(),
333333333333333333333333334
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
3,
SignedRounding::NearestPrefLow
)
.into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
6,
SignedRounding::Minor
)
.into_inner(),
166666666666666666666666666
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
6,
SignedRounding::Major
)
.into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
6,
SignedRounding::NearestPrefLow
)
.into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
222220,
SignedRounding::Minor
)
.into_inner(),
4500045000450004500045
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
222220,
SignedRounding::Major
)
.into_inner(),
4500045000450004500046
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_with_rounding(
1,
222220,
SignedRounding::NearestPrefLow
)
.into_inner(),
4500045000450004500045
);
}
#[test]
#[should_panic(
expected = "attempted to create fixed point from rational with zero denominator"
)]
fn saturating_from_rational_floor_panics_on_zero_divisor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_rational_floor(1, 0);
}
#[test]
fn saturating_from_rational_floor_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(0, 1),
FixedU128::<DECIMALS_27>::zero()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(
5,
FixedU128::<DECIMALS_27>::accuracy() * 10,
)
.into_inner(),
0
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(
1,
FixedU128::<DECIMALS_27>::accuracy()
)
.into_inner(),
1
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(1, 3).into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(1, 6).into_inner(),
166666666666666666666666666
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_floor(1, 222220).into_inner(),
4500045000450004500045
);
}
#[test]
#[should_panic(
expected = "attempted to create fixed point from rational with zero denominator"
)]
fn saturating_from_rational_ceil_panics_on_zero_divisor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(1, 0);
}
#[test]
fn saturating_from_rational_ceil_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(0, 1),
FixedU128::<DECIMALS_27>::zero()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(
1,
FixedU128::<DECIMALS_27>::accuracy()
)
.into_inner(),
1
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(
5,
FixedU128::<DECIMALS_27>::accuracy() * 10,
)
.into_inner(),
1
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(1, 3).into_inner(),
333333333333333333333333334
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(1, 6).into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational_ceil(1, 222220).into_inner(),
4500045000450004500046
);
}
#[test]
fn checked_from_rational_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 0);
assert_eq!(a, None);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_max - 1, accuracy).unwrap();
assert_eq!(a.into_inner(), inner_max - 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_min + 1, accuracy).unwrap();
assert_eq!(a.into_inner(), inner_min + 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_max, accuracy).unwrap();
assert_eq!(a.into_inner(), inner_max);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_min, accuracy).unwrap();
assert_eq!(a.into_inner(), inner_min);
let a =
FixedU128::<DECIMALS_27>::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
assert_eq!(a, None);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::checked_from_rational(
inner_max as u128 + 2,
0.saturating_sub(accuracy),
);
assert_eq!(a, None);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_max, 0 - 3 * accuracy)
.unwrap();
assert_eq!(a.into_inner(), 0 - inner_max / 3);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_min, 0 - accuracy / 3);
assert_eq!(a, None);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 0 - accuracy).unwrap();
assert_eq!(a.into_inner(), 0.saturating_sub(1));
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 0 - accuracy - 1).unwrap();
assert_eq!(a.into_inner(), 0);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_min, accuracy / 3);
assert_eq!(a, None);
}
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_max, 3 * accuracy).unwrap();
assert_eq!(a.into_inner(), inner_max / 3);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(inner_min, 2 * accuracy).unwrap();
assert_eq!(a.into_inner(), inner_min / 2);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, accuracy).unwrap();
assert_eq!(a.into_inner(), 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy).unwrap();
assert_eq!(a.into_inner(), 0);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy - 1).unwrap();
assert_eq!(a.into_inner(), 1);
let a = FixedU128::<DECIMALS_27>::checked_from_rational(1, 2 * accuracy + 1).unwrap();
assert_eq!(a.into_inner(), 0);
}
#[test]
fn checked_from_rational_with_rounding_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
0,
SignedRounding::NearestPrefLow
),
None
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
0,
1,
SignedRounding::NearestPrefLow
),
Some(FixedU128::<DECIMALS_27>::zero())
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
3,
SignedRounding::Minor
)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
3,
SignedRounding::Major
)
.unwrap()
.into_inner(),
333333333333333333333333334
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
3,
SignedRounding::NearestPrefLow
)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
6,
SignedRounding::Minor
)
.unwrap()
.into_inner(),
166666666666666666666666666
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
6,
SignedRounding::Major
)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
6,
SignedRounding::NearestPrefLow
)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
222220,
SignedRounding::Minor
)
.unwrap()
.into_inner(),
4500045000450004500045
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
222220,
SignedRounding::Major
)
.unwrap()
.into_inner(),
4500045000450004500046
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_with_rounding(
1,
222220,
SignedRounding::NearestPrefLow
)
.unwrap()
.into_inner(),
4500045000450004500045
);
}
#[test]
fn checked_from_rational_floor_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 0),
None
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_floor(0, 1),
Some(FixedU128::<DECIMALS_27>::zero())
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 3)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 6)
.unwrap()
.into_inner(),
166666666666666666666666666
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 222220)
.unwrap()
.into_inner(),
4500045000450004500045
);
}
#[test]
fn checked_from_rational_ceil_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(1, 0),
None
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(0, 1),
Some(FixedU128::<DECIMALS_27>::zero())
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(1, 3)
.unwrap()
.into_inner(),
333333333333333333333333334
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(1, 6)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(1, 222220)
.unwrap()
.into_inner(),
4500045000450004500046
);
}
#[test]
fn checked_mul_int_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(2);
assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
if FixedU128::<DECIMALS_27>::SIGNED {
assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, -2);
assert_eq!(b.checked_mul_int(42i128), Some(-21));
assert_eq!(b.checked_mul_int(u128::MAX), None);
assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
}
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
assert_eq!(a.checked_mul_int(42i128), Some(21));
assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(255);
assert_eq!(c.checked_mul_int(2i8), None);
assert_eq!(c.checked_mul_int(2i128), Some(510));
assert_eq!(c.checked_mul_int(i128::MAX), None);
assert_eq!(c.checked_mul_int(i128::MIN), None);
}
#[test]
fn checked_mul_int_with_rounding_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().checked_mul_int_with_rounding(
FixedU128::<DECIMALS_27>::max_value().into_inner(),
SignedRounding::NearestPrefLow
),
None
);
assert_eq!(
a.checked_mul_int_with_rounding(5, SignedRounding::NearestPrefLow),
Some(2)
);
assert_eq!(
a.checked_mul_int_with_rounding(5, SignedRounding::Minor),
Some(2)
);
assert_eq!(
a.checked_mul_int_with_rounding(5, SignedRounding::Major),
Some(3)
);
assert_eq!(
b.checked_mul_int_with_rounding(100, SignedRounding::NearestPrefLow),
Some(33)
);
assert_eq!(
b.checked_mul_int_with_rounding(100, SignedRounding::Minor),
Some(33)
);
assert_eq!(
b.checked_mul_int_with_rounding(100, SignedRounding::Major),
Some(34)
);
assert_eq!(
b.checked_mul_int_with_rounding(200, SignedRounding::NearestPrefLow),
Some(67)
);
assert_eq!(
b.checked_mul_int_with_rounding(200, SignedRounding::Minor),
Some(66)
);
assert_eq!(
b.checked_mul_int_with_rounding(200, SignedRounding::Major),
Some(67)
)
}
#[test]
fn checked_mul_int_floor_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.checked_mul_int_floor(FixedU128::<DECIMALS_27>::max_value().into_inner()),
None
);
assert_eq!(a.checked_mul_int_floor(5), Some(2));
assert_eq!(b.checked_mul_int_floor(100), Some(33));
assert_eq!(b.checked_mul_int_floor(200), Some(66));
}
#[test]
fn checked_mul_int_ceil_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.checked_mul_int_ceil(FixedU128::<DECIMALS_27>::max_value().into_inner()),
None
);
assert_eq!(a.checked_mul_int_ceil(5), Some(3));
assert_eq!(b.checked_mul_int_ceil(100), Some(34));
assert_eq!(b.checked_mul_int_ceil(200), Some(67));
}
#[test]
fn saturating_mul_int_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(2);
assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
if FixedU128::<DECIMALS_27>::SIGNED {
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, -2);
assert_eq!(b.saturating_mul_int(42i32), -21);
assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
}
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
assert_eq!(a.saturating_mul_int(42i32), 21);
assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(255);
assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
}
#[test]
fn saturating_mul_int_with_rounding_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().saturating_mul_int_with_rounding(
FixedU128::<DECIMALS_27>::max_value().into_inner(),
SignedRounding::NearestPrefLow
),
FixedU128::<DECIMALS_27>::max_value().into_inner()
);
assert_eq!(
a.saturating_mul_int_with_rounding(5, SignedRounding::NearestPrefLow),
2
);
assert_eq!(
a.saturating_mul_int_with_rounding(5, SignedRounding::Minor),
2
);
assert_eq!(
a.saturating_mul_int_with_rounding(5, SignedRounding::Major),
3
);
assert_eq!(
b.saturating_mul_int_with_rounding(100, SignedRounding::NearestPrefLow),
33
);
assert_eq!(
b.saturating_mul_int_with_rounding(100, SignedRounding::Minor),
33
);
assert_eq!(
b.saturating_mul_int_with_rounding(100, SignedRounding::Major),
34
);
assert_eq!(
b.saturating_mul_int_with_rounding(200, SignedRounding::NearestPrefLow),
67
);
assert_eq!(
b.saturating_mul_int_with_rounding(200, SignedRounding::Minor),
66
);
assert_eq!(
b.saturating_mul_int_with_rounding(200, SignedRounding::Major),
67
)
}
#[test]
fn saturating_mul_int_floor_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.saturating_mul_int_floor(FixedU128::<DECIMALS_27>::max_value().into_inner()),
FixedU128::<DECIMALS_27>::max_value().into_inner()
);
assert_eq!(a.saturating_mul_int_floor(5), 2);
assert_eq!(b.saturating_mul_int_floor(100), 33);
assert_eq!(b.saturating_mul_int_floor(200), 66);
}
#[test]
fn saturating_mul_int_ceil_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.saturating_mul_int_ceil(FixedU128::<DECIMALS_27>::max_value().into_inner()),
FixedU128::<DECIMALS_27>::max_value().into_inner()
);
assert_eq!(a.saturating_mul_int_ceil(5), 3);
assert_eq!(b.saturating_mul_int_ceil(100), 34);
assert_eq!(b.saturating_mul_int_ceil(200), 67);
}
#[test]
fn checked_mul_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(2);
let b = FixedU128::<DECIMALS_27>::from_inner(inner_max - 1);
assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
let c = FixedU128::<DECIMALS_27>::from_inner(inner_max);
assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
let e = FixedU128::<DECIMALS_27>::from_inner(1);
assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
if FixedU128::<DECIMALS_27>::SIGNED {
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min + 1) / 2.into();
let c = FixedU128::<DECIMALS_27>::from_inner(inner_min + 2);
assert_eq!(a.checked_mul(&b), Some(c));
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min) / 2.into();
let c = FixedU128::<DECIMALS_27>::from_inner(inner_min);
assert_eq!(a.checked_mul(&b), Some(c));
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min) / 2.into()
- FixedU128::<DECIMALS_27>::from_inner(1);
assert_eq!(a.checked_mul(&b), None);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(255);
let b = FixedU128::<DECIMALS_27>::saturating_from_rational(1, -2);
assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
assert_eq!(
b.checked_mul(&FixedU128::<DECIMALS_27>::max_value()),
FixedU128::<DECIMALS_27>::max_value().checked_div(&0.saturating_sub(2).into())
);
assert_eq!(
b.checked_mul(&FixedU128::<DECIMALS_27>::min_value()),
FixedU128::<DECIMALS_27>::min_value().checked_div(&0.saturating_sub(2).into())
);
assert_eq!(c.checked_mul(&FixedU128::<DECIMALS_27>::min_value()), None);
}
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(255);
assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
assert_eq!(c.checked_mul(&FixedU128::<DECIMALS_27>::max_value()), None);
assert_eq!(
a.checked_mul(&FixedU128::<DECIMALS_27>::max_value()),
FixedU128::<DECIMALS_27>::max_value().checked_div(&2.into())
);
assert_eq!(
a.checked_mul(&FixedU128::<DECIMALS_27>::min_value()),
FixedU128::<DECIMALS_27>::min_value().checked_div(&2.into())
);
}
#[test]
fn checked_mul_floor_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.checked_mul_floor(&FixedU128::<DECIMALS_27>::max_value()),
None
);
assert_eq!(
a.checked_mul_floor(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2))
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_floor(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3))
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_floor(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 6))
.unwrap()
.into_inner(),
0
);
}
#[test]
fn checked_mul_ceil_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.checked_mul_floor(&FixedU128::<DECIMALS_27>::max_value()),
None
);
assert_eq!(
a.checked_mul_ceil(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2))
.unwrap()
.into_inner(),
1
);
assert_eq!(
a.checked_mul_ceil(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3))
.unwrap()
.into_inner(),
1
);
assert_eq!(
a.checked_mul_ceil(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 6))
.unwrap()
.into_inner(),
1
);
}
#[test]
fn checked_mul_with_rounding_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::max_value(),
SignedRounding::NearestPrefLow
),
None
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::NearestPrefLow
)
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::NearestPrefLow
)
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_floor(&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 6))
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::Minor
)
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::Minor
)
.unwrap()
.into_inner(),
0
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 6),
SignedRounding::Minor
)
.unwrap()
.into_inner(),
0
);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::Major
)
.unwrap()
.into_inner(),
1
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::Major
)
.unwrap()
.into_inner(),
1
);
assert_eq!(
a.checked_mul_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(1, 6),
SignedRounding::Major
)
.unwrap()
.into_inner(),
1
);
}
#[test]
fn saturating_mul_with_rounding_works() {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::NearestPrefLow
)
.into_inner(),
0
);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::NearestPrefHigh
)
.into_inner(),
1
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::NearestPrefLow
)
.into_inner(),
0
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(2, 3),
SignedRounding::NearestPrefLow
)
.into_inner(),
1
);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_integer(2),
SignedRounding::Major
),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::Minor
)
.into_inner(),
0
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::Minor
)
.into_inner(),
0
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(2, 3),
SignedRounding::Minor
)
.into_inner(),
0
);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2),
SignedRounding::Major
)
.into_inner(),
1
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3),
SignedRounding::Major
)
.into_inner(),
1
);
assert_eq!(
a.saturating_mul_with_rounding(
FixedU128::<DECIMALS_27>::saturating_from_rational(2, 3),
SignedRounding::Major
)
.into_inner(),
1
);
}
#[test]
fn saturating_mul_floor_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.saturating_mul_floor(FixedU128::<DECIMALS_27>::saturating_from_integer(2)),
FixedU128::<DECIMALS_27>::max_value()
);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(1);
assert_eq!(
a.saturating_mul_floor(FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2))
.into_inner(),
0
);
assert_eq!(
a.saturating_mul_floor(FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3))
.into_inner(),
0
);
assert_eq!(
b.saturating_mul_floor(FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3))
.into_inner(),
333333333333333333333333333
);
assert_eq!(
a.saturating_mul_floor(FixedU128::<DECIMALS_27>::saturating_from_rational(2, 3))
.into_inner(),
0
);
}
#[test]
fn saturating_mul_ceil_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::max_value()
.saturating_mul_ceil(FixedU128::<DECIMALS_27>::saturating_from_integer(2)),
FixedU128::<DECIMALS_27>::max_value()
);
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
a.saturating_mul_ceil(FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2))
.into_inner(),
1
);
assert_eq!(
a.saturating_mul_ceil(FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3))
.into_inner(),
1
);
assert_eq!(
a.saturating_mul_ceil(FixedU128::<DECIMALS_27>::saturating_from_rational(2, 3))
.into_inner(),
1
);
}
#[test]
fn checked_div_int_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::from_inner(inner_max);
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min);
let c = FixedU128::<DECIMALS_27>::zero();
let d = FixedU128::<DECIMALS_27>::one();
let e = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let f = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(e.checked_div_int(2.into()), Some(3));
assert_eq!(f.checked_div_int(2.into()), Some(2));
assert_eq!(a.checked_div_int(i128::MAX), Some(0));
assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
assert_eq!(a.checked_div_int(1i8), None);
if b < c {
assert_eq!(
a.checked_div_int(0.saturating_sub(2)),
Some(0.saturating_sub(inner_max / (2 * accuracy)))
);
assert_eq!(
a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
Some(0.saturating_sub(1))
);
assert_eq!(b.checked_div_int(i128::MIN), Some(0));
assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
assert_eq!(b.checked_div_int(1i8), None);
assert_eq!(
b.checked_div_int(0.saturating_sub(2)),
Some(0.saturating_sub(inner_min / (2 * accuracy)))
);
assert_eq!(
b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
Some(0.saturating_sub(1))
);
assert_eq!(c.checked_div_int(i128::MIN), Some(0));
assert_eq!(d.checked_div_int(i32::MIN), Some(0));
}
assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
assert_eq!(c.checked_div_int(1), Some(0));
assert_eq!(c.checked_div_int(i128::MAX), Some(0));
assert_eq!(c.checked_div_int(1i8), Some(0));
assert_eq!(d.checked_div_int(1), Some(1));
assert_eq!(d.checked_div_int(i32::MAX), Some(0));
assert_eq!(d.checked_div_int(1i8), Some(1));
assert_eq!(a.checked_div_int(0), None);
assert_eq!(b.checked_div_int(0), None);
assert_eq!(c.checked_div_int(0), None);
assert_eq!(d.checked_div_int(0), None);
}
#[test]
fn checked_div_int_with_rounding_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::from_inner(inner_max);
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min);
let c = FixedU128::<DECIMALS_27>::zero();
let d = FixedU128::<DECIMALS_27>::one();
let e = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let f = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let max = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(
max.checked_div_int_with_rounding(2, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
d.checked_div_int_with_rounding(3 * accuracy, SignedRounding::Minor),
Some(333333333333333333333333333)
);
assert_eq!(
d.checked_div_int_with_rounding(3 * accuracy, SignedRounding::Major),
Some(333333333333333333333333334)
);
assert_eq!(
d.checked_div_int_with_rounding(3 * accuracy, SignedRounding::NearestPrefLow),
Some(333333333333333333333333333)
);
assert_eq!(
d.checked_div_int_with_rounding(6 * accuracy, SignedRounding::Minor),
Some(166666666666666666666666666)
);
assert_eq!(
d.checked_div_int_with_rounding(6 * accuracy, SignedRounding::Major),
Some(166666666666666666666666667)
);
assert_eq!(
d.checked_div_int_with_rounding(6 * accuracy, SignedRounding::NearestPrefLow),
Some(166666666666666666666666667)
);
assert_eq!(
f.checked_div_int_with_rounding(9 * accuracy, SignedRounding::Minor),
Some(555555555555555555555555555)
);
assert_eq!(
f.checked_div_int_with_rounding(9 * accuracy, SignedRounding::Major),
Some(555555555555555555555555556)
);
assert_eq!(
f.checked_div_int_with_rounding(9 * accuracy, SignedRounding::NearestPrefLow),
Some(555555555555555555555555556)
);
assert_eq!(
e.checked_div_int_with_rounding(
2000000000000000000000000000u128,
SignedRounding::NearestPrefLow
),
Some(3000000000000000000000000000)
);
assert_eq!(
f.checked_div_int_with_rounding(
2000000000000000000000000000u128,
SignedRounding::NearestPrefLow
),
Some(2500000000000000000000000000u128) );
assert_eq!(
a.checked_div_int_with_rounding(u128::MAX, SignedRounding::NearestPrefLow),
Some(1 * accuracy)
);
assert_eq!(
a.checked_div_int_with_rounding(
2000000000000000000000000000u128,
SignedRounding::NearestPrefLow
),
Some(170141183460469231731687303715884105727)
);
assert_eq!(
a.checked_div_int_with_rounding(
340282366920938463463374607431768211455u128,
SignedRounding::NearestPrefLow
),
Some(1 * accuracy)
);
assert_eq!(
a.checked_div_int_with_rounding(1i8, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
b.checked_div_int_with_rounding(2, SignedRounding::NearestPrefLow),
Some(inner_min / (2 * accuracy))
);
assert_eq!(
c.checked_div_int_with_rounding(1, SignedRounding::NearestPrefLow),
Some(0)
);
assert_eq!(
c.checked_div_int_with_rounding(inner_max, SignedRounding::Major),
Some(0)
);
assert_eq!(
c.checked_div_int_with_rounding(inner_min, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
a.checked_div_int_with_rounding(0, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
b.checked_div_int_with_rounding(0, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
c.checked_div_int_with_rounding(0, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
d.checked_div_int_with_rounding(0, SignedRounding::NearestPrefLow),
None
);
}
#[test]
fn checked_div_int_floor() {
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::one();
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let max = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(max.checked_div_int_floor(2), None);
assert_eq!(
a.checked_div_int_floor(3 * accuracy),
Some(333333333333333333333333333)
);
assert_eq!(
a.checked_div_int_floor(6 * accuracy),
Some(166666666666666666666666666)
);
assert_eq!(
b.checked_div_int_floor(9 * accuracy),
Some(555555555555555555555555555)
)
}
#[test]
fn checked_div_int_ceil() {
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::one();
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let max = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(max.checked_div_int_ceil(2), None);
assert_eq!(
a.checked_div_int_with_rounding(3 * accuracy, SignedRounding::Major),
Some(333333333333333333333333334)
);
assert_eq!(
a.checked_div_int_with_rounding(6 * accuracy, SignedRounding::Major),
Some(166666666666666666666666667)
);
assert_eq!(
b.checked_div_int_with_rounding(9 * accuracy, SignedRounding::Major),
Some(555555555555555555555555556)
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_int_panics_when_divisor_is_zero() {
let _ = FixedU128::<DECIMALS_27>::one().saturating_div_int(0);
}
#[test]
fn saturating_div_int_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(a.saturating_div_int(2), 2);
let a = FixedU128::<DECIMALS_27>::min_value();
assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(a.saturating_div_int(-2), -2);
let a = FixedU128::<DECIMALS_27>::min_value();
assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
}
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_int_with_rounding_panics_when_divisor_is_zero() {
let _ = FixedU128::<DECIMALS_27>::one()
.saturating_div_int_with_rounding(0, SignedRounding::NearestPrefLow);
}
#[test]
fn saturating_div_int_with_rounding_works() {
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let b = FixedU128::<DECIMALS_27>::min_value();
let d = FixedU128::<DECIMALS_27>::one();
let e = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let max = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(
a.saturating_div_int_with_rounding(2 * accuracy, SignedRounding::NearestPrefLow),
2500000000000000000000000000
);
assert_eq!(
b.saturating_div_int_with_rounding(1i128, SignedRounding::NearestPrefLow),
(inner_min / accuracy) as i128
);
assert_eq!(
max.saturating_div_int_with_rounding(2, SignedRounding::NearestPrefLow),
inner_max
);
assert_eq!(
d.saturating_div_int_with_rounding(3 * accuracy, SignedRounding::Minor),
333333333333333333333333333
);
assert_eq!(
d.saturating_div_int_with_rounding(3 * accuracy, SignedRounding::Major),
333333333333333333333333334
);
assert_eq!(
d.saturating_div_int_with_rounding(3 * accuracy, SignedRounding::NearestPrefLow),
333333333333333333333333333
);
assert_eq!(
d.saturating_div_int_with_rounding(6 * accuracy, SignedRounding::Minor),
166666666666666666666666666
);
assert_eq!(
d.saturating_div_int_with_rounding(6 * accuracy, SignedRounding::Major),
166666666666666666666666667
);
assert_eq!(
d.saturating_div_int_with_rounding(6 * accuracy, SignedRounding::NearestPrefLow),
166666666666666666666666667
);
assert_eq!(
e.saturating_div_int_with_rounding(9 * accuracy, SignedRounding::Minor),
555555555555555555555555555
);
assert_eq!(
e.saturating_div_int_with_rounding(9 * accuracy, SignedRounding::Major),
555555555555555555555555556
);
assert_eq!(
e.saturating_div_int_with_rounding(9 * accuracy, SignedRounding::NearestPrefLow),
555555555555555555555555556
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_int_floor_panics_when_divisor_is_zero() {
let _ = FixedU128::<DECIMALS_27>::one().saturating_div_int_floor(0);
}
#[test]
fn saturating_div_int_floor() {
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::one();
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().saturating_div_int_floor(2),
FixedU128::<DECIMALS_27>::max_value().into_inner()
);
assert_eq!(
a.saturating_div_int_floor(3 * accuracy),
333333333333333333333333333
);
assert_eq!(
a.saturating_div_int_floor(6 * accuracy),
166666666666666666666666666
);
assert_eq!(
b.saturating_div_int_floor(9 * accuracy),
555555555555555555555555555
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_int_ceil_panics_when_divisor_is_zero() {
let _ = FixedU128::<DECIMALS_27>::one().saturating_div_int_ceil(0);
}
#[test]
fn saturating_div_int_ceil() {
let accuracy = FixedU128::<DECIMALS_27>::accuracy();
let a = FixedU128::<DECIMALS_27>::one();
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().saturating_div_int_ceil(2),
FixedU128::<DECIMALS_27>::max_value().into_inner()
);
assert_eq!(
a.saturating_div_int_ceil(3 * accuracy),
333333333333333333333333334
);
assert_eq!(
a.saturating_div_int_ceil(6 * accuracy),
166666666666666666666666667
);
assert_eq!(
b.saturating_div_int_ceil(9 * accuracy),
555555555555555555555555556
);
}
#[test]
fn saturating_abs_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
assert_eq!(
FixedU128::<DECIMALS_27>::from_inner(inner_max).saturating_abs(),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(FixedU128::<DECIMALS_27>::zero().saturating_abs(), 0.into());
if FixedU128::<DECIMALS_27>::SIGNED {
assert_eq!(
FixedU128::<DECIMALS_27>::from_inner(inner_min).saturating_abs(),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(-1, 2).saturating_abs(),
(1, 2).into()
);
}
}
#[test]
fn saturating_mul_acc_int_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::zero().saturating_mul_acc_int(42i8),
42i8
);
assert_eq!(
FixedU128::<DECIMALS_27>::one().saturating_mul_acc_int(42i8),
2 * 42i8
);
assert_eq!(
FixedU128::<DECIMALS_27>::one().saturating_mul_acc_int(i128::MAX),
i128::MAX
);
assert_eq!(
FixedU128::<DECIMALS_27>::one().saturating_mul_acc_int(i128::MIN),
i128::MIN
);
assert_eq!(
FixedU128::<DECIMALS_27>::one().saturating_mul_acc_int(u128::MAX / 2),
u128::MAX - 1
);
assert_eq!(
FixedU128::<DECIMALS_27>::one().saturating_mul_acc_int(u128::MIN),
u128::MIN
);
if FixedU128::<DECIMALS_27>::SIGNED {
let a = FixedU128::<DECIMALS_27>::saturating_from_rational(-1, 2);
assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
}
}
#[test]
fn saturating_pow_should_work() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(0),
FixedU128::<DECIMALS_27>::saturating_from_integer(1)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(1),
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(2),
FixedU128::<DECIMALS_27>::saturating_from_integer(4)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(50),
FixedU128::<DECIMALS_27>::saturating_from_integer(1125899906842624i64)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(1).saturating_pow(1000),
(1).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(1).saturating_pow(usize::MAX),
(1).into()
);
if FixedU128::<DECIMALS_27>::SIGNED {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(68),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-1).saturating_pow(1000),
(1).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-1).saturating_pow(1001),
0.saturating_sub(1).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-1).saturating_pow(usize::MAX),
0.saturating_sub(1).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(-1)
.saturating_pow(usize::MAX - 1),
(1).into()
);
}
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(114209).saturating_pow(5),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(1).saturating_pow(usize::MAX),
(1).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(0).saturating_pow(usize::MAX),
(0).into()
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow(usize::MAX),
FixedU128::<DECIMALS_27>::max_value()
);
}
#[test]
fn saturating_pow_with_rounding_works() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
.saturating_pow_with_rounding(0, SignedRounding::NearestPrefLow),
FixedU128::<DECIMALS_27>::saturating_from_integer(1)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
.saturating_pow_with_rounding(1, SignedRounding::NearestPrefLow),
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
.saturating_pow_with_rounding(2, SignedRounding::NearestPrefLow),
FixedU128::<DECIMALS_27>::saturating_from_integer(4)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3)
.saturating_pow_with_rounding(2, SignedRounding::Minor)
.into_inner(),
111111111111111111111111110
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3)
.saturating_pow_with_rounding(2, SignedRounding::NearestPrefLow)
.into_inner(),
111111111111111111111111111
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3)
.saturating_pow_with_rounding(2, SignedRounding::Major)
.into_inner(),
111111111111111111111111111
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 15)
.saturating_pow_with_rounding(2, SignedRounding::Minor)
.into_inner(),
4444444444444444444444444
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 15)
.saturating_pow_with_rounding(2, SignedRounding::NearestPrefLow)
.into_inner(),
4444444444444444444444444
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 15)
.saturating_pow_with_rounding(2, SignedRounding::Major)
.into_inner(),
4444444444444444444444445
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_with_rounding(2, SignedRounding::Minor)
.into_inner(),
0000000000000000000000000002
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_with_rounding(2, SignedRounding::NearestPrefLow)
.into_inner(),
0000000000000000000000000002
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_with_rounding(2, SignedRounding::NearestPrefHigh)
.into_inner(),
0000000000000000000000000003
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_with_rounding(2, SignedRounding::Major)
.into_inner(),
0000000000000000000000000003
)
}
#[test]
fn saturating_pow_floor() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_floor(0),
FixedU128::<DECIMALS_27>::saturating_from_integer(1)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_floor(1),
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_floor(2),
FixedU128::<DECIMALS_27>::saturating_from_integer(4)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3)
.saturating_pow_floor(2)
.into_inner(),
111111111111111111111111110
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 15)
.saturating_pow_floor(2)
.into_inner(),
4444444444444444444444444
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_floor(2)
.into_inner(),
0000000000000000000000000002
);
}
#[test]
fn saturating_pow_ceil() {
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_ceil(0),
FixedU128::<DECIMALS_27>::saturating_from_integer(1)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_ceil(1),
FixedU128::<DECIMALS_27>::saturating_from_integer(2)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_integer(2).saturating_pow_ceil(2),
FixedU128::<DECIMALS_27>::saturating_from_integer(4)
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 3)
.saturating_pow_ceil(2)
.into_inner(),
111111111111111111111111111
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(1, 15)
.saturating_pow_ceil(2)
.into_inner(),
4444444444444444444444445
);
assert_eq!(
FixedU128::<DECIMALS_27>::saturating_from_rational(5, 100000000000000i64)
.saturating_pow_ceil(2)
.into_inner(),
0000000000000000000000000003
);
}
#[test]
fn checked_div_works() {
let inner_max = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::max_value();
let inner_min = <FixedU128<DECIMALS_27> as FixedPointNumber>::Inner::min_value();
let a = FixedU128::<DECIMALS_27>::from_inner(inner_max);
let b = FixedU128::<DECIMALS_27>::from_inner(inner_min);
let c = FixedU128::<DECIMALS_27>::zero();
let d = FixedU128::<DECIMALS_27>::one();
let e = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let f = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(e.checked_div(&2.into()), Some(3.into()));
assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
assert_eq!(
a.checked_div(&2.into()),
Some(FixedU128::<DECIMALS_27>::from_inner(inner_max / 2))
);
assert_eq!(
a.checked_div(&FixedU128::<DECIMALS_27>::max_value()),
Some(1.into())
);
assert_eq!(a.checked_div(&d), Some(a));
if b < c {
assert_eq!(
a.checked_div(&0.saturating_sub(2).into()),
Some(FixedU128::<DECIMALS_27>::from_inner(
0.saturating_sub(inner_max / 2)
))
);
assert_eq!(
a.checked_div(&-FixedU128::<DECIMALS_27>::max_value()),
Some(0.saturating_sub(1).into())
);
assert_eq!(
b.checked_div(&0.saturating_sub(2).into()),
Some(FixedU128::<DECIMALS_27>::from_inner(
0.saturating_sub(inner_min / 2)
))
);
assert_eq!(
c.checked_div(&FixedU128::<DECIMALS_27>::max_value()),
Some(0.into())
);
assert_eq!(b.checked_div(&b), Some(FixedU128::<DECIMALS_27>::one()));
}
assert_eq!(
b.checked_div(&2.into()),
Some(FixedU128::<DECIMALS_27>::from_inner(inner_min / 2))
);
assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
assert_eq!(c.checked_div(&1.into()), Some(0.into()));
assert_eq!(d.checked_div(&1.into()), Some(1.into()));
assert_eq!(a.checked_div(&FixedU128::<DECIMALS_27>::one()), Some(a));
assert_eq!(b.checked_div(&FixedU128::<DECIMALS_27>::one()), Some(b));
assert_eq!(c.checked_div(&FixedU128::<DECIMALS_27>::one()), Some(c));
assert_eq!(d.checked_div(&FixedU128::<DECIMALS_27>::one()), Some(d));
assert_eq!(a.checked_div(&FixedU128::<DECIMALS_27>::zero()), None);
assert_eq!(b.checked_div(&FixedU128::<DECIMALS_27>::zero()), None);
assert_eq!(c.checked_div(&FixedU128::<DECIMALS_27>::zero()), None);
assert_eq!(d.checked_div(&FixedU128::<DECIMALS_27>::zero()), None);
}
#[test]
fn checked_div_with_rounding_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(
one.checked_div_with_rounding(&zero, SignedRounding::NearestPrefLow),
None
);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().checked_div_with_rounding(
&FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy()
),
SignedRounding::NearestPrefLow
),
None
);
assert_eq!(
one.checked_div_with_rounding(&a, SignedRounding::Minor)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
one.checked_div_with_rounding(&a, SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
one.checked_div_with_rounding(&a, SignedRounding::Major)
.unwrap()
.into_inner(),
333333333333333333333333334
);
assert_eq!(
one.checked_div_with_rounding(&b, SignedRounding::Minor)
.unwrap()
.into_inner(),
166666666666666666666666666
);
assert_eq!(
one.checked_div_with_rounding(&b, SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
one.checked_div_with_rounding(&b, SignedRounding::Major)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
d.checked_div_with_rounding(&c, SignedRounding::Minor)
.unwrap()
.into_inner(),
555555555555555555555555555
);
assert_eq!(
d.checked_div_with_rounding(&c, SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
555555555555555555555555556
);
assert_eq!(
d.checked_div_with_rounding(&c, SignedRounding::Major)
.unwrap()
.into_inner(),
555555555555555555555555556
);
}
#[test]
fn checked_div_floor_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(one.checked_div_floor(&zero), None);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().checked_div_floor(
&FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy()
)
),
None
);
assert_eq!(
one.checked_div_floor(&a).unwrap().into_inner(),
333333333333333333333333333
);
assert_eq!(
one.checked_div_floor(&b).unwrap().into_inner(),
166666666666666666666666666
);
assert_eq!(
d.checked_div_floor(&c).unwrap().into_inner(),
555555555555555555555555555
);
}
#[test]
fn checked_div_ceil_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
assert_eq!(one.checked_div_ceil(&zero), None);
assert_eq!(
FixedU128::<DECIMALS_27>::max_value().checked_div_floor(
&FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy()
)
),
None
);
assert_eq!(
one.checked_div_ceil(&a).unwrap().into_inner(),
333333333333333333333333334
);
assert_eq!(
one.checked_div_ceil(&b).unwrap().into_inner(),
166666666666666666666666667
);
assert_eq!(
d.checked_div_ceil(&c).unwrap().into_inner(),
555555555555555555555555556
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_with_rounding_panics_on_zero_divizor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_integer(6).saturating_div_with_rounding(
&FixedU128::<DECIMALS_27>::zero(),
SignedRounding::NearestPrefLow,
);
}
#[test]
fn saturating_div_with_rounding_works() {
let one = FixedU128::<DECIMALS_27>::one();
let zero = FixedU128::<DECIMALS_27>::zero();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let e = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(
zero.saturating_div_with_rounding(&a, SignedRounding::NearestPrefLow)
.into_inner(),
0
);
assert_eq!(
d.saturating_div_with_rounding(&e, SignedRounding::NearestPrefLow),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
one.saturating_div_with_rounding(&a, SignedRounding::Minor)
.into_inner(),
333333333333333333333333333
);
assert_eq!(
one.saturating_div_with_rounding(&a, SignedRounding::NearestPrefLow)
.into_inner(),
333333333333333333333333333
);
assert_eq!(
one.saturating_div_with_rounding(&a, SignedRounding::Major)
.into_inner(),
333333333333333333333333334
);
assert_eq!(
one.saturating_div_with_rounding(&b, SignedRounding::Minor)
.into_inner(),
166666666666666666666666666
);
assert_eq!(
one.saturating_div_with_rounding(&b, SignedRounding::NearestPrefLow)
.into_inner(),
166666666666666666666666667
);
assert_eq!(
one.saturating_div_with_rounding(&b, SignedRounding::Major)
.into_inner(),
166666666666666666666666667
);
assert_eq!(
d.saturating_div_with_rounding(&c, SignedRounding::Minor)
.into_inner(),
555555555555555555555555555
);
assert_eq!(
d.saturating_div_with_rounding(&c, SignedRounding::NearestPrefLow)
.into_inner(),
555555555555555555555555556
);
assert_eq!(
d.saturating_div_with_rounding(&c, SignedRounding::Major)
.into_inner(),
555555555555555555555555556
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_floor_panics_on_zero_divizor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_integer(6)
.saturating_div_floor(&FixedU128::<DECIMALS_27>::zero());
}
#[test]
fn saturating_div_floor_works() {
let one = FixedU128::<DECIMALS_27>::one();
let zero = FixedU128::<DECIMALS_27>::zero();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let e = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(zero.saturating_div_floor(&a).into_inner(), 0);
assert_eq!(
d.saturating_div_floor(&e),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
one.saturating_div_floor(&a).into_inner(),
333333333333333333333333333
);
assert_eq!(
one.saturating_div_floor(&b).into_inner(),
166666666666666666666666666
);
assert_eq!(
d.saturating_div_floor(&c).into_inner(),
555555555555555555555555555
);
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn saturating_div_ceil_panics_on_zero_divizor() {
let _ = FixedU128::<DECIMALS_27>::saturating_from_integer(6)
.saturating_div_ceil(&FixedU128::<DECIMALS_27>::zero());
}
#[test]
fn saturating_div_ceil_works() {
let one = FixedU128::<DECIMALS_27>::one();
let zero = FixedU128::<DECIMALS_27>::zero();
let a = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let b = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let c = FixedU128::<DECIMALS_27>::saturating_from_integer(9);
let d = FixedU128::<DECIMALS_27>::saturating_from_integer(5);
let e = FixedU128::<DECIMALS_27>::saturating_from_rational(
1,
FixedU128::<DECIMALS_27>::accuracy(),
);
assert_eq!(zero.saturating_div_ceil(&a).into_inner(), 0);
assert_eq!(
d.saturating_div_ceil(&e),
FixedU128::<DECIMALS_27>::max_value()
);
assert_eq!(
one.saturating_div_ceil(&a).into_inner(),
333333333333333333333333334
);
assert_eq!(
one.saturating_div_ceil(&b).into_inner(),
166666666666666666666666667
);
assert_eq!(
d.saturating_div_ceil(&c).into_inner(),
555555555555555555555555556
);
}
#[test]
fn is_positive_negative_works() {
let one = FixedU128::<DECIMALS_27>::one();
assert!(one.is_positive());
assert!(!one.is_negative());
let zero = FixedU128::<DECIMALS_27>::zero();
assert!(!zero.is_positive());
assert!(!zero.is_negative());
if false {
let minus_one = FixedU128::<DECIMALS_27>::saturating_from_integer(-1);
assert!(minus_one.is_negative());
assert!(!minus_one.is_positive());
}
}
#[test]
fn trunc_works() {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2).trunc();
assert_eq!(n, FixedU128::<DECIMALS_27>::saturating_from_integer(2));
if FixedU128::<DECIMALS_27>::SIGNED {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2).trunc();
assert_eq!(n, FixedU128::<DECIMALS_27>::saturating_from_integer(-2));
}
}
#[test]
fn frac_works() {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
let i = n.trunc();
let f = n.frac();
assert_eq!(n, i + f);
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2)
.frac()
.saturating_mul(10.into());
assert_eq!(n, 5.into());
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2)
.frac()
.saturating_mul(10.into());
assert_eq!(n, 5.into());
if FixedU128::<DECIMALS_27>::SIGNED {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2);
let i = n.trunc();
let f = n.frac();
assert_eq!(n, i - f);
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2)
.frac()
.saturating_mul(10.into());
assert_eq!(n, 5.into());
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-1, 2)
.frac()
.saturating_mul(10.into());
assert_eq!(n, 0.saturating_sub(5).into());
}
}
#[test]
fn ceil_works() {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
assert_eq!(n.ceil(), 3.into());
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2);
assert_eq!(n.ceil(), 0.saturating_sub(2).into());
let n = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(n.ceil(), n.trunc());
let n = FixedU128::<DECIMALS_27>::min_value();
assert_eq!(n.ceil(), n.trunc());
}
#[test]
fn floor_works() {
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
assert_eq!(n.floor(), 2.into());
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2);
assert_eq!(n.floor(), 0.saturating_sub(3).into());
let n = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(n.floor(), n.trunc());
let n = FixedU128::<DECIMALS_27>::min_value();
assert_eq!(n.floor(), n.trunc());
}
#[test]
fn round_works() {
let n = FixedU128::<DECIMALS_27>::zero();
assert_eq!(n.round(), n);
let n = FixedU128::<DECIMALS_27>::one();
assert_eq!(n.round(), n);
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
assert_eq!(n.round(), 3.into());
let n = FixedU128::<DECIMALS_27>::saturating_from_rational(-5, 2);
assert_eq!(n.round(), 0.saturating_sub(3).into());
let n = FixedU128::<DECIMALS_27>::max_value();
assert_eq!(n.round(), n.trunc());
let n = FixedU128::<DECIMALS_27>::min_value();
assert_eq!(n.round(), n.trunc());
let n = FixedU128::<DECIMALS_27>::max_value()
.saturating_sub(1.into())
.trunc()
.saturating_add((1, 3).into());
assert_eq!(
n.round(),
(FixedU128::<DECIMALS_27>::max_value() - 1.into()).trunc()
);
let n = FixedU128::<DECIMALS_27>::max_value()
.saturating_sub(1.into())
.trunc()
.saturating_add((1, 2).into());
assert_eq!(n.round(), FixedU128::<DECIMALS_27>::max_value().trunc());
if FixedU128::<DECIMALS_27>::SIGNED {
let n = FixedU128::<DECIMALS_27>::min_value()
.saturating_add(1.into())
.trunc()
.saturating_sub((1, 3).into());
assert_eq!(
n.round(),
(FixedU128::<DECIMALS_27>::min_value() + 1.into()).trunc()
);
let n = FixedU128::<DECIMALS_27>::min_value()
.saturating_add(1.into())
.trunc()
.saturating_sub((1, 2).into());
assert_eq!(n.round(), FixedU128::<DECIMALS_27>::min_value().trunc());
}
}
#[test]
fn reciprocal_with_rounding_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let three = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let six = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let pref_precision_check_val = FixedU128::<DECIMALS_27>::saturating_from_integer(222220);
assert_eq!(zero.reciprocal_with_rounding(SignedRounding::Minor), None);
assert_eq!(zero.reciprocal_with_rounding(SignedRounding::Major), None);
assert_eq!(
one.reciprocal_with_rounding(SignedRounding::Major),
Some(FixedU128::<DECIMALS_27>::one())
);
assert_eq!(
one.reciprocal_with_rounding(SignedRounding::Minor),
Some(FixedU128::<DECIMALS_27>::one())
);
assert_eq!(
three
.reciprocal_with_rounding(SignedRounding::Minor)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
three
.reciprocal_with_rounding(SignedRounding::Major)
.unwrap()
.into_inner(),
333333333333333333333333334
);
assert_eq!(
three
.reciprocal_with_rounding(SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
333333333333333333333333333
);
assert_eq!(
three.reciprocal_with_rounding(SignedRounding::Minor),
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 3),
);
assert_eq!(
six.reciprocal_with_rounding(SignedRounding::Minor)
.unwrap()
.into_inner(),
166666666666666666666666666
);
assert_eq!(
six.reciprocal_with_rounding(SignedRounding::Major)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
six.reciprocal_with_rounding(SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
166666666666666666666666667
);
assert_eq!(
pref_precision_check_val
.reciprocal_with_rounding(SignedRounding::Minor)
.unwrap()
.into_inner(),
4500045000450004500045
);
assert_eq!(
pref_precision_check_val
.reciprocal_with_rounding(SignedRounding::Major)
.unwrap()
.into_inner(),
4500045000450004500046
);
assert_eq!(
pref_precision_check_val
.reciprocal_with_rounding(SignedRounding::NearestPrefLow)
.unwrap()
.into_inner(),
4500045000450004500045
);
}
#[test]
fn reciprocal_floor_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let three = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let six = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let pref_precision_check_val = FixedU128::<DECIMALS_27>::saturating_from_integer(222220);
assert_eq!(zero.reciprocal_floor(), None);
assert_eq!(
one.reciprocal_floor(),
Some(FixedU128::<DECIMALS_27>::one())
);
assert_eq!(
three.reciprocal_floor().unwrap().into_inner(),
333333333333333333333333333
);
assert_eq!(
three.reciprocal_floor(),
FixedU128::<DECIMALS_27>::checked_from_rational_floor(1, 3),
);
assert_eq!(
six.reciprocal_floor().unwrap().into_inner(),
166666666666666666666666666
);
assert_eq!(
pref_precision_check_val
.reciprocal_floor()
.unwrap()
.into_inner(),
4500045000450004500045
);
}
#[test]
fn reciprocal_ceil_works() {
let zero = FixedU128::<DECIMALS_27>::zero();
let one = FixedU128::<DECIMALS_27>::one();
let three = FixedU128::<DECIMALS_27>::saturating_from_integer(3);
let six = FixedU128::<DECIMALS_27>::saturating_from_integer(6);
let pref_precision_check_val = FixedU128::<DECIMALS_27>::saturating_from_integer(222220);
assert_eq!(zero.reciprocal_ceil(), None);
assert_eq!(one.reciprocal_ceil(), Some(FixedU128::<DECIMALS_27>::one()));
assert_eq!(
three.reciprocal_ceil().unwrap().into_inner(),
333333333333333333333333334
);
assert_eq!(
three.reciprocal_ceil(),
FixedU128::<DECIMALS_27>::checked_from_rational_ceil(1, 3),
);
assert_eq!(
six.reciprocal_ceil().unwrap().into_inner(),
166666666666666666666666667
);
assert_eq!(
pref_precision_check_val
.reciprocal_ceil()
.unwrap()
.into_inner(),
4500045000450004500046
);
}
#[test]
fn fmt_should_work() {
let zero = FixedU128::<DECIMALS_27>::zero();
assert_eq!(
format!("{:?}", zero),
format!(
"{}(0.{:0>weight$})",
stringify!(FixedU128),
0,
weight = precision()
)
);
let one = FixedU128::<DECIMALS_27>::one();
assert_eq!(
format!("{:?}", one),
format!(
"{}(1.{:0>weight$})",
stringify!(FixedU128),
0,
weight = precision()
)
);
let frac = FixedU128::<DECIMALS_27>::saturating_from_rational(1, 2);
assert_eq!(
format!("{:?}", frac),
format!(
"{}(0.{:0<weight$})",
stringify!(FixedU128),
5,
weight = precision()
)
);
let frac = FixedU128::<DECIMALS_27>::saturating_from_rational(5, 2);
assert_eq!(
format!("{:?}", frac),
format!(
"{}(2.{:0<weight$})",
stringify!(FixedU128),
5,
weight = precision()
)
);
let frac = FixedU128::<DECIMALS_27>::saturating_from_rational(314, 100);
assert_eq!(
format!("{:?}", frac),
format!(
"{}(3.{:0<weight$})",
stringify!(FixedU128),
14,
weight = precision()
)
);
if FixedU128::<DECIMALS_27>::SIGNED {
let neg = -FixedU128::<DECIMALS_27>::one();
assert_eq!(
format!("{:?}", neg),
format!(
"{}(-1.{:0>weight$})",
stringify!(FixedU128),
0,
weight = precision()
)
);
let frac = FixedU128::<DECIMALS_27>::saturating_from_rational(-314, 100);
assert_eq!(
format!("{:?}", frac),
format!(
"{}(-3.{:0<weight$})",
stringify!(FixedU128),
14,
weight = precision()
)
);
}
}
}