mirror of
https://github.com/rust-lang/rust.git
synced 2025-11-24 03:57:33 +00:00
This standardizes how max and min subnormals are generated. Since the new method doesn't use powf, it also enables some of the tests for f128 that were previously disabled due to issues with powf (although it looks like those issues were already fixed anyway). f16 signalling nan tests previously disabled are not re-enabled, since the underlying LLVM issue has not been closed.
166 lines
5.5 KiB
Rust
166 lines
5.5 KiB
Rust
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
|
|
#![cfg(target_has_reliable_f16)]
|
|
|
|
use std::f16::consts;
|
|
|
|
use super::{assert_approx_eq, assert_biteq};
|
|
|
|
/// Tolerance for results on the order of 10.0e-2
|
|
#[allow(unused)]
|
|
const TOL_N2: f16 = 0.0001;
|
|
|
|
/// Tolerance for results on the order of 10.0e+0
|
|
#[allow(unused)]
|
|
const TOL_0: f16 = 0.01;
|
|
|
|
/// Tolerance for results on the order of 10.0e+2
|
|
#[allow(unused)]
|
|
const TOL_P2: f16 = 0.5;
|
|
|
|
/// Tolerance for results on the order of 10.0e+4
|
|
#[allow(unused)]
|
|
const TOL_P4: f16 = 10.0;
|
|
|
|
/// First pattern over the mantissa
|
|
const NAN_MASK1: u16 = 0x02aa;
|
|
|
|
/// Second pattern over the mantissa
|
|
const NAN_MASK2: u16 = 0x0155;
|
|
|
|
// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
|
|
// the intrinsics.
|
|
|
|
#[test]
|
|
#[cfg(not(miri))]
|
|
#[cfg(target_has_reliable_f16_math)]
|
|
fn test_mul_add() {
|
|
let nan: f16 = f16::NAN;
|
|
let inf: f16 = f16::INFINITY;
|
|
let neg_inf: f16 = f16::NEG_INFINITY;
|
|
assert_biteq!(12.3f16.mul_add(4.5, 6.7), 62.031);
|
|
assert_biteq!((-12.3f16).mul_add(-4.5, -6.7), 48.625);
|
|
assert_biteq!(0.0f16.mul_add(8.9, 1.2), 1.2);
|
|
assert_biteq!(3.4f16.mul_add(-0.0, 5.6), 5.6);
|
|
assert!(nan.mul_add(7.8, 9.0).is_nan());
|
|
assert_biteq!(inf.mul_add(7.8, 9.0), inf);
|
|
assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
|
|
assert_biteq!(8.9f16.mul_add(inf, 3.2), inf);
|
|
assert_biteq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(any(miri, target_has_reliable_f16_math))]
|
|
fn test_recip() {
|
|
let nan: f16 = f16::NAN;
|
|
let inf: f16 = f16::INFINITY;
|
|
let neg_inf: f16 = f16::NEG_INFINITY;
|
|
assert_biteq!(1.0f16.recip(), 1.0);
|
|
assert_biteq!(2.0f16.recip(), 0.5);
|
|
assert_biteq!((-0.4f16).recip(), -2.5);
|
|
assert_biteq!(0.0f16.recip(), inf);
|
|
assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
|
|
assert!(nan.recip().is_nan());
|
|
assert_biteq!(inf.recip(), 0.0);
|
|
assert_biteq!(neg_inf.recip(), -0.0);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(miri))]
|
|
#[cfg(target_has_reliable_f16_math)]
|
|
fn test_powi() {
|
|
let nan: f16 = f16::NAN;
|
|
let inf: f16 = f16::INFINITY;
|
|
let neg_inf: f16 = f16::NEG_INFINITY;
|
|
assert_biteq!(1.0f16.powi(1), 1.0);
|
|
assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
|
|
assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
|
|
assert_biteq!(8.3f16.powi(0), 1.0);
|
|
assert!(nan.powi(2).is_nan());
|
|
assert_biteq!(inf.powi(3), inf);
|
|
assert_biteq!(neg_inf.powi(2), inf);
|
|
}
|
|
|
|
#[test]
|
|
fn test_to_degrees() {
|
|
let pi: f16 = consts::PI;
|
|
let nan: f16 = f16::NAN;
|
|
let inf: f16 = f16::INFINITY;
|
|
let neg_inf: f16 = f16::NEG_INFINITY;
|
|
assert_biteq!(0.0f16.to_degrees(), 0.0);
|
|
assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
|
|
assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
|
|
assert!(nan.to_degrees().is_nan());
|
|
assert_biteq!(inf.to_degrees(), inf);
|
|
assert_biteq!(neg_inf.to_degrees(), neg_inf);
|
|
assert_biteq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
|
|
}
|
|
|
|
#[test]
|
|
fn test_to_radians() {
|
|
let pi: f16 = consts::PI;
|
|
let nan: f16 = f16::NAN;
|
|
let inf: f16 = f16::INFINITY;
|
|
let neg_inf: f16 = f16::NEG_INFINITY;
|
|
assert_biteq!(0.0f16.to_radians(), 0.0);
|
|
assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
|
|
assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
|
|
assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
|
|
assert!(nan.to_radians().is_nan());
|
|
assert_biteq!(inf.to_radians(), inf);
|
|
assert_biteq!(neg_inf.to_radians(), neg_inf);
|
|
}
|
|
|
|
#[test]
|
|
fn test_float_bits_conv() {
|
|
assert_eq!((1f16).to_bits(), 0x3c00);
|
|
assert_eq!((12.5f16).to_bits(), 0x4a40);
|
|
assert_eq!((1337f16).to_bits(), 0x6539);
|
|
assert_eq!((-14.25f16).to_bits(), 0xcb20);
|
|
assert_biteq!(f16::from_bits(0x3c00), 1.0);
|
|
assert_biteq!(f16::from_bits(0x4a40), 12.5);
|
|
assert_biteq!(f16::from_bits(0x6539), 1337.0);
|
|
assert_biteq!(f16::from_bits(0xcb20), -14.25);
|
|
|
|
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
|
let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
|
|
let masked_nan2 = f16::NAN.to_bits() ^ NAN_MASK2;
|
|
assert!(f16::from_bits(masked_nan1).is_nan());
|
|
assert!(f16::from_bits(masked_nan2).is_nan());
|
|
|
|
assert_eq!(f16::from_bits(masked_nan1).to_bits(), masked_nan1);
|
|
assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_algebraic() {
|
|
let a: f16 = 123.0;
|
|
let b: f16 = 456.0;
|
|
|
|
// Check that individual operations match their primitive counterparts.
|
|
//
|
|
// This is a check of current implementations and does NOT imply any form of
|
|
// guarantee about future behavior. The compiler reserves the right to make
|
|
// these operations inexact matches in the future.
|
|
let eps_add = if cfg!(miri) { 1e1 } else { 0.0 };
|
|
let eps_mul = if cfg!(miri) { 1e3 } else { 0.0 };
|
|
let eps_div = if cfg!(miri) { 1e0 } else { 0.0 };
|
|
|
|
assert_approx_eq!(a.algebraic_add(b), a + b, eps_add);
|
|
assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add);
|
|
assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul);
|
|
assert_approx_eq!(a.algebraic_div(b), a / b, eps_div);
|
|
assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div);
|
|
}
|
|
|
|
#[test]
|
|
fn test_from() {
|
|
assert_biteq!(f16::from(false), 0.0);
|
|
assert_biteq!(f16::from(true), 1.0);
|
|
assert_biteq!(f16::from(u8::MIN), 0.0);
|
|
assert_biteq!(f16::from(42_u8), 42.0);
|
|
assert_biteq!(f16::from(u8::MAX), 255.0);
|
|
assert_biteq!(f16::from(i8::MIN), -128.0);
|
|
assert_biteq!(f16::from(42_i8), 42.0);
|
|
assert_biteq!(f16::from(i8::MAX), 127.0);
|
|
}
|