Merge pull request rust-lang/libm#465 from tgross35/generic-round
Add `roundf16` and `roundf128`
This commit is contained in:
commit
453bebf7c1
15 changed files with 132 additions and 57 deletions
|
|
@ -9,7 +9,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
|
|||
FloatTy::F16,
|
||||
Signature { args: &[Ty::F16], returns: &[Ty::F16] },
|
||||
None,
|
||||
&["ceilf16", "fabsf16", "floorf16", "rintf16", "sqrtf16", "truncf16"],
|
||||
&["ceilf16", "fabsf16", "floorf16", "rintf16", "roundf16", "sqrtf16", "truncf16"],
|
||||
),
|
||||
(
|
||||
// `fn(f32) -> f32`
|
||||
|
|
@ -40,7 +40,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option<Signature>, &[&str])]
|
|||
FloatTy::F128,
|
||||
Signature { args: &[Ty::F128], returns: &[Ty::F128] },
|
||||
None,
|
||||
&["ceilf128", "fabsf128", "floorf128", "rintf128", "sqrtf128", "truncf128"],
|
||||
&["ceilf128", "fabsf128", "floorf128", "rintf128", "roundf128", "sqrtf128", "truncf128"],
|
||||
),
|
||||
(
|
||||
// `(f16, f16) -> f16`
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ libm_macros::for_each_function! {
|
|||
| floorf16
|
||||
| rintf128
|
||||
| rintf16
|
||||
| roundf128
|
||||
| roundf16
|
||||
| sqrtf128
|
||||
| sqrtf16
|
||||
| truncf128
|
||||
|
|
|
|||
|
|
@ -175,6 +175,8 @@ libm_macros::for_each_function! {
|
|||
rintf16,
|
||||
round,
|
||||
roundf,
|
||||
roundf128,
|
||||
roundf16,
|
||||
scalbn,
|
||||
scalbnf,
|
||||
sincos,sincosf,
|
||||
|
|
@ -247,6 +249,7 @@ impl_no_round! {
|
|||
fabsf16 => abs_mut;
|
||||
floorf16 => floor_mut;
|
||||
rintf16 => round_even_mut; // FIXME: respect rounding mode
|
||||
roundf16 => round_mut;
|
||||
truncf16 => trunc_mut;
|
||||
}
|
||||
|
||||
|
|
@ -256,6 +259,7 @@ impl_no_round! {
|
|||
fabsf128 => abs_mut;
|
||||
floorf128 => floor_mut;
|
||||
rintf128 => round_even_mut; // FIXME: respect rounding mode
|
||||
roundf128 => round_mut;
|
||||
truncf128 => trunc_mut;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ use crate::{BaseName, CheckBasis, CheckCtx, Float, Identifier, Int, TestResult};
|
|||
pub struct SpecialCase;
|
||||
|
||||
/// ULP allowed to differ from the results returned by a test basis.
|
||||
///
|
||||
/// Note that these results were obtained using 400M rounds of random inputs, which
|
||||
/// is not a value used by default.
|
||||
pub fn default_ulp(ctx: &CheckCtx) -> u32 {
|
||||
// ULP compared to the infinite (MPFR) result.
|
||||
let mut ulp = match ctx.base_name {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ libm_macros::for_each_function! {
|
|||
floorf16,
|
||||
rintf128,
|
||||
rintf16,
|
||||
roundf128,
|
||||
roundf16,
|
||||
sqrtf128,
|
||||
sqrtf16,
|
||||
truncf128,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
|
|||
| floorf16
|
||||
| rintf128
|
||||
| rintf16
|
||||
| roundf128
|
||||
| roundf16
|
||||
| sqrtf128
|
||||
| sqrtf16
|
||||
| truncf128
|
||||
|
|
|
|||
|
|
@ -685,16 +685,32 @@
|
|||
"round": {
|
||||
"sources": [
|
||||
"src/libm_helper.rs",
|
||||
"src/math/generic/round.rs",
|
||||
"src/math/round.rs"
|
||||
],
|
||||
"type": "f64"
|
||||
},
|
||||
"roundf": {
|
||||
"sources": [
|
||||
"src/math/generic/round.rs",
|
||||
"src/math/roundf.rs"
|
||||
],
|
||||
"type": "f32"
|
||||
},
|
||||
"roundf128": {
|
||||
"sources": [
|
||||
"src/math/generic/round.rs",
|
||||
"src/math/roundf128.rs"
|
||||
],
|
||||
"type": "f128"
|
||||
},
|
||||
"roundf16": {
|
||||
"sources": [
|
||||
"src/math/generic/round.rs",
|
||||
"src/math/roundf16.rs"
|
||||
],
|
||||
"type": "f16"
|
||||
},
|
||||
"scalbn": {
|
||||
"sources": [
|
||||
"src/libm_helper.rs",
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ rintf128
|
|||
rintf16
|
||||
round
|
||||
roundf
|
||||
roundf128
|
||||
roundf16
|
||||
scalbn
|
||||
scalbnf
|
||||
sin
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ mod fabs;
|
|||
mod fdim;
|
||||
mod floor;
|
||||
mod rint;
|
||||
mod round;
|
||||
mod scalbn;
|
||||
mod sqrt;
|
||||
mod trunc;
|
||||
|
|
@ -14,6 +15,7 @@ pub use fabs::fabs;
|
|||
pub use fdim::fdim;
|
||||
pub use floor::floor;
|
||||
pub use rint::rint;
|
||||
pub use round::round;
|
||||
pub use scalbn::scalbn;
|
||||
pub use sqrt::sqrt;
|
||||
pub use trunc::trunc;
|
||||
|
|
|
|||
82
library/compiler-builtins/libm/src/math/generic/round.rs
Normal file
82
library/compiler-builtins/libm/src/math/generic/round.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
use super::super::{Float, MinInt};
|
||||
use super::{copysign, trunc};
|
||||
|
||||
pub fn round<F: Float>(x: F) -> F {
|
||||
let f0p5 = F::from_parts(false, F::EXP_BIAS - 1, F::Int::ZERO); // 0.5
|
||||
let f0p25 = F::from_parts(false, F::EXP_BIAS - 2, F::Int::ZERO); // 0.25
|
||||
|
||||
trunc(x + copysign(f0p5 - f0p25 * F::EPSILON, x))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg(f16_enabled)]
|
||||
fn zeroes_f16() {
|
||||
assert_biteq!(round(0.0_f16), 0.0_f16);
|
||||
assert_biteq!(round(-0.0_f16), -0.0_f16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(f16_enabled)]
|
||||
fn sanity_check_f16() {
|
||||
assert_eq!(round(-1.0_f16), -1.0);
|
||||
assert_eq!(round(2.8_f16), 3.0);
|
||||
assert_eq!(round(-0.5_f16), -1.0);
|
||||
assert_eq!(round(0.5_f16), 1.0);
|
||||
assert_eq!(round(-1.5_f16), -2.0);
|
||||
assert_eq!(round(1.5_f16), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zeroes_f32() {
|
||||
assert_biteq!(round(0.0_f32), 0.0_f32);
|
||||
assert_biteq!(round(-0.0_f32), -0.0_f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check_f32() {
|
||||
assert_eq!(round(-1.0_f32), -1.0);
|
||||
assert_eq!(round(2.8_f32), 3.0);
|
||||
assert_eq!(round(-0.5_f32), -1.0);
|
||||
assert_eq!(round(0.5_f32), 1.0);
|
||||
assert_eq!(round(-1.5_f32), -2.0);
|
||||
assert_eq!(round(1.5_f32), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zeroes_f64() {
|
||||
assert_biteq!(round(0.0_f64), 0.0_f64);
|
||||
assert_biteq!(round(-0.0_f64), -0.0_f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check_f64() {
|
||||
assert_eq!(round(-1.0_f64), -1.0);
|
||||
assert_eq!(round(2.8_f64), 3.0);
|
||||
assert_eq!(round(-0.5_f64), -1.0);
|
||||
assert_eq!(round(0.5_f64), 1.0);
|
||||
assert_eq!(round(-1.5_f64), -2.0);
|
||||
assert_eq!(round(1.5_f64), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(f128_enabled)]
|
||||
fn zeroes_f128() {
|
||||
assert_biteq!(round(0.0_f128), 0.0_f128);
|
||||
assert_biteq!(round(-0.0_f128), -0.0_f128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(f128_enabled)]
|
||||
fn sanity_check_f128() {
|
||||
assert_eq!(round(-1.0_f128), -1.0);
|
||||
assert_eq!(round(2.8_f128), 3.0);
|
||||
assert_eq!(round(-0.5_f128), -1.0);
|
||||
assert_eq!(round(0.5_f128), 1.0);
|
||||
assert_eq!(round(-1.5_f128), -2.0);
|
||||
assert_eq!(round(1.5_f128), 2.0);
|
||||
}
|
||||
}
|
||||
|
|
@ -347,6 +347,7 @@ cfg_if! {
|
|||
mod fdimf16;
|
||||
mod floorf16;
|
||||
mod rintf16;
|
||||
mod roundf16;
|
||||
mod sqrtf16;
|
||||
mod truncf16;
|
||||
|
||||
|
|
@ -356,6 +357,7 @@ cfg_if! {
|
|||
pub use self::fdimf16::fdimf16;
|
||||
pub use self::floorf16::floorf16;
|
||||
pub use self::rintf16::rintf16;
|
||||
pub use self::roundf16::roundf16;
|
||||
pub use self::sqrtf16::sqrtf16;
|
||||
pub use self::truncf16::truncf16;
|
||||
}
|
||||
|
|
@ -369,6 +371,7 @@ cfg_if! {
|
|||
mod fdimf128;
|
||||
mod floorf128;
|
||||
mod rintf128;
|
||||
mod roundf128;
|
||||
mod sqrtf128;
|
||||
mod truncf128;
|
||||
|
||||
|
|
@ -378,6 +381,7 @@ cfg_if! {
|
|||
pub use self::fdimf128::fdimf128;
|
||||
pub use self::floorf128::floorf128;
|
||||
pub use self::rintf128::rintf128;
|
||||
pub use self::roundf128::roundf128;
|
||||
pub use self::sqrtf128::sqrtf128;
|
||||
pub use self::truncf128::truncf128;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,5 @@
|
|||
use core::f64;
|
||||
|
||||
use super::{copysign, trunc};
|
||||
|
||||
/// Round `x` to the nearest integer, breaking ties away from zero.
|
||||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn round(x: f64) -> f64 {
|
||||
trunc(x + copysign(0.5 - 0.25 * f64::EPSILON, x))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::round;
|
||||
|
||||
#[test]
|
||||
fn negative_zero() {
|
||||
assert_eq!(round(-0.0_f64).to_bits(), (-0.0_f64).to_bits());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check() {
|
||||
assert_eq!(round(-1.0), -1.0);
|
||||
assert_eq!(round(2.8), 3.0);
|
||||
assert_eq!(round(-0.5), -1.0);
|
||||
assert_eq!(round(0.5), 1.0);
|
||||
assert_eq!(round(-1.5), -2.0);
|
||||
assert_eq!(round(1.5), 2.0);
|
||||
}
|
||||
super::generic::round(x)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,5 @@
|
|||
use core::f32;
|
||||
|
||||
use super::{copysignf, truncf};
|
||||
|
||||
/// Round `x` to the nearest integer, breaking ties away from zero.
|
||||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn roundf(x: f32) -> f32 {
|
||||
truncf(x + copysignf(0.5 - 0.25 * f32::EPSILON, x))
|
||||
}
|
||||
|
||||
// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
|
||||
#[cfg(not(target_arch = "powerpc64"))]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::roundf;
|
||||
|
||||
#[test]
|
||||
fn negative_zero() {
|
||||
assert_eq!(roundf(-0.0_f32).to_bits(), (-0.0_f32).to_bits());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_check() {
|
||||
assert_eq!(roundf(-1.0), -1.0);
|
||||
assert_eq!(roundf(2.8), 3.0);
|
||||
assert_eq!(roundf(-0.5), -1.0);
|
||||
assert_eq!(roundf(0.5), 1.0);
|
||||
assert_eq!(roundf(-1.5), -2.0);
|
||||
assert_eq!(roundf(1.5), 2.0);
|
||||
}
|
||||
super::generic::round(x)
|
||||
}
|
||||
|
|
|
|||
5
library/compiler-builtins/libm/src/math/roundf128.rs
Normal file
5
library/compiler-builtins/libm/src/math/roundf128.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/// Round `x` to the nearest integer, breaking ties away from zero.
|
||||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn roundf128(x: f128) -> f128 {
|
||||
super::generic::round(x)
|
||||
}
|
||||
5
library/compiler-builtins/libm/src/math/roundf16.rs
Normal file
5
library/compiler-builtins/libm/src/math/roundf16.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/// Round `x` to the nearest integer, breaking ties away from zero.
|
||||
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
|
||||
pub fn roundf16(x: f16) -> f16 {
|
||||
super::generic::round(x)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue