Skip to content

Commit 9975c79

Browse files
authored
Merge pull request #614 from tgross35/f16-f128-powi
Add `__powitf2` symbol for `f128` integer exponentiation
2 parents d50b093 + 31c4a8e commit 9975c79

File tree

7 files changed

+112
-61
lines changed

7 files changed

+112
-61
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ of being added to Rust.
240240
- [ ] floatunsitf.c
241241
- [ ] floatuntitf.c
242242
- [x] multf3.c
243-
- [ ] powitf2.c
243+
- [x] powitf2.c
244244
- [x] subtf3.c
245245
- [x] truncdfhf2.c
246246
- [x] truncsfhf2.c

build.rs

-1
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ mod c {
526526
("__floatsitf", "floatsitf.c"),
527527
("__floatunditf", "floatunditf.c"),
528528
("__floatunsitf", "floatunsitf.c"),
529-
("__powitf2", "powitf2.c"),
530529
("__fe_getround", "fp_mode.c"),
531530
("__fe_raise_inexact", "fp_mode.c"),
532531
]);

src/float/pow.rs

+9
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,13 @@ intrinsics! {
3535
pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 {
3636
pow(a, b)
3737
}
38+
39+
#[avr_skip]
40+
#[ppc_alias = __powikf2]
41+
#[cfg(f128_enabled)]
42+
// FIXME(f16_f128): MSVC cannot build these until `__divtf3` is available in nightly.
43+
#[cfg(not(target_env = "msvc"))]
44+
pub extern "C" fn __powitf2(a: f128, b: i32) -> f128 {
45+
pow(a, b)
46+
}
3847
}

testcrate/benches/float_pow.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
#![cfg_attr(f128_enabled, feature(f128))]
2+
13
use compiler_builtins::float::pow;
2-
use criterion::{criterion_group, criterion_main, Criterion};
4+
use criterion::{criterion_main, Criterion};
35
use testcrate::float_bench;
46

57
float_bench! {
@@ -20,5 +22,28 @@ float_bench! {
2022
asm: [],
2123
}
2224

23-
criterion_group!(float_add, powi_f32, powi_f64);
24-
criterion_main!(float_add);
25+
// FIXME(f16_f128): can be changed to only `f128_enabled` once `__multf3` and `__divtf3` are
26+
// distributed by nightly.
27+
#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
28+
float_bench! {
29+
name: powi_f128,
30+
sig: (a: f128, b: i32) -> f128,
31+
crate_fn: pow::__powitf2,
32+
crate_fn_ppc: pow::__powikf2,
33+
sys_fn: __powitf2,
34+
sys_fn_ppc: __powikf2,
35+
sys_available: not(feature = "no-sys-f128"),
36+
asm: []
37+
}
38+
39+
pub fn float_pow() {
40+
let mut criterion = Criterion::default().configure_from_args();
41+
42+
powi_f32(&mut criterion);
43+
powi_f64(&mut criterion);
44+
45+
#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
46+
powi_f128(&mut criterion);
47+
}
48+
49+
criterion_main!(float_pow);

testcrate/src/bench.rs

+2
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,5 @@ impl_testio!(int i16, i32, i64, i128);
360360
impl_testio!(int u16, u32, u64, u128);
361361
impl_testio!((float, int)(f32, i32));
362362
impl_testio!((float, int)(f64, i32));
363+
#[cfg(f128_enabled)]
364+
impl_testio!((float, int)(f128, i32));

testcrate/tests/float_pow.rs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#![allow(unused_macros)]
2+
#![cfg_attr(f128_enabled, feature(f128))]
3+
#![cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
4+
5+
use testcrate::*;
6+
7+
// This is approximate because of issues related to
8+
// https://github.com/rust-lang/rust/issues/73920.
9+
// TODO how do we resolve this indeterminacy?
10+
macro_rules! pow {
11+
($($f:ty, $tolerance:expr, $fn:ident, $sys_available:meta);*;) => {
12+
$(
13+
#[test]
14+
// FIXME(apfloat): We skip tests if system symbols aren't available rather
15+
// than providing a fallback, since `rustc_apfloat` does not provide `pow`.
16+
#[cfg($sys_available)]
17+
fn $fn() {
18+
use compiler_builtins::float::pow::$fn;
19+
use compiler_builtins::float::Float;
20+
fuzz_float_2(N, |x: $f, y: $f| {
21+
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
22+
let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK;
23+
let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS;
24+
let n = n as i32;
25+
let tmp0: $f = x.powi(n);
26+
let tmp1: $f = $fn(x, n);
27+
let (a, b) = if tmp0 < tmp1 {
28+
(tmp0, tmp1)
29+
} else {
30+
(tmp1, tmp0)
31+
};
32+
33+
let good = if a == b {
34+
// handles infinity equality
35+
true
36+
} else if a < $tolerance {
37+
b < $tolerance
38+
} else {
39+
let quo = b / a;
40+
(quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
41+
};
42+
43+
assert!(
44+
good,
45+
"{}({:?}, {:?}): std: {:?}, builtins: {:?}",
46+
stringify!($fn), x, n, tmp0, tmp1
47+
);
48+
}
49+
});
50+
}
51+
)*
52+
};
53+
}
54+
55+
pow! {
56+
f32, 1e-4, __powisf2, all();
57+
f64, 1e-12, __powidf2, all();
58+
}
59+
60+
#[cfg(f128_enabled)]
61+
// FIXME(f16_f128): MSVC cannot build these until `__divtf3` is available in nightly.
62+
#[cfg(not(target_env = "msvc"))]
63+
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
64+
pow! {
65+
f128, 1e-36, __powitf2, not(feature = "no-sys-f128");
66+
}
67+
68+
#[cfg(f128_enabled)]
69+
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
70+
pow! {
71+
f128, 1e-36, __powikf2, not(feature = "no-sys-f128");
72+
}

testcrate/tests/misc.rs

-56
Original file line numberDiff line numberDiff line change
@@ -207,59 +207,3 @@ fn bswap() {
207207
);
208208
}
209209
}
210-
211-
// This is approximate because of issues related to
212-
// https://github.com/rust-lang/rust/issues/73920.
213-
// TODO how do we resolve this indeterminacy?
214-
macro_rules! pow {
215-
($($f:ty, $tolerance:expr, $fn:ident);*;) => {
216-
$(
217-
#[test]
218-
fn $fn() {
219-
use compiler_builtins::float::pow::$fn;
220-
use compiler_builtins::float::Float;
221-
fuzz_float_2(N, |x: $f, y: $f| {
222-
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
223-
let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK;
224-
let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS;
225-
let n = n as i32;
226-
let tmp0: $f = x.powi(n);
227-
let tmp1: $f = $fn(x, n);
228-
let (a, b) = if tmp0 < tmp1 {
229-
(tmp0, tmp1)
230-
} else {
231-
(tmp1, tmp0)
232-
};
233-
let good = {
234-
if a == b {
235-
// handles infinity equality
236-
true
237-
} else if a < $tolerance {
238-
b < $tolerance
239-
} else {
240-
let quo = b / a;
241-
(quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
242-
}
243-
};
244-
if !good {
245-
panic!(
246-
"{}({}, {}): std: {}, builtins: {}",
247-
stringify!($fn), x, n, tmp0, tmp1
248-
);
249-
}
250-
}
251-
});
252-
}
253-
)*
254-
};
255-
}
256-
257-
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
258-
mod float_pow {
259-
use super::*;
260-
261-
pow! {
262-
f32, 1e-4, __powisf2;
263-
f64, 1e-12, __powidf2;
264-
}
265-
}

0 commit comments

Comments
 (0)