about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2024-10-31 23:47:41 -0500
committerTrevor Gross <t.gross35@gmail.com>2024-11-01 00:06:04 -0500
commit5f54ad6389397af45bf38e1deed2dc8d92bd11ca (patch)
tree7a9941b2f74c773921820dc9936a6abf4820c627
parent4c1772ed85c9cc7cb37ab26a2f369a1e54fda748 (diff)
downloadrust-5f54ad6389397af45bf38e1deed2dc8d92bd11ca.tar.gz
rust-5f54ad6389397af45bf38e1deed2dc8d92bd11ca.zip
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.
-rw-r--r--library/compiler-builtins/libm/src/math/support/float_traits.rs50
-rw-r--r--library/compiler-builtins/libm/src/math/support/int_traits.rs43
2 files changed, 77 insertions, 16 deletions
diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs
index f90e99d5228..a1d84faf2e2 100644
--- a/library/compiler-builtins/libm/src/math/support/float_traits.rs
+++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs
@@ -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) }
             }
         }
     };
diff --git a/library/compiler-builtins/libm/src/math/support/int_traits.rs b/library/compiler-builtins/libm/src/math/support/int_traits.rs
index bdf3afd48ce..c5feef8d726 100644
--- a/library/compiler-builtins/libm/src/math/support/int_traits.rs
+++ b/library/compiler-builtins/libm/src/math/support/int_traits.rs
@@ -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
             }