Skip to content

Commit 54ef3d9

Browse files
committed
Use our generic implementations to add math to apfloat
1 parent b6e15ef commit 54ef3d9

File tree

4 files changed

+281
-2
lines changed

4 files changed

+281
-2
lines changed

libm/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ edition = "2021"
1313
rust-version = "1.63"
1414

1515
[features]
16-
default = ["arch"]
16+
default = ["arch", "apfloat"]
17+
18+
apfloat = ["dep:rustc_apfloat"]
1719

1820
# Enable architecture-specific features such as SIMD or assembly routines.
1921
arch = []
@@ -39,6 +41,9 @@ unstable-float = []
3941
# hard float operations.
4042
force-soft-floats = []
4143

44+
[dependencies]
45+
rustc_apfloat = { version = "0.2.2", optional = true }
46+
4247
[dev-dependencies]
4348
no-panic = "0.1.35"
4449

libm/src/math/apfloat/mod.rs

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
use core::mem::transmute;
2+
use core::ops;
3+
4+
use rustc_apfloat::Float as ApFloat;
5+
#[cfg(f16_enabled)]
6+
use rustc_apfloat::ieee::Half;
7+
#[cfg(f128_enabled)]
8+
use rustc_apfloat::ieee::Quad;
9+
use rustc_apfloat::ieee::{Double, Single};
10+
11+
use super::generic::SqrtHelper;
12+
use crate::support::Float;
13+
14+
macro_rules! fake_float {
15+
($FTy:ty, $WrapTy:ident, $ApTy:ty, $one:ident) => {
16+
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq)]
17+
pub struct $WrapTy($ApTy);
18+
19+
impl ops::Add for $WrapTy {
20+
type Output = Self;
21+
22+
fn add(self, rhs: Self) -> Self::Output {
23+
Self((self.0 + rhs.0).value)
24+
}
25+
}
26+
27+
impl ops::AddAssign for $WrapTy {
28+
fn add_assign(&mut self, rhs: Self) {
29+
self.0 += rhs.0
30+
}
31+
}
32+
33+
impl ops::Sub for $WrapTy {
34+
type Output = Self;
35+
36+
fn sub(self, rhs: Self) -> Self::Output {
37+
Self((self.0 - rhs.0).value)
38+
}
39+
}
40+
41+
impl ops::SubAssign for $WrapTy {
42+
fn sub_assign(&mut self, rhs: Self) {
43+
self.0 -= rhs.0
44+
}
45+
}
46+
47+
impl ops::Mul for $WrapTy {
48+
type Output = Self;
49+
50+
fn mul(self, rhs: Self) -> Self::Output {
51+
Self((self.0 * rhs.0).value)
52+
}
53+
}
54+
55+
impl ops::MulAssign for $WrapTy {
56+
fn mul_assign(&mut self, rhs: Self) {
57+
self.0 *= rhs.0
58+
}
59+
}
60+
61+
impl ops::Div for $WrapTy {
62+
type Output = Self;
63+
64+
fn div(self, rhs: Self) -> Self::Output {
65+
Self((self.0 / rhs.0).value)
66+
}
67+
}
68+
69+
impl ops::Rem for $WrapTy {
70+
type Output = Self;
71+
72+
fn rem(self, rhs: Self) -> Self::Output {
73+
Self((self.0 % rhs.0).value)
74+
}
75+
}
76+
77+
impl ops::Neg for $WrapTy {
78+
type Output = Self;
79+
80+
fn neg(self) -> Self::Output {
81+
Self(-self.0)
82+
}
83+
}
84+
85+
impl Float for $WrapTy {
86+
type Int = <$FTy as Float>::Int;
87+
type SignedInt = <$FTy as Float>::SignedInt;
88+
89+
const ZERO: Self = $WrapTy(<$ApTy>::ZERO);
90+
const INFINITY: Self = $WrapTy(<$ApTy>::INFINITY);
91+
const NAN: Self = $WrapTy(<$ApTy>::NAN);
92+
const ONE: Self = $WrapTy($one);
93+
94+
// TODO these are all garbage
95+
const NEG_ZERO: Self = $WrapTy(<$ApTy>::ZERO);
96+
const NEG_ONE: Self = $WrapTy(<$ApTy>::ZERO);
97+
const NEG_INFINITY: Self = $WrapTy(<$ApTy>::ZERO);
98+
const NEG_NAN: Self = $WrapTy(<$ApTy>::ZERO);
99+
const MAX: Self = $WrapTy(<$ApTy>::ZERO);
100+
const MIN: Self = $WrapTy(<$ApTy>::ZERO);
101+
const EPSILON: Self = $WrapTy(<$ApTy>::ZERO);
102+
const PI: Self = $WrapTy(<$ApTy>::ZERO);
103+
const NEG_PI: Self = $WrapTy(<$ApTy>::ZERO);
104+
const FRAC_PI_2: Self = $WrapTy(<$ApTy>::ZERO);
105+
const MIN_POSITIVE_NORMAL: Self = $WrapTy(<$ApTy>::ZERO);
106+
107+
const BITS: u32 = <$ApTy>::BITS as u32;
108+
const SIG_BITS: u32 = <$FTy>::SIG_BITS;
109+
const SIGN_MASK: Self::Int = <$FTy>::SIGN_MASK;
110+
const SIG_MASK: Self::Int = <$FTy>::SIG_MASK;
111+
const EXP_MASK: Self::Int = <$FTy>::EXP_MASK;
112+
const IMPLICIT_BIT: Self::Int = <$FTy>::IMPLICIT_BIT;
113+
114+
fn to_bits(self) -> Self::Int {
115+
self.0.to_bits().try_into().unwrap()
116+
}
117+
118+
fn is_nan(self) -> bool {
119+
self.0.is_nan()
120+
}
121+
122+
fn is_infinite(self) -> bool {
123+
self.0.is_infinite()
124+
}
125+
126+
fn is_sign_negative(self) -> bool {
127+
self.0.is_negative()
128+
}
129+
130+
fn from_bits(a: Self::Int) -> Self {
131+
Self(<$ApTy>::from_bits(a.into()))
132+
}
133+
134+
fn abs(self) -> Self {
135+
Self(self.0.abs())
136+
}
137+
138+
fn copysign(self, other: Self) -> Self {
139+
Self(self.0.copy_sign(other.0))
140+
}
141+
142+
fn fma(self, y: Self, z: Self) -> Self {
143+
Self(self.0.mul_add(y.0, z.0).unwrap())
144+
}
145+
146+
fn normalize(_significand: Self::Int) -> (i32, Self::Int) {
147+
todo!()
148+
}
149+
}
150+
151+
impl SqrtHelper for $WrapTy {
152+
type ISet1 = <$FTy as SqrtHelper>::ISet1;
153+
154+
type ISet2 = <$FTy as SqrtHelper>::ISet2;
155+
156+
const FINAL_ROUNDS: u32 = <$FTy>::FINAL_ROUNDS;
157+
}
158+
159+
impl $WrapTy {
160+
pub fn sqrt(self) -> Self {
161+
crate::math::generic::sqrt(self)
162+
}
163+
164+
pub fn fdim(self, other: Self) -> Self {
165+
crate::math::generic::fdim(self, other)
166+
}
167+
}
168+
};
169+
}
170+
171+
// Curesed, apfloat needs const constructors
172+
#[cfg(f16_enabled)]
173+
const F16_ONE: Half = unsafe { transmute::<[u128; 2], _>([1024, 159766282927565248636202778624]) };
174+
const F32_ONE: Single =
175+
unsafe { transmute::<[u128; 2], _>([8388608, 113833225510946001209798950912]) };
176+
const F64_ONE: Double =
177+
unsafe { transmute::<[u128; 2], _>([4503599627370496, 112524264621533123623119749120]) };
178+
#[cfg(f128_enabled)]
179+
const F128_ONE: Quad = unsafe {
180+
transmute::<[u128; 2], _>([
181+
5192296858534827628530496329220096,
182+
112524268163307985775353659392,
183+
])
184+
};
185+
186+
#[cfg(f16_enabled)]
187+
fake_float!(f16, ApF16, Half, F16_ONE);
188+
fake_float!(f32, ApF32, Single, F32_ONE);
189+
fake_float!(f64, ApF64, Double, F64_ONE);
190+
#[cfg(f128_enabled)]
191+
fake_float!(f128, ApF128, Quad, F128_ONE);
192+
193+
#[cfg(test)]
194+
mod tests {
195+
extern crate std;
196+
use super::*;
197+
198+
#[test]
199+
#[cfg(f16_enabled)]
200+
fn test_f16() {
201+
let check_sqrt = |x: f16| {
202+
let lhs = ApF16(Half::from_bits(x.to_bits().into())).sqrt();
203+
let rhs = ApF16(Half::from_bits(x.sqrt().to_bits().into()));
204+
if lhs.is_nan() && rhs.is_nan() {
205+
return;
206+
}
207+
assert_eq!(lhs, rhs);
208+
};
209+
210+
check_sqrt(0.0);
211+
check_sqrt(4.0);
212+
check_sqrt(1234.23);
213+
check_sqrt(-2.0);
214+
check_sqrt(f16::MAX);
215+
}
216+
217+
#[test]
218+
fn test_f32() {
219+
let check_sqrt = |x: f32| {
220+
let lhs = ApF32(Single::from_bits(x.to_bits().into())).sqrt();
221+
let rhs = ApF32(Single::from_bits(x.sqrt().to_bits().into()));
222+
if lhs.is_nan() && rhs.is_nan() {
223+
return;
224+
}
225+
assert_eq!(lhs, rhs);
226+
};
227+
228+
check_sqrt(0.0);
229+
check_sqrt(4.0);
230+
check_sqrt(123421.23423);
231+
check_sqrt(-2.0);
232+
check_sqrt(f32::MAX);
233+
}
234+
235+
#[test]
236+
fn test_f64() {
237+
let check_sqrt = |x: f64| {
238+
let lhs = ApF64(Double::from_bits(x.to_bits().into())).sqrt();
239+
let rhs = ApF64(Double::from_bits(x.sqrt().to_bits().into()));
240+
if lhs.is_nan() && rhs.is_nan() {
241+
return;
242+
}
243+
assert_eq!(lhs, rhs);
244+
};
245+
246+
check_sqrt(0.0);
247+
check_sqrt(4.0);
248+
check_sqrt(12334421.23234423);
249+
check_sqrt(-2.0);
250+
check_sqrt(f64::MAX);
251+
}
252+
253+
#[test]
254+
#[cfg(f128_enabled)]
255+
fn test_f128() {
256+
let check_sqrt = |x: f128| {
257+
let lhs = ApF128(Quad::from_bits(x.to_bits().into())).sqrt();
258+
let rhs = ApF128(Quad::from_bits(x.sqrt().to_bits().into()));
259+
if lhs.is_nan() && rhs.is_nan() {
260+
return;
261+
}
262+
assert_eq!(lhs, rhs);
263+
};
264+
265+
check_sqrt(0.0);
266+
check_sqrt(4.0);
267+
check_sqrt(12342110234.23123432423);
268+
check_sqrt(-2.0);
269+
check_sqrt(f128::MAX);
270+
}
271+
}

libm/src/math/generic/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ pub use fmod::fmod;
3838
pub use rint::rint_round;
3939
pub use round::round;
4040
pub use scalbn::scalbn;
41-
pub use sqrt::sqrt;
41+
pub use sqrt::{SqrtHelper, sqrt};
4242
pub use trunc::trunc;

libm/src/math/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ cfg_if! {
9191
}
9292
}
9393

94+
#[cfg(feature = "apfloat")]
95+
pub mod apfloat;
96+
9497
// Private modules
9598
mod arch;
9699
mod expo2;

0 commit comments

Comments
 (0)