Remove WideInt
This commit is contained in:
parent
fac884b0c4
commit
cb4e9755b8
5 changed files with 36 additions and 79 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(unreachable_code)]
|
||||
|
||||
use float::Float;
|
||||
use int::{CastInto, Int};
|
||||
use int::Int;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Result {
|
||||
|
|
@ -31,13 +31,7 @@ impl Result {
|
|||
}
|
||||
}
|
||||
|
||||
fn cmp<F: Float>(a: F, b: F) -> Result
|
||||
where
|
||||
u32: CastInto<F::Int>,
|
||||
F::Int: CastInto<u32>,
|
||||
i32: CastInto<F::Int>,
|
||||
F::Int: CastInto<i32>,
|
||||
{
|
||||
fn cmp<F: Float>(a: F, b: F) -> Result {
|
||||
let one = F::Int::ONE;
|
||||
let zero = F::Int::ZERO;
|
||||
let szero = F::SignedInt::ZERO;
|
||||
|
|
@ -90,13 +84,8 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
fn unord<F: Float>(a: F, b: F) -> bool
|
||||
where
|
||||
u32: CastInto<F::Int>,
|
||||
F::Int: CastInto<u32>,
|
||||
i32: CastInto<F::Int>,
|
||||
F::Int: CastInto<i32>,
|
||||
{
|
||||
|
||||
fn unord<F: Float>(a: F, b: F) -> bool {
|
||||
let one = F::Int::ONE;
|
||||
|
||||
let sign_bit = F::SIGN_MASK as F::Int;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use float::Float;
|
||||
use int::{CastInto, Int, WideInt};
|
||||
use int::{CastInto, DInt, HInt, Int};
|
||||
|
||||
fn div32<F: Float>(a: F, b: F) -> F
|
||||
where
|
||||
|
|
@ -7,7 +7,7 @@ where
|
|||
F::Int: CastInto<u32>,
|
||||
i32: CastInto<F::Int>,
|
||||
F::Int: CastInto<i32>,
|
||||
F::Int: WideInt,
|
||||
F::Int: HInt,
|
||||
{
|
||||
let one = F::Int::ONE;
|
||||
let zero = F::Int::ZERO;
|
||||
|
|
@ -156,7 +156,7 @@ where
|
|||
// is the error in the reciprocal of b scaled by the maximum
|
||||
// possible value of a. As a consequence of this error bound,
|
||||
// either q or nextafter(q) is the correctly rounded
|
||||
let (mut quotient, _) = <F::Int as WideInt>::wide_mul(a_significand << 1, reciprocal.cast());
|
||||
let mut quotient = (a_significand << 1).widen_mul(reciprocal.cast()).hi();
|
||||
|
||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||
// In either case, we are going to compute a residual of the form
|
||||
|
|
@ -211,7 +211,7 @@ where
|
|||
F::Int: CastInto<u64>,
|
||||
i64: CastInto<F::Int>,
|
||||
F::Int: CastInto<i64>,
|
||||
F::Int: WideInt,
|
||||
F::Int: HInt,
|
||||
{
|
||||
let one = F::Int::ONE;
|
||||
let zero = F::Int::ZERO;
|
||||
|
|
@ -394,7 +394,7 @@ where
|
|||
|
||||
// We need a 64 x 64 multiply high to compute q, which isn't a basic
|
||||
// operation in C, so we need to be a little bit fussy.
|
||||
let (mut quotient, _) = <F::Int as WideInt>::wide_mul(a_significand << 2, reciprocal.cast());
|
||||
let mut quotient = (a_significand << 2).widen_mul(reciprocal.cast()).hi();
|
||||
|
||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||
// In either case, we are going to compute a residual of the form
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ pub mod pow;
|
|||
pub mod sub;
|
||||
|
||||
/// Trait for some basic operations on floats
|
||||
pub(crate) trait Float:
|
||||
#[doc(hidden)]
|
||||
pub trait Float:
|
||||
Copy
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
|
|
@ -66,7 +67,6 @@ pub(crate) trait Float:
|
|||
/// Returns `self` transmuted to `Self::SignedInt`
|
||||
fn signed_repr(self) -> Self::SignedInt;
|
||||
|
||||
#[cfg(test)]
|
||||
/// 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
|
||||
/// compared.
|
||||
|
|
@ -80,6 +80,9 @@ pub(crate) trait Float:
|
|||
|
||||
/// Returns (normalized exponent, normalized significand)
|
||||
fn normalize(significand: Self::Int) -> (i32, Self::Int);
|
||||
|
||||
/// Returns if `self` is subnormal
|
||||
fn is_subnormal(&self) -> bool;
|
||||
}
|
||||
|
||||
// FIXME: Some of this can be removed if RFC Issue #1424 is resolved
|
||||
|
|
@ -106,7 +109,6 @@ macro_rules! float_impl {
|
|||
fn signed_repr(self) -> Self::SignedInt {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
#[cfg(test)]
|
||||
fn eq_repr(self, rhs: Self) -> bool {
|
||||
if self.is_nan() && rhs.is_nan() {
|
||||
true
|
||||
|
|
@ -133,6 +135,9 @@ macro_rules! float_impl {
|
|||
significand << shift as Self::Int,
|
||||
)
|
||||
}
|
||||
fn is_subnormal(&self) -> bool {
|
||||
(self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use float::Float;
|
||||
use int::{CastInto, Int, WideInt};
|
||||
use int::{CastInto, DInt, HInt, Int};
|
||||
|
||||
fn mul<F: Float>(a: F, b: F) -> F
|
||||
where
|
||||
|
|
@ -7,7 +7,7 @@ where
|
|||
F::Int: CastInto<u32>,
|
||||
i32: CastInto<F::Int>,
|
||||
F::Int: CastInto<i32>,
|
||||
F::Int: WideInt,
|
||||
F::Int: HInt,
|
||||
{
|
||||
let one = F::Int::ONE;
|
||||
let zero = F::Int::ZERO;
|
||||
|
|
@ -112,8 +112,9 @@ where
|
|||
// have (exponentBits + 2) integral digits, all but two of which must be
|
||||
// zero. Normalizing this result is just a conditional left-shift by one
|
||||
// and bumping the exponent accordingly.
|
||||
let (mut product_high, mut product_low) =
|
||||
<F::Int as WideInt>::wide_mul(a_significand, b_significand << exponent_bits);
|
||||
let (mut product_low, mut product_high) = a_significand
|
||||
.widen_mul(b_significand << exponent_bits)
|
||||
.lo_hi();
|
||||
|
||||
let a_exponent_i32: i32 = a_exponent.cast();
|
||||
let b_exponent_i32: i32 = b_exponent.cast();
|
||||
|
|
@ -126,7 +127,8 @@ where
|
|||
if (product_high & implicit_bit) != zero {
|
||||
product_exponent = product_exponent.wrapping_add(1);
|
||||
} else {
|
||||
<F::Int as WideInt>::wide_shift_left(&mut product_high, &mut product_low, 1);
|
||||
product_high = (product_high << 1) | (product_low >> (bits - 1));
|
||||
product_low <<= 1;
|
||||
}
|
||||
|
||||
// If we have overflowed the type, return +/- infinity.
|
||||
|
|
@ -142,17 +144,23 @@ where
|
|||
// handle this case separately, but we make it a special case to
|
||||
// simplify the shift logic.
|
||||
let shift = one.wrapping_sub(product_exponent.cast()).cast();
|
||||
if shift >= bits as i32 {
|
||||
if shift >= bits {
|
||||
return F::from_repr(product_sign);
|
||||
}
|
||||
|
||||
// Otherwise, shift the significand of the result so that the round
|
||||
// bit is the high bit of productLo.
|
||||
<F::Int as WideInt>::wide_shift_right_with_sticky(
|
||||
&mut product_high,
|
||||
&mut product_low,
|
||||
shift,
|
||||
)
|
||||
if shift < bits {
|
||||
let sticky = product_low << (bits - shift);
|
||||
product_low = product_high << (bits - shift) | product_low >> shift | sticky;
|
||||
product_high >>= shift;
|
||||
} else if shift < (2 * bits) {
|
||||
let sticky = product_high << (2 * bits - shift) | product_low;
|
||||
product_low = product_high >> (shift - bits) | sticky;
|
||||
product_high = zero;
|
||||
} else {
|
||||
product_high = zero;
|
||||
}
|
||||
} else {
|
||||
// Result is normal before rounding; insert the exponent.
|
||||
product_high &= significand_mask;
|
||||
|
|
|
|||
|
|
@ -408,48 +408,3 @@ cast_into!(u64);
|
|||
cast_into!(i64);
|
||||
cast_into!(u128);
|
||||
cast_into!(i128);
|
||||
|
||||
pub(crate) trait WideInt: Int {
|
||||
type Output: Int;
|
||||
|
||||
fn wide_mul(self, other: Self) -> (Self, Self);
|
||||
fn wide_shift_left(&mut self, low: &mut Self, count: i32);
|
||||
fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32);
|
||||
}
|
||||
|
||||
macro_rules! impl_wide_int {
|
||||
($ty:ty, $tywide:ty, $bits:expr) => {
|
||||
impl WideInt for $ty {
|
||||
type Output = $ty;
|
||||
|
||||
fn wide_mul(self, other: Self) -> (Self, Self) {
|
||||
let product = (self as $tywide).wrapping_mul(other as $tywide);
|
||||
((product >> ($bits as $ty)) as $ty, product as $ty)
|
||||
}
|
||||
|
||||
fn wide_shift_left(&mut self, low: &mut Self, count: i32) {
|
||||
*self = (*self << count) | (*low >> ($bits - count));
|
||||
*low = *low << count;
|
||||
}
|
||||
|
||||
fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32) {
|
||||
if count < $bits {
|
||||
let sticky = *low << ($bits - count);
|
||||
*low = *self << ($bits - count) | *low >> count | sticky;
|
||||
*self = *self >> count;
|
||||
} else if count < 2 * $bits {
|
||||
let sticky = *self << (2 * $bits - count) | *low;
|
||||
*low = *self >> (count - $bits) | sticky;
|
||||
*self = 0;
|
||||
} else {
|
||||
let sticky = *self | *low;
|
||||
*self = sticky;
|
||||
*self = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_wide_int!(u32, u64, 32);
|
||||
impl_wide_int!(u64, u128, 64);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue