Skip to content

Commit f1ea040

Browse files
committed
Make fma a trait method on Float
1 parent 7672bd0 commit f1ea040

File tree

5 files changed

+30
-25
lines changed

5 files changed

+30
-25
lines changed

libm/crates/libm-test/src/f8_impl.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ impl Float for f8 {
7878
libm::generic::copysign(self, other)
7979
}
8080

81+
fn fma(self, _y: Self, _z: Self) -> Self {
82+
unimplemented!()
83+
}
84+
8185
fn normalize(_significand: Self::Int) -> (i32, Self::Int) {
8286
unimplemented!()
8387
}

libm/etc/function-definitions.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@
130130
"copysign": {
131131
"sources": [
132132
"src/math/copysign.rs",
133-
"src/math/generic/copysign.rs",
134-
"src/math/support/float_traits.rs"
133+
"src/math/generic/copysign.rs"
135134
],
136135
"type": "f64"
137136
},

libm/etc/update-api-list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
DIRECTORIES = [".github", "ci", "crates", "etc", "src"]
2525

2626
# These files do not trigger a retest.
27-
IGNORED_SOURCES = ["src/libm_helper.rs"]
27+
IGNORED_SOURCES = ["src/libm_helper.rs", "src/math/support/float_traits.rs"]
2828

2929
IndexTy: TypeAlias = dict[str, dict[str, Any]]
3030
"""Type of the `index` item in rustdoc's JSON output"""

libm/src/math/cbrt.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
103103
* and rr an approximation of 1/zz. We now perform another iteration of
104104
* Newton-Raphson, this time with a linear approximation only. */
105105
y2 = y * y;
106-
let mut y2l: f64 = fmaf64(y, y, -y2);
106+
let mut y2l: f64 = y.fma(y, -y2);
107107

108108
/* y2 + y2l = y^2 exactly */
109109
let mut y3: f64 = y2 * y;
110-
let mut y3l: f64 = fmaf64(y, y2, -y3) + y * y2l;
110+
let mut y3l: f64 = y.fma(y2, -y3) + y * y2l;
111111

112112
/* y3 + y3l approximates y^3 with about 106 bits of accuracy */
113113
h = ((y3 - zz) + y3l) * rr;
@@ -132,9 +132,9 @@ pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
132132
cold_path();
133133

134134
y2 = y1 * y1;
135-
y2l = fmaf64(y1, y1, -y2);
135+
y2l = y1.fma(y1, -y2);
136136
y3 = y2 * y1;
137-
y3l = fmaf64(y1, y2, -y3) + y1 * y2l;
137+
y3l = y1.fma(y2, -y3) + y1 * y2l;
138138
h = ((y3 - zz) + y3l) * rr;
139139
dy = h * (y1 * u0);
140140
y = y1 - dy;
@@ -198,18 +198,6 @@ pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
198198
FpResult::ok(f64::from_bits(cvt3))
199199
}
200200

201-
fn fmaf64(x: f64, y: f64, z: f64) -> f64 {
202-
#[cfg(intrinsics_enabled)]
203-
{
204-
return unsafe { core::intrinsics::fmaf64(x, y, z) };
205-
}
206-
207-
#[cfg(not(intrinsics_enabled))]
208-
{
209-
return super::fma(x, y, z);
210-
}
211-
}
212-
213201
#[cfg(test)]
214202
mod tests {
215203
use super::*;

libm/src/math/support/float_traits.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,11 @@ pub trait Float:
160160
fn abs(self) -> Self;
161161

162162
/// Returns a number composed of the magnitude of self and the sign of sign.
163-
#[allow(dead_code)]
164163
fn copysign(self, other: Self) -> Self;
165164

165+
/// Fused multiply add, rounding once.
166+
fn fma(self, y: Self, z: Self) -> Self;
167+
166168
/// Returns (normalized exponent, normalized significand)
167169
#[allow(dead_code)]
168170
fn normalize(significand: Self::Int) -> (i32, Self::Int);
@@ -184,7 +186,9 @@ macro_rules! float_impl {
184186
$sity:ident,
185187
$bits:expr,
186188
$significand_bits:expr,
187-
$from_bits:path
189+
$from_bits:path,
190+
$fma_fn:ident,
191+
$fma_intrinsic:ident
188192
) => {
189193
impl Float for $ty {
190194
type Int = $ity;
@@ -252,6 +256,16 @@ macro_rules! float_impl {
252256
}
253257
}
254258
}
259+
fn fma(self, y: Self, z: Self) -> Self {
260+
cfg_if! {
261+
// fma is not yet available in `core`
262+
if #[cfg(intrinsics_enabled)] {
263+
unsafe{ core::intrinsics::$fma_intrinsic(self, y, z) }
264+
} else {
265+
super::super::$fma_fn(self, y, z)
266+
}
267+
}
268+
}
255269
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
256270
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
257271
(1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
@@ -261,11 +275,11 @@ macro_rules! float_impl {
261275
}
262276

263277
#[cfg(f16_enabled)]
264-
float_impl!(f16, u16, i16, 16, 10, f16::from_bits);
265-
float_impl!(f32, u32, i32, 32, 23, f32_from_bits);
266-
float_impl!(f64, u64, i64, 64, 52, f64_from_bits);
278+
float_impl!(f16, u16, i16, 16, 10, f16::from_bits, fmaf16, fmaf16);
279+
float_impl!(f32, u32, i32, 32, 23, f32_from_bits, fmaf, fmaf32);
280+
float_impl!(f64, u64, i64, 64, 52, f64_from_bits, fma, fmaf64);
267281
#[cfg(f128_enabled)]
268-
float_impl!(f128, u128, i128, 128, 112, f128::from_bits);
282+
float_impl!(f128, u128, i128, 128, 112, f128::from_bits, fmaf128, fmaf128);
269283

270284
/* FIXME(msrv): vendor some things that are not const stable at our MSRV */
271285

0 commit comments

Comments
 (0)