@@ -11,6 +11,22 @@ use core::f64;
1111
1212use 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
859891impl 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" ) ]
22332281float_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" ) ) ]
22362341impl 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+
23272489macro_rules! float_const_impl {
23282490 ( $( #[ $doc: meta] $constant: ident, ) +) => (
23292491 #[ allow( non_snake_case) ]
0 commit comments