From 65841d8e32f6245b9947ae11650527ebc7e72dbe Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 16 May 2024 14:41:55 -0500 Subject: [PATCH] Add support for `f128` integer exponentiation Adds `__powitf2` --- README.md | 2 +- build.rs | 1 - src/float/pow.rs | 12 ++++++++++++ testcrate/tests/misc.rs | 26 +++++++++++++++++++++++--- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 37d7ab2e..fde542ee 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,7 @@ These builtins are needed to support `f16` and `f128`, which are in the process - [ ] floatunditf.c - [ ] floatunsitf.c - [x] multf3.c -- [ ] powitf2.c +- [x] powitf2.c - [ ] ppc/fixtfdi.c - [ ] ppc/fixunstfdi.c - [ ] ppc/floatditf.c diff --git a/build.rs b/build.rs index ec830ecb..60dc8715 100644 --- a/build.rs +++ b/build.rs @@ -544,7 +544,6 @@ mod c { ("__floatunditf", "floatunditf.c"), ("__floatunsitf", "floatunsitf.c"), ("__divtf3", "divtf3.c"), - ("__powitf2", "powitf2.c"), ("__fe_getround", "fp_mode.c"), ("__fe_raise_inexact", "fp_mode.c"), ]); diff --git a/src/float/pow.rs b/src/float/pow.rs index 3103fe6f..1e0f2289 100644 --- a/src/float/pow.rs +++ b/src/float/pow.rs @@ -35,4 +35,16 @@ intrinsics! { pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 { pow(a, b) } + + #[avr_skip] + #[cfg(not(any(feature = "no-f16-f128", target_arch = "powerpc", target_arch = "powerpc64")))] + pub extern "C" fn __powitf2(a: f128, b: i32) -> f128 { + pow(a, b) + } + + #[avr_skip] + #[cfg(all(not(feature = "no-f16-f128"), any(target_arch = "powerpc", target_arch = "powerpc64")))] + pub extern "C" fn __powikf2(a: f128, b: i32) -> f128 { + pow(a, b) + } } diff --git a/testcrate/tests/misc.rs b/testcrate/tests/misc.rs index cdc37e2a..2fca23c6 100644 --- a/testcrate/tests/misc.rs +++ b/testcrate/tests/misc.rs @@ -1,5 +1,6 @@ // makes configuration easier #![allow(unused_macros)] +#![feature(f128)] use testcrate::*; @@ -96,7 +97,7 @@ fn leading_zeros() { // https://github.com/rust-lang/rust/issues/73920. // TODO how do we resolve this indeterminacy? macro_rules! pow { - ($($f:ty, $tolerance:expr, $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.is_nan()) { @@ -118,12 +119,12 @@ macro_rules! pow { b < $tolerance } else { let quo = b / a; - (quo < (1. + $tolerance)) && (quo > (1. - $tolerance)) + (quo < (1. + black_box($tolerance))) && (quo > (1. - black_box($tolerance))) } }; if !good { panic!( - "{}({}, {}): std: {}, builtins: {}", + "{}({:?}, {:?}): std: {:?}, builtins: {:?}", stringify!($fn), x, n, tmp0, tmp1 ); } @@ -139,8 +140,27 @@ fn float_pow() { use compiler_builtins::float::pow::{__powidf2, __powisf2}; use compiler_builtins::float::Float; + fn black_box(val: T) -> T { + val + } + pow!( f32, 1e-4, __powisf2; f64, 1e-12, __powidf2; ); + + // There is no apfloat fallback for `powi` so we just skip these tests on these platforms + #[cfg(not(any(feature = "no-f16-f128", feature = "no-sys-f128")))] + { + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] + use compiler_builtins::float::pow::__powikf2; + #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] + use compiler_builtins::float::pow::__powitf2; + + // FIXME(f16_f128): we do this to block const eval which currently ICEs. Change this + // once it works correctly. + use core::hint::black_box; + + pow!(f128, 1e-24, __powitf2;); + } }