Skip to content

Commit ad9a84a

Browse files
committed
Eliminate the use of public_test_dep! for a third time
Replace `public_test_dep!` by placing optionally public items into new modules, then controlling what is exported with the `public-test-deps` feature. This is nicer for automatic formatting and diagnostics. This is a reland of 2e2a925 ("Eliminate the use of `public_test_dep!`"), which was reverted in 47e50fd ('Revert "Eliminate the use of..."') due to a bug exposed at [1], reapplied in d4abaf4 because the issue should have been fixed in [2], then reverted again in f6eef07 because [2] did not actually fix the issue. [3] has landed in rust-lang/rust since then, which should resolve the last problem remaining after [2]. So, apply this change for what is hopefully the final time. [1]: rust-lang/rust#128691 [2]: rust-lang/rust#135278 [3]: rust-lang/rust#135501
1 parent f322090 commit ad9a84a

File tree

8 files changed

+763
-772
lines changed

8 files changed

+763
-772
lines changed

src/float/mod.rs

+5-190
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use core::ops;
2-
3-
use crate::int::{DInt, Int, MinInt};
4-
51
pub mod add;
62
pub mod cmp;
73
pub mod conv;
@@ -10,192 +6,11 @@ pub mod extend;
106
pub mod mul;
117
pub mod pow;
128
pub mod sub;
9+
pub(crate) mod traits;
1310
pub mod trunc;
1411

15-
/// Wrapper to extract the integer type half of the float's size
16-
pub(crate) type HalfRep<F> = <<F as Float>::Int as DInt>::H;
17-
18-
public_test_dep! {
19-
/// Trait for some basic operations on floats
20-
#[allow(dead_code)]
21-
pub(crate) trait Float:
22-
Copy
23-
+ core::fmt::Debug
24-
+ PartialEq
25-
+ PartialOrd
26-
+ ops::AddAssign
27-
+ ops::MulAssign
28-
+ ops::Add<Output = Self>
29-
+ ops::Sub<Output = Self>
30-
+ ops::Div<Output = Self>
31-
+ ops::Rem<Output = Self>
32-
{
33-
/// A uint of the same width as the float
34-
type Int: Int<OtherSign = Self::SignedInt, UnsignedInt = Self::Int>;
35-
36-
/// A int of the same width as the float
37-
type SignedInt: Int + MinInt<OtherSign = Self::Int, UnsignedInt = Self::Int>;
38-
39-
/// An int capable of containing the exponent bits plus a sign bit. This is signed.
40-
type ExpInt: Int;
41-
42-
const ZERO: Self;
43-
const ONE: Self;
44-
45-
/// The bitwidth of the float type.
46-
const BITS: u32;
47-
48-
/// The bitwidth of the significand.
49-
const SIG_BITS: u32;
50-
51-
/// The bitwidth of the exponent.
52-
const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
53-
54-
/// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
55-
/// representation.
56-
///
57-
/// This is in the rightmost position, use `EXP_MASK` for the shifted value.
58-
const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
59-
60-
/// The exponent bias value.
61-
const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
62-
63-
/// A mask for the sign bit.
64-
const SIGN_MASK: Self::Int;
65-
66-
/// A mask for the significand.
67-
const SIG_MASK: Self::Int;
68-
69-
/// The implicit bit of the float format.
70-
const IMPLICIT_BIT: Self::Int;
71-
72-
/// A mask for the exponent.
73-
const EXP_MASK: Self::Int;
74-
75-
/// Returns `self` transmuted to `Self::Int`
76-
fn to_bits(self) -> Self::Int;
77-
78-
/// Returns `self` transmuted to `Self::SignedInt`
79-
fn to_bits_signed(self) -> Self::SignedInt;
80-
81-
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
82-
/// represented in multiple different ways. This method returns `true` if two NaNs are
83-
/// compared.
84-
fn eq_repr(self, rhs: Self) -> bool;
85-
86-
/// Returns true if the sign is negative
87-
fn is_sign_negative(self) -> bool;
88-
89-
/// Returns the exponent, not adjusting for bias.
90-
fn exp(self) -> Self::ExpInt;
91-
92-
/// Returns the significand with no implicit bit (or the "fractional" part)
93-
fn frac(self) -> Self::Int;
94-
95-
/// Returns the significand with implicit bit
96-
fn imp_frac(self) -> Self::Int;
97-
98-
/// Returns a `Self::Int` transmuted back to `Self`
99-
fn from_bits(a: Self::Int) -> Self;
100-
101-
/// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
102-
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self;
103-
104-
fn abs(self) -> Self {
105-
let abs_mask = !Self::SIGN_MASK ;
106-
Self::from_bits(self.to_bits() & abs_mask)
107-
}
108-
109-
/// Returns (normalized exponent, normalized significand)
110-
fn normalize(significand: Self::Int) -> (i32, Self::Int);
111-
112-
/// Returns if `self` is subnormal
113-
fn is_subnormal(self) -> bool;
114-
}
115-
}
116-
117-
macro_rules! float_impl {
118-
($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {
119-
impl Float for $ty {
120-
type Int = $ity;
121-
type SignedInt = $sity;
122-
type ExpInt = $expty;
123-
124-
const ZERO: Self = 0.0;
125-
const ONE: Self = 1.0;
126-
127-
const BITS: u32 = $bits;
128-
const SIG_BITS: u32 = $significand_bits;
129-
130-
const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
131-
const SIG_MASK: Self::Int = (1 << Self::SIG_BITS) - 1;
132-
const IMPLICIT_BIT: Self::Int = 1 << Self::SIG_BITS;
133-
const EXP_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIG_MASK);
134-
135-
fn to_bits(self) -> Self::Int {
136-
self.to_bits()
137-
}
138-
fn to_bits_signed(self) -> Self::SignedInt {
139-
self.to_bits() as Self::SignedInt
140-
}
141-
fn eq_repr(self, rhs: Self) -> bool {
142-
#[cfg(feature = "mangled-names")]
143-
fn is_nan(x: $ty) -> bool {
144-
// When using mangled-names, the "real" compiler-builtins might not have the
145-
// necessary builtin (__unordtf2) to test whether `f128` is NaN.
146-
// FIXME(f16_f128): Remove once the nightly toolchain has the __unordtf2 builtin
147-
// x is NaN if all the bits of the exponent are set and the significand is non-0
148-
x.to_bits() & $ty::EXP_MASK == $ty::EXP_MASK && x.to_bits() & $ty::SIG_MASK != 0
149-
}
150-
#[cfg(not(feature = "mangled-names"))]
151-
fn is_nan(x: $ty) -> bool {
152-
x.is_nan()
153-
}
154-
if is_nan(self) && is_nan(rhs) {
155-
true
156-
} else {
157-
self.to_bits() == rhs.to_bits()
158-
}
159-
}
160-
fn is_sign_negative(self) -> bool {
161-
self.is_sign_negative()
162-
}
163-
fn exp(self) -> Self::ExpInt {
164-
((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
165-
}
166-
fn frac(self) -> Self::Int {
167-
self.to_bits() & Self::SIG_MASK
168-
}
169-
fn imp_frac(self) -> Self::Int {
170-
self.frac() | Self::IMPLICIT_BIT
171-
}
172-
fn from_bits(a: Self::Int) -> Self {
173-
Self::from_bits(a)
174-
}
175-
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self {
176-
Self::from_bits(
177-
((negative as Self::Int) << (Self::BITS - 1))
178-
| ((exponent << Self::SIG_BITS) & Self::EXP_MASK)
179-
| (significand & Self::SIG_MASK),
180-
)
181-
}
182-
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
183-
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
184-
(
185-
1i32.wrapping_sub(shift as i32),
186-
significand << shift as Self::Int,
187-
)
188-
}
189-
fn is_subnormal(self) -> bool {
190-
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
191-
}
192-
}
193-
};
194-
}
12+
#[cfg(not(feature = "public-test-deps"))]
13+
pub(crate) use traits::{Float, HalfRep};
19514

196-
#[cfg(f16_enabled)]
197-
float_impl!(f16, u16, i16, i8, 16, 10);
198-
float_impl!(f32, u32, i32, i16, 32, 23);
199-
float_impl!(f64, u64, i64, i16, 64, 52);
200-
#[cfg(f128_enabled)]
201-
float_impl!(f128, u128, i128, i16, 128, 112);
15+
#[cfg(feature = "public-test-deps")]
16+
pub use traits::{Float, HalfRep};

src/float/traits.rs

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
use core::ops;
2+
3+
use crate::int::{DInt, Int, MinInt};
4+
5+
/// Wrapper to extract the integer type half of the float's size
6+
pub type HalfRep<F> = <<F as Float>::Int as DInt>::H;
7+
8+
/// Trait for some basic operations on floats
9+
#[allow(dead_code)]
10+
pub trait Float:
11+
Copy
12+
+ core::fmt::Debug
13+
+ PartialEq
14+
+ PartialOrd
15+
+ ops::AddAssign
16+
+ ops::MulAssign
17+
+ ops::Add<Output = Self>
18+
+ ops::Sub<Output = Self>
19+
+ ops::Div<Output = Self>
20+
+ ops::Rem<Output = Self>
21+
{
22+
/// A uint of the same width as the float
23+
type Int: Int<OtherSign = Self::SignedInt, UnsignedInt = Self::Int>;
24+
25+
/// A int of the same width as the float
26+
type SignedInt: Int + MinInt<OtherSign = Self::Int, UnsignedInt = Self::Int>;
27+
28+
/// An int capable of containing the exponent bits plus a sign bit. This is signed.
29+
type ExpInt: Int;
30+
31+
const ZERO: Self;
32+
const ONE: Self;
33+
34+
/// The bitwidth of the float type.
35+
const BITS: u32;
36+
37+
/// The bitwidth of the significand.
38+
const SIG_BITS: u32;
39+
40+
/// The bitwidth of the exponent.
41+
const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
42+
43+
/// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
44+
/// representation.
45+
///
46+
/// This is in the rightmost position, use `EXP_MASK` for the shifted value.
47+
const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
48+
49+
/// The exponent bias value.
50+
const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
51+
52+
/// A mask for the sign bit.
53+
const SIGN_MASK: Self::Int;
54+
55+
/// A mask for the significand.
56+
const SIG_MASK: Self::Int;
57+
58+
/// The implicit bit of the float format.
59+
const IMPLICIT_BIT: Self::Int;
60+
61+
/// A mask for the exponent.
62+
const EXP_MASK: Self::Int;
63+
64+
/// Returns `self` transmuted to `Self::Int`
65+
fn to_bits(self) -> Self::Int;
66+
67+
/// Returns `self` transmuted to `Self::SignedInt`
68+
fn to_bits_signed(self) -> Self::SignedInt;
69+
70+
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
71+
/// represented in multiple different ways. This method returns `true` if two NaNs are
72+
/// compared.
73+
fn eq_repr(self, rhs: Self) -> bool;
74+
75+
/// Returns true if the sign is negative
76+
fn is_sign_negative(self) -> bool;
77+
78+
/// Returns the exponent, not adjusting for bias.
79+
fn exp(self) -> Self::ExpInt;
80+
81+
/// Returns the significand with no implicit bit (or the "fractional" part)
82+
fn frac(self) -> Self::Int;
83+
84+
/// Returns the significand with implicit bit
85+
fn imp_frac(self) -> Self::Int;
86+
87+
/// Returns a `Self::Int` transmuted back to `Self`
88+
fn from_bits(a: Self::Int) -> Self;
89+
90+
/// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
91+
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self;
92+
93+
fn abs(self) -> Self {
94+
let abs_mask = !Self::SIGN_MASK;
95+
Self::from_bits(self.to_bits() & abs_mask)
96+
}
97+
98+
/// Returns (normalized exponent, normalized significand)
99+
fn normalize(significand: Self::Int) -> (i32, Self::Int);
100+
101+
/// Returns if `self` is subnormal
102+
fn is_subnormal(self) -> bool;
103+
}
104+
105+
macro_rules! float_impl {
106+
($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {
107+
impl Float for $ty {
108+
type Int = $ity;
109+
type SignedInt = $sity;
110+
type ExpInt = $expty;
111+
112+
const ZERO: Self = 0.0;
113+
const ONE: Self = 1.0;
114+
115+
const BITS: u32 = $bits;
116+
const SIG_BITS: u32 = $significand_bits;
117+
118+
const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
119+
const SIG_MASK: Self::Int = (1 << Self::SIG_BITS) - 1;
120+
const IMPLICIT_BIT: Self::Int = 1 << Self::SIG_BITS;
121+
const EXP_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIG_MASK);
122+
123+
fn to_bits(self) -> Self::Int {
124+
self.to_bits()
125+
}
126+
fn to_bits_signed(self) -> Self::SignedInt {
127+
self.to_bits() as Self::SignedInt
128+
}
129+
fn eq_repr(self, rhs: Self) -> bool {
130+
#[cfg(feature = "mangled-names")]
131+
fn is_nan(x: $ty) -> bool {
132+
// When using mangled-names, the "real" compiler-builtins might not have the
133+
// necessary builtin (__unordtf2) to test whether `f128` is NaN.
134+
// FIXME(f16_f128): Remove once the nightly toolchain has the __unordtf2 builtin
135+
// x is NaN if all the bits of the exponent are set and the significand is non-0
136+
x.to_bits() & $ty::EXP_MASK == $ty::EXP_MASK && x.to_bits() & $ty::SIG_MASK != 0
137+
}
138+
#[cfg(not(feature = "mangled-names"))]
139+
fn is_nan(x: $ty) -> bool {
140+
x.is_nan()
141+
}
142+
if is_nan(self) && is_nan(rhs) {
143+
true
144+
} else {
145+
self.to_bits() == rhs.to_bits()
146+
}
147+
}
148+
fn is_sign_negative(self) -> bool {
149+
self.is_sign_negative()
150+
}
151+
fn exp(self) -> Self::ExpInt {
152+
((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
153+
}
154+
fn frac(self) -> Self::Int {
155+
self.to_bits() & Self::SIG_MASK
156+
}
157+
fn imp_frac(self) -> Self::Int {
158+
self.frac() | Self::IMPLICIT_BIT
159+
}
160+
fn from_bits(a: Self::Int) -> Self {
161+
Self::from_bits(a)
162+
}
163+
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self {
164+
Self::from_bits(
165+
((negative as Self::Int) << (Self::BITS - 1))
166+
| ((exponent << Self::SIG_BITS) & Self::EXP_MASK)
167+
| (significand & Self::SIG_MASK),
168+
)
169+
}
170+
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
171+
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
172+
(
173+
1i32.wrapping_sub(shift as i32),
174+
significand << shift as Self::Int,
175+
)
176+
}
177+
fn is_subnormal(self) -> bool {
178+
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
179+
}
180+
}
181+
};
182+
}
183+
184+
#[cfg(f16_enabled)]
185+
float_impl!(f16, u16, i16, i8, 16, 10);
186+
float_impl!(f32, u32, i32, i16, 32, 23);
187+
float_impl!(f64, u64, i64, i16, 64, 52);
188+
#[cfg(f128_enabled)]
189+
float_impl!(f128, u128, i128, i16, 128, 112);

0 commit comments

Comments
 (0)