Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}
Loading