#[doc(hidden)]
#[macro_export]
macro_rules! __float_fix_ceil_body {
($float:ty, $Fixed:ident, $Frac:ty, $Bits:ty, $v:ident) => {{
if $v.is_nan() {
$crate::extended::Extended::PosInf
} else if $v == <$float>::NEG_INFINITY {
$crate::extended::Extended::NegInf
} else if $v == <$float>::INFINITY {
$crate::extended::Extended::PosInf
} else {
let v_f64: f64 = $v as f64;
let max_q: $Fixed<$Frac> = <$Fixed<$Frac>>::MAX;
let min_q: $Fixed<$Frac> = <$Fixed<$Frac>>::MIN;
let max_v_f64: f64 = max_q.to_num::<f64>();
let min_v_f64: f64 = min_q.to_num::<f64>();
if v_f64 > max_v_f64 {
$crate::extended::Extended::PosInf
} else if v_f64 < min_v_f64 {
$crate::extended::Extended::Finite(min_q)
} else {
let scale: f64 =
$crate::float::scale_pow2_f64(<$Frac as ::fixed::types::extra::Unsigned>::U32);
let scaled: f64 = v_f64 * scale;
let scaled_ceil: f64 = scaled.ceil();
let bits: $Bits = scaled_ceil as $Bits;
if bits == <$Bits>::MAX
&& <$Bits as $crate::float::BitsToF64Rd>::to_f64_rd(<$Bits>::MAX) < scaled_ceil
{
$crate::extended::Extended::PosInf
} else {
$crate::extended::Extended::Finite(<$Fixed<$Frac>>::from_bits(bits))
}
}
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __float_fix_floor_body {
($float:ty, $Fixed:ident, $Frac:ty, $Bits:ty, $v:ident) => {{
if $v.is_nan() {
$crate::extended::Extended::NegInf
} else if $v == <$float>::NEG_INFINITY {
$crate::extended::Extended::NegInf
} else if $v == <$float>::INFINITY {
$crate::extended::Extended::PosInf
} else {
let v_f64: f64 = $v as f64;
let max_q: $Fixed<$Frac> = <$Fixed<$Frac>>::MAX;
let min_q: $Fixed<$Frac> = <$Fixed<$Frac>>::MIN;
let max_v_f64: f64 = max_q.to_num::<f64>();
let min_v_f64: f64 = min_q.to_num::<f64>();
if v_f64 > max_v_f64 {
$crate::extended::Extended::Finite(max_q)
} else if v_f64 < min_v_f64 {
$crate::extended::Extended::NegInf
} else {
let scale: f64 =
$crate::float::scale_pow2_f64(<$Frac as ::fixed::types::extra::Unsigned>::U32);
let scaled: f64 = v_f64 * scale;
let bits: $Bits = scaled.floor() as $Bits;
$crate::extended::Extended::Finite(<$Fixed<$Frac>>::from_bits(bits))
}
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __float_fix_inner_body {
($float:ty, $Fixed:ident, $Frac:ty, $Bits:ty, $b:ident) => {
match $b {
$crate::extended::Extended::NegInf => $crate::float::N5::new(<$float>::NEG_INFINITY),
$crate::extended::Extended::PosInf => $crate::float::N5::new(<$float>::INFINITY),
$crate::extended::Extended::Finite(q) => {
let approx_f64: f64 = <$Bits as $crate::float::BitsToF64Rd>::to_f64_rd(q.to_bits());
let scale_neg: f64 = $crate::float::scale_pow2_f64_neg(
<$Frac as ::fixed::types::extra::Unsigned>::U32,
);
let value_f64: f64 = approx_f64 * scale_neg;
let value: $float =
<$float as $crate::float::RoundDownFromF64>::from_f64_rd(value_f64);
$crate::float::N5::new(value)
}
}
};
}
#[cfg_attr(feature = "macros", macro_export)]
macro_rules! float_fixed {
($(#[$meta:meta])* $vis:vis $name:ident, $float:ty, $Fixed:ident, $Frac:ty, $Bits:ty) => {
$crate::conn_k! {
$(#[$meta])*
$vis $name : $crate::float::N5<$float> => $crate::extended::Extended<$Fixed<$Frac>> {
ceil: {
fn ceil(x: $crate::float::N5<$float>)
-> $crate::extended::Extended<$Fixed<$Frac>>
{
let v = x.into_inner();
$crate::__float_fix_ceil_body!($float, $Fixed, $Frac, $Bits, v)
}
ceil
},
inner: {
fn inner(b: $crate::extended::Extended<$Fixed<$Frac>>)
-> $crate::float::N5<$float>
{
$crate::__float_fix_inner_body!($float, $Fixed, $Frac, $Bits, b)
}
inner
},
floor: {
fn floor(x: $crate::float::N5<$float>)
-> $crate::extended::Extended<$Fixed<$Frac>>
{
let v = x.into_inner();
$crate::__float_fix_floor_body!($float, $Fixed, $Frac, $Bits, v)
}
floor
},
}
}
};
}
#[cfg_attr(feature = "macros", macro_export)]
macro_rules! float_fixed_l {
($(#[$meta:meta])* $vis:vis $name:ident, $float:ty, $Fixed:ident, $Frac:ty, $Bits:ty) => {
$(#[$meta])*
$vis const $name: $crate::conn::Conn<
$crate::float::N5<$float>,
$crate::extended::Extended<$Fixed<$Frac>>,
> = {
fn ceil(x: $crate::float::N5<$float>)
-> $crate::extended::Extended<$Fixed<$Frac>>
{
let v = x.into_inner();
$crate::__float_fix_ceil_body!($float, $Fixed, $Frac, $Bits, v)
}
fn inner(b: $crate::extended::Extended<$Fixed<$Frac>>)
-> $crate::float::N5<$float>
{
$crate::__float_fix_inner_body!($float, $Fixed, $Frac, $Bits, b)
}
$crate::conn::Conn::new_l(ceil, inner)
};
};
}
pub(crate) use float_fixed;
pub(crate) use float_fixed_l;
#[cfg(test)]
mod tests {
use crate::extended::Extended;
use fixed::FixedI8;
use fixed::types::extra::U0;
#[test]
fn float_fix_helper_boundary_policy() {
let v = f32::NAN;
assert_eq!(
crate::__float_fix_ceil_body!(f32, FixedI8, U0, i8, v),
Extended::PosInf
);
assert_eq!(
crate::__float_fix_floor_body!(f32, FixedI8, U0, i8, v),
Extended::NegInf
);
let v = f32::NEG_INFINITY;
assert_eq!(
crate::__float_fix_ceil_body!(f32, FixedI8, U0, i8, v),
Extended::NegInf
);
assert_eq!(
crate::__float_fix_floor_body!(f32, FixedI8, U0, i8, v),
Extended::NegInf
);
let v = f32::INFINITY;
assert_eq!(
crate::__float_fix_ceil_body!(f32, FixedI8, U0, i8, v),
Extended::PosInf
);
assert_eq!(
crate::__float_fix_floor_body!(f32, FixedI8, U0, i8, v),
Extended::PosInf
);
}
#[cfg(feature = "f16")]
#[test]
fn float_fix_helper_f16_wide_boundary_policy() {
use fixed::FixedI16;
let v = f16::NAN;
assert_eq!(
crate::__float_fix_ceil_body!(f16, FixedI16, U0, i16, v),
Extended::PosInf
);
assert_eq!(
crate::__float_fix_floor_body!(f16, FixedI16, U0, i16, v),
Extended::NegInf
);
let v = f16::NEG_INFINITY;
assert_eq!(
crate::__float_fix_ceil_body!(f16, FixedI16, U0, i16, v),
Extended::NegInf
);
assert_eq!(
crate::__float_fix_floor_body!(f16, FixedI16, U0, i16, v),
Extended::NegInf
);
let v = f16::INFINITY;
assert_eq!(
crate::__float_fix_ceil_body!(f16, FixedI16, U0, i16, v),
Extended::PosInf
);
assert_eq!(
crate::__float_fix_floor_body!(f16, FixedI16, U0, i16, v),
Extended::PosInf
);
}
}
pub mod i008;
pub mod i016;
pub mod i032;
pub mod i064;
pub mod i128;
pub mod u008;
pub mod u016;
pub mod u032;
pub mod u064;
pub mod u128;