This commit is contained in:
Aaron Kutch
2020-12-10 20:30:48 -06:00
parent 96a6110d69
commit 3871282eee
3 changed files with 51 additions and 44 deletions

View File

@@ -15,6 +15,7 @@ pub mod sub;
#[doc(hidden)]
pub trait Float:
Copy
+ core::fmt::Debug
+ PartialEq
+ PartialOrd
+ ops::AddAssign

View File

@@ -1,39 +1,36 @@
use float::Float;
use int::Int;
trait Pow: Float {
/// Returns `a` raised to the power `b`
fn pow(self, mut b: i32) -> Self {
let mut a = self;
fn pow<F: Float>(a: F, b: i32) -> F {
let mut a = a;
let recip = b < 0;
let mut r = Self::ONE;
let mut pow = i32::abs_diff(b, 0);
let mut mul = F::ONE;
loop {
if (b & 1) != 0 {
r *= a;
if (pow & 1) != 0 {
mul *= a;
}
b = ((b as u32) >> 1) as i32;
if b == 0 {
pow >>= 1;
if pow == 0 {
break;
}
a *= a;
}
if recip {
Self::ONE / r
F::ONE / mul
} else {
r
mul
}
}
}
impl Pow for f32 {}
impl Pow for f64 {}
intrinsics! {
pub extern "C" fn __powisf2(a: f32, b: i32) -> f32 {
a.pow(b)
pow(a, b)
}
pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 {
a.pow(b)
pow(a, b)
}
}

View File

@@ -126,22 +126,39 @@ fn float_extend_arm() {
extend!(f32, f64, __extendsfdf2vfp);
}
// This doesn't quite work because of issues related to
// This is approximate because of issues related to
// https://github.com/rust-lang/rust/issues/73920.
// TODO how do we resolve this?
/*
// TODO how do we resolve this indeterminacy?
macro_rules! pow {
($($f:ty, $fn:ident);*;) => {
($($f:ty, $tolerance:expr, $fn:ident);*;) => {
$(
fuzz_float_2(N, |x: $f, y: $f| {
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x < 0. || y < 0.) {
let n = y as i32;
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);
if tmp0 != tmp1 {
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, y, tmp0, tmp1
stringify!($fn), x, n, tmp0, tmp1
);
}
}
@@ -150,21 +167,13 @@ macro_rules! pow {
};
}
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[test]
fn float_pow() {
use compiler_builtins::float::pow::{__powidf2, __powisf2};
pow!(
f32, __powisf2;
f64, __powidf2;
f32, 1e-4, __powisf2;
f64, 1e-12, __powidf2;
);
}
*/
// placeholder test to make sure basic functionality works
#[test]
fn float_pow() {
use compiler_builtins::float::pow::{__powidf2, __powisf2};
assert_eq!(__powisf2(-3.0, 3), -27.0);
assert_eq!(__powidf2(-3.0, 3), -27.0);
}