Add floating point deconstruction helpers

This commit is contained in:
Matt Ickstadt 2016-09-29 20:48:20 -05:00
parent cab88e6133
commit 58e89b3024
2 changed files with 39 additions and 1 deletions

View File

@ -14,7 +14,7 @@ macro_rules! add {
let bits = Wrapping(<$ty>::bits() as <$ty as Float>::Int);
let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int);
let exponent_bits = bits - significand_bits - one;
let exponent_bits = Wrapping(<$ty>::exponent_bits() as <$ty as Float>::Int);
let max_exponent = (one << exponent_bits.0 as usize) - one;
let implicit_bit = one << significand_bits.0 as usize;

View File

@ -10,6 +10,9 @@ pub trait Float: Sized + Copy {
/// Returns the bitwidth of the float type
fn bits() -> u32;
/// Returns the bitwidth of the exponent
fn exponent_bits() -> u32;
/// Returns the bitwidth of the significand
fn significand_bits() -> u32;
@ -25,6 +28,15 @@ pub trait Float: Sized + Copy {
/// Returns a `Self::Int` transmuted back to `Self`
fn from_repr(a: Self::Int) -> Self;
/// Returns the sign bit of `self`
fn sign(self) -> bool;
/// Returns the exponent portion of `self`, shifted to the right
fn exponent(self) -> Self::Int;
/// Returns the significand portion of `self`
fn significand(self) -> Self::Int;
/// Returns (normalized exponent, normalized significand)
fn normalize(significand: Self::Int) -> (i32, Self::Int);
}
@ -34,6 +46,9 @@ impl Float for f32 {
fn bits() -> u32 {
32
}
fn exponent_bits() -> u32 {
8
}
fn significand_bits() -> u32 {
23
}
@ -51,6 +66,16 @@ impl Float for f32 {
fn from_repr(a: Self::Int) -> Self {
unsafe { mem::transmute(a) }
}
fn sign(self) -> bool {
(self.repr() & 1 << Self::bits()) != 0
}
fn exponent(self) -> Self::Int {
self.repr() >> Self::significand_bits()
& ((1 << Self::exponent_bits()) - 1)
}
fn significand(self) -> Self::Int {
self.repr() & ((1 << Self::significand_bits()) - 1)
}
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand.leading_zeros()
.wrapping_sub((1u32 << Self::significand_bits()).leading_zeros());
@ -62,6 +87,9 @@ impl Float for f64 {
fn bits() -> u32 {
64
}
fn exponent_bits() -> u32 {
11
}
fn significand_bits() -> u32 {
52
}
@ -79,6 +107,16 @@ impl Float for f64 {
fn from_repr(a: Self::Int) -> Self {
unsafe { mem::transmute(a) }
}
fn sign(self) -> bool {
(self.repr() & 1 << Self::bits()) != 0
}
fn exponent(self) -> Self::Int {
self.repr() >> Self::significand_bits()
& ((1 << Self::exponent_bits()) - 1)
}
fn significand(self) -> Self::Int {
self.repr() & ((1 << Self::significand_bits()) - 1)
}
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand.leading_zeros()
.wrapping_sub((1u64 << Self::significand_bits()).leading_zeros());