Refactor float builtins to use associated consts
This commit is contained in:
parent
c9a261895e
commit
9bdedec38e
@ -10,8 +10,8 @@ macro_rules! add {
|
|||||||
let one = Wrapping(1 as <$ty as Float>::Int);
|
let one = Wrapping(1 as <$ty as Float>::Int);
|
||||||
let zero = Wrapping(0 as <$ty as Float>::Int);
|
let zero = Wrapping(0 as <$ty as Float>::Int);
|
||||||
|
|
||||||
let bits = Wrapping(<$ty>::bits() as <$ty as Float>::Int);
|
let bits = Wrapping(<$ty>::BITS as <$ty as Float>::Int);
|
||||||
let significand_bits = Wrapping(<$ty>::significand_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 = bits - significand_bits - one;
|
||||||
let max_exponent = (one << exponent_bits.0 as usize) - one;
|
let max_exponent = (one << exponent_bits.0 as usize) - one;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ macro_rules! int_to_float {
|
|||||||
return 0.0
|
return 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let mant_dig = <$fty>::significand_bits() + 1;
|
let mant_dig = <$fty>::SIGNIFICAND_BITS + 1;
|
||||||
let exponent_bias = <$fty>::exponent_bias();
|
let exponent_bias = <$fty>::EXPONENT_BIAS;
|
||||||
|
|
||||||
let n = <$ity>::BITS;
|
let n = <$ity>::BITS;
|
||||||
let (s, a) = i.extract_sign();
|
let (s, a) = i.extract_sign();
|
||||||
@ -145,9 +145,9 @@ macro_rules! float_to_int {
|
|||||||
let fixint_bits = <$ity>::BITS as usize;
|
let fixint_bits = <$ity>::BITS as usize;
|
||||||
let fixint_unsigned = fixint_min == 0;
|
let fixint_unsigned = fixint_min == 0;
|
||||||
|
|
||||||
let sign_bit = <$fty>::sign_mask();
|
let sign_bit = <$fty>::SIGN_MASK;
|
||||||
let significand_bits = <$fty>::significand_bits() as usize;
|
let significand_bits = <$fty>::SIGNIFICAND_BITS as usize;
|
||||||
let exponent_bias = <$fty>::exponent_bias() as usize;
|
let exponent_bias = <$fty>::EXPONENT_BIAS as usize;
|
||||||
//let exponent_max = <$fty>::exponent_max() as usize;
|
//let exponent_max = <$fty>::exponent_max() as usize;
|
||||||
|
|
||||||
// Break a into sign, exponent, significand
|
// Break a into sign, exponent, significand
|
||||||
@ -157,7 +157,7 @@ macro_rules! float_to_int {
|
|||||||
// this is used to work around -1 not being available for unsigned
|
// this is used to work around -1 not being available for unsigned
|
||||||
let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative };
|
let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative };
|
||||||
let mut exponent = (a_abs >> significand_bits) as usize;
|
let mut exponent = (a_abs >> significand_bits) as usize;
|
||||||
let significand = (a_abs & <$fty>::significand_mask()) | <$fty>::implicit_bit();
|
let significand = (a_abs & <$fty>::SIGNIFICAND_MASK) | <$fty>::IMPLICIT_BIT;
|
||||||
|
|
||||||
// if < 1 or unsigned & negative
|
// if < 1 or unsigned & negative
|
||||||
if exponent < exponent_bias ||
|
if exponent < exponent_bias ||
|
||||||
|
116
src/float/mod.rs
116
src/float/mod.rs
@ -1,5 +1,7 @@
|
|||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
|
use super::int::Int;
|
||||||
|
|
||||||
pub mod conv;
|
pub mod conv;
|
||||||
pub mod add;
|
pub mod add;
|
||||||
pub mod pow;
|
pub mod pow;
|
||||||
@ -8,39 +10,34 @@ pub mod sub;
|
|||||||
/// Trait for some basic operations on floats
|
/// Trait for some basic operations on floats
|
||||||
pub trait Float: Sized + Copy {
|
pub trait Float: Sized + Copy {
|
||||||
/// A uint of the same with as the float
|
/// A uint of the same with as the float
|
||||||
type Int;
|
type Int: Int;
|
||||||
|
|
||||||
/// Returns the bitwidth of the float type
|
/// The bitwidth of the float type
|
||||||
fn bits() -> u32;
|
const BITS: u32;
|
||||||
|
|
||||||
/// Returns the bitwidth of the significand
|
/// The bitwidth of the significand
|
||||||
fn significand_bits() -> u32;
|
const SIGNIFICAND_BITS: u32;
|
||||||
|
|
||||||
/// Returns the bitwidth of the exponent
|
/// The bitwidth of the exponent
|
||||||
fn exponent_bits() -> u32 {
|
const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1;
|
||||||
Self::bits() - Self::significand_bits() - 1
|
|
||||||
}
|
|
||||||
/// Returns the maximum value of the exponent
|
|
||||||
fn exponent_max() -> u32 {
|
|
||||||
(1 << Self::exponent_bits()) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the exponent bias value
|
/// The maximum value of the exponent
|
||||||
fn exponent_bias() -> u32 {
|
const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1;
|
||||||
Self::exponent_max() >> 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a mask for the sign bit
|
/// The exponent bias value
|
||||||
fn sign_mask() -> Self::Int;
|
const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1;
|
||||||
|
|
||||||
/// Returns a mask for the significand
|
/// A mask for the sign bit
|
||||||
fn significand_mask() -> Self::Int;
|
const SIGN_MASK: Self::Int;
|
||||||
|
|
||||||
// Returns the implicit bit of the float format
|
/// A mask for the significand
|
||||||
fn implicit_bit() -> Self::Int;
|
const SIGNIFICAND_MASK: Self::Int;
|
||||||
|
|
||||||
/// Returns a mask for the exponent
|
// The implicit bit of the float format
|
||||||
fn exponent_mask() -> Self::Int;
|
const IMPLICIT_BIT: Self::Int;
|
||||||
|
|
||||||
|
/// A mask for the exponent
|
||||||
|
const EXPONENT_MASK: Self::Int;
|
||||||
|
|
||||||
/// Returns `self` transmuted to `Self::Int`
|
/// Returns `self` transmuted to `Self::Int`
|
||||||
fn repr(self) -> Self::Int;
|
fn repr(self) -> Self::Int;
|
||||||
@ -65,24 +62,14 @@ pub trait Float: Sized + Copy {
|
|||||||
// https://github.com/rust-lang/rfcs/issues/1424
|
// https://github.com/rust-lang/rfcs/issues/1424
|
||||||
impl Float for f32 {
|
impl Float for f32 {
|
||||||
type Int = u32;
|
type Int = u32;
|
||||||
fn bits() -> u32 {
|
const BITS: u32 = 32;
|
||||||
32
|
const SIGNIFICAND_BITS: u32 = 23;
|
||||||
}
|
|
||||||
fn significand_bits() -> u32 {
|
const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
|
||||||
23
|
const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1;
|
||||||
}
|
const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
|
||||||
fn implicit_bit() -> Self::Int {
|
const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
|
||||||
1 << Self::significand_bits()
|
|
||||||
}
|
|
||||||
fn sign_mask() -> Self::Int {
|
|
||||||
1 << (Self::bits() - 1)
|
|
||||||
}
|
|
||||||
fn significand_mask() -> Self::Int {
|
|
||||||
(1 << Self::significand_bits()) - 1
|
|
||||||
}
|
|
||||||
fn exponent_mask() -> Self::Int {
|
|
||||||
!(Self::sign_mask() | Self::significand_mask())
|
|
||||||
}
|
|
||||||
fn repr(self) -> Self::Int {
|
fn repr(self) -> Self::Int {
|
||||||
unsafe { mem::transmute(self) }
|
unsafe { mem::transmute(self) }
|
||||||
}
|
}
|
||||||
@ -98,37 +85,26 @@ impl Float for f32 {
|
|||||||
unsafe { mem::transmute(a) }
|
unsafe { mem::transmute(a) }
|
||||||
}
|
}
|
||||||
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
|
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
|
||||||
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
|
Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) |
|
||||||
((exponent << Self::significand_bits()) & Self::exponent_mask()) |
|
((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) |
|
||||||
(significand & Self::significand_mask()))
|
(significand & Self::SIGNIFICAND_MASK))
|
||||||
}
|
}
|
||||||
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
|
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
|
||||||
let shift = significand.leading_zeros()
|
let shift = significand.leading_zeros()
|
||||||
.wrapping_sub((1u32 << Self::significand_bits()).leading_zeros());
|
.wrapping_sub((1u32 << Self::SIGNIFICAND_BITS).leading_zeros());
|
||||||
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
|
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Float for f64 {
|
impl Float for f64 {
|
||||||
type Int = u64;
|
type Int = u64;
|
||||||
fn bits() -> u32 {
|
const BITS: u32 = 64;
|
||||||
64
|
const SIGNIFICAND_BITS: u32 = 52;
|
||||||
}
|
|
||||||
fn significand_bits() -> u32 {
|
const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
|
||||||
52
|
const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1;
|
||||||
}
|
const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
|
||||||
// Returns the implicit bit of the float format
|
const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
|
||||||
fn implicit_bit() -> Self::Int {
|
|
||||||
1 << Self::significand_bits()
|
|
||||||
}
|
|
||||||
fn sign_mask() -> Self::Int {
|
|
||||||
1 << (Self::bits() - 1)
|
|
||||||
}
|
|
||||||
fn significand_mask() -> Self::Int {
|
|
||||||
(1 << Self::significand_bits()) - 1
|
|
||||||
}
|
|
||||||
fn exponent_mask() -> Self::Int {
|
|
||||||
!(Self::sign_mask() | Self::significand_mask())
|
|
||||||
}
|
|
||||||
fn repr(self) -> Self::Int {
|
fn repr(self) -> Self::Int {
|
||||||
unsafe { mem::transmute(self) }
|
unsafe { mem::transmute(self) }
|
||||||
}
|
}
|
||||||
@ -144,13 +120,13 @@ impl Float for f64 {
|
|||||||
unsafe { mem::transmute(a) }
|
unsafe { mem::transmute(a) }
|
||||||
}
|
}
|
||||||
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
|
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
|
||||||
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
|
Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) |
|
||||||
((exponent << Self::significand_bits()) & Self::exponent_mask()) |
|
((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) |
|
||||||
(significand & Self::significand_mask()))
|
(significand & Self::SIGNIFICAND_MASK))
|
||||||
}
|
}
|
||||||
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
|
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
|
||||||
let shift = significand.leading_zeros()
|
let shift = significand.leading_zeros()
|
||||||
.wrapping_sub((1u64 << Self::significand_bits()).leading_zeros());
|
.wrapping_sub((1u64 << Self::SIGNIFICAND_BITS).leading_zeros());
|
||||||
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
|
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ use float::Float;
|
|||||||
intrinsics! {
|
intrinsics! {
|
||||||
#[arm_aeabi_alias = __aeabi_fsub]
|
#[arm_aeabi_alias = __aeabi_fsub]
|
||||||
pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
|
pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
|
||||||
a + f32::from_repr(b.repr() ^ f32::sign_mask())
|
a + f32::from_repr(b.repr() ^ f32::SIGN_MASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[arm_aeabi_alias = __aeabi_dsub]
|
#[arm_aeabi_alias = __aeabi_dsub]
|
||||||
pub extern "C" fn __subdf3(a: f64, b: f64) -> f64 {
|
pub extern "C" fn __subdf3(a: f64, b: f64) -> f64 {
|
||||||
a + f64::from_repr(b.repr() ^ f64::sign_mask())
|
a + f64::from_repr(b.repr() ^ f64::SIGN_MASK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user