start refactoring to_f32, to_f64
This commit is contained in:
parent
f043eacbfa
commit
5977bfc780
|
@ -20,6 +20,99 @@ use {
|
|||
FixedU8,
|
||||
};
|
||||
|
||||
pub(crate) trait FloatHelper {
|
||||
type Bits;
|
||||
|
||||
fn prec() -> u32;
|
||||
fn exp_bias() -> i32;
|
||||
fn exp_min() -> i32;
|
||||
fn exp_max() -> i32;
|
||||
|
||||
fn zero(neg: bool) -> Self;
|
||||
fn infinite(neg: bool) -> Self;
|
||||
fn from_parts(neg: bool, exp: i32, mant: Self::Bits) -> Self;
|
||||
fn parts(self) -> (bool, i32, Self::Bits);
|
||||
}
|
||||
|
||||
macro_rules! float_helper {
|
||||
($Float:ident($Bits:ty, $prec:expr)) => {
|
||||
impl FloatHelper for $Float {
|
||||
type Bits = $Bits;
|
||||
|
||||
#[inline]
|
||||
fn prec() -> u32 {
|
||||
$prec
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exp_bias() -> i32 {
|
||||
let nbits = mem::size_of::<$Bits>() * 8;
|
||||
let exp_bits = nbits - $prec;
|
||||
(1 << (exp_bits - 1)) - 1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exp_min() -> i32 {
|
||||
1 - <$Float as FloatHelper>::exp_bias()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exp_max() -> i32 {
|
||||
<$Float as FloatHelper>::exp_bias()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn zero(neg: bool) -> $Float {
|
||||
let nbits = mem::size_of::<$Bits>() * 8;
|
||||
let neg_mask = !0 << (nbits - 1);
|
||||
let neg_bits = if neg { neg_mask } else { 0 };
|
||||
<$Float>::from_bits(neg_bits)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn infinite(neg: bool) -> $Float {
|
||||
let nbits = mem::size_of::<$Bits>() * 8;
|
||||
let neg_mask = !0 << (nbits - 1);
|
||||
let mant_mask = !(!0 << ($prec - 1));
|
||||
let exp_mask = !(neg_mask | mant_mask);
|
||||
|
||||
let neg_bits = if neg { neg_mask } else { 0 };
|
||||
<$Float>::from_bits(neg_bits | exp_mask)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_parts(neg: bool, exp: i32, mant: Self::Bits) -> $Float {
|
||||
let nbits = mem::size_of::<$Bits>() * 8;
|
||||
let neg_mask = !0 << (nbits - 1);
|
||||
|
||||
let neg_bits = if neg { neg_mask } else { 0 };
|
||||
let biased_exp = (exp + <$Float as FloatHelper>::exp_bias()) as Self::Bits;
|
||||
let exp_bits = biased_exp << ($prec - 1);
|
||||
<$Float>::from_bits(neg_bits | exp_bits | mant)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parts(self) -> (bool, i32, $Bits) {
|
||||
let nbits = mem::size_of::<$Bits>() * 8;
|
||||
let neg_mask = !0 << (nbits - 1);
|
||||
let mant_mask = !(!0 << ($prec - 1));
|
||||
let exp_mask = !(neg_mask | mant_mask);
|
||||
|
||||
let bits = self.to_bits();
|
||||
let neg = bits & neg_mask != 0;
|
||||
let biased_exp = (bits & exp_mask) >> ($prec - 1);
|
||||
let exp = (biased_exp as i32) - <$Float as FloatHelper>::exp_bias();
|
||||
let mant = bits & mant_mask;
|
||||
|
||||
(neg, exp, mant)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
float_helper! { f32(u32, 24) }
|
||||
float_helper! { f64(u64, 53) }
|
||||
|
||||
pub(crate) trait FixedHelper<Frac: Unsigned>: Sized {
|
||||
type Inner;
|
||||
|
||||
|
|
31
src/lib.rs
31
src/lib.rs
|
@ -148,7 +148,7 @@ use core::f64;
|
|||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::PhantomData;
|
||||
use frac::Unsigned;
|
||||
use helper::FixedHelper;
|
||||
use helper::{FixedHelper, FloatHelper};
|
||||
|
||||
macro_rules! pass_method {
|
||||
($comment:expr, $Fixed:ident($Inner:ty) => fn $method:ident()) => {
|
||||
|
@ -199,15 +199,16 @@ macro_rules! doc_comment_signed_unsigned {
|
|||
}
|
||||
|
||||
macro_rules! to_f {
|
||||
($method:ident -> $f:ident($u:ident), $exp_bits:expr, $prec:expr) => {
|
||||
(fn $method:ident(self) -> $f:ident) => {
|
||||
doc_comment! {
|
||||
concat!(
|
||||
"Converts the fixed-point number to `", stringify!($f), "`."
|
||||
),
|
||||
pub fn $method(self) -> $f {
|
||||
// exponent is IEEE754 style (1 <= significand < 2)
|
||||
let exp_max = (1 << ($exp_bits - 1)) - 1;
|
||||
let exp_min = 1 - exp_max;
|
||||
type Bits = <$f as FloatHelper>::Bits;
|
||||
let prec = <$f as FloatHelper>::prec();
|
||||
let exp_min = <$f as FloatHelper>::exp_min();
|
||||
let exp_max = <$f as FloatHelper>::exp_max();
|
||||
let (int_bits, frac_bits) = (Self::int_bits(), Self::frac_bits());
|
||||
|
||||
let (neg, int, frac) = self.parts();
|
||||
|
@ -240,11 +241,11 @@ macro_rules! to_f {
|
|||
}
|
||||
0
|
||||
} else {
|
||||
(exponent + exp_max) as $u
|
||||
(exponent + exp_max) as Bits
|
||||
};
|
||||
// check for rounding
|
||||
let round_up = (int_bits + frac_bits >= $prec) && {
|
||||
let shift = $prec - 1;
|
||||
let round_up = (int_bits + frac_bits >= prec) && {
|
||||
let shift = prec - 1;
|
||||
let mid_bit = !(!0 >> 1) >> shift;
|
||||
let lower_bits = mid_bit - 1;
|
||||
if mantissa & mid_bit == 0 {
|
||||
|
@ -257,18 +258,18 @@ macro_rules! to_f {
|
|||
}
|
||||
};
|
||||
let bits_sign = if neg { !(!0 >> 1) } else { 0 };
|
||||
let bits_exp = biased_exponent << ($prec - 1);
|
||||
let bits_mantissa = (if int_bits + frac_bits >= $prec - 1 {
|
||||
let bits_exp = biased_exponent << (prec - 1);
|
||||
let bits_mantissa = (if int_bits + frac_bits >= prec - 1 {
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||
{
|
||||
(mantissa >> (int_bits + frac_bits - ($prec - 1))) as $u
|
||||
(mantissa >> (int_bits + frac_bits - (prec - 1))) as Bits
|
||||
}
|
||||
} else {
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||
{
|
||||
(mantissa as $u) << ($prec - 1 - (int_bits + frac_bits))
|
||||
(mantissa as Bits) << (prec - 1 - (int_bits + frac_bits))
|
||||
}
|
||||
}) & !(!0 << ($prec - 1));
|
||||
}) & !(!0 << (prec - 1));
|
||||
let mut bits_exp_mantissa = bits_exp | bits_mantissa;
|
||||
if round_up {
|
||||
// cannot be infinite already, so we won't get NaN
|
||||
|
@ -745,8 +746,8 @@ macro_rules! fixed {
|
|||
}
|
||||
}
|
||||
|
||||
to_f! { to_f32 -> f32(u32), 8, 24 }
|
||||
to_f! { to_f64 -> f64(u64), 11, 53 }
|
||||
to_f! { fn to_f32(self) -> f32 }
|
||||
to_f! { fn to_f64(self) -> f64 }
|
||||
|
||||
pass_method! {
|
||||
"Returns the number of ones in the binary representation.",
|
||||
|
|
Loading…
Reference in New Issue