Skip to content

Commit 510dfa4

Browse files
committed
fix no_std + libm
1 parent b7780e6 commit 510dfa4

File tree

2 files changed

+183
-4
lines changed

2 files changed

+183
-4
lines changed

src/float.rs

Lines changed: 166 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ use core::f64;
1111

1212
use crate::{Num, NumCast, ToPrimitive};
1313

14+
#[cfg(all(not(feature = "std"), feature = "libm"))]
15+
mod compiler_builtins {
16+
extern "C" {
17+
pub fn floorf16(x: f16) -> f16;
18+
pub fn floorf128(x: f128) -> f128;
19+
pub fn ceilf16(x: f16) -> f16;
20+
pub fn ceilf128(x: f128) -> f128;
21+
pub fn roundf16(x: f16) -> f16;
22+
pub fn roundf128(x: f128) -> f128;
23+
pub fn truncf16(x: f16) -> f16;
24+
pub fn truncf128(x: f128) -> f128;
25+
pub fn fdimf16(x: f16, y: f16) -> f16;
26+
pub fn fdimf128(x: f128, y: f128) -> f128;
27+
}
28+
}
29+
1430
/// Generic trait for floating point numbers that works with `no_std`.
1531
///
1632
/// This trait implements a subset of the `Float` trait.
@@ -852,8 +868,24 @@ impl FloatCore for f16 {
852868
Self::powi(self, n: i32) -> Self;
853869
}
854870

855-
// TODO:
856-
// use floor, ceil, round, trunc, abs and fract provided by libm
871+
#[cfg(all(not(feature = "std"), feature = "libm"))]
872+
forward! {
873+
unsafe compiler_builtins::floorf16 as floor(self) -> Self;
874+
unsafe compiler_builtins::ceilf16 as ceil(self) -> Self;
875+
unsafe compiler_builtins::roundf16 as round(self) -> Self;
876+
unsafe compiler_builtins::truncf16 as trunc(self) -> Self;
877+
}
878+
879+
#[cfg(all(not(feature = "std"), feature = "libm"))]
880+
forward! {
881+
f16::abs as abs(self) -> Self;
882+
}
883+
884+
#[cfg(all(not(feature = "std"), feature = "libm"))]
885+
#[inline]
886+
fn fract(self) -> Self {
887+
self - unsafe { compiler_builtins::truncf16(self) as Self }
888+
}
857889
}
858890

859891
impl FloatCore for f32 {
@@ -1026,8 +1058,24 @@ impl FloatCore for f128 {
10261058
Self::powi(self, n: i32) -> Self;
10271059
}
10281060

1029-
// TODO:
1030-
// use floor, ceil, round, trunc, abs and fract provided by libm
1061+
#[cfg(all(not(feature = "std"), feature = "libm"))]
1062+
forward! {
1063+
unsafe compiler_builtins::floorf128 as floor(self) -> Self;
1064+
unsafe compiler_builtins::ceilf128 as ceil(self) -> Self;
1065+
unsafe compiler_builtins::roundf128 as round(self) -> Self;
1066+
unsafe compiler_builtins::truncf128 as trunc(self) -> Self;
1067+
}
1068+
1069+
#[cfg(all(not(feature = "std"), feature = "libm"))]
1070+
forward! {
1071+
f128::abs as abs(self) -> Self;
1072+
}
1073+
1074+
#[cfg(all(not(feature = "std"), feature = "libm"))]
1075+
#[inline]
1076+
fn fract(self) -> Self {
1077+
self - unsafe { compiler_builtins::truncf128(self) as Self }
1078+
}
10311079
}
10321080

10331081
// FIXME: these doctests aren't actually helpful, because they're using and
@@ -2232,6 +2280,63 @@ float_impl_std!(f64 integer_decode_f64);
22322280
#[cfg(feature = "std")]
22332281
float_impl_std!(f128 integer_decode_f128_truncated);
22342282

2283+
#[cfg(all(not(feature = "std"), feature = "libm"))]
2284+
impl Float for f16 {
2285+
float_impl_libm!(f16 integer_decode_f16);
2286+
2287+
#[inline]
2288+
#[allow(deprecated)]
2289+
fn abs_sub(self, other: Self) -> Self {
2290+
unsafe { compiler_builtins::fdimf16(self, other) as Self }
2291+
}
2292+
2293+
forward! {
2294+
unsafe compiler_builtins::floorf16 as floor(self) -> Self;
2295+
unsafe compiler_builtins::ceilf16 as ceil(self) -> Self;
2296+
unsafe compiler_builtins::roundf16 as round(self) -> Self;
2297+
unsafe compiler_builtins::truncf16 as trunc(self) -> Self;
2298+
}
2299+
2300+
cast_forward_cast! {
2301+
[f32] libm::fmaf as mul_add(self, a: Self, b: Self) -> Self;
2302+
[f32] libm::powf as powf(self, n: Self) -> Self;
2303+
[f32] libm::sqrtf as sqrt(self) -> Self;
2304+
[f32] libm::expf as exp(self) -> Self;
2305+
[f32] libm::exp2f as exp2(self) -> Self;
2306+
[f32] libm::logf as ln(self) -> Self;
2307+
[f32] libm::log2f as log2(self) -> Self;
2308+
[f32] libm::log10f as log10(self) -> Self;
2309+
[f32] libm::cbrtf as cbrt(self) -> Self;
2310+
[f32] libm::hypotf as hypot(self, other: Self) -> Self;
2311+
[f32] libm::sinf as sin(self) -> Self;
2312+
[f32] libm::cosf as cos(self) -> Self;
2313+
[f32] libm::tanf as tan(self) -> Self;
2314+
[f32] libm::asinf as asin(self) -> Self;
2315+
[f32] libm::acosf as acos(self) -> Self;
2316+
[f32] libm::atanf as atan(self) -> Self;
2317+
[f32] libm::atan2f as atan2(self, other: Self) -> Self;
2318+
[f32] libm::expm1f as exp_m1(self) -> Self;
2319+
[f32] libm::log1pf as ln_1p(self) -> Self;
2320+
[f32] libm::sinhf as sinh(self) -> Self;
2321+
[f32] libm::coshf as cosh(self) -> Self;
2322+
[f32] libm::tanhf as tanh(self) -> Self;
2323+
[f32] libm::asinhf as asinh(self) -> Self;
2324+
[f32] libm::acoshf as acosh(self) -> Self;
2325+
[f32] libm::atanhf as atanh(self) -> Self;
2326+
}
2327+
2328+
forward! {
2329+
f16::abs as abs(self) -> Self;
2330+
f16::copysign as copysign(self, other: Self) -> Self;
2331+
}
2332+
2333+
#[inline]
2334+
fn sin_cos(self) -> (Self, Self) {
2335+
let (x, y) = libm::sincosf(self as f32);
2336+
(x as Self, y as Self)
2337+
}
2338+
}
2339+
22352340
#[cfg(all(not(feature = "std"), feature = "libm"))]
22362341
impl Float for f32 {
22372342
float_impl_libm!(f32 integer_decode_f32);
@@ -2324,6 +2429,63 @@ impl Float for f64 {
23242429
}
23252430
}
23262431

2432+
#[cfg(all(not(feature = "std"), feature = "libm"))]
2433+
impl Float for f128 {
2434+
float_impl_libm!(f128 integer_decode_f128_truncated);
2435+
2436+
#[inline]
2437+
#[allow(deprecated)]
2438+
fn abs_sub(self, other: Self) -> Self {
2439+
unsafe { compiler_builtins::fdimf128(self, other) as Self }
2440+
}
2441+
2442+
forward! {
2443+
unsafe compiler_builtins::floorf128 as floor(self) -> Self;
2444+
unsafe compiler_builtins::ceilf128 as ceil(self) -> Self;
2445+
unsafe compiler_builtins::roundf128 as round(self) -> Self;
2446+
unsafe compiler_builtins::truncf128 as trunc(self) -> Self;
2447+
}
2448+
2449+
cast_forward_cast! {
2450+
[f64] libm::fma as mul_add(self, a: Self, b: Self) -> Self;
2451+
[f64] libm::pow as powf(self, n: Self) -> Self;
2452+
[f64] libm::sqrt as sqrt(self) -> Self;
2453+
[f64] libm::exp as exp(self) -> Self;
2454+
[f64] libm::exp2 as exp2(self) -> Self;
2455+
[f64] libm::log as ln(self) -> Self;
2456+
[f64] libm::log2 as log2(self) -> Self;
2457+
[f64] libm::log10 as log10(self) -> Self;
2458+
[f64] libm::cbrt as cbrt(self) -> Self;
2459+
[f64] libm::hypot as hypot(self, other: Self) -> Self;
2460+
[f64] libm::sin as sin(self) -> Self;
2461+
[f64] libm::cos as cos(self) -> Self;
2462+
[f64] libm::tan as tan(self) -> Self;
2463+
[f64] libm::asin as asin(self) -> Self;
2464+
[f64] libm::acos as acos(self) -> Self;
2465+
[f64] libm::atan as atan(self) -> Self;
2466+
[f64] libm::atan2 as atan2(self, other: Self) -> Self;
2467+
[f64] libm::expm1 as exp_m1(self) -> Self;
2468+
[f64] libm::log1p as ln_1p(self) -> Self;
2469+
[f64] libm::sinh as sinh(self) -> Self;
2470+
[f64] libm::cosh as cosh(self) -> Self;
2471+
[f64] libm::tanh as tanh(self) -> Self;
2472+
[f64] libm::asinh as asinh(self) -> Self;
2473+
[f64] libm::acosh as acosh(self) -> Self;
2474+
[f64] libm::atanh as atanh(self) -> Self;
2475+
}
2476+
2477+
forward! {
2478+
f128::abs as abs(self) -> Self;
2479+
f128::copysign as copysign(self, other: Self) -> Self;
2480+
}
2481+
2482+
#[inline]
2483+
fn sin_cos(self) -> (Self, Self) {
2484+
let (x, y) = libm::sincos(self as f64);
2485+
(x as Self, y as Self)
2486+
}
2487+
}
2488+
23272489
macro_rules! float_const_impl {
23282490
($(#[$doc:meta] $constant:ident,)+) => (
23292491
#[allow(non_snake_case)]

src/macros.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33

44
/// Forward a method to an inherent method or a base trait method.
55
macro_rules! forward {
6+
($( unsafe $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
7+
=> {$(
8+
#[inline]
9+
fn $method(self $( , $arg : $ty )* ) -> $ret {
10+
unsafe { $imp(self $( , $arg )* ) }
11+
}
12+
)*};
613
($( Self :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
714
=> {$(
815
#[inline]
@@ -33,6 +40,16 @@ macro_rules! forward {
3340
)*};
3441
}
3542

43+
macro_rules! cast_forward_cast {
44+
($( [$cast:ty] $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
45+
=> {$(
46+
#[inline]
47+
fn $method(self $( , $arg : $ty )* ) -> $ret {
48+
$imp(self as $cast $( , $arg as $cast)* ) as $ret
49+
}
50+
)*};
51+
}
52+
3653
macro_rules! constant {
3754
($( $method:ident () -> $ret:expr ; )*)
3855
=> {$(

0 commit comments

Comments
 (0)