Update and slightly refactor some of the Float trait
Add a constant for negative pi and provide a standalone const `from_bits`, which can be combined with what we already had in `hex_float`. Also provide another default method to reduce what needs to be provided by the macro.
This commit is contained in:
parent
2323d3a2e3
commit
5e6b813e51
3 changed files with 36 additions and 24 deletions
|
|
@ -38,6 +38,7 @@ pub trait Float:
|
|||
const MAX: Self;
|
||||
const MIN: Self;
|
||||
const PI: Self;
|
||||
const NEG_PI: Self;
|
||||
const FRAC_PI_2: Self;
|
||||
|
||||
/// The bitwidth of the float type
|
||||
|
|
@ -71,7 +72,9 @@ pub trait Float:
|
|||
fn to_bits(self) -> Self::Int;
|
||||
|
||||
/// Returns `self` transmuted to `Self::SignedInt`
|
||||
fn to_bits_signed(self) -> Self::SignedInt;
|
||||
fn to_bits_signed(self) -> Self::SignedInt {
|
||||
self.to_bits().signed()
|
||||
}
|
||||
|
||||
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
|
||||
/// represented in multiple different ways. This method returns `true` if two NaNs are
|
||||
|
|
@ -158,7 +161,15 @@ pub trait Float:
|
|||
pub type IntTy<F> = <F as Float>::Int;
|
||||
|
||||
macro_rules! float_impl {
|
||||
($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {
|
||||
(
|
||||
$ty:ident,
|
||||
$ity:ident,
|
||||
$sity:ident,
|
||||
$expty:ident,
|
||||
$bits:expr,
|
||||
$significand_bits:expr,
|
||||
$from_bits:path
|
||||
) => {
|
||||
impl Float for $ty {
|
||||
type Int = $ity;
|
||||
type SignedInt = $sity;
|
||||
|
|
@ -173,13 +184,10 @@ macro_rules! float_impl {
|
|||
const NAN: Self = Self::NAN;
|
||||
const MAX: Self = -Self::MIN;
|
||||
// Sign bit set, saturated mantissa, saturated exponent with last bit zeroed
|
||||
// FIXME(msrv): just use `from_bits` when available
|
||||
// SAFETY: POD cast with no preconditions
|
||||
const MIN: Self = unsafe {
|
||||
mem::transmute::<Self::Int, Self>(Self::Int::MAX & !(1 << Self::SIG_BITS))
|
||||
};
|
||||
const MIN: Self = $from_bits(Self::Int::MAX & !(1 << Self::SIG_BITS));
|
||||
|
||||
const PI: Self = core::$ty::consts::PI;
|
||||
const NEG_PI: Self = -Self::PI;
|
||||
const FRAC_PI_2: Self = core::$ty::consts::FRAC_PI_2;
|
||||
|
||||
const BITS: u32 = $bits;
|
||||
|
|
@ -193,9 +201,6 @@ macro_rules! float_impl {
|
|||
fn to_bits(self) -> Self::Int {
|
||||
self.to_bits()
|
||||
}
|
||||
fn to_bits_signed(self) -> Self::SignedInt {
|
||||
self.to_bits() as Self::SignedInt
|
||||
}
|
||||
fn is_nan(self) -> bool {
|
||||
self.is_nan()
|
||||
}
|
||||
|
|
@ -220,8 +225,22 @@ macro_rules! float_impl {
|
|||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
float_impl!(f16, u16, i16, i8, 16, 10);
|
||||
float_impl!(f32, u32, i32, i16, 32, 23);
|
||||
float_impl!(f64, u64, i64, i16, 64, 52);
|
||||
float_impl!(f16, u16, i16, i8, 16, 10, f16::from_bits);
|
||||
float_impl!(f32, u32, i32, i16, 32, 23, f32_from_bits);
|
||||
float_impl!(f64, u64, i64, i16, 64, 52, f64_from_bits);
|
||||
#[cfg(f128_enabled)]
|
||||
float_impl!(f128, u128, i128, i16, 128, 112);
|
||||
float_impl!(f128, u128, i128, i16, 128, 112, f128::from_bits);
|
||||
|
||||
/* FIXME(msrv): vendor some things that are not const stable at our MSRV */
|
||||
|
||||
/// `f32::from_bits`
|
||||
pub const fn f32_from_bits(bits: u32) -> f32 {
|
||||
// SAFETY: POD cast with no preconditions
|
||||
unsafe { mem::transmute::<u32, f32>(bits) }
|
||||
}
|
||||
|
||||
/// `f64::from_bits`
|
||||
pub const fn f64_from_bits(bits: u64) -> f64 {
|
||||
// SAFETY: POD cast with no preconditions
|
||||
unsafe { mem::transmute::<u64, f64>(bits) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#![allow(dead_code)] // FIXME: remove once this gets used
|
||||
|
||||
use super::{f32_from_bits, f64_from_bits};
|
||||
|
||||
/// Construct a 32-bit float from hex float representation (C-style)
|
||||
pub const fn hf32(s: &str) -> f32 {
|
||||
f32_from_bits(parse_any(s, 32, 23) as u32)
|
||||
|
|
@ -159,16 +161,6 @@ const fn hex_digit(c: u8) -> u8 {
|
|||
|
||||
/* FIXME(msrv): vendor some things that are not const stable at our MSRV */
|
||||
|
||||
/// `f32::from_bits`
|
||||
const fn f32_from_bits(v: u32) -> f32 {
|
||||
unsafe { core::mem::transmute(v) }
|
||||
}
|
||||
|
||||
/// `f64::from_bits`
|
||||
const fn f64_from_bits(v: u64) -> f64 {
|
||||
unsafe { core::mem::transmute(v) }
|
||||
}
|
||||
|
||||
/// `u128::ilog2`
|
||||
const fn u128_ilog2(v: u128) -> u32 {
|
||||
assert!(v != 0);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ mod int_traits;
|
|||
|
||||
#[allow(unused_imports)]
|
||||
pub use float_traits::{Float, IntTy};
|
||||
pub(crate) use float_traits::{f32_from_bits, f64_from_bits};
|
||||
#[allow(unused_imports)]
|
||||
pub use hex_float::{hf32, hf64};
|
||||
pub use int_traits::{CastFrom, CastInto, DInt, HInt, Int, MinInt};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue