Skip to content

Commit 4845a7e

Browse files
authored
Merge pull request rust-lang#347 from tgross35/numeric-traits
Add float and integer traits from compiler-builtins
2 parents d9bfeca + e86594b commit 4845a7e

File tree

4 files changed

+518
-0
lines changed

4 files changed

+518
-0
lines changed

src/math/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ use self::k_tanf::k_tanf;
105105
use self::rem_pio2::rem_pio2;
106106
use self::rem_pio2_large::rem_pio2_large;
107107
use self::rem_pio2f::rem_pio2f;
108+
#[allow(unused_imports)]
109+
use self::support::{CastFrom, CastInto, DInt, Float, HInt, Int, MinInt};
108110

109111
// Public modules
110112
mod acos;

src/math/support/float_traits.rs

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

0 commit comments

Comments
 (0)