Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 5b1e5f9

Browse files
committed
Add fmaf16 and fmaf128
1 parent 31a58aa commit 5b1e5f9

15 files changed

+139
-6
lines changed

crates/libm-macros/src/shared.rs

+14
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
9292
None,
9393
&["copysignf128"],
9494
),
95+
(
96+
// `(f16, f16, f16) -> f16`
97+
FloatTy::F16,
98+
Signature { args: &[Ty::F16, Ty::F16, Ty::F16], returns: &[Ty::F16] },
99+
None,
100+
&["fmaf16"],
101+
),
95102
(
96103
// `(f32, f32, f32) -> f32`
97104
FloatTy::F32,
@@ -106,6 +113,13 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
106113
None,
107114
&["fma"],
108115
),
116+
(
117+
// `(f128, f128, f128) -> f128`
118+
FloatTy::F128,
119+
Signature { args: &[Ty::F128, Ty::F128, Ty::F128], returns: &[Ty::F128] },
120+
None,
121+
&["fmaf128"],
122+
),
109123
(
110124
// `(f32) -> i32`
111125
FloatTy::F32,

crates/libm-test/src/mpfloat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ libm_macros::for_each_function! {
144144
expm1 | expm1f => exp_m1,
145145
fabs | fabsf => abs,
146146
fdim | fdimf => positive_diff,
147-
fma | fmaf => mul_add,
147+
fma | fmaf | fmaf16 | fmaf128 => mul_add,
148148
fmax | fmaxf => max,
149149
fmin | fminf => min,
150150
lgamma | lgammaf => ln_gamma,

crates/libm-test/src/precision.rs

+5
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,12 @@ fn bessel_prec_dropoff<F: Float>(
401401
None
402402
}
403403

404+
#[cfg(f16_enabled)]
405+
impl MaybeOverride<(f16, f16, f16)> for SpecialCase {}
404406
impl MaybeOverride<(f32, f32, f32)> for SpecialCase {}
405407
impl MaybeOverride<(f64, f64, f64)> for SpecialCase {}
408+
#[cfg(f128_enabled)]
409+
impl MaybeOverride<(f128, f128, f128)> for SpecialCase {}
410+
406411
impl MaybeOverride<(f32, i32)> for SpecialCase {}
407412
impl MaybeOverride<(f64, i32)> for SpecialCase {}

crates/libm-test/tests/compare_built_musl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ where
4747
libm_macros::for_each_function! {
4848
callback: musl_rand_tests,
4949
// Musl does not support `f16` and `f128` on all platforms.
50-
skip: [copysignf16, copysignf128, fabsf16, fabsf128],
50+
skip: [copysignf16, copysignf128, fabsf16, fabsf128, fmaf16, fmaf128],
5151
attributes: [
5252
#[cfg_attr(x86_no_sse, ignore)] // FIXME(correctness): wrong result on i586
5353
[exp10, exp10f, exp2, exp2f, rint]

crates/libm-test/tests/multiprecision.rs

+2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ libm_macros::for_each_function! {
136136
fdimf,
137137
fma,
138138
fmaf,
139+
fmaf16,
140+
fmaf128,
139141
fmax,
140142
fmaxf,
141143
fmin,

etc/function-definitions.json

+18-2
Original file line numberDiff line numberDiff line change
@@ -318,16 +318,32 @@
318318
"fma": {
319319
"sources": [
320320
"src/libm_helper.rs",
321-
"src/math/fma.rs"
321+
"src/math/fma.rs",
322+
"src/math/generic/fma.rs"
322323
],
323324
"type": "f64"
324325
},
325326
"fmaf": {
326327
"sources": [
327-
"src/math/fmaf.rs"
328+
"src/math/fmaf.rs",
329+
"src/math/generic/fma.rs"
328330
],
329331
"type": "f32"
330332
},
333+
"fmaf128": {
334+
"sources": [
335+
"src/math/fmaf128.rs",
336+
"src/math/generic/fma.rs"
337+
],
338+
"type": "f128"
339+
},
340+
"fmaf16": {
341+
"sources": [
342+
"src/math/fmaf16.rs",
343+
"src/math/generic/fma.rs"
344+
],
345+
"type": "f16"
346+
},
331347
"fmax": {
332348
"sources": [
333349
"src/libm_helper.rs",

etc/function-list.txt

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ floor
4747
floorf
4848
fma
4949
fmaf
50+
fmaf128
51+
fmaf16
5052
fmax
5153
fmaxf
5254
fmin

src/math/fmaf.rs

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ use super::fenv::{
4747
/// according to the rounding mode characterized by the value of FLT_ROUNDS.
4848
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
4949
pub fn fmaf(x: f32, y: f32, mut z: f32) -> f32 {
50+
if true {
51+
return super::generic::fma_big::<f32, f64>(x, y, z);
52+
}
53+
5054
let xy: f64;
5155
let mut result: f64;
5256
let mut ui: u64;

src/math/fmaf128.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
2+
pub fn fmaf128(x: f128, y: f128, z: f128) -> f128 {
3+
super::generic::fma(x, y, z)
4+
}

src/math/fmaf16.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
2+
pub fn fmaf16(x: f16, y: f16, z: f16) -> f16 {
3+
super::generic::fma_big::<f16, f32>(x, y, z)
4+
}

src/math/generic/fma.rs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#![allow(unused)]
2+
3+
use super::super::fenv::{
4+
FE_INEXACT, FE_TONEAREST, FE_UNDERFLOW, feclearexcept, fegetround, feraiseexcept, fetestexcept,
5+
};
6+
use super::super::{CastFrom, CastInto, Float, IntTy, MinInt};
7+
8+
/// Fused multiply add.
9+
pub fn fma<F: Float>(x: F, y: F, z: F) -> F {
10+
todo!()
11+
}
12+
13+
pub fn fma_big<F: Float, B: Float>(x: F, y: F, z: F) -> F
14+
where
15+
F: CastInto<B>,
16+
B: CastInto<F>,
17+
B::Int: CastInto<i32>,
18+
i32: CastFrom<i32>,
19+
B: CastFrom<F>,
20+
{
21+
let one = IntTy::<B>::ONE;
22+
23+
let xy: B;
24+
let mut result: B;
25+
let mut ui: B::Int;
26+
let e: i32;
27+
28+
xy = x.cast() * y.cast();
29+
result = xy + z.cast();
30+
ui = result.to_bits();
31+
e = i32::cast_from(ui >> F::SIG_BITS) & F::EXP_MAX as i32;
32+
let zb = B::cast_from(z);
33+
34+
let prec_diff = B::SIG_BITS - F::SIG_BITS;
35+
let excess_prec = ui & ((one << prec_diff) - one);
36+
let x = one << (prec_diff - 1);
37+
38+
// Common case: the larger precision is fine
39+
if excess_prec != x
40+
|| e == i32::cast_from(F::EXP_MAX)
41+
|| (result - xy == zb && result - zb == xy)
42+
|| fegetround() != FE_TONEAREST
43+
{
44+
// TODO: feclearexcept
45+
46+
return result.cast();
47+
}
48+
49+
let neg = ui & B::SIGN_MASK > IntTy::<B>::ZERO;
50+
let err = if neg == (zb > xy) { xy - result + zb } else { zb - result + xy };
51+
if neg == (err < B::ZERO) {
52+
ui += one;
53+
} else {
54+
ui -= one;
55+
}
56+
57+
B::from_bits(ui).cast()
58+
}

src/math/generic/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod copysign;
22
mod fabs;
3+
mod fma;
34

45
pub use copysign::copysign;
56
pub use fabs::fabs;
7+
pub use fma::{fma, fma_big};

src/math/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ use self::rem_pio2::rem_pio2;
114114
use self::rem_pio2_large::rem_pio2_large;
115115
use self::rem_pio2f::rem_pio2f;
116116
#[allow(unused_imports)]
117-
use self::support::{CastFrom, CastInto, DInt, Float, HInt, Int, MinInt};
117+
use self::support::{CastFrom, CastInto, DInt, Float, HInt, Int, IntTy, MinInt};
118118

119119
// Public modules
120120
mod acos;
@@ -336,19 +336,23 @@ cfg_if! {
336336
if #[cfg(f16_enabled)] {
337337
mod copysignf16;
338338
mod fabsf16;
339+
mod fmaf16;
339340

340341
pub use self::copysignf16::copysignf16;
341342
pub use self::fabsf16::fabsf16;
343+
pub use self::fmaf16::fmaf16;
342344
}
343345
}
344346

345347
cfg_if! {
346348
if #[cfg(f128_enabled)] {
347349
mod copysignf128;
348350
mod fabsf128;
351+
mod fmaf128;
349352

350353
pub use self::copysignf128::copysignf128;
351354
pub use self::fabsf128::fabsf128;
355+
pub use self::fmaf128::fmaf128;
352356
}
353357
}
354358

src/math/support/float_traits.rs

-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ pub trait Float:
147147
}
148148

149149
/// Access the associated `Int` type from a float (helper to avoid ambiguous associated types).
150-
#[allow(dead_code)]
151150
pub type IntTy<F> = <F as Float>::Int;
152151

153152
macro_rules! float_impl {

src/math/support/int_traits.rs

+19
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,22 @@ cast_into!(u64);
382382
cast_into!(i64);
383383
cast_into!(u128);
384384
cast_into!(i128);
385+
386+
cast_into!(f32; f64);
387+
cast_into!(f64; f32);
388+
389+
cfg_if! {
390+
if #[cfg(f16_enabled)] {
391+
cast_into!(f16; f32, f64);
392+
cast_into!(f32; f16);
393+
cast_into!(f64; f16);
394+
}
395+
}
396+
397+
cfg_if! {
398+
if #[cfg(f128_enabled)] {
399+
cast_into!(f128; f32, f64);
400+
cast_into!(f32; f128);
401+
cast_into!(f64; f128);
402+
}
403+
}

0 commit comments

Comments
 (0)