Skip to content

Commit 4384fc7

Browse files
committed
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.
1 parent 830ddc5 commit 4384fc7

File tree

2 files changed

+77
-16
lines changed

2 files changed

+77
-16
lines changed

src/math/support/float_traits.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use core::ops;
1+
use core::{fmt, ops};
22

33
use super::int_traits::{Int, MinInt};
44

55
/// Trait for some basic operations on floats
66
#[allow(dead_code)]
77
pub trait Float:
88
Copy
9-
+ core::fmt::Debug
9+
+ fmt::Debug
10+
+ fmt::Display
1011
+ PartialEq
1112
+ PartialOrd
1213
+ ops::AddAssign
@@ -17,16 +18,17 @@ pub trait Float:
1718
+ ops::Rem<Output = Self>
1819
{
1920
/// A uint of the same width as the float
20-
type Int: Int<OtherSign = Self::SignedInt, UnsignedInt = Self::Int>;
21+
type Int: Int<OtherSign = Self::SignedInt, Unsigned = Self::Int>;
2122

2223
/// A int of the same width as the float
23-
type SignedInt: Int + MinInt<OtherSign = Self::Int, UnsignedInt = Self::Int>;
24+
type SignedInt: Int + MinInt<OtherSign = Self::Int, Unsigned = Self::Int>;
2425

2526
/// An int capable of containing the exponent bits plus a sign bit. This is signed.
2627
type ExpInt: Int;
2728

2829
const ZERO: Self;
2930
const ONE: Self;
31+
const NEG_ONE: Self;
3032
const INFINITY: Self;
3133
const NEG_INFINITY: Self;
3234
const NAN: Self;
@@ -69,9 +71,18 @@ pub trait Float:
6971
/// compared.
7072
fn eq_repr(self, rhs: Self) -> bool;
7173

72-
/// Returns true if the sign is negative
74+
/// Returns true if the value is NaN.
75+
fn is_nan(self) -> bool;
76+
77+
/// Returns true if the value is +inf or -inf.
78+
fn is_infinite(self) -> bool;
79+
80+
/// Returns true if the sign is negative.
7381
fn is_sign_negative(self) -> bool;
7482

83+
/// Returns if `self` is subnormal
84+
fn is_subnormal(self) -> bool;
85+
7586
/// Returns the exponent, not adjusting for bias.
7687
fn exp(self) -> Self::ExpInt;
7788

@@ -95,8 +106,11 @@ pub trait Float:
95106
/// Returns (normalized exponent, normalized significand)
96107
fn normalize(significand: Self::Int) -> (i32, Self::Int);
97108

98-
/// Returns if `self` is subnormal
99-
fn is_subnormal(self) -> bool;
109+
/// Returns a number composed of the magnitude of self and the sign of sign.
110+
fn copysign(self, other: Self) -> Self;
111+
112+
/// Returns a number that represents the sign of self.
113+
fn signum(self) -> Self;
100114
}
101115

102116
macro_rules! float_impl {
@@ -108,6 +122,7 @@ macro_rules! float_impl {
108122

109123
const ZERO: Self = 0.0;
110124
const ONE: Self = 1.0;
125+
const NEG_ONE: Self = -1.0;
111126
const INFINITY: Self = Self::INFINITY;
112127
const NEG_INFINITY: Self = Self::NEG_INFINITY;
113128
const NAN: Self = Self::NAN;
@@ -136,9 +151,18 @@ macro_rules! float_impl {
136151
}
137152
if is_nan(self) && is_nan(rhs) { true } else { self.to_bits() == rhs.to_bits() }
138153
}
154+
fn is_nan(self) -> bool {
155+
self.is_nan()
156+
}
157+
fn is_infinite(self) -> bool {
158+
self.is_infinite()
159+
}
139160
fn is_sign_negative(self) -> bool {
140161
self.is_sign_negative()
141162
}
163+
fn is_subnormal(self) -> bool {
164+
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
165+
}
142166
fn exp(self) -> Self::ExpInt {
143167
((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
144168
}
@@ -162,8 +186,16 @@ macro_rules! float_impl {
162186
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
163187
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
164188
}
165-
fn is_subnormal(self) -> bool {
166-
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
189+
fn copysign(self, other: Self) -> Self {
190+
let mut x = self.to_bits();
191+
let y = other.to_bits();
192+
x &= !Self::SIGN_MASK;
193+
x |= y & Self::SIGN_MASK;
194+
Self::from_bits(x)
195+
}
196+
197+
fn signum(self) -> Self {
198+
if self.is_nan() { self } else { Self::ONE.copysign(self) }
167199
}
168200
}
169201
};

src/math/support/int_traits.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub trait MinInt:
1212
/// Type with the same width but other signedness
1313
type OtherSign: MinInt;
1414
/// Unsigned version of Self
15-
type UnsignedInt: MinInt;
15+
type Unsigned: MinInt;
1616

1717
/// If `Self` is a signed integer
1818
const SIGNED: bool;
@@ -30,6 +30,7 @@ pub trait MinInt:
3030
#[allow(dead_code)]
3131
pub trait Int:
3232
MinInt
33+
+ fmt::Display
3334
+ PartialEq
3435
+ PartialOrd
3536
+ ops::AddAssign
@@ -47,19 +48,23 @@ pub trait Int:
4748
+ ops::BitXor<Output = Self>
4849
+ ops::BitAnd<Output = Self>
4950
{
50-
fn unsigned(self) -> Self::UnsignedInt;
51-
fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
51+
fn signed(self) -> <Self::Unsigned as MinInt>::OtherSign;
52+
fn unsigned(self) -> Self::Unsigned;
53+
fn from_unsigned(unsigned: Self::Unsigned) -> Self;
54+
fn abs(self) -> Self;
5255

5356
fn from_bool(b: bool) -> Self;
5457

5558
/// Prevents the need for excessive conversions between signed and unsigned
5659
fn logical_shr(self, other: u32) -> Self;
5760

5861
/// Absolute difference between two integers.
59-
fn abs_diff(self, other: Self) -> Self::UnsignedInt;
62+
fn abs_diff(self, other: Self) -> Self::Unsigned;
6063

6164
// copied from primitive integers, but put in a trait
6265
fn is_zero(self) -> bool;
66+
fn checked_add(self, other: Self) -> Option<Self>;
67+
fn checked_sub(self, other: Self) -> Option<Self>;
6368
fn wrapping_neg(self) -> Self;
6469
fn wrapping_add(self, other: Self) -> Self;
6570
fn wrapping_mul(self, other: Self) -> Self;
@@ -86,6 +91,14 @@ macro_rules! int_impl_common {
8691
self == Self::ZERO
8792
}
8893

94+
fn checked_add(self, other: Self) -> Option<Self> {
95+
self.checked_add(other)
96+
}
97+
98+
fn checked_sub(self, other: Self) -> Option<Self> {
99+
self.checked_sub(other)
100+
}
101+
89102
fn wrapping_neg(self) -> Self {
90103
<Self>::wrapping_neg(self)
91104
}
@@ -132,7 +145,7 @@ macro_rules! int_impl {
132145
($ity:ty, $uty:ty) => {
133146
impl MinInt for $uty {
134147
type OtherSign = $ity;
135-
type UnsignedInt = $uty;
148+
type Unsigned = $uty;
136149

137150
const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
138151
const SIGNED: bool = Self::MIN != Self::ZERO;
@@ -144,10 +157,18 @@ macro_rules! int_impl {
144157
}
145158

146159
impl Int for $uty {
147-
fn unsigned(self) -> $uty {
160+
fn signed(self) -> $ity {
161+
self as $ity
162+
}
163+
164+
fn unsigned(self) -> Self {
148165
self
149166
}
150167

168+
fn abs(self) -> Self {
169+
unimplemented!()
170+
}
171+
151172
// It makes writing macros easier if this is implemented for both signed and unsigned
152173
#[allow(clippy::wrong_self_convention)]
153174
fn from_unsigned(me: $uty) -> Self {
@@ -163,7 +184,7 @@ macro_rules! int_impl {
163184

164185
impl MinInt for $ity {
165186
type OtherSign = $uty;
166-
type UnsignedInt = $uty;
187+
type Unsigned = $uty;
167188

168189
const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
169190
const SIGNED: bool = Self::MIN != Self::ZERO;
@@ -175,10 +196,18 @@ macro_rules! int_impl {
175196
}
176197

177198
impl Int for $ity {
199+
fn signed(self) -> Self {
200+
self
201+
}
202+
178203
fn unsigned(self) -> $uty {
179204
self as $uty
180205
}
181206

207+
fn abs(self) -> Self {
208+
self.abs()
209+
}
210+
182211
fn from_unsigned(me: $uty) -> Self {
183212
me as $ity
184213
}

0 commit comments

Comments
 (0)