#[cfg(feature = "radix_engine_fuzzing")]
use arbitrary::Arbitrary;
use core::cmp::Ordering;
use sbor::Sbor;
#[cfg(feature = "radix_engine_fuzzing")]
use serde::{Deserialize, Serialize};
#[cfg_attr(
feature = "radix_engine_fuzzing",
derive(Arbitrary, Serialize, Deserialize)
)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Sbor)]
pub enum RoundingMode {
ToPositiveInfinity,
ToNegativeInfinity,
ToZero,
AwayFromZero,
ToNearestMidpointTowardZero,
ToNearestMidpointAwayFromZero,
ToNearestMidpointToEven,
}
pub(crate) enum ResolvedRoundingStrategy {
RoundUp,
RoundDown,
RoundToEven,
}
impl ResolvedRoundingStrategy {
pub fn from_mode(
mode: RoundingMode,
is_positive: bool,
compare_to_midpoint: impl FnOnce() -> Ordering,
) -> Self {
match mode {
RoundingMode::ToPositiveInfinity => ResolvedRoundingStrategy::RoundUp,
RoundingMode::ToNegativeInfinity => ResolvedRoundingStrategy::RoundDown,
RoundingMode::ToZero => ResolvedRoundingStrategy::towards_zero(is_positive),
RoundingMode::AwayFromZero => ResolvedRoundingStrategy::away_from_zero(is_positive),
RoundingMode::ToNearestMidpointTowardZero => Self::from_midpoint_ordering(
compare_to_midpoint(),
ResolvedRoundingStrategy::towards_zero(is_positive),
),
RoundingMode::ToNearestMidpointAwayFromZero => Self::from_midpoint_ordering(
compare_to_midpoint(),
ResolvedRoundingStrategy::away_from_zero(is_positive),
),
RoundingMode::ToNearestMidpointToEven => Self::from_midpoint_ordering(
compare_to_midpoint(),
ResolvedRoundingStrategy::RoundToEven,
),
}
}
fn from_midpoint_ordering(ordering: Ordering, equal_strategy: Self) -> Self {
match ordering {
Ordering::Less => Self::RoundDown,
Ordering::Equal => equal_strategy,
Ordering::Greater => Self::RoundUp,
}
}
fn towards_zero(is_positive: bool) -> Self {
if is_positive {
Self::RoundDown
} else {
Self::RoundUp
}
}
fn away_from_zero(is_positive: bool) -> Self {
if is_positive {
Self::RoundUp
} else {
Self::RoundDown
}
}
}