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

Add fminf16, fmaxf16, fminf128, and fmaxf128 #466

Merged
merged 2 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/libm-macros/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
FloatTy::F16,
Signature { args: &[Ty::F16, Ty::F16], returns: &[Ty::F16] },
None,
&["copysignf16", "fdimf16"],
&["copysignf16", "fdimf16", "fmaxf16", "fminf16"],
),
(
// `(f32, f32) -> f32`
Expand Down Expand Up @@ -90,7 +90,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
FloatTy::F128,
Signature { args: &[Ty::F128, Ty::F128], returns: &[Ty::F128] },
None,
&["copysignf128", "fdimf128"],
&["copysignf128", "fdimf128", "fmaxf128", "fminf128"],
),
(
// `(f32, f32, f32) -> f32`
Expand Down
4 changes: 4 additions & 0 deletions crates/libm-test/benches/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ libm_macros::for_each_function! {
| fdimf16
| floorf128
| floorf16
| fmaxf128
| fmaxf16
| fminf128
| fminf16
| rintf128
| rintf16
| roundf128
Expand Down
4 changes: 2 additions & 2 deletions crates/libm-test/src/mpfloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ libm_macros::for_each_function! {
fabs | fabsf => abs,
fdim | fdimf | fdimf16 | fdimf128 => positive_diff,
fma | fmaf => mul_add,
fmax | fmaxf => max,
fmin | fminf => min,
fmax | fmaxf | fmaxf16 | fmaxf128 => max,
fmin | fminf | fminf16 | fminf128 => min,
lgamma | lgammaf => ln_gamma,
log | logf => ln,
log1p | log1pf => ln_1p,
Expand Down
4 changes: 4 additions & 0 deletions crates/libm-test/tests/compare_built_musl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ libm_macros::for_each_function! {
fdimf16,
floorf128,
floorf16,
fmaxf128,
fmaxf16,
fminf128,
fminf16,
rintf128,
rintf16,
roundf128,
Expand Down
4 changes: 4 additions & 0 deletions crates/util/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
| fdimf16
| floorf128
| floorf16
| fmaxf128
| fmaxf16
| fminf128
| fminf16
| rintf128
| rintf16
| roundf128
Expand Down
40 changes: 36 additions & 4 deletions etc/function-definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -379,29 +379,61 @@
"fmax": {
"sources": [
"src/libm_helper.rs",
"src/math/fmax.rs"
"src/math/fmax.rs",
"src/math/generic/fmax.rs"
],
"type": "f64"
},
"fmaxf": {
"sources": [
"src/math/fmaxf.rs"
"src/math/fmaxf.rs",
"src/math/generic/fmax.rs"
],
"type": "f32"
},
"fmaxf128": {
"sources": [
"src/math/fmaxf128.rs",
"src/math/generic/fmax.rs"
],
"type": "f128"
},
"fmaxf16": {
"sources": [
"src/math/fmaxf16.rs",
"src/math/generic/fmax.rs"
],
"type": "f16"
},
"fmin": {
"sources": [
"src/libm_helper.rs",
"src/math/fmin.rs"
"src/math/fmin.rs",
"src/math/generic/fmin.rs"
],
"type": "f64"
},
"fminf": {
"sources": [
"src/math/fminf.rs"
"src/math/fminf.rs",
"src/math/generic/fmin.rs"
],
"type": "f32"
},
"fminf128": {
"sources": [
"src/math/fminf128.rs",
"src/math/generic/fmin.rs"
],
"type": "f128"
},
"fminf16": {
"sources": [
"src/math/fminf16.rs",
"src/math/generic/fmin.rs"
],
"type": "f16"
},
"fmod": {
"sources": [
"src/libm_helper.rs",
Expand Down
4 changes: 4 additions & 0 deletions etc/function-list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ fma
fmaf
fmax
fmaxf
fmaxf128
fmaxf16
fmin
fminf
fminf128
fminf16
fmod
fmodf
frexp
Expand Down
11 changes: 2 additions & 9 deletions src/math/fmax.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/// Return the greater of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmax(x: f64, y: f64) -> f64 {
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if x.is_nan() || x < y { y } else { x }) * 1.0
super::generic::fmax(x, y)
}
11 changes: 2 additions & 9 deletions src/math/fmaxf.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/// Return the greater of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmaxf(x: f32, y: f32) -> f32 {
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if x.is_nan() || x < y { y } else { x }) * 1.0
super::generic::fmax(x, y)
}
5 changes: 5 additions & 0 deletions src/math/fmaxf128.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Return the greater of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmaxf128(x: f128, y: f128) -> f128 {
super::generic::fmax(x, y)
}
5 changes: 5 additions & 0 deletions src/math/fmaxf16.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Return the greater of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmaxf16(x: f16, y: f16) -> f16 {
super::generic::fmax(x, y)
}
11 changes: 2 additions & 9 deletions src/math/fmin.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmin(x: f64, y: f64) -> f64 {
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if y.is_nan() || x < y { x } else { y }) * 1.0
super::generic::fmin(x, y)
}
11 changes: 2 additions & 9 deletions src/math/fminf.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fminf(x: f32, y: f32) -> f32 {
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if y.is_nan() || x < y { x } else { y }) * 1.0
super::generic::fmin(x, y)
}
5 changes: 5 additions & 0 deletions src/math/fminf128.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fminf128(x: f128, y: f128) -> f128 {
super::generic::fmin(x, y)
}
5 changes: 5 additions & 0 deletions src/math/fminf16.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fminf16(x: f16, y: f16) -> f16 {
super::generic::fmin(x, y)
}
14 changes: 14 additions & 0 deletions src/math/generic/fmax.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::super::Float;

#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn fmax<F: Float>(x: F, y: F) -> F {
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if x.is_nan() || x < y { y } else { x }) * F::ONE
}
13 changes: 13 additions & 0 deletions src/math/generic/fmin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use super::super::Float;

pub fn fmin<F: Float>(x: F, y: F) -> F {
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
// is either x or y, canonicalized (this means results might differ among implementations).
// When either x or y is a signalingNaN, then the result is according to 6.2.
//
// Since we do not support sNaN in Rust yet, we do not need to handle them.
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
(if y.is_nan() || x < y { x } else { y }) * F::ONE
}
4 changes: 4 additions & 0 deletions src/math/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ mod copysign;
mod fabs;
mod fdim;
mod floor;
mod fmax;
mod fmin;
mod rint;
mod round;
mod scalbn;
Expand All @@ -14,6 +16,8 @@ pub use copysign::copysign;
pub use fabs::fabs;
pub use fdim::fdim;
pub use floor::floor;
pub use fmax::fmax;
pub use fmin::fmin;
pub use rint::rint;
pub use round::round;
pub use scalbn::scalbn;
Expand Down
8 changes: 8 additions & 0 deletions src/math/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ cfg_if! {
mod fabsf16;
mod fdimf16;
mod floorf16;
mod fmaxf16;
mod fminf16;
mod rintf16;
mod roundf16;
mod sqrtf16;
Expand All @@ -356,6 +358,8 @@ cfg_if! {
pub use self::fabsf16::fabsf16;
pub use self::fdimf16::fdimf16;
pub use self::floorf16::floorf16;
pub use self::fmaxf16::fmaxf16;
pub use self::fminf16::fminf16;
pub use self::rintf16::rintf16;
pub use self::roundf16::roundf16;
pub use self::sqrtf16::sqrtf16;
Expand All @@ -370,6 +374,8 @@ cfg_if! {
mod fabsf128;
mod fdimf128;
mod floorf128;
mod fmaxf128;
mod fminf128;
mod rintf128;
mod roundf128;
mod sqrtf128;
Expand All @@ -380,6 +386,8 @@ cfg_if! {
pub use self::fabsf128::fabsf128;
pub use self::fdimf128::fdimf128;
pub use self::floorf128::floorf128;
pub use self::fmaxf128::fmaxf128;
pub use self::fminf128::fminf128;
pub use self::rintf128::rintf128;
pub use self::roundf128::roundf128;
pub use self::sqrtf128::sqrtf128;
Expand Down