Update libm Float and Int with functions from the test traits
The test versions of `Float` and `Int` have a few more methods and constants availablee. Update the in `libm` with everything missing from `libm_test` so we will be able to merge these.
This commit is contained in:
parent
4c1772ed85
commit
5f54ad6389
2 changed files with 77 additions and 16 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use core::ops;
|
||||
use core::{fmt, ops};
|
||||
|
||||
use super::int_traits::{Int, MinInt};
|
||||
|
||||
|
|
@ -6,7 +6,8 @@ use super::int_traits::{Int, MinInt};
|
|||
#[allow(dead_code)]
|
||||
pub trait Float:
|
||||
Copy
|
||||
+ core::fmt::Debug
|
||||
+ fmt::Debug
|
||||
+ fmt::Display
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ ops::AddAssign
|
||||
|
|
@ -17,16 +18,17 @@ pub trait Float:
|
|||
+ ops::Rem<Output = Self>
|
||||
{
|
||||
/// A uint of the same width as the float
|
||||
type Int: Int<OtherSign = Self::SignedInt, UnsignedInt = Self::Int>;
|
||||
type Int: Int<OtherSign = Self::SignedInt, Unsigned = Self::Int>;
|
||||
|
||||
/// A int of the same width as the float
|
||||
type SignedInt: Int + MinInt<OtherSign = Self::Int, UnsignedInt = Self::Int>;
|
||||
type SignedInt: Int + MinInt<OtherSign = Self::Int, Unsigned = Self::Int>;
|
||||
|
||||
/// An int capable of containing the exponent bits plus a sign bit. This is signed.
|
||||
type ExpInt: Int;
|
||||
|
||||
const ZERO: Self;
|
||||
const ONE: Self;
|
||||
const NEG_ONE: Self;
|
||||
const INFINITY: Self;
|
||||
const NEG_INFINITY: Self;
|
||||
const NAN: Self;
|
||||
|
|
@ -69,9 +71,18 @@ pub trait Float:
|
|||
/// compared.
|
||||
fn eq_repr(self, rhs: Self) -> bool;
|
||||
|
||||
/// Returns true if the sign is negative
|
||||
/// Returns true if the value is NaN.
|
||||
fn is_nan(self) -> bool;
|
||||
|
||||
/// Returns true if the value is +inf or -inf.
|
||||
fn is_infinite(self) -> bool;
|
||||
|
||||
/// Returns true if the sign is negative.
|
||||
fn is_sign_negative(self) -> bool;
|
||||
|
||||
/// Returns if `self` is subnormal
|
||||
fn is_subnormal(self) -> bool;
|
||||
|
||||
/// Returns the exponent, not adjusting for bias.
|
||||
fn exp(self) -> Self::ExpInt;
|
||||
|
||||
|
|
@ -95,8 +106,11 @@ pub trait Float:
|
|||
/// Returns (normalized exponent, normalized significand)
|
||||
fn normalize(significand: Self::Int) -> (i32, Self::Int);
|
||||
|
||||
/// Returns if `self` is subnormal
|
||||
fn is_subnormal(self) -> bool;
|
||||
/// Returns a number composed of the magnitude of self and the sign of sign.
|
||||
fn copysign(self, other: Self) -> Self;
|
||||
|
||||
/// Returns a number that represents the sign of self.
|
||||
fn signum(self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! float_impl {
|
||||
|
|
@ -108,6 +122,7 @@ macro_rules! float_impl {
|
|||
|
||||
const ZERO: Self = 0.0;
|
||||
const ONE: Self = 1.0;
|
||||
const NEG_ONE: Self = -1.0;
|
||||
const INFINITY: Self = Self::INFINITY;
|
||||
const NEG_INFINITY: Self = Self::NEG_INFINITY;
|
||||
const NAN: Self = Self::NAN;
|
||||
|
|
@ -136,9 +151,18 @@ macro_rules! float_impl {
|
|||
}
|
||||
if is_nan(self) && is_nan(rhs) { true } else { self.to_bits() == rhs.to_bits() }
|
||||
}
|
||||
fn is_nan(self) -> bool {
|
||||
self.is_nan()
|
||||
}
|
||||
fn is_infinite(self) -> bool {
|
||||
self.is_infinite()
|
||||
}
|
||||
fn is_sign_negative(self) -> bool {
|
||||
self.is_sign_negative()
|
||||
}
|
||||
fn is_subnormal(self) -> bool {
|
||||
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
|
||||
}
|
||||
fn exp(self) -> Self::ExpInt {
|
||||
((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
|
||||
}
|
||||
|
|
@ -162,8 +186,16 @@ macro_rules! float_impl {
|
|||
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
|
||||
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
|
||||
}
|
||||
fn is_subnormal(self) -> bool {
|
||||
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
|
||||
fn copysign(self, other: Self) -> Self {
|
||||
let mut x = self.to_bits();
|
||||
let y = other.to_bits();
|
||||
x &= !Self::SIGN_MASK;
|
||||
x |= y & Self::SIGN_MASK;
|
||||
Self::from_bits(x)
|
||||
}
|
||||
|
||||
fn signum(self) -> Self {
|
||||
if self.is_nan() { self } else { Self::ONE.copysign(self) }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub trait MinInt:
|
|||
/// Type with the same width but other signedness
|
||||
type OtherSign: MinInt;
|
||||
/// Unsigned version of Self
|
||||
type UnsignedInt: MinInt;
|
||||
type Unsigned: MinInt;
|
||||
|
||||
/// If `Self` is a signed integer
|
||||
const SIGNED: bool;
|
||||
|
|
@ -30,6 +30,7 @@ pub trait MinInt:
|
|||
#[allow(dead_code)]
|
||||
pub trait Int:
|
||||
MinInt
|
||||
+ fmt::Display
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ ops::AddAssign
|
||||
|
|
@ -47,8 +48,10 @@ pub trait Int:
|
|||
+ ops::BitXor<Output = Self>
|
||||
+ ops::BitAnd<Output = Self>
|
||||
{
|
||||
fn unsigned(self) -> Self::UnsignedInt;
|
||||
fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
|
||||
fn signed(self) -> <Self::Unsigned as MinInt>::OtherSign;
|
||||
fn unsigned(self) -> Self::Unsigned;
|
||||
fn from_unsigned(unsigned: Self::Unsigned) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
|
||||
fn from_bool(b: bool) -> Self;
|
||||
|
||||
|
|
@ -56,10 +59,12 @@ pub trait Int:
|
|||
fn logical_shr(self, other: u32) -> Self;
|
||||
|
||||
/// Absolute difference between two integers.
|
||||
fn abs_diff(self, other: Self) -> Self::UnsignedInt;
|
||||
fn abs_diff(self, other: Self) -> Self::Unsigned;
|
||||
|
||||
// copied from primitive integers, but put in a trait
|
||||
fn is_zero(self) -> bool;
|
||||
fn checked_add(self, other: Self) -> Option<Self>;
|
||||
fn checked_sub(self, other: Self) -> Option<Self>;
|
||||
fn wrapping_neg(self) -> Self;
|
||||
fn wrapping_add(self, other: Self) -> Self;
|
||||
fn wrapping_mul(self, other: Self) -> Self;
|
||||
|
|
@ -86,6 +91,14 @@ macro_rules! int_impl_common {
|
|||
self == Self::ZERO
|
||||
}
|
||||
|
||||
fn checked_add(self, other: Self) -> Option<Self> {
|
||||
self.checked_add(other)
|
||||
}
|
||||
|
||||
fn checked_sub(self, other: Self) -> Option<Self> {
|
||||
self.checked_sub(other)
|
||||
}
|
||||
|
||||
fn wrapping_neg(self) -> Self {
|
||||
<Self>::wrapping_neg(self)
|
||||
}
|
||||
|
|
@ -132,7 +145,7 @@ macro_rules! int_impl {
|
|||
($ity:ty, $uty:ty) => {
|
||||
impl MinInt for $uty {
|
||||
type OtherSign = $ity;
|
||||
type UnsignedInt = $uty;
|
||||
type Unsigned = $uty;
|
||||
|
||||
const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
|
||||
const SIGNED: bool = Self::MIN != Self::ZERO;
|
||||
|
|
@ -144,10 +157,18 @@ macro_rules! int_impl {
|
|||
}
|
||||
|
||||
impl Int for $uty {
|
||||
fn unsigned(self) -> $uty {
|
||||
fn signed(self) -> $ity {
|
||||
self as $ity
|
||||
}
|
||||
|
||||
fn unsigned(self) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
fn abs(self) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// It makes writing macros easier if this is implemented for both signed and unsigned
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn from_unsigned(me: $uty) -> Self {
|
||||
|
|
@ -163,7 +184,7 @@ macro_rules! int_impl {
|
|||
|
||||
impl MinInt for $ity {
|
||||
type OtherSign = $uty;
|
||||
type UnsignedInt = $uty;
|
||||
type Unsigned = $uty;
|
||||
|
||||
const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
|
||||
const SIGNED: bool = Self::MIN != Self::ZERO;
|
||||
|
|
@ -175,10 +196,18 @@ macro_rules! int_impl {
|
|||
}
|
||||
|
||||
impl Int for $ity {
|
||||
fn signed(self) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
fn unsigned(self) -> $uty {
|
||||
self as $uty
|
||||
}
|
||||
|
||||
fn abs(self) -> Self {
|
||||
self.abs()
|
||||
}
|
||||
|
||||
fn from_unsigned(me: $uty) -> Self {
|
||||
me as $ity
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue