Skip to content

Commit

Permalink
Merge pull request rust-lang#614 from tgross35/f16-f128-powi
Browse files Browse the repository at this point in the history
Add `__powitf2` symbol for `f128` integer exponentiation
  • Loading branch information
tgross35 authored Sep 28, 2024
2 parents d50b093 + 31c4a8e commit 9975c79
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 61 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ of being added to Rust.
- [ ] floatunsitf.c
- [ ] floatuntitf.c
- [x] multf3.c
- [ ] powitf2.c
- [x] powitf2.c
- [x] subtf3.c
- [x] truncdfhf2.c
- [x] truncsfhf2.c
Expand Down
1 change: 0 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,6 @@ mod c {
("__floatsitf", "floatsitf.c"),
("__floatunditf", "floatunditf.c"),
("__floatunsitf", "floatunsitf.c"),
("__powitf2", "powitf2.c"),
("__fe_getround", "fp_mode.c"),
("__fe_raise_inexact", "fp_mode.c"),
]);
Expand Down
9 changes: 9 additions & 0 deletions src/float/pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ intrinsics! {
pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 {
pow(a, b)
}

#[avr_skip]
#[ppc_alias = __powikf2]
#[cfg(f128_enabled)]
// FIXME(f16_f128): MSVC cannot build these until `__divtf3` is available in nightly.
#[cfg(not(target_env = "msvc"))]
pub extern "C" fn __powitf2(a: f128, b: i32) -> f128 {
pow(a, b)
}
}
31 changes: 28 additions & 3 deletions testcrate/benches/float_pow.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![cfg_attr(f128_enabled, feature(f128))]

use compiler_builtins::float::pow;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;

float_bench! {
Expand All @@ -20,5 +22,28 @@ float_bench! {
asm: [],
}

criterion_group!(float_add, powi_f32, powi_f64);
criterion_main!(float_add);
// FIXME(f16_f128): can be changed to only `f128_enabled` once `__multf3` and `__divtf3` are
// distributed by nightly.
#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
float_bench! {
name: powi_f128,
sig: (a: f128, b: i32) -> f128,
crate_fn: pow::__powitf2,
crate_fn_ppc: pow::__powikf2,
sys_fn: __powitf2,
sys_fn_ppc: __powikf2,
sys_available: not(feature = "no-sys-f128"),
asm: []
}

pub fn float_pow() {
let mut criterion = Criterion::default().configure_from_args();

powi_f32(&mut criterion);
powi_f64(&mut criterion);

#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
powi_f128(&mut criterion);
}

criterion_main!(float_pow);
2 changes: 2 additions & 0 deletions testcrate/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,5 @@ impl_testio!(int i16, i32, i64, i128);
impl_testio!(int u16, u32, u64, u128);
impl_testio!((float, int)(f32, i32));
impl_testio!((float, int)(f64, i32));
#[cfg(f128_enabled)]
impl_testio!((float, int)(f128, i32));
72 changes: 72 additions & 0 deletions testcrate/tests/float_pow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#![allow(unused_macros)]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]

use testcrate::*;

// This is approximate because of issues related to
// https://github.com/rust-lang/rust/issues/73920.
// TODO how do we resolve this indeterminacy?
macro_rules! pow {
($($f:ty, $tolerance:expr, $fn:ident, $sys_available:meta);*;) => {
$(
#[test]
// FIXME(apfloat): We skip tests if system symbols aren't available rather
// than providing a fallback, since `rustc_apfloat` does not provide `pow`.
#[cfg($sys_available)]
fn $fn() {
use compiler_builtins::float::pow::$fn;
use compiler_builtins::float::Float;
fuzz_float_2(N, |x: $f, y: $f| {
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK;
let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS;
let n = n as i32;
let tmp0: $f = x.powi(n);
let tmp1: $f = $fn(x, n);
let (a, b) = if tmp0 < tmp1 {
(tmp0, tmp1)
} else {
(tmp1, tmp0)
};

let good = if a == b {
// handles infinity equality
true
} else if a < $tolerance {
b < $tolerance
} else {
let quo = b / a;
(quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
};

assert!(
good,
"{}({:?}, {:?}): std: {:?}, builtins: {:?}",
stringify!($fn), x, n, tmp0, tmp1
);
}
});
}
)*
};
}

pow! {
f32, 1e-4, __powisf2, all();
f64, 1e-12, __powidf2, all();
}

#[cfg(f128_enabled)]
// FIXME(f16_f128): MSVC cannot build these until `__divtf3` is available in nightly.
#[cfg(not(target_env = "msvc"))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
pow! {
f128, 1e-36, __powitf2, not(feature = "no-sys-f128");
}

#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pow! {
f128, 1e-36, __powikf2, not(feature = "no-sys-f128");
}
56 changes: 0 additions & 56 deletions testcrate/tests/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,59 +207,3 @@ fn bswap() {
);
}
}

// This is approximate because of issues related to
// https://github.com/rust-lang/rust/issues/73920.
// TODO how do we resolve this indeterminacy?
macro_rules! pow {
($($f:ty, $tolerance:expr, $fn:ident);*;) => {
$(
#[test]
fn $fn() {
use compiler_builtins::float::pow::$fn;
use compiler_builtins::float::Float;
fuzz_float_2(N, |x: $f, y: $f| {
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK;
let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS;
let n = n as i32;
let tmp0: $f = x.powi(n);
let tmp1: $f = $fn(x, n);
let (a, b) = if tmp0 < tmp1 {
(tmp0, tmp1)
} else {
(tmp1, tmp0)
};
let good = {
if a == b {
// handles infinity equality
true
} else if a < $tolerance {
b < $tolerance
} else {
let quo = b / a;
(quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
}
};
if !good {
panic!(
"{}({}, {}): std: {}, builtins: {}",
stringify!($fn), x, n, tmp0, tmp1
);
}
}
});
}
)*
};
}

#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
mod float_pow {
use super::*;

pow! {
f32, 1e-4, __powisf2;
f64, 1e-12, __powidf2;
}
}

0 comments on commit 9975c79

Please sign in to comment.