Reuse libm's Caat and CastFrom in compiler-builtins
This commit is contained in:
parent
851aa05aa0
commit
877feef541
8 changed files with 16 additions and 52 deletions
|
|
@ -168,7 +168,7 @@ where
|
|||
}
|
||||
|
||||
// Low three bits are round, guard, and sticky.
|
||||
let a_significand_i32: i32 = a_significand.cast();
|
||||
let a_significand_i32: i32 = a_significand.cast_lossy();
|
||||
let round_guard_sticky: i32 = a_significand_i32 & 0x7;
|
||||
|
||||
// Shift the significand into place, and mask off the implicit bit.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ mod int_to_float {
|
|||
F::Int: CastFrom<I>,
|
||||
Conv: Fn(I::Unsigned) -> F::Int,
|
||||
{
|
||||
let sign_bit = F::Int::cast_from(i >> (I::BITS - 1)) << (F::BITS - 1);
|
||||
let sign_bit = F::Int::cast_from_lossy(i >> (I::BITS - 1)) << (F::BITS - 1);
|
||||
F::from_bits(conv(i.unsigned_abs()) | sign_bit)
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ mod int_to_float {
|
|||
|
||||
// Within the upper `F::BITS`, everything except for the signifcand
|
||||
// gets truncated
|
||||
let d1: u32 = (i_m >> (u128::BITS - f32::BITS - f32::SIG_BITS - 1)).cast();
|
||||
let d1: u32 = (i_m >> (u128::BITS - f32::BITS - f32::SIG_BITS - 1)).cast_lossy();
|
||||
|
||||
// The entire rest of `i_m` gets truncated. Zero the upper `F::BITS` then just
|
||||
// check if it is nonzero.
|
||||
|
|
@ -371,7 +371,7 @@ where
|
|||
let m_base = if I::Unsigned::BITS >= F::Int::BITS {
|
||||
I::Unsigned::cast_from(fbits) << (I::BITS - F::SIG_BITS - 1)
|
||||
} else {
|
||||
I::Unsigned::cast_from(fbits >> (F::SIG_BITS - I::BITS + 1))
|
||||
I::Unsigned::cast_from_lossy(fbits >> (F::SIG_BITS - I::BITS + 1))
|
||||
};
|
||||
|
||||
// Set the implicit 1-bit.
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ where
|
|||
|
||||
let ret = quotient.wrapping_shr(u32::cast_from(res_exponent.wrapping_neg()) + 1);
|
||||
residual_lo = a_significand
|
||||
.wrapping_shl(significand_bits.wrapping_add(CastInto::<u32>::cast(res_exponent)))
|
||||
.wrapping_shl(significand_bits.wrapping_add(CastInto::<u32>::cast_lossy(res_exponent)))
|
||||
.wrapping_sub(ret.wrapping_mul(b_significand) << 1);
|
||||
ret
|
||||
};
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ where
|
|||
// a zero of the appropriate sign. Mathematically there is no need to
|
||||
// handle this case separately, but we make it a special case to
|
||||
// simplify the shift logic.
|
||||
let shift: u32 = one.wrapping_sub(product_exponent.cast()).cast();
|
||||
let shift: u32 = one.wrapping_sub(product_exponent.cast_lossy()).cast();
|
||||
if shift >= bits {
|
||||
return F::from_bits(product_sign);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ where
|
|||
// The exponent of a is within the range of normal numbers in the
|
||||
// destination format. We can convert by simply right-shifting with
|
||||
// rounding and adjusting the exponent.
|
||||
abs_result = (a_abs >> sig_bits_delta).cast();
|
||||
abs_result = (a_abs >> sig_bits_delta).cast_lossy();
|
||||
// Cast before shifting to prevent overflow.
|
||||
let bias_diff: R::Int = src_exp_bias.wrapping_sub(dst_exp_bias).cast();
|
||||
let tmp = bias_diff << R::SIG_BITS;
|
||||
|
|
|
|||
|
|
@ -20,18 +20,18 @@ mod implementation {
|
|||
|
||||
const { assert!(I::BITS <= 64) };
|
||||
if I::BITS >= 64 {
|
||||
r += ((u32::cast_from(x) == 0) as u32) << 5; // if (x has no 32 small bits) t = 32 else 0
|
||||
r += ((u32::cast_from_lossy(x) == 0) as u32) << 5; // if (x has no 32 small bits) t = 32 else 0
|
||||
x >>= r; // remove 32 zero bits
|
||||
}
|
||||
|
||||
if I::BITS >= 32 {
|
||||
t = ((u16::cast_from(x) == 0) as u32) << 4; // if (x has no 16 small bits) t = 16 else 0
|
||||
t = ((u16::cast_from_lossy(x) == 0) as u32) << 4; // if (x has no 16 small bits) t = 16 else 0
|
||||
r += t;
|
||||
x >>= t; // x = [0 - 0xFFFF] + higher garbage bits
|
||||
}
|
||||
|
||||
const { assert!(I::BITS >= 16) };
|
||||
t = ((u8::cast_from(x) == 0) as u32) << 3;
|
||||
t = ((u8::cast_from_lossy(x) == 0) as u32) << 3;
|
||||
x >>= t; // x = [0 - 0xFF] + higher garbage bits
|
||||
r += t;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
pub use crate::support::{Int, MinInt};
|
||||
pub use crate::support::{CastFrom, CastInto, Int, MinInt};
|
||||
|
||||
/// Trait for integers twice the bit width of another integer. This is implemented for all
|
||||
/// primitives except for `u8`, because there is not a smaller primitive.
|
||||
|
|
@ -97,44 +97,3 @@ impl_h_int!(
|
|||
i32 u32 i64,
|
||||
i64 u64 i128
|
||||
);
|
||||
|
||||
/// Trait to express (possibly lossy) casting of integers
|
||||
pub trait CastInto<T: Copy>: Copy {
|
||||
fn cast(self) -> T;
|
||||
}
|
||||
|
||||
pub trait CastFrom<T: Copy>: Copy {
|
||||
fn cast_from(value: T) -> Self;
|
||||
}
|
||||
|
||||
impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {
|
||||
fn cast_from(value: U) -> Self {
|
||||
value.cast()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cast_into {
|
||||
($ty:ty) => {
|
||||
cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);
|
||||
};
|
||||
($ty:ty; $($into:ty),*) => {$(
|
||||
impl CastInto<$into> for $ty {
|
||||
fn cast(self) -> $into {
|
||||
self as $into
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
cast_into!(usize);
|
||||
cast_into!(isize);
|
||||
cast_into!(u8);
|
||||
cast_into!(i8);
|
||||
cast_into!(u16);
|
||||
cast_into!(i16);
|
||||
cast_into!(u32);
|
||||
cast_into!(i32);
|
||||
cast_into!(u64);
|
||||
cast_into!(i64);
|
||||
cast_into!(u128);
|
||||
cast_into!(i128);
|
||||
|
|
|
|||
|
|
@ -374,14 +374,19 @@ impl_h_int!(
|
|||
/// Trait to express (possibly lossy) casting of integers
|
||||
pub trait CastInto<T: Copy>: Copy {
|
||||
/// By default, casts should be exact.
|
||||
#[track_caller]
|
||||
fn cast(self) -> T;
|
||||
|
||||
/// Call for casts that are expected to truncate.
|
||||
///
|
||||
/// In practice, this is exactly the same as `cast`; the main difference is to document intent
|
||||
/// in code. `cast` may panic in debug mode.
|
||||
fn cast_lossy(self) -> T;
|
||||
}
|
||||
|
||||
pub trait CastFrom<T: Copy>: Copy {
|
||||
/// By default, casts should be exact.
|
||||
#[track_caller]
|
||||
fn cast_from(value: T) -> Self;
|
||||
|
||||
/// Call for casts that are expected to truncate.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue