Skip to content

Commit 37480bc

Browse files
committed
coretests/num: use ldexp instead of hard-coding a power of 2
1 parent 9982d64 commit 37480bc

File tree

4 files changed

+38
-32
lines changed

4 files changed

+38
-32
lines changed

library/coretests/tests/num/dec2flt/float.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use core::num::dec2flt::float::RawFloat;
22

3+
use crate::num::{ldexp_f32, ldexp_f64};
4+
35
// FIXME(f16_f128): enable on all targets once possible.
46
#[test]
57
#[cfg(target_has_reliable_f16)]
68
fn test_f16_integer_decode() {
79
assert_eq!(3.14159265359f16.integer_decode(), (1608, -9, 1));
810
assert_eq!((-8573.5918555f16).integer_decode(), (1072, 3, -1));
9-
#[cfg(not(miri))] // miri doesn't have powf16
10-
assert_eq!(2f16.powf(14.0).integer_decode(), (1 << 10, 4, 1));
11+
assert_eq!(crate::num::ldexp_f16(1.0, 14).integer_decode(), (1 << 10, 4, 1));
1112
assert_eq!(0f16.integer_decode(), (0, -25, 1));
1213
assert_eq!((-0f16).integer_decode(), (0, -25, -1));
1314
assert_eq!(f16::INFINITY.integer_decode(), (1 << 10, 6, 1));
@@ -23,8 +24,7 @@ fn test_f16_integer_decode() {
2324
fn test_f32_integer_decode() {
2425
assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
2526
assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1));
26-
// Set 2^100 directly instead of using powf, because it doesn't guarantee precision
27-
assert_eq!(1.2676506e30_f32.integer_decode(), (8388608, 77, 1));
27+
assert_eq!(ldexp_f32(1.0, 100).integer_decode(), (8388608, 77, 1));
2828
assert_eq!(0f32.integer_decode(), (0, -150, 1));
2929
assert_eq!((-0f32).integer_decode(), (0, -150, -1));
3030
assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1));
@@ -40,8 +40,7 @@ fn test_f32_integer_decode() {
4040
fn test_f64_integer_decode() {
4141
assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
4242
assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
43-
// Set 2^100 directly instead of using powf, because it doesn't guarantee precision
44-
assert_eq!(1.2676506002282294e30_f64.integer_decode(), (4503599627370496, 48, 1));
43+
assert_eq!(ldexp_f64(1.0, 100).integer_decode(), (4503599627370496, 48, 1));
4544
assert_eq!(0f64.integer_decode(), (0, -1075, 1));
4645
assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
4746
assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1));

library/coretests/tests/num/flt2dec/estimator.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use core::num::flt2dec::estimator::*;
22

3+
use crate::num::ldexp_f64;
4+
35
#[test]
46
fn test_estimate_scaling_factor() {
57
macro_rules! assert_almost_eq {
@@ -56,7 +58,7 @@ fn test_estimate_scaling_factor() {
5658
let step = if cfg!(miri) { 37 } else { 1 };
5759

5860
for i in (-1074..972).step_by(step) {
59-
let expected = super::ldexp_f64(1.0, i).log10().ceil();
61+
let expected = ldexp_f64(1.0, i).log10().ceil();
6062
assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
6163
}
6264
}

library/coretests/tests/num/flt2dec/mod.rs

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use core::num::fmt::{Formatted, Part};
66
use std::mem::MaybeUninit;
77
use std::{fmt, str};
88

9+
use crate::num::{ldexp_f32, ldexp_f64};
10+
911
mod estimator;
1012
mod strategy {
1113
mod dragon;
@@ -75,24 +77,6 @@ macro_rules! try_fixed {
7577
})
7678
}
7779

78-
#[cfg(target_has_reliable_f16)]
79-
fn ldexp_f16(a: f16, b: i32) -> f16 {
80-
ldexp_f64(a as f64, b) as f16
81-
}
82-
83-
fn ldexp_f32(a: f32, b: i32) -> f32 {
84-
ldexp_f64(a as f64, b) as f32
85-
}
86-
87-
fn ldexp_f64(a: f64, b: i32) -> f64 {
88-
unsafe extern "C" {
89-
fn ldexp(x: f64, n: i32) -> f64;
90-
}
91-
// SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly
92-
// cause undefined behavior
93-
unsafe { ldexp(a, b) }
94-
}
95-
9680
fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16)
9781
where
9882
T: DecodableFloat,
@@ -268,7 +252,7 @@ where
268252
// 10^2 * 0.31984375
269253
// 10^2 * 0.32
270254
// 10^2 * 0.3203125
271-
check_shortest!(f(ldexp_f16(1.0, 5)) => b"32", 2);
255+
check_shortest!(f(crate::num::ldexp_f16(1.0, 5)) => b"32", 2);
272256

273257
// 10^5 * 0.65472
274258
// 10^5 * 0.65504
@@ -283,7 +267,7 @@ where
283267
// 10^-9 * 0
284268
// 10^-9 * 0.59604644775390625
285269
// 10^-8 * 0.11920928955078125
286-
let minf16 = ldexp_f16(1.0, -24);
270+
let minf16 = crate::num::ldexp_f16(1.0, -24);
287271
check_shortest!(f(minf16) => b"6", -7);
288272
}
289273

@@ -292,7 +276,7 @@ pub fn f16_exact_sanity_test<F>(mut f: F)
292276
where
293277
F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
294278
{
295-
let minf16 = ldexp_f16(1.0, -24);
279+
let minf16 = crate::num::ldexp_f16(1.0, -24);
296280

297281
check_exact!(f(0.1f16) => b"999755859375 ", -1);
298282
check_exact!(f(0.5f16) => b"5 ", 0);
@@ -642,7 +626,7 @@ where
642626
assert_eq!(to_string(f, f16::MAX, Minus, 1), "65500.0");
643627
assert_eq!(to_string(f, f16::MAX, Minus, 8), "65500.00000000");
644628

645-
let minf16 = ldexp_f16(1.0, -24);
629+
let minf16 = crate::num::ldexp_f16(1.0, -24);
646630
assert_eq!(to_string(f, minf16, Minus, 0), "0.00000006");
647631
assert_eq!(to_string(f, minf16, Minus, 8), "0.00000006");
648632
assert_eq!(to_string(f, minf16, Minus, 9), "0.000000060");
@@ -766,7 +750,7 @@ where
766750
assert_eq!(to_string(f, f16::MAX, Minus, (-4, 4), false), "6.55e4");
767751
assert_eq!(to_string(f, f16::MAX, Minus, (-5, 5), false), "65500");
768752

769-
let minf16 = ldexp_f16(1.0, -24);
753+
let minf16 = crate::num::ldexp_f16(1.0, -24);
770754
assert_eq!(to_string(f, minf16, Minus, (-2, 2), false), "6e-8");
771755
assert_eq!(to_string(f, minf16, Minus, (-7, 7), false), "6e-8");
772756
assert_eq!(to_string(f, minf16, Minus, (-8, 8), false), "0.00000006");
@@ -922,7 +906,7 @@ where
922906
assert_eq!(to_string(f, f16::MAX, Minus, 6, false), "6.55040e4");
923907
assert_eq!(to_string(f, f16::MAX, Minus, 16, false), "6.550400000000000e4");
924908

925-
let minf16 = ldexp_f16(1.0, -24);
909+
let minf16 = crate::num::ldexp_f16(1.0, -24);
926910
assert_eq!(to_string(f, minf16, Minus, 1, false), "6e-8");
927911
assert_eq!(to_string(f, minf16, Minus, 2, false), "6.0e-8");
928912
assert_eq!(to_string(f, minf16, Minus, 4, false), "5.960e-8");
@@ -1229,7 +1213,7 @@ where
12291213

12301214
#[cfg(target_has_reliable_f16)]
12311215
{
1232-
let minf16 = ldexp_f16(1.0, -24);
1216+
let minf16 = crate::num::ldexp_f16(1.0, -24);
12331217
assert_eq!(to_string(f, minf16, Minus, 0), "0");
12341218
assert_eq!(to_string(f, minf16, Minus, 1), "0.0");
12351219
assert_eq!(to_string(f, minf16, Minus, 2), "0.00");

library/coretests/tests/num/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ macro_rules! assume_usize_width {
5454
}
5555
}
5656

57+
/// Return `a * 2^b`.
58+
#[cfg(target_has_reliable_f16)]
59+
fn ldexp_f16(a: f16, b: i32) -> f16 {
60+
ldexp_f64(a as f64, b) as f16
61+
}
62+
63+
/// Return `a * 2^b`.
64+
fn ldexp_f32(a: f32, b: i32) -> f32 {
65+
ldexp_f64(a as f64, b) as f32
66+
}
67+
68+
/// Return `a * 2^b`.
69+
fn ldexp_f64(a: f64, b: i32) -> f64 {
70+
unsafe extern "C" {
71+
fn ldexp(x: f64, n: i32) -> f64;
72+
}
73+
// SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly
74+
// cause undefined behavior
75+
unsafe { ldexp(a, b) }
76+
}
77+
5778
/// Helper function for testing numeric operations
5879
pub fn test_num<T>(ten: T, two: T)
5980
where

0 commit comments

Comments
 (0)