Merge pull request #718 from tgross35/float-trait-refactor

Rename Float::repr and Float::from_repr
This commit is contained in:
Trevor Gross 2024-10-25 14:38:01 -05:00 committed by GitHub
commit 8184473187
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 76 additions and 72 deletions

View file

@ -25,8 +25,8 @@ where
let quiet_bit = implicit_bit >> 1;
let qnan_rep = exponent_mask | quiet_bit;
let mut a_rep = a.repr();
let mut b_rep = b.repr();
let mut a_rep = a.to_bits();
let mut b_rep = b.to_bits();
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;
@ -34,17 +34,17 @@ where
if a_abs.wrapping_sub(one) >= inf_rep - one || b_abs.wrapping_sub(one) >= inf_rep - one {
// NaN + anything = qNaN
if a_abs > inf_rep {
return F::from_repr(a_abs | quiet_bit);
return F::from_bits(a_abs | quiet_bit);
}
// anything + NaN = qNaN
if b_abs > inf_rep {
return F::from_repr(b_abs | quiet_bit);
return F::from_bits(b_abs | quiet_bit);
}
if a_abs == inf_rep {
// +/-infinity + -/+infinity = qNaN
if (a.repr() ^ b.repr()) == sign_bit {
return F::from_repr(qnan_rep);
if (a.to_bits() ^ b.to_bits()) == sign_bit {
return F::from_bits(qnan_rep);
} else {
// +/-infinity + anything remaining = +/- infinity
return a;
@ -60,7 +60,7 @@ where
if a_abs == MinInt::ZERO {
// but we need to get the sign right for zero + zero
if b_abs == MinInt::ZERO {
return F::from_repr(a.repr() & b.repr());
return F::from_bits(a.to_bits() & b.to_bits());
} else {
return b;
}
@ -126,7 +126,7 @@ where
a_significand = a_significand.wrapping_sub(b_significand);
// If a == -b, return +zero.
if a_significand == MinInt::ZERO {
return F::from_repr(MinInt::ZERO);
return F::from_bits(MinInt::ZERO);
}
// If partial cancellation occured, we need to left-shift the result
@ -152,7 +152,7 @@ where
// If we have overflowed the type, return +/- infinity:
if a_exponent >= max_exponent as i32 {
return F::from_repr(inf_rep | result_sign);
return F::from_bits(inf_rep | result_sign);
}
if a_exponent <= 0 {
@ -185,7 +185,7 @@ where
result += result & one;
}
F::from_repr(result)
F::from_bits(result)
}
intrinsics! {

View file

@ -41,8 +41,8 @@ fn cmp<F: Float>(a: F, b: F) -> Result {
let exponent_mask = F::EXPONENT_MASK;
let inf_rep = exponent_mask;
let a_rep = a.repr();
let b_rep = b.repr();
let a_rep = a.to_bits();
let b_rep = b.to_bits();
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;
@ -56,8 +56,8 @@ fn cmp<F: Float>(a: F, b: F) -> Result {
return Result::Equal;
}
let a_srep = a.signed_repr();
let b_srep = b.signed_repr();
let a_srep = a.to_bits_signed();
let b_srep = b.to_bits_signed();
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a fp_ting-point compare.
@ -90,8 +90,8 @@ fn unord<F: Float>(a: F, b: F) -> bool {
let exponent_mask = F::EXPONENT_MASK;
let inf_rep = exponent_mask;
let a_rep = a.repr();
let b_rep = b.repr();
let a_rep = a.to_bits();
let b_rep = b.to_bits();
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;

View file

@ -158,7 +158,7 @@ where
F::Int: CastInto<U::UnsignedInt>,
u32: CastFrom<F::Int>,
{
float_to_int_inner::<F, U, _, _>(f.repr(), |i: U| i, || U::MAX)
float_to_int_inner::<F, U, _, _>(f.to_bits(), |i: U| i, || U::MAX)
}
/// Generic float to signed int conversions.
@ -172,7 +172,7 @@ where
u32: CastFrom<F::Int>,
{
float_to_int_inner::<F, I, _, _>(
f.repr() & !F::SIGN_MASK,
f.to_bits() & !F::SIGN_MASK,
|i: I| if f.is_sign_negative() { -i } else { i },
|| if f.is_sign_negative() { I::MIN } else { I::MAX },
)
@ -203,7 +203,7 @@ where
let int_max_exp = F::EXPONENT_BIAS + I::MAX.ilog2() + 1;
let foobar = F::EXPONENT_BIAS + I::UnsignedInt::BITS - 1;
if fbits < F::ONE.repr() {
if fbits < F::ONE.to_bits() {
// < 0 gets rounded to 0
I::ZERO
} else if fbits < F::Int::cast_from(int_max_exp) << F::SIGNIFICAND_BITS {

View file

@ -126,8 +126,8 @@ where
half_iterations += 1;
}
let a_rep = a.repr();
let b_rep = b.repr();
let a_rep = a.to_bits();
let b_rep = b.to_bits();
// Exponent numeric representationm not accounting for bias
let a_exponent = (a_rep >> significand_bits) & exponent_sat;
@ -150,42 +150,42 @@ where
// NaN / anything = qNaN
if a_abs > inf_rep {
return F::from_repr(a_rep | quiet_bit);
return F::from_bits(a_rep | quiet_bit);
}
// anything / NaN = qNaN
if b_abs > inf_rep {
return F::from_repr(b_rep | quiet_bit);
return F::from_bits(b_rep | quiet_bit);
}
if a_abs == inf_rep {
if b_abs == inf_rep {
// infinity / infinity = NaN
return F::from_repr(qnan_rep);
return F::from_bits(qnan_rep);
} else {
// infinity / anything else = +/- infinity
return F::from_repr(a_abs | quotient_sign);
return F::from_bits(a_abs | quotient_sign);
}
}
// anything else / infinity = +/- 0
if b_abs == inf_rep {
return F::from_repr(quotient_sign);
return F::from_bits(quotient_sign);
}
if a_abs == zero {
if b_abs == zero {
// zero / zero = NaN
return F::from_repr(qnan_rep);
return F::from_bits(qnan_rep);
} else {
// zero / anything else = +/- zero
return F::from_repr(quotient_sign);
return F::from_bits(quotient_sign);
}
}
// anything else / zero = +/- infinity
if b_abs == zero {
return F::from_repr(inf_rep | quotient_sign);
return F::from_bits(inf_rep | quotient_sign);
}
// a is denormal. Renormalize it and set the scale to include the necessary exponent
@ -463,7 +463,7 @@ where
//
// If we have overflowed the exponent, return infinity
if res_exponent >= i32::cast_from(exponent_sat) {
return F::from_repr(inf_rep | quotient_sign);
return F::from_bits(inf_rep | quotient_sign);
}
// Now, quotient <= the correctly-rounded result
@ -476,7 +476,7 @@ where
ret
} else {
if ((significand_bits as i32) + res_exponent) < 0 {
return F::from_repr(quotient_sign);
return F::from_bits(quotient_sign);
}
let ret = quotient.wrapping_shr(u32::cast_from(res_exponent.wrapping_neg()) + 1);
@ -501,7 +501,7 @@ where
u8::from(abs_result < inf_rep && residual_lo > (4 + 1).cast() * b_significand).into();
}
F::from_repr(abs_result | quotient_sign)
F::from_bits(abs_result | quotient_sign)
}
/// Calculate the number of iterations required for a float type's precision.

View file

@ -32,7 +32,7 @@ where
let sign_bits_delta = dst_sign_bits - src_sign_bits;
let exp_bias_delta = dst_exp_bias - src_exp_bias;
let a_abs = a.repr() & src_abs_mask;
let a_abs = a.to_bits() & src_abs_mask;
let mut abs_result = R::Int::ZERO;
if a_abs.wrapping_sub(src_min_normal) < src_infinity.wrapping_sub(src_min_normal) {
@ -65,8 +65,8 @@ where
abs_result = (abs_result ^ dst_min_normal) | (bias_dst.wrapping_shl(dst_sign_bits));
}
let sign_result: R::Int = (a.repr() & src_sign_mask).cast();
R::from_repr(abs_result | (sign_result.wrapping_shl(dst_bits - src_bits)))
let sign_result: R::Int = (a.to_bits() & src_sign_mask).cast();
R::from_bits(abs_result | (sign_result.wrapping_shl(dst_bits - src_bits)))
}
intrinsics! {

View file

@ -70,10 +70,10 @@ pub(crate) trait Float:
const EXPONENT_MASK: Self::Int;
/// Returns `self` transmuted to `Self::Int`
fn repr(self) -> Self::Int;
fn to_bits(self) -> Self::Int;
/// Returns `self` transmuted to `Self::SignedInt`
fn signed_repr(self) -> Self::SignedInt;
fn to_bits_signed(self) -> Self::SignedInt;
/// 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
@ -93,10 +93,15 @@ pub(crate) trait Float:
fn imp_frac(self) -> Self::Int;
/// Returns a `Self::Int` transmuted back to `Self`
fn from_repr(a: Self::Int) -> Self;
fn from_bits(a: Self::Int) -> Self;
/// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self;
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self;
fn abs(self) -> Self {
let abs_mask = !Self::SIGN_MASK ;
Self::from_bits(self.to_bits() & abs_mask)
}
/// Returns (normalized exponent, normalized significand)
fn normalize(significand: Self::Int) -> (i32, Self::Int);
@ -124,10 +129,10 @@ macro_rules! float_impl {
const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
fn repr(self) -> Self::Int {
fn to_bits(self) -> Self::Int {
self.to_bits()
}
fn signed_repr(self) -> Self::SignedInt {
fn to_bits_signed(self) -> Self::SignedInt {
self.to_bits() as Self::SignedInt
}
fn eq_repr(self, rhs: Self) -> bool {
@ -137,8 +142,8 @@ macro_rules! float_impl {
// necessary builtin (__unordtf2) to test whether `f128` is NaN.
// FIXME(f16_f128): Remove once the nightly toolchain has the __unordtf2 builtin
// x is NaN if all the bits of the exponent are set and the significand is non-0
x.repr() & $ty::EXPONENT_MASK == $ty::EXPONENT_MASK
&& x.repr() & $ty::SIGNIFICAND_MASK != 0
x.to_bits() & $ty::EXPONENT_MASK == $ty::EXPONENT_MASK
&& x.to_bits() & $ty::SIGNIFICAND_MASK != 0
}
#[cfg(not(feature = "mangled-names"))]
fn is_nan(x: $ty) -> bool {
@ -147,7 +152,7 @@ macro_rules! float_impl {
if is_nan(self) && is_nan(rhs) {
true
} else {
self.repr() == rhs.repr()
self.to_bits() == rhs.to_bits()
}
}
fn is_sign_negative(self) -> bool {
@ -162,12 +167,12 @@ macro_rules! float_impl {
fn imp_frac(self) -> Self::Int {
self.frac() | Self::IMPLICIT_BIT
}
fn from_repr(a: Self::Int) -> Self {
fn from_bits(a: Self::Int) -> Self {
Self::from_bits(a)
}
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_repr(
((sign as Self::Int) << (Self::BITS - 1))
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_bits(
((negative as Self::Int) << (Self::BITS - 1))
| ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK)
| (significand & Self::SIGNIFICAND_MASK),
)
@ -182,7 +187,7 @@ macro_rules! float_impl {
)
}
fn is_subnormal(self) -> bool {
(self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO
(self.to_bits() & Self::EXPONENT_MASK) == Self::Int::ZERO
}
}
};

View file

@ -28,8 +28,8 @@ where
let qnan_rep = exponent_mask | quiet_bit;
let exponent_bits = F::EXPONENT_BITS;
let a_rep = a.repr();
let b_rep = b.repr();
let a_rep = a.to_bits();
let b_rep = b.to_bits();
let a_exponent = (a_rep >> significand_bits) & max_exponent.cast();
let b_exponent = (b_rep >> significand_bits) & max_exponent.cast();
@ -48,41 +48,41 @@ where
// NaN + anything = qNaN
if a_abs > inf_rep {
return F::from_repr(a_rep | quiet_bit);
return F::from_bits(a_rep | quiet_bit);
}
// anything + NaN = qNaN
if b_abs > inf_rep {
return F::from_repr(b_rep | quiet_bit);
return F::from_bits(b_rep | quiet_bit);
}
if a_abs == inf_rep {
if b_abs != zero {
// infinity * non-zero = +/- infinity
return F::from_repr(a_abs | product_sign);
return F::from_bits(a_abs | product_sign);
} else {
// infinity * zero = NaN
return F::from_repr(qnan_rep);
return F::from_bits(qnan_rep);
}
}
if b_abs == inf_rep {
if a_abs != zero {
// infinity * non-zero = +/- infinity
return F::from_repr(b_abs | product_sign);
return F::from_bits(b_abs | product_sign);
} else {
// infinity * zero = NaN
return F::from_repr(qnan_rep);
return F::from_bits(qnan_rep);
}
}
// zero * anything = +/- zero
if a_abs == zero {
return F::from_repr(product_sign);
return F::from_bits(product_sign);
}
// anything * zero = +/- zero
if b_abs == zero {
return F::from_repr(product_sign);
return F::from_bits(product_sign);
}
// one or both of a or b is denormal, the other (if applicable) is a
@ -133,7 +133,7 @@ where
// If we have overflowed the type, return +/- infinity.
if product_exponent >= max_exponent as i32 {
return F::from_repr(inf_rep | product_sign);
return F::from_bits(inf_rep | product_sign);
}
if product_exponent <= 0 {
@ -145,7 +145,7 @@ where
// simplify the shift logic.
let shift = one.wrapping_sub(product_exponent.cast()).cast();
if shift >= bits {
return F::from_repr(product_sign);
return F::from_bits(product_sign);
}
// Otherwise, shift the significand of the result so that the round
@ -176,7 +176,7 @@ where
product_high += product_high & one;
}
F::from_repr(product_high)
F::from_bits(product_high)
}
intrinsics! {

View file

@ -4,13 +4,13 @@ intrinsics! {
#[avr_skip]
#[arm_aeabi_alias = __aeabi_fsub]
pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
crate::float::add::__addsf3(a, f32::from_repr(b.repr() ^ f32::SIGN_MASK))
crate::float::add::__addsf3(a, f32::from_bits(b.to_bits() ^ f32::SIGN_MASK))
}
#[avr_skip]
#[arm_aeabi_alias = __aeabi_dsub]
pub extern "C" fn __subdf3(a: f64, b: f64) -> f64 {
crate::float::add::__adddf3(a, f64::from_repr(b.repr() ^ f64::SIGN_MASK))
crate::float::add::__adddf3(a, f64::from_bits(b.to_bits() ^ f64::SIGN_MASK))
}
#[ppc_alias = __subkf3]
@ -21,6 +21,6 @@ intrinsics! {
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
use crate::float::add::__addtf3;
__addtf3(a, f128::from_repr(b.repr() ^ f128::SIGN_MASK))
__addtf3(a, f128::from_bits(b.to_bits() ^ f128::SIGN_MASK))
}
}

View file

@ -7,7 +7,6 @@ where
F::Int: CastInto<u32>,
u64: CastInto<F::Int>,
u32: CastInto<F::Int>,
R::Int: CastInto<u32>,
u32: CastInto<R::Int>,
F::Int: CastInto<R::Int>,
@ -43,8 +42,8 @@ where
let sign_bits_delta = F::SIGNIFICAND_BITS - R::SIGNIFICAND_BITS;
// Break a into a sign and representation of the absolute value.
let a_abs = a.repr() & src_abs_mask;
let sign = a.repr() & src_sign_mask;
let a_abs = a.to_bits() & src_abs_mask;
let sign = a.to_bits() & src_sign_mask;
let mut abs_result: R::Int;
if a_abs.wrapping_sub(underflow) < a_abs.wrapping_sub(overflow) {
@ -87,7 +86,7 @@ where
let a_exp: u32 = (a_abs >> F::SIGNIFICAND_BITS).cast();
let shift = src_exp_bias - dst_exp_bias - a_exp + 1;
let significand = (a.repr() & src_significand_mask) | src_min_normal;
let significand = (a.to_bits() & src_significand_mask) | src_min_normal;
// Right shift by the denormalization amount with sticky.
if shift > F::SIGNIFICAND_BITS {
@ -114,7 +113,7 @@ where
}
// Apply the signbit to the absolute value.
R::from_repr(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast())
R::from_bits(abs_result | sign.wrapping_shr(src_bits - dst_bits).cast())
}
intrinsics! {

View file

@ -190,7 +190,7 @@ fn fuzz_float_step<F: Float>(rng: &mut Xoshiro128StarStar, f: &mut F) {
let tmp = ones.wrapping_shr(r0);
(tmp.wrapping_shl(r1) | tmp.wrapping_shr(F::EXPONENT_BITS - r1)) & ones
};
let mut exp = (f.repr() & F::EXPONENT_MASK) >> F::SIGNIFICAND_BITS;
let mut exp = (f.to_bits() & F::EXPONENT_MASK) >> F::SIGNIFICAND_BITS;
match (rng32 >> 9) % 4 {
0 => exp |= mask,
1 => exp &= mask,
@ -198,7 +198,7 @@ fn fuzz_float_step<F: Float>(rng: &mut Xoshiro128StarStar, f: &mut F) {
}
// significand fuzzing
let mut sig = f.repr() & F::SIGNIFICAND_MASK;
let mut sig = f.to_bits() & F::SIGNIFICAND_MASK;
fuzz_step(rng, &mut sig);
sig &= F::SIGNIFICAND_MASK;