From 322b8f7c5fb0074c1cfc959b8bba4e991d604438 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Mon, 27 May 2019 17:00:03 +0700 Subject: [PATCH 1/8] Add newlib fdlibm Ported from https://github.com/eblot/newlib/blob/master/newlib/libm/common/fdlibm.h --- src/math/mod.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/math/mod.rs b/src/math/mod.rs index 48b400a92..d1a872759 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -344,3 +344,97 @@ fn with_set_low_word(f: f64, lo: u32) -> f64 { fn combine_words(hi: u32, lo: u32) -> f64 { f64::from_bits((hi as u64) << 32 | lo as u64) } + +mod fdlibm { + /* @(#)fdlibm.h 5.1 93/09/24 */ + /* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + #![allow(dead_code)] + + /* Most routines need to check whether a float is finite, infinite, or not a + number, and many need to know whether the result of an operation will + overflow. These conditions depend on whether the largest exponent is + used for NaNs & infinities, or whether it's used for finite numbers. */ + + /// True if a positive float with bitmask X is finite. + #[inline] + #[allow(non_snake_case)] + pub fn FLT_UWORD_IS_FINITE(x: u32) -> bool { + x < INFINITE + } + + /// True if a positive float with bitmask X is not a number. + #[inline] + #[allow(non_snake_case)] + pub fn FLT_UWORD_IS_NAN(x: u32) -> bool { + x > INFINITE + } + + /// True if a positive float with bitmask X is +infinity. + #[inline] + #[allow(non_snake_case)] + pub fn FLT_UWORD_IS_INFINITE(x: u32) -> bool { + x == INFINITE + } + + const INFINITE: u32 = 0x7f80_0000; + + /// The bitmask of FLT_MAX. + pub const FLT_UWORD_MAX: u32 = 0x7f7f_ffff; + /// The bitmask of FLT_MAX/2. + pub const FLT_UWORD_HALF_MAX: u32 = FLT_UWORD_MAX - (1 << 23); + /// The bitmask of the largest finite exponent (129 if the largest + /// exponent is used for finite numbers, 128 otherwise). + pub const FLT_UWORD_EXP_MAX: u32 = 0x4300_0000; + /// The bitmask of log(FLT_MAX), rounded down. This value is the largest + /// input that can be passed to exp() without producing overflow. + pub const FLT_UWORD_LOG_MAX: u32 = 0x42b1_7217; + /// The bitmask of log(2*FLT_MAX), rounded down. This value is the + /// largest input than can be passed to cosh() without producing + /// overflow. + pub const FLT_UWORD_LOG_2MAX: u32 = 0x42b2_d4fc; + /// The largest biased exponent that can be used for finite numbers + /// (255 if the largest exponent is used for finite numbers, 254 + /// otherwise) + pub const FLT_LARGEST_EXP: u32 = FLT_UWORD_MAX >> 23; + pub const HUGE: f32 = 3.402_823_466_385_288_60e+38; + + /* Many routines check for zero and subnormal numbers. Such things depend + on whether the target supports denormals or not */ + + /// True if a positive float with bitmask X is +0. Without denormals, + /// any float with a zero exponent is a +0 representation. With + /// denormals, the only +0 representation is a 0 bitmask. + #[inline] + #[allow(non_snake_case)] + pub fn FLT_UWORD_IS_ZERO(x: u32) -> bool { + x == 0 + } + + /// True if a non-zero positive float with bitmask X is subnormal. + /// (Routines should check for zeros first.) + #[inline] + #[allow(non_snake_case)] + pub fn FLT_UWORD_IS_SUBNORMAL(x: u32) -> bool { + x < 0x0080_0000 + } + + /// The bitmask of the smallest float above +0. Call this number REAL_FLT_MIN... + pub const FLT_UWORD_MIN: u32 = 0x0000_0001; + /// The bitmask of the float representation of REAL_FLT_MIN's exponent. + pub const FLT_UWORD_EXP_MIN: u32 = 0x4316_0000; + /// The bitmask of |log(REAL_FLT_MIN)|, rounding down. + pub const FLT_UWORD_LOG_MIN: u32 = 0x42cf_f1b5; + /// REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, + /// -22 if they are). + pub const FLT_SMALLEST_EXP: i32 = -22; +} From ce5dd4701e1690e56450f7b84e81ab31c6b33f68 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 7 Jul 2019 15:26:08 +0700 Subject: [PATCH 2/8] WIP make functions pub(crate) --- src/math/mod.rs | 52 +++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/math/mod.rs b/src/math/mod.rs index d1a872759..be28649e7 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -346,6 +346,9 @@ fn combine_words(hi: u32, lo: u32) -> f64 { } mod fdlibm { + #![allow(dead_code)] // FIXME: remove it after other dependent codes merged + #![allow(non_snake_case)] + /* @(#)fdlibm.h 5.1 93/09/24 */ /* * ==================================================== @@ -358,55 +361,50 @@ mod fdlibm { * ==================================================== */ - #![allow(dead_code)] - /* Most routines need to check whether a float is finite, infinite, or not a number, and many need to know whether the result of an operation will overflow. These conditions depend on whether the largest exponent is used for NaNs & infinities, or whether it's used for finite numbers. */ /// True if a positive float with bitmask X is finite. - #[inline] - #[allow(non_snake_case)] - pub fn FLT_UWORD_IS_FINITE(x: u32) -> bool { + #[inline(always)] + pub(crate) fn FLT_UWORD_IS_FINITE(x: u32) -> bool { x < INFINITE } /// True if a positive float with bitmask X is not a number. - #[inline] - #[allow(non_snake_case)] - pub fn FLT_UWORD_IS_NAN(x: u32) -> bool { + #[inline(always)] + pub(crate) fn FLT_UWORD_IS_NAN(x: u32) -> bool { x > INFINITE } /// True if a positive float with bitmask X is +infinity. - #[inline] - #[allow(non_snake_case)] - pub fn FLT_UWORD_IS_INFINITE(x: u32) -> bool { + #[inline(always)] + pub(crate) fn FLT_UWORD_IS_INFINITE(x: u32) -> bool { x == INFINITE } const INFINITE: u32 = 0x7f80_0000; /// The bitmask of FLT_MAX. - pub const FLT_UWORD_MAX: u32 = 0x7f7f_ffff; + pub(crate) const FLT_UWORD_MAX: u32 = 0x7f7f_ffff; /// The bitmask of FLT_MAX/2. - pub const FLT_UWORD_HALF_MAX: u32 = FLT_UWORD_MAX - (1 << 23); + pub(crate) const FLT_UWORD_HALF_MAX: u32 = FLT_UWORD_MAX - (1 << 23); /// The bitmask of the largest finite exponent (129 if the largest /// exponent is used for finite numbers, 128 otherwise). - pub const FLT_UWORD_EXP_MAX: u32 = 0x4300_0000; + pub(crate) const FLT_UWORD_EXP_MAX: u32 = 0x4300_0000; /// The bitmask of log(FLT_MAX), rounded down. This value is the largest /// input that can be passed to exp() without producing overflow. - pub const FLT_UWORD_LOG_MAX: u32 = 0x42b1_7217; + pub(crate) const FLT_UWORD_LOG_MAX: u32 = 0x42b1_7217; /// The bitmask of log(2*FLT_MAX), rounded down. This value is the /// largest input than can be passed to cosh() without producing /// overflow. - pub const FLT_UWORD_LOG_2MAX: u32 = 0x42b2_d4fc; + pub(crate) const FLT_UWORD_LOG_2MAX: u32 = 0x42b2_d4fc; /// The largest biased exponent that can be used for finite numbers /// (255 if the largest exponent is used for finite numbers, 254 /// otherwise) - pub const FLT_LARGEST_EXP: u32 = FLT_UWORD_MAX >> 23; - pub const HUGE: f32 = 3.402_823_466_385_288_60e+38; + pub(crate) const FLT_LARGEST_EXP: u32 = FLT_UWORD_MAX >> 23; + pub(crate) const HUGE: f32 = 3.402_823_466_385_288_60e+38; /* Many routines check for zero and subnormal numbers. Such things depend on whether the target supports denormals or not */ @@ -414,27 +412,25 @@ mod fdlibm { /// True if a positive float with bitmask X is +0. Without denormals, /// any float with a zero exponent is a +0 representation. With /// denormals, the only +0 representation is a 0 bitmask. - #[inline] - #[allow(non_snake_case)] - pub fn FLT_UWORD_IS_ZERO(x: u32) -> bool { + #[inline(always)] + pub(crate) fn FLT_UWORD_IS_ZERO(x: u32) -> bool { x == 0 } /// True if a non-zero positive float with bitmask X is subnormal. /// (Routines should check for zeros first.) - #[inline] - #[allow(non_snake_case)] - pub fn FLT_UWORD_IS_SUBNORMAL(x: u32) -> bool { + #[inline(always)] + pub(crate) fn FLT_UWORD_IS_SUBNORMAL(x: u32) -> bool { x < 0x0080_0000 } /// The bitmask of the smallest float above +0. Call this number REAL_FLT_MIN... - pub const FLT_UWORD_MIN: u32 = 0x0000_0001; + pub(crate) const FLT_UWORD_MIN: u32 = 0x0000_0001; /// The bitmask of the float representation of REAL_FLT_MIN's exponent. - pub const FLT_UWORD_EXP_MIN: u32 = 0x4316_0000; + pub(crate) const FLT_UWORD_EXP_MIN: u32 = 0x4316_0000; /// The bitmask of |log(REAL_FLT_MIN)|, rounding down. - pub const FLT_UWORD_LOG_MIN: u32 = 0x42cf_f1b5; + pub(crate) const FLT_UWORD_LOG_MIN: u32 = 0x42cf_f1b5; /// REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, /// -22 if they are). - pub const FLT_SMALLEST_EXP: i32 = -22; + pub(crate) const FLT_SMALLEST_EXP: i32 = -22; } From 80a730c6de17a5dd2f87f1601d8b84cb00fd63e5 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 7 Jul 2019 16:05:38 +0700 Subject: [PATCH 3/8] WIP do not always inline, let LLVM decide --- src/math/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/math/mod.rs b/src/math/mod.rs index be28649e7..3c7d05111 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -367,19 +367,19 @@ mod fdlibm { used for NaNs & infinities, or whether it's used for finite numbers. */ /// True if a positive float with bitmask X is finite. - #[inline(always)] + #[inline] pub(crate) fn FLT_UWORD_IS_FINITE(x: u32) -> bool { x < INFINITE } /// True if a positive float with bitmask X is not a number. - #[inline(always)] + #[inline] pub(crate) fn FLT_UWORD_IS_NAN(x: u32) -> bool { x > INFINITE } /// True if a positive float with bitmask X is +infinity. - #[inline(always)] + #[inline] pub(crate) fn FLT_UWORD_IS_INFINITE(x: u32) -> bool { x == INFINITE } @@ -412,14 +412,14 @@ mod fdlibm { /// True if a positive float with bitmask X is +0. Without denormals, /// any float with a zero exponent is a +0 representation. With /// denormals, the only +0 representation is a 0 bitmask. - #[inline(always)] + #[inline] pub(crate) fn FLT_UWORD_IS_ZERO(x: u32) -> bool { x == 0 } /// True if a non-zero positive float with bitmask X is subnormal. /// (Routines should check for zeros first.) - #[inline(always)] + #[inline] pub(crate) fn FLT_UWORD_IS_SUBNORMAL(x: u32) -> bool { x < 0x0080_0000 } From 4bbd418b76d3849c6126e796d7a85c027e595db0 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 26 May 2019 18:28:06 +0700 Subject: [PATCH 4/8] Move src/math/sqrtf.rs -> src/musl/ --- src/lib.rs | 1 + src/musl.rs | 14 ++++++++++++++ src/{math => musl}/sqrtf.rs | 1 + 3 files changed, 16 insertions(+) create mode 100644 src/musl.rs rename src/{math => musl}/sqrtf.rs (97%) diff --git a/src/lib.rs b/src/lib.rs index b15857dbe..8dee60ac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ )] mod math; +mod musl; use core::{f32, f64}; diff --git a/src/musl.rs b/src/musl.rs new file mode 100644 index 000000000..e808087fa --- /dev/null +++ b/src/musl.rs @@ -0,0 +1,14 @@ +macro_rules! llvm_intrinsically_optimized { + (#[cfg($($clause:tt)*)] $e:expr) => { + #[cfg(all(not(feature = "stable"), $($clause)*))] + { + if true { // thwart the dead code lint + $e + } + } + }; +} + +mod sqrtf; + +pub use self::sqrtf::sqrtf; diff --git a/src/math/sqrtf.rs b/src/musl/sqrtf.rs similarity index 97% rename from src/math/sqrtf.rs rename to src/musl/sqrtf.rs index b9365c617..5244af6d3 100644 --- a/src/math/sqrtf.rs +++ b/src/musl/sqrtf.rs @@ -12,6 +12,7 @@ * is preserved. * ==================================================== */ +#![allow(dead_code)] // not deadcode, just for debug and warnings const TINY: f32 = 1.0e-30; From 5915a19218f953e6efba1d14cd127fe034766e9e Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 26 May 2019 20:40:19 +0700 Subject: [PATCH 5/8] Add newlib sqrtf --- src/math/sqrtf.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/math/sqrtf.rs diff --git a/src/math/sqrtf.rs b/src/math/sqrtf.rs new file mode 100644 index 000000000..9593687b3 --- /dev/null +++ b/src/math/sqrtf.rs @@ -0,0 +1,115 @@ +/* ef_sqrtf.c -- float version of e_sqrt.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +const ONE: f32 = 1.0; +const TINY: f32 = 1.0e-30; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sqrtf(x: f32) -> f32 { + use super::fdlibm::{FLT_UWORD_IS_FINITE, FLT_UWORD_IS_SUBNORMAL, FLT_UWORD_IS_ZERO}; + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.sqrt` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return if x < 0.0 { + ::core::f32::NAN + } else { + unsafe { ::core::intrinsics::sqrtf32(x) } + } + } + } + + let mut z: f32; + + let mut r: u32; + let hx: u32; + + let mut ix: i32; + let mut s: i32; + let mut q: i32; + let mut m: i32; + let mut t: i32; + let mut i: i32; + + ix = x.to_bits() as i32; + hx = ix as u32 & 0x7fff_ffff; + + /* take care of Inf and NaN */ + if !FLT_UWORD_IS_FINITE(hx) { + return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ + } + + /* take care of zero and -ves */ + if FLT_UWORD_IS_ZERO(hx) { + return x; /* sqrt(+-0) = +-0 */ + } + if ix < 0 { + return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ + } + + /* normalize x */ + m = ix >> 23; + if FLT_UWORD_IS_SUBNORMAL(hx) { + /* subnormal x */ + i = 0; + while ix & 0x0080_0000 == 0 { + ix <<= 1; + i += 1; + } + m -= i - 1; + } + m -= 127; /* unbias exponent */ + ix = (ix & 0x007f_ffff) | 0x0080_0000; + /* odd m, double x to make it even */ + if m & 1 == 1 { + ix += ix; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = 0; + s = 0; /* q = sqrt(x) */ + r = 0x0100_0000; /* r = moving bit from right to left */ + + while r != 0 { + t = s + r as i32; + if t <= ix { + s = t + r as i32; + ix -= t; + q += r as i32; + } + ix += ix; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if ix != 0 { + z = ONE - TINY; /* trigger inexact flag */ + if z >= ONE { + z = ONE + TINY; + if z > ONE { + q += 2; + } else { + q += q & 1; + } + } + } + ix = (q >> 1) + 0x3f00_0000; + ix += m << 23; + f32::from_bits(ix as u32) +} From 09b9214f57c62470c35be686ee5089b9b5247420 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 7 Jul 2019 16:19:59 +0700 Subject: [PATCH 6/8] Revert "Move src/math/sqrtf.rs -> src/musl/" This reverts commit 4bbd418b76d3849c6126e796d7a85c027e595db0. --- src/lib.rs | 1 - src/musl.rs | 14 ------ src/musl/sqrtf.rs | 113 ---------------------------------------------- 3 files changed, 128 deletions(-) delete mode 100644 src/musl.rs delete mode 100644 src/musl/sqrtf.rs diff --git a/src/lib.rs b/src/lib.rs index 8dee60ac8..b15857dbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ )] mod math; -mod musl; use core::{f32, f64}; diff --git a/src/musl.rs b/src/musl.rs deleted file mode 100644 index e808087fa..000000000 --- a/src/musl.rs +++ /dev/null @@ -1,14 +0,0 @@ -macro_rules! llvm_intrinsically_optimized { - (#[cfg($($clause:tt)*)] $e:expr) => { - #[cfg(all(not(feature = "stable"), $($clause)*))] - { - if true { // thwart the dead code lint - $e - } - } - }; -} - -mod sqrtf; - -pub use self::sqrtf::sqrtf; diff --git a/src/musl/sqrtf.rs b/src/musl/sqrtf.rs deleted file mode 100644 index 5244af6d3..000000000 --- a/src/musl/sqrtf.rs +++ /dev/null @@ -1,113 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -#![allow(dead_code)] // not deadcode, just for debug and warnings - -const TINY: f32 = 1.0e-30; - -#[inline] -#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] -pub fn sqrtf(x: f32) -> f32 { - // On wasm32 we know that LLVM's intrinsic will compile to an optimized - // `f32.sqrt` native instruction, so we can leverage this for both code size - // and speed. - llvm_intrinsically_optimized! { - #[cfg(target_arch = "wasm32")] { - return if x < 0.0 { - ::core::f32::NAN - } else { - unsafe { ::core::intrinsics::sqrtf32(x) } - } - } - } - let mut z: f32; - let sign: i32 = 0x80000000u32 as i32; - let mut ix: i32; - let mut s: i32; - let mut q: i32; - let mut m: i32; - let mut t: i32; - let mut i: i32; - let mut r: u32; - - ix = x.to_bits() as i32; - - /* take care of Inf and NaN */ - if (ix as u32 & 0x7f800000) == 0x7f800000 { - return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ - } - - /* take care of zero */ - if ix <= 0 { - if (ix & !sign) == 0 { - return x; /* sqrt(+-0) = +-0 */ - } - if ix < 0 { - return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ - } - } - - /* normalize x */ - m = ix >> 23; - if m == 0 { - /* subnormal x */ - i = 0; - while ix & 0x00800000 == 0 { - ix <<= 1; - i = i + 1; - } - m -= i - 1; - } - m -= 127; /* unbias exponent */ - ix = (ix & 0x007fffff) | 0x00800000; - if m & 1 == 1 { - /* odd m, double x to make it even */ - ix += ix; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix += ix; - q = 0; - s = 0; - r = 0x01000000; /* r = moving bit from right to left */ - - while r != 0 { - t = s + r as i32; - if t <= ix { - s = t + r as i32; - ix -= t; - q += r as i32; - } - ix += ix; - r >>= 1; - } - - /* use floating add to find out rounding direction */ - if ix != 0 { - z = 1.0 - TINY; /* raise inexact flag */ - if z >= 1.0 { - z = 1.0 + TINY; - if z > 1.0 { - q += 2; - } else { - q += q & 1; - } - } - } - - ix = (q >> 1) + 0x3f000000; - ix += m << 23; - f32::from_bits(ix as u32) -} From 55f0f16b66bba8e204cc215dd0ee087ad2397245 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 7 Jul 2019 16:27:42 +0700 Subject: [PATCH 7/8] chore: Make extern C --- src/math/sqrtf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/math/sqrtf.rs b/src/math/sqrtf.rs index 9593687b3..4fe0da5be 100644 --- a/src/math/sqrtf.rs +++ b/src/math/sqrtf.rs @@ -18,7 +18,7 @@ const TINY: f32 = 1.0e-30; #[inline] #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] -pub fn sqrtf(x: f32) -> f32 { +pub extern "C" fn sqrtf(x: f32) -> f32 { use super::fdlibm::{FLT_UWORD_IS_FINITE, FLT_UWORD_IS_SUBNORMAL, FLT_UWORD_IS_ZERO}; // On wasm32 we know that LLVM's intrinsic will compile to an optimized // `f32.sqrt` native instruction, so we can leverage this for both code size From 66d77d97045638f939502cd1ed47b185466769ed Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 7 Jul 2019 16:49:09 +0700 Subject: [PATCH 8/8] WIP tiny fix --- src/math/sqrtf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/math/sqrtf.rs b/src/math/sqrtf.rs index 4fe0da5be..9a4d50205 100644 --- a/src/math/sqrtf.rs +++ b/src/math/sqrtf.rs @@ -26,9 +26,9 @@ pub extern "C" fn sqrtf(x: f32) -> f32 { llvm_intrinsically_optimized! { #[cfg(target_arch = "wasm32")] { return if x < 0.0 { - ::core::f32::NAN + core::f32::NAN } else { - unsafe { ::core::intrinsics::sqrtf32(x) } + unsafe { core::intrinsics::sqrtf32(x) } } } }