remove trait use in float_helper

This commit is contained in:
Trevor Spiteri 2021-10-27 21:27:20 +02:00
parent 41fd8bc46e
commit 66d7fe8ba2
6 changed files with 93 additions and 97 deletions

View File

@ -118,7 +118,7 @@ x86_64-gnulinux-tarpaulin:
- cargo/
script:
- rustup toolchain install --profile minimal beta-$TARGET
- cargo +beta-$TARGET install --version 0.18.2 --locked cargo-tarpaulin
- cargo +beta-$TARGET install --version 0.18.3 --locked cargo-tarpaulin
- stdbuf -oL cargo +beta-$TARGET tarpaulin -v --ignore-tests --exclude-files build.rs --features "arbitrary num-traits serde std" | tee tarpaulin.log
- echo "Check that coverage not less than $REQ_COVERAGE%"
- tail -1 tarpaulin.log | awk '{ if ($1 < '$REQ_COVERAGE') { exit 1 } }'

View File

@ -14,7 +14,8 @@
// <https://opensource.org/licenses/MIT>.
use crate::{
helpers::{FloatHelper, FloatKind, Widest},
float_helper,
helpers::{FloatKind, Widest},
int_helper::{self, IntFixed},
types::extra::{LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8},
F128Bits, FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32,
@ -199,7 +200,9 @@ macro_rules! fixed_cmp_float {
impl<Frac: $LeEqU> PartialEq<$Float> for $Fix<Frac> {
#[inline]
fn eq(&self, rhs: &$Float) -> bool {
let conv = match rhs.to_float_kind(Self::FRAC_NBITS, Self::INT_NBITS) {
let kind =
float_helper::$Float::to_float_kind(*rhs, Self::FRAC_NBITS, Self::INT_NBITS);
let conv = match kind {
FloatKind::Finite { conv, .. } => conv,
_ => return false,
};
@ -225,8 +228,9 @@ macro_rules! fixed_cmp_float {
#[inline]
fn partial_cmp(&self, rhs: &$Float) -> Option<Ordering> {
let lhs_is_neg = int_helper::$Inner::is_negative(self.to_bits());
let (rhs_is_neg, conv) = match rhs.to_float_kind(Self::FRAC_NBITS, Self::INT_NBITS)
{
let kind =
float_helper::$Float::to_float_kind(*rhs, Self::FRAC_NBITS, Self::INT_NBITS);
let (rhs_is_neg, conv) = match kind {
FloatKind::NaN => return None,
FloatKind::Infinite { neg } => {
return if neg {
@ -259,8 +263,9 @@ macro_rules! fixed_cmp_float {
#[inline]
fn lt(&self, rhs: &$Float) -> bool {
let lhs_is_neg = int_helper::$Inner::is_negative(self.to_bits());
let (rhs_is_neg, conv) = match rhs.to_float_kind(Self::FRAC_NBITS, Self::INT_NBITS)
{
let kind =
float_helper::$Float::to_float_kind(*rhs, Self::FRAC_NBITS, Self::INT_NBITS);
let (rhs_is_neg, conv) = match kind {
FloatKind::NaN => return false,
FloatKind::Infinite { neg } => return !neg,
FloatKind::Finite { neg, conv } => (neg, conv),
@ -284,7 +289,7 @@ macro_rules! fixed_cmp_float {
#[inline]
fn le(&self, rhs: &$Float) -> bool {
!FloatHelper::is_nan(*rhs) && !rhs.lt(self)
!rhs.is_nan() && !rhs.lt(self)
}
#[inline]
@ -294,7 +299,7 @@ macro_rules! fixed_cmp_float {
#[inline]
fn ge(&self, rhs: &$Float) -> bool {
!FloatHelper::is_nan(*rhs) && !self.lt(rhs)
!rhs.is_nan() && !self.lt(rhs)
}
}
@ -306,12 +311,16 @@ macro_rules! fixed_cmp_float {
#[inline]
fn lt(&self, rhs: &$Fix<Frac>) -> bool {
let (lhs_is_neg, conv) =
match self.to_float_kind(<$Fix<Frac>>::FRAC_NBITS, <$Fix<Frac>>::INT_NBITS) {
FloatKind::NaN => return false,
FloatKind::Infinite { neg } => return neg,
FloatKind::Finite { neg, conv } => (neg, conv),
};
let kind = float_helper::$Float::to_float_kind(
*self,
<$Fix<Frac>>::FRAC_NBITS,
<$Fix<Frac>>::INT_NBITS,
);
let (lhs_is_neg, conv) = match kind {
FloatKind::NaN => return false,
FloatKind::Infinite { neg } => return neg,
FloatKind::Finite { neg, conv } => (neg, conv),
};
let rhs_is_neg = int_helper::$Inner::is_negative(rhs.to_bits());
match (lhs_is_neg, rhs_is_neg) {
(false, true) => return false,
@ -331,7 +340,7 @@ macro_rules! fixed_cmp_float {
#[inline]
fn le(&self, rhs: &$Fix<Frac>) -> bool {
!FloatHelper::is_nan(*self) && !rhs.lt(self)
!self.is_nan() && !rhs.lt(self)
}
#[inline]
@ -341,7 +350,7 @@ macro_rules! fixed_cmp_float {
#[inline]
fn ge(&self, rhs: &$Fix<Frac>) -> bool {
!FloatHelper::is_nan(*self) && !self.lt(rhs)
!self.is_nan() && !self.lt(rhs)
}
}
};

View File

@ -13,80 +13,59 @@
// <https://www.apache.org/licenses/LICENSE-2.0> and
// <https://opensource.org/licenses/MIT>.
use crate::{
helpers::{FloatKind, ToFixedHelper, ToFloatHelper, Widest},
int_helper, F128Bits,
};
use core::cmp::Ordering;
use half::{bf16, f16};
pub trait FloatHelper: Copy {
type Bits;
const PREC: u32;
const EXP_BIAS: i32;
const EXP_MIN: i32;
const EXP_MAX: i32;
const SIGN_MASK: Self::Bits;
const EXP_MASK: Self::Bits;
const MANT_MASK: Self::Bits;
fn is_nan(self) -> bool;
fn parts(self) -> (bool, i32, Self::Bits);
fn from_to_float_helper(val: ToFloatHelper, frac_bits: u32, int_bits: u32) -> Self;
fn to_float_kind(self, dst_frac_bits: u32, dst_int_bits: u32) -> FloatKind;
}
macro_rules! sealed_float {
($Float:ident($Bits:ty, $IBits:ident, $prec:expr)) => {
impl FloatHelper for $Float {
type Bits = $Bits;
macro_rules! make_helper {
($Float:ident($Bits:ty, $IBits:ident, $prec:expr) $(; use $path:path)?) => {
#[allow(non_snake_case)]
pub mod $Float {
use crate::{
helpers::{FloatKind, ToFixedHelper, ToFloatHelper, Widest},
int_helper,
};
use core::cmp::Ordering;
$(use $path;)?
const PREC: u32 = $prec;
const EXP_BIAS: i32 = (1 << (<$Bits>::BITS - Self::PREC - 1)) - 1;
const EXP_MIN: i32 = 1 - Self::EXP_BIAS;
const EXP_MAX: i32 = Self::EXP_BIAS;
const SIGN_MASK: $Bits = 1 << (<$Bits>::BITS - 1);
const EXP_MASK: $Bits = !(Self::SIGN_MASK | Self::MANT_MASK);
const MANT_MASK: $Bits = (1 << (Self::PREC - 1)) - 1;
const EXP_BIAS: i32 = (1 << (<$Bits>::BITS - PREC - 1)) - 1;
const EXP_MIN: i32 = 1 - EXP_BIAS;
const EXP_MAX: i32 = EXP_BIAS;
pub const SIGN_MASK: $Bits = 1 << (<$Bits>::BITS - 1);
pub const EXP_MASK: $Bits = !(SIGN_MASK | MANT_MASK);
const MANT_MASK: $Bits = (1 << (PREC - 1)) - 1;
#[inline]
fn is_nan(self) -> bool {
(self.to_bits() & !Self::SIGN_MASK) > Self::EXP_MASK
}
#[inline]
fn parts(self) -> (bool, i32, $Bits) {
let bits = self.to_bits();
let neg = bits & Self::SIGN_MASK != 0;
let biased_exp = (bits & Self::EXP_MASK) >> (Self::PREC - 1);
let exp = biased_exp as i32 - Self::EXP_BIAS;
let mant = bits & Self::MANT_MASK;
fn parts(val: $Float) -> (bool, i32, $Bits) {
let bits = val.to_bits();
let neg = bits & SIGN_MASK != 0;
let biased_exp = (bits & EXP_MASK) >> (PREC - 1);
let exp = biased_exp as i32 - EXP_BIAS;
let mant = bits & MANT_MASK;
(neg, exp, mant)
}
#[inline]
fn from_to_float_helper(val: ToFloatHelper, frac_bits: u32, int_bits: u32) -> $Float {
pub fn from_to_float_helper(
val: ToFloatHelper,
frac_bits: u32,
int_bits: u32,
) -> $Float {
let fix_bits = frac_bits + int_bits;
let bits_sign = if val.neg { Self::SIGN_MASK } else { 0 };
let bits_sign = if val.neg { SIGN_MASK } else { 0 };
let extra_zeros = 128 - fix_bits;
let leading_zeros = val.abs.leading_zeros() - extra_zeros;
let signif_bits = fix_bits - leading_zeros;
if signif_bits == 0 {
return Self::from_bits(bits_sign);
return $Float::from_bits(bits_sign);
}
// remove leading zeros and implicit one
let mut mantissa = val.abs << leading_zeros << 1;
let exponent = int_bits as i32 - 1 - leading_zeros as i32;
let biased_exponent = if exponent > Self::EXP_MAX {
return Self::from_bits(Self::EXP_MASK | bits_sign);
} else if exponent < Self::EXP_MIN {
let lost_prec = Self::EXP_MIN - exponent;
let biased_exponent = if exponent > EXP_MAX {
return $Float::from_bits(EXP_MASK | bits_sign);
} else if exponent < EXP_MIN {
let lost_prec = EXP_MIN - exponent;
if lost_prec as u32 >= (int_bits + frac_bits) {
mantissa = 0;
} else {
@ -96,11 +75,11 @@ macro_rules! sealed_float {
}
0
} else {
(exponent + Self::EXP_MAX) as $Bits
(exponent + EXP_MAX) as $Bits
};
// check for rounding
let round_up = (fix_bits >= Self::PREC) && {
let shift = Self::PREC - 1;
let round_up = (fix_bits >= PREC) && {
let shift = PREC - 1;
let mid_bit = !(!0 >> 1) >> (shift + extra_zeros);
let lower_bits = mid_bit - 1;
if mantissa & mid_bit == 0 {
@ -112,25 +91,25 @@ macro_rules! sealed_float {
mantissa & (mid_bit << 1) != 0
}
};
let bits_exp = biased_exponent << (Self::PREC - 1);
let bits_mantissa = (if fix_bits >= Self::PREC - 1 {
(mantissa >> (fix_bits - (Self::PREC - 1))) as $Bits
let bits_exp = biased_exponent << (PREC - 1);
let bits_mantissa = (if fix_bits >= PREC - 1 {
(mantissa >> (fix_bits - (PREC - 1))) as $Bits
} else {
(mantissa as $Bits) << (Self::PREC - 1 - fix_bits)
}) & !(!0 << (Self::PREC - 1));
(mantissa as $Bits) << (PREC - 1 - fix_bits)
}) & !(!0 << (PREC - 1));
let mut bits_exp_mantissa = bits_exp | bits_mantissa;
if round_up {
bits_exp_mantissa += 1;
}
Self::from_bits(bits_sign | bits_exp_mantissa)
$Float::from_bits(bits_sign | bits_exp_mantissa)
}
#[inline]
fn to_float_kind(self, dst_frac_bits: u32, dst_int_bits: u32) -> FloatKind {
let prec = Self::PREC as i32;
pub fn to_float_kind(val: $Float, dst_frac_bits: u32, dst_int_bits: u32) -> FloatKind {
let prec = PREC as i32;
let (neg, exp, mut mantissa) = self.parts();
if exp > Self::EXP_MAX {
let (neg, exp, mut mantissa) = parts(val);
if exp > EXP_MAX {
if mantissa == 0 {
return FloatKind::Infinite { neg };
} else {
@ -138,7 +117,7 @@ macro_rules! sealed_float {
};
}
// if not subnormal, add implicit bit
if exp >= Self::EXP_MIN {
if exp >= EXP_MIN {
mantissa |= 1 << (prec - 1);
}
if mantissa == 0 {
@ -201,8 +180,8 @@ macro_rules! sealed_float {
};
}
sealed_float! { f16(u16, i16, 11) }
sealed_float! { bf16(u16, i16, 8) }
sealed_float! { f32(u32, i32, 24) }
sealed_float! { f64(u64, i64, 53) }
sealed_float! { F128Bits(u128, i128, 113) }
make_helper! { f16(u16, i16, 11); use half::f16 }
make_helper! { bf16(u16, i16, 8); use half::bf16 }
make_helper! { f32(u32, i32, 24) }
make_helper! { f64(u64, i64, 53) }
make_helper! { F128Bits(u128, i128, 113); use crate::F128Bits }

View File

@ -13,7 +13,6 @@
// <https://www.apache.org/licenses/LICENSE-2.0> and
// <https://opensource.org/licenses/MIT>.
pub use crate::float_helper::FloatHelper;
use crate::{
int_helper,
types::extra::{LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8},

View File

@ -674,10 +674,16 @@ impl F128Bits {
pub(crate) fn to_bits(self) -> u128 {
self.0
}
#[inline]
pub(crate) fn from_bits(bits: u128) -> F128Bits {
F128Bits(bits)
}
#[inline]
pub(crate) fn is_nan(self) -> bool {
(self.to_bits() & !float_helper::F128Bits::SIGN_MASK) > float_helper::F128Bits::EXP_MASK
}
}
/// Defines constant fixed-point numbers from integer expressions.

View File

@ -14,7 +14,8 @@
// <https://opensource.org/licenses/MIT>.
use crate::{
helpers::{FloatHelper, FloatKind, FromFloatHelper},
float_helper,
helpers::{FloatKind, FromFloatHelper},
int_helper::IntFixed,
traits::{Fixed, FixedEquiv, FromFixed, ToFixed},
types::extra::U0,
@ -266,7 +267,7 @@ impl_int! { u128, FixedU128 }
impl_int! { usize }
macro_rules! impl_float {
($Float:ty, $link:expr, $overflows_fmt:expr, $overflows_filt:expr) => {
($Float:ident, $link:expr, $overflows_fmt:expr, $overflows_filt:expr) => {
impl FromFixed for $Float {
/// Converts a fixed-point number to a floating-point number.
///
@ -285,7 +286,7 @@ macro_rules! impl_float {
#[inline]
fn from_fixed<F: Fixed>(src: F) -> Self {
let helper = src.private_to_float_helper();
FloatHelper::from_to_float_helper(helper, F::FRAC_NBITS, F::INT_NBITS)
float_helper::$Float::from_to_float_helper(helper, F::FRAC_NBITS, F::INT_NBITS)
}
/// Converts a fixed-point number to a floating-point
@ -375,7 +376,7 @@ it panics; if wrapping is required use [`wrapping_to_fixed`] instead.
/// Rounding is to the nearest, with ties rounded to even.
#[inline]
fn checked_to_fixed<F: Fixed>(self) -> Option<F> {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
let kind = float_helper::$Float::to_float_kind(self, F::FRAC_NBITS, F::INT_NBITS);
match kind {
FloatKind::Finite { .. } => {
let helper = FromFloatHelper { kind };
@ -402,7 +403,8 @@ Panics if `self` is [NaN].
";
#[inline]
fn saturating_to_fixed<F: Fixed>(self) -> F {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
let kind =
float_helper::$Float::to_float_kind(self, F::FRAC_NBITS, F::INT_NBITS);
let helper = FromFloatHelper { kind };
F::private_saturating_from_float_helper(helper)
}
@ -445,7 +447,8 @@ Panics if `self` is not [finite].
#[inline]
#[track_caller]
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool) {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
let kind =
float_helper::$Float::to_float_kind(self, F::FRAC_NBITS, F::INT_NBITS);
let helper = FromFloatHelper { kind };
F::private_overflowing_from_float_helper(helper)
}