implement from_f32 and from_f64
This commit is contained in:
parent
d139bef602
commit
364b4ef23c
|
@ -38,6 +38,10 @@ fixed-point numbers.
|
|||
### Version 0.1.2 news (unreleased)
|
||||
|
||||
* The crate can now be used without the standard library `std`.
|
||||
* New methods [`from_f32`] and [`from_f64`] were added.
|
||||
|
||||
[`from_f32`]: https://docs.rs/fixed/0.1.1/fixed/struct.FixedI32.html#method.from_f32
|
||||
[`from_f64`]: https://docs.rs/fixed/0.1.1/fixed/struct.FixedI32.html#method.from_f64
|
||||
|
||||
### Version 0.1.1 news (2018-08-11)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ Version 0.1.2 (unreleased)
|
|||
==========================
|
||||
|
||||
* The crate can now be used without the standard library `std`.
|
||||
* New methods `from_f32` and `from_f64` were added.
|
||||
|
||||
Version 0.1.1 (2018-08-11)
|
||||
==========================
|
||||
|
|
261
src/float.rs
261
src/float.rs
|
@ -21,8 +21,60 @@ use {FixedI16, FixedI32, FixedI8, FixedU16, FixedU32, FixedU8};
|
|||
macro_rules! from_float {
|
||||
(fn $method:ident($Float:ty) -> $Uns:ty) => {
|
||||
fn $method(val: $Float, frac_bits: u32) -> Option<($Uns, bool)> {
|
||||
let _ = (val, frac_bits);
|
||||
unimplemented!()
|
||||
let float_bits = mem::size_of::<$Float>() as i32 * 8;
|
||||
let prec = <$Float as FloatHelper>::prec() as i32;
|
||||
let exp_min = <$Float as FloatHelper>::exp_min();
|
||||
let exp_max = <$Float as FloatHelper>::exp_max();
|
||||
let fix_bits = mem::size_of::<$Uns>() as i32 * 8;
|
||||
|
||||
let (neg, exp, mut mantissa) = <$Float as FloatHelper>::parts(val);
|
||||
if exp > exp_max {
|
||||
return None;
|
||||
}
|
||||
// if not subnormal, add implicit bit
|
||||
if exp >= exp_min {
|
||||
mantissa |= 1 << (prec - 1);
|
||||
}
|
||||
if mantissa == 0 {
|
||||
return Some((0, neg));
|
||||
}
|
||||
let leading_zeros = mantissa.leading_zeros();
|
||||
mantissa <<= leading_zeros;
|
||||
let mut need_to_shr = -exp + leading_zeros as i32 + prec - 1 - frac_bits as i32;
|
||||
let rounding_bit = need_to_shr - 1;
|
||||
if 0 <= rounding_bit && rounding_bit < float_bits && mantissa & (1 << rounding_bit) != 0
|
||||
{
|
||||
// Rounding bit is one.
|
||||
// If any lower bit is one, round up.
|
||||
// If bit exactly above rounding is one, round up (tie to even).
|
||||
let round_up = (rounding_bit > 0 && mantissa & ((1 << rounding_bit) - 1) != 0)
|
||||
|| (rounding_bit + 1 < float_bits && mantissa & (1 << (rounding_bit + 1)) != 0);
|
||||
if round_up {
|
||||
mantissa = match mantissa.overflowing_add(1 << rounding_bit) {
|
||||
(m, false) => m,
|
||||
(m, true) => {
|
||||
need_to_shr -= 1;
|
||||
(m >> 1) | (1 << (float_bits - 1))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// now rounding is done, we can truncate extra right bits
|
||||
if float_bits - need_to_shr > fix_bits {
|
||||
return None;
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||
{
|
||||
if need_to_shr == 0 {
|
||||
Some(((mantissa as $Uns), neg))
|
||||
} else if need_to_shr < 0 {
|
||||
Some(((mantissa as $Uns) << -need_to_shr, neg))
|
||||
} else if need_to_shr < float_bits {
|
||||
Some(((mantissa >> need_to_shr) as $Uns, neg))
|
||||
} else {
|
||||
Some((0, neg))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -136,3 +188,208 @@ lossless_from_fixed! { FixedI32::to_f64 -> f64 }
|
|||
lossless_from_fixed! { FixedU8::to_f64 -> f64 }
|
||||
lossless_from_fixed! { FixedU16::to_f64 -> f64 }
|
||||
lossless_from_fixed! { FixedU32::to_f64 -> f64 }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use *;
|
||||
|
||||
#[test]
|
||||
fn signed_from_f32() {
|
||||
type Fix = FixedI8<frac::U4>;
|
||||
// 1.1 -> 0001.1000
|
||||
assert_eq!(Fix::from_f32(3.0 / 2.0).unwrap(), Fix::from_bits(24));
|
||||
// 0.11 -> 0000.1100
|
||||
assert_eq!(Fix::from_f32(3.0 / 4.0).unwrap(), Fix::from_bits(12));
|
||||
// 0.011 -> 0000.0110
|
||||
assert_eq!(Fix::from_f32(3.0 / 8.0).unwrap(), Fix::from_bits(6));
|
||||
// 0.0011 -> 0000.0011
|
||||
assert_eq!(Fix::from_f32(3.0 / 16.0).unwrap(), Fix::from_bits(3));
|
||||
// 0.00011 -> 0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(3.0 / 32.0).unwrap(), Fix::from_bits(2));
|
||||
// 0.00101 -> 0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(5.0 / 32.0).unwrap(), Fix::from_bits(2));
|
||||
// 0.000011 -> 0000.0001 (nearest)
|
||||
assert_eq!(Fix::from_f32(3.0 / 64.0).unwrap(), Fix::from_bits(1));
|
||||
// 0.00001 -> 0000.0000 (tie to even)
|
||||
assert_eq!(Fix::from_f32(1.0 / 32.0).unwrap(), Fix::from_bits(0));
|
||||
|
||||
// -1.1 -> -0001.1000
|
||||
assert_eq!(Fix::from_f32(-3.0 / 2.0).unwrap(), Fix::from_bits(-24));
|
||||
// -0.11 -> -0000.1100
|
||||
assert_eq!(Fix::from_f32(-3.0 / 4.0).unwrap(), Fix::from_bits(-12));
|
||||
// -0.011 -> -0000.0110
|
||||
assert_eq!(Fix::from_f32(-3.0 / 8.0).unwrap(), Fix::from_bits(-6));
|
||||
// -0.0011 -> -0000.0011
|
||||
assert_eq!(Fix::from_f32(-3.0 / 16.0).unwrap(), Fix::from_bits(-3));
|
||||
// -0.00011 -> -0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(-3.0 / 32.0).unwrap(), Fix::from_bits(-2));
|
||||
// -0.00101 -> -0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(-5.0 / 32.0).unwrap(), Fix::from_bits(-2));
|
||||
// -0.000011 -> -0000.0001 (nearest)
|
||||
assert_eq!(Fix::from_f32(-3.0 / 64.0).unwrap(), Fix::from_bits(-1));
|
||||
// -0.00001 -> 0000.0000 (tie to even)
|
||||
assert_eq!(Fix::from_f32(-1.0 / 32.0).unwrap(), Fix::from_bits(0));
|
||||
|
||||
// 111.1111 -> 111.1111
|
||||
assert_eq!(Fix::from_f32(127.0 / 16.0).unwrap(), Fix::from_bits(127));
|
||||
// 111.11111 -> too large (tie to even)
|
||||
assert!(Fix::from_f32(255.0 / 32.0).is_none());
|
||||
|
||||
// -111.1111 -> -111.1111
|
||||
assert_eq!(Fix::from_f32(-127.0 / 16.0).unwrap(), Fix::from_bits(-127));
|
||||
// -111.11111 -> -1000.0000
|
||||
assert_eq!(Fix::from_f32(-255.0 / 32.0).unwrap(), Fix::from_bits(-128));
|
||||
// -1000.00001 -> -1000.0000 (tie to even)
|
||||
assert_eq!(Fix::from_f32(-257.0 / 32.0).unwrap(), Fix::from_bits(-128));
|
||||
// -1000.0001 -> too small
|
||||
assert!(Fix::from_f32(-129.0 / 16.0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_from_f32() {
|
||||
type Fix = FixedU8<frac::U4>;
|
||||
// 1.1 -> 0001.1000
|
||||
assert_eq!(Fix::from_f32(3.0 / 2.0).unwrap(), Fix::from_bits(24));
|
||||
// 0.11 -> 0000.1100
|
||||
assert_eq!(Fix::from_f32(3.0 / 4.0).unwrap(), Fix::from_bits(12));
|
||||
// 0.011 -> 0000.0110
|
||||
assert_eq!(Fix::from_f32(3.0 / 8.0).unwrap(), Fix::from_bits(6));
|
||||
// 0.0011 -> 0000.0011
|
||||
assert_eq!(Fix::from_f32(3.0 / 16.0).unwrap(), Fix::from_bits(3));
|
||||
// 0.00011 -> 0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(3.0 / 32.0).unwrap(), Fix::from_bits(2));
|
||||
// 0.00101 -> 0000.0010 (tie to even)
|
||||
assert_eq!(Fix::from_f32(5.0 / 32.0).unwrap(), Fix::from_bits(2));
|
||||
// 0.000011 -> 0000.0001 (nearest)
|
||||
assert_eq!(Fix::from_f32(3.0 / 64.0).unwrap(), Fix::from_bits(1));
|
||||
// 0.00001 -> 0000.0000 (tie to even)
|
||||
assert_eq!(Fix::from_f32(1.0 / 32.0).unwrap(), Fix::from_bits(0));
|
||||
// -0.00001 -> 0000.0000 (tie to even)
|
||||
assert_eq!(Fix::from_f32(-1.0 / 32.0).unwrap(), Fix::from_bits(0));
|
||||
// -0.0001 -> -ve
|
||||
assert!(Fix::from_f32(-1.0 / 16.0).is_none());
|
||||
|
||||
// 1111.1111 -> 1111.1111
|
||||
assert_eq!(Fix::from_f32(255.0 / 16.0).unwrap(), Fix::from_bits(255));
|
||||
// 1111.11111 -> too large (tie to even)
|
||||
assert!(Fix::from_f32(511.0 / 32.0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_f32() {
|
||||
for u in 0x00..=0xff {
|
||||
let fu = FixedU8::<frac::U7>::from_bits(u);
|
||||
assert_eq!(fu.to_f32(), u as f32 / 128.0);
|
||||
let i = u as i8;
|
||||
let fi = FixedI8::<frac::U7>::from_bits(i);
|
||||
assert_eq!(fi.to_f32(), i as f32 / 128.0);
|
||||
|
||||
for hi in &[
|
||||
0u32,
|
||||
0x0000_0100,
|
||||
0x7fff_ff00,
|
||||
0x8000_0000,
|
||||
0x8100_0000,
|
||||
0xffff_fe00,
|
||||
0xffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u32;
|
||||
let fuu = FixedU32::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f32(), uu as f32 / 128.0);
|
||||
let ii = uu as i32;
|
||||
let fii = FixedI32::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f32(), ii as f32 / 128.0);
|
||||
}
|
||||
|
||||
for hi in &[
|
||||
0u128,
|
||||
0x0000_0000_0000_0000_0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000_0000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000_0000_0000_0000_0000,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u128;
|
||||
let fuu = FixedU128::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f32(), (uu as f64 / 128.0) as f32);
|
||||
let ii = uu as i128;
|
||||
let fii = FixedI128::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f32(), (ii as f64 / 128.0) as f32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_infinite_f32() {
|
||||
// too_large is 1.ffff_ffff_ffff... << 127,
|
||||
// which will be rounded to 1.0 << 128.
|
||||
let too_large = FixedU128::<frac::U0>::max_value();
|
||||
assert_eq!(too_large.count_ones(), 128);
|
||||
assert!(too_large.to_f32().is_infinite());
|
||||
|
||||
// still_too_large is 1.ffff_ff << 127,
|
||||
// which is exactly midway between 1.0 << 128 (even)
|
||||
// and the largest normal f32 that is 1.ffff_fe << 127 (odd).
|
||||
// The tie will be rounded to even, which is to 1.0 << 128.
|
||||
let still_too_large = too_large << 103u32;
|
||||
assert_eq!(still_too_large.count_ones(), 25);
|
||||
assert!(still_too_large.to_f32().is_infinite());
|
||||
|
||||
// not_too_large is 1.ffff_feff_ffff... << 127,
|
||||
// which will be rounded to 1.ffff_fe << 127.
|
||||
let not_too_large = still_too_large - FixedU128::from_bits(1);
|
||||
assert_eq!(not_too_large.count_ones(), 127);
|
||||
assert!(!not_too_large.to_f32().is_infinite());
|
||||
|
||||
// min_128 is -1.0 << 127.
|
||||
let min_i128 = FixedI128::<frac::U0>::min_value();
|
||||
assert_eq!(min_i128.count_ones(), 1);
|
||||
assert_eq!(min_i128.to_f32(), -127f32.exp2());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_f64() {
|
||||
for u in 0x00..=0xff {
|
||||
let fu = FixedU8::<frac::U7>::from_bits(u);
|
||||
assert_eq!(fu.to_f32(), u as f32 / 128.0);
|
||||
let i = u as i8;
|
||||
let fi = FixedI8::<frac::U7>::from_bits(i);
|
||||
assert_eq!(fi.to_f32(), i as f32 / 128.0);
|
||||
|
||||
for hi in &[
|
||||
0u64,
|
||||
0x0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000,
|
||||
0xffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u64;
|
||||
let fuu = FixedU64::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f64(), uu as f64 / 128.0);
|
||||
let ii = uu as i64;
|
||||
let fii = FixedI64::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f64(), ii as f64 / 128.0);
|
||||
}
|
||||
|
||||
for hi in &[
|
||||
0u128,
|
||||
0x0000_0000_0000_0000_0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000_0000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000_0000_0000_0000_0000,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u128;
|
||||
let fuu = FixedU128::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f64(), uu as f64 / 128.0);
|
||||
let ii = uu as i128;
|
||||
let fii = FixedI128::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f64(), ii as f64 / 128.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ pub(crate) trait FixedHelper<Frac: Unsigned>: Sized {
|
|||
mem::size_of::<Self::UInner>() as u32 * 8
|
||||
}
|
||||
|
||||
fn is_signed() -> bool;
|
||||
fn one() -> Option<Self>;
|
||||
fn minus_one() -> Option<Self>;
|
||||
fn from_parts(neg: bool, int_abs: Self::UInner, frac_abs: Self::UInner) -> Self;
|
||||
|
@ -132,6 +133,11 @@ macro_rules! fixed_num_unsigned {
|
|||
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
||||
type UInner = $UInner;
|
||||
|
||||
#[inline]
|
||||
fn is_signed() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn one() -> Option<Self> {
|
||||
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||
|
@ -189,6 +195,11 @@ macro_rules! fixed_num_signed {
|
|||
impl<Frac: Unsigned> FixedHelper<Frac> for $Fixed<Frac> {
|
||||
type UInner = $UInner;
|
||||
|
||||
#[inline]
|
||||
fn is_signed() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn one() -> Option<Self> {
|
||||
let int_bits = <$Fixed<Frac>>::int_bits();
|
||||
|
|
136
src/lib.rs
136
src/lib.rs
|
@ -212,6 +212,23 @@ macro_rules! from_float {
|
|||
let frac_bits = Self::frac_bits();
|
||||
|
||||
let (int_frac, neg) = FloatConv::$method(val, frac_bits)?;
|
||||
|
||||
if <$Fixed<$Frac> as FixedHelper<$Frac>>::is_signed() {
|
||||
// most significant bit (msb) can be one only for min value,
|
||||
// that is for a negative value with only the msb true.
|
||||
let msb = 1 << (int_bits + frac_bits - 1);
|
||||
if int_frac & msb != 0 {
|
||||
if !neg || (int_frac & !msb) != 0 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
} else if neg {
|
||||
if int_frac != 0 {
|
||||
return None;
|
||||
}
|
||||
return Some($Fixed::from_bits(0));
|
||||
}
|
||||
|
||||
let (int, frac) = if frac_bits == 0 {
|
||||
(int_frac, 0)
|
||||
} else if int_bits == 0 {
|
||||
|
@ -219,6 +236,7 @@ macro_rules! from_float {
|
|||
} else {
|
||||
((int_frac >> frac_bits), (int_frac << int_bits))
|
||||
};
|
||||
|
||||
Some(FixedHelper::from_parts(neg, int, frac))
|
||||
}
|
||||
}
|
||||
|
@ -1081,124 +1099,6 @@ fixed! { "A 128-bit fixed-point signed integer", FixedI128(i128, 128), Signed }
|
|||
mod tests {
|
||||
use *;
|
||||
|
||||
#[test]
|
||||
fn to_f32() {
|
||||
for u in 0x00..=0xff {
|
||||
let fu = FixedU8::<frac::U7>::from_bits(u);
|
||||
assert_eq!(fu.to_f32(), u as f32 / 128.0);
|
||||
let i = u as i8;
|
||||
let fi = FixedI8::<frac::U7>::from_bits(i);
|
||||
assert_eq!(fi.to_f32(), i as f32 / 128.0);
|
||||
|
||||
for hi in &[
|
||||
0u32,
|
||||
0x0000_0100,
|
||||
0x7fff_ff00,
|
||||
0x8000_0000,
|
||||
0x8100_0000,
|
||||
0xffff_fe00,
|
||||
0xffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u32;
|
||||
let fuu = FixedU32::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f32(), uu as f32 / 128.0);
|
||||
let ii = uu as i32;
|
||||
let fii = FixedI32::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f32(), ii as f32 / 128.0);
|
||||
}
|
||||
|
||||
for hi in &[
|
||||
0u128,
|
||||
0x0000_0000_0000_0000_0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000_0000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000_0000_0000_0000_0000,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u128;
|
||||
let fuu = FixedU128::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f32(), (uu as f64 / 128.0) as f32);
|
||||
let ii = uu as i128;
|
||||
let fii = FixedI128::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f32(), (ii as f64 / 128.0) as f32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_infinite_f32() {
|
||||
// too_large is 1.ffff_ffff_ffff... << 127,
|
||||
// which will be rounded to 1.0 << 128.
|
||||
let too_large = FixedU128::<frac::U0>::max_value();
|
||||
assert_eq!(too_large.count_ones(), 128);
|
||||
assert!(too_large.to_f32().is_infinite());
|
||||
|
||||
// still_too_large is 1.ffff_ff << 127,
|
||||
// which is exactly midway between 1.0 << 128 (even)
|
||||
// and the largest normal f32 that is 1.ffff_fe << 127 (odd).
|
||||
// The tie will be rounded to even, which is to 1.0 << 128.
|
||||
let still_too_large = too_large << 103u32;
|
||||
assert_eq!(still_too_large.count_ones(), 25);
|
||||
assert!(still_too_large.to_f32().is_infinite());
|
||||
|
||||
// not_too_large is 1.ffff_feff_ffff... << 127,
|
||||
// which will be rounded to 1.ffff_fe << 127.
|
||||
let not_too_large = still_too_large - FixedU128::from_bits(1);
|
||||
assert_eq!(not_too_large.count_ones(), 127);
|
||||
assert!(!not_too_large.to_f32().is_infinite());
|
||||
|
||||
// min_128 is -1.0 << 127.
|
||||
let min_i128 = FixedI128::<frac::U0>::min_value();
|
||||
assert_eq!(min_i128.count_ones(), 1);
|
||||
assert_eq!(min_i128.to_f32(), -127f32.exp2());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_f64() {
|
||||
for u in 0x00..=0xff {
|
||||
let fu = FixedU8::<frac::U7>::from_bits(u);
|
||||
assert_eq!(fu.to_f32(), u as f32 / 128.0);
|
||||
let i = u as i8;
|
||||
let fi = FixedI8::<frac::U7>::from_bits(i);
|
||||
assert_eq!(fi.to_f32(), i as f32 / 128.0);
|
||||
|
||||
for hi in &[
|
||||
0u64,
|
||||
0x0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000,
|
||||
0xffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u64;
|
||||
let fuu = FixedU64::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f64(), uu as f64 / 128.0);
|
||||
let ii = uu as i64;
|
||||
let fii = FixedI64::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f64(), ii as f64 / 128.0);
|
||||
}
|
||||
|
||||
for hi in &[
|
||||
0u128,
|
||||
0x0000_0000_0000_0000_0000_0000_0000_0100,
|
||||
0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
0x8000_0000_0000_0000_0000_0000_0000_0000,
|
||||
0x8100_0000_0000_0000_0000_0000_0000_0000,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fe00,
|
||||
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff00,
|
||||
] {
|
||||
let uu = *hi | u as u128;
|
||||
let fuu = FixedU128::<frac::U7>::from_bits(uu);
|
||||
assert_eq!(fuu.to_f64(), uu as f64 / 128.0);
|
||||
let ii = uu as i128;
|
||||
let fii = FixedI128::<frac::U7>::from_bits(ii);
|
||||
assert_eq!(fii.to_f64(), ii as f64 / 128.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
use frac::{U16, U32};
|
||||
|
|
Loading…
Reference in New Issue