macro_rules! decl_decimal_float_bridge {
(wide $Type:ident, $Storage:ty) => {
impl<const SCALE: u32> $Type<SCALE> {
#[inline]
#[must_use]
pub fn from_f64(value: f64) -> Self {
Self::from_f64_with(value, $crate::support::rounding::DEFAULT_ROUNDING_MODE)
}
#[inline]
#[must_use]
pub fn from_f64_with(
value: f64,
mode: $crate::support::rounding::RoundingMode,
) -> Self {
if value.is_nan() {
return Self::ZERO;
}
if value.is_infinite() {
return if value > 0.0 { Self::MAX } else { Self::MIN };
}
let mult_f64: f64 = Self::multiplier().as_f64();
let scaled = value * mult_f64;
let storage_max_f64: f64 = <$Storage>::MAX.as_f64();
let storage_min_f64: f64 = <$Storage>::MIN.as_f64();
if scaled >= storage_max_f64 {
return Self::MAX;
}
if scaled < storage_min_f64 {
return Self::MIN;
}
let rounded = match mode {
$crate::support::rounding::RoundingMode::HalfToEven => {
$crate::support::rounding::round_half_even_f64(scaled)
}
$crate::support::rounding::RoundingMode::HalfAwayFromZero => {
$crate::support::rounding::round_half_away_f64(scaled)
}
$crate::support::rounding::RoundingMode::HalfTowardZero => {
$crate::support::rounding::round_half_toward_zero_f64(scaled)
}
$crate::support::rounding::RoundingMode::Trunc => {
$crate::support::rounding::trunc_f64(scaled)
}
$crate::support::rounding::RoundingMode::Floor => {
$crate::support::rounding::floor_f64(scaled)
}
$crate::support::rounding::RoundingMode::Ceiling => {
$crate::support::rounding::ceil_f64(scaled)
}
};
Self(<$Storage>::from_f64(rounded))
}
#[inline]
#[must_use]
pub fn to_f64(self) -> f64 {
let raw_f64: f64 = self.0.as_f64();
let mult_f64: f64 = Self::multiplier().as_f64();
raw_f64 / mult_f64
}
#[inline]
#[must_use]
pub fn to_f32(self) -> f32 {
self.to_f64() as f32
}
#[cfg(all(feature = "std", feature = "experimental-floats"))]
#[inline]
#[must_use]
pub fn from_f16(value: f16) -> Self {
Self::from_f64(value as f64)
}
#[cfg(all(feature = "std", feature = "experimental-floats"))]
#[inline]
#[must_use]
pub fn to_f16(self) -> f16 {
self.to_f64() as f16
}
#[cfg(all(feature = "std", feature = "experimental-floats"))]
#[inline]
#[must_use]
pub fn from_f128(value: f128) -> Self {
Self::from_f128_with(value, $crate::support::rounding::DEFAULT_ROUNDING_MODE)
}
#[cfg(all(feature = "std", feature = "experimental-floats"))]
#[inline]
#[must_use]
pub fn from_f128_with(
value: f128,
mode: $crate::support::rounding::RoundingMode,
) -> Self {
Self::from_f64_with(value as f64, mode)
}
#[cfg(all(feature = "std", feature = "experimental-floats"))]
#[inline]
#[must_use]
pub fn to_f128(self) -> f128 {
self.to_f64() as f128
}
}
};
}
pub(crate) use decl_decimal_float_bridge;