#![no_std]
#[cfg(feature = "std")]
extern crate std;
pub trait WasmFloat {
fn wasm_trunc(self) -> Self;
fn wasm_copysign(self, sign: Self) -> Self;
fn wasm_floor(self) -> Self;
fn wasm_ceil(self) -> Self;
fn wasm_sqrt(self) -> Self;
fn wasm_abs(self) -> Self;
fn wasm_nearest(self) -> Self;
fn wasm_minimum(self, other: Self) -> Self;
fn wasm_maximum(self, other: Self) -> Self;
fn wasm_mul_add(self, b: Self, c: Self) -> Self;
}
impl WasmFloat for f32 {
#[inline]
fn wasm_trunc(self) -> f32 {
#[cfg(feature = "std")]
if !cfg!(windows) && !cfg!(target_arch = "riscv64") {
return self.trunc();
}
if self.is_nan() {
return f32::NAN;
}
libm::truncf(self)
}
#[inline]
fn wasm_copysign(self, sign: f32) -> f32 {
#[cfg(feature = "std")]
if true {
return self.copysign(sign);
}
libm::copysignf(self, sign)
}
#[inline]
fn wasm_floor(self) -> f32 {
#[cfg(feature = "std")]
if !cfg!(target_arch = "riscv64") {
return self.floor();
}
if self.is_nan() {
return f32::NAN;
}
libm::floorf(self)
}
#[inline]
fn wasm_ceil(self) -> f32 {
#[cfg(feature = "std")]
if !cfg!(target_arch = "riscv64") {
return self.ceil();
}
if self.is_nan() {
return f32::NAN;
}
libm::ceilf(self)
}
#[inline]
fn wasm_sqrt(self) -> f32 {
#[cfg(feature = "std")]
if true {
return self.sqrt();
}
libm::sqrtf(self)
}
#[inline]
fn wasm_abs(self) -> f32 {
#[cfg(feature = "std")]
if true {
return self.abs();
}
libm::fabsf(self)
}
#[inline]
fn wasm_nearest(self) -> f32 {
#[cfg(feature = "std")]
if !cfg!(windows) && !cfg!(target_arch = "riscv64") {
return self.round_ties_even();
}
if self.is_nan() {
return f32::NAN;
}
let round = libm::roundf(self);
if libm::fabsf(self - round) != 0.5 {
return round;
}
match round % 2.0 {
1.0 => libm::floorf(self),
-1.0 => libm::ceilf(self),
_ => round,
}
}
#[inline]
fn wasm_maximum(self, other: f32) -> f32 {
if self > other {
self
} else if other > self {
other
} else if self == other {
if self.is_sign_positive() && other.is_sign_negative() {
self
} else {
other
}
} else {
self + other
}
}
#[inline]
fn wasm_minimum(self, other: f32) -> f32 {
if self < other {
self
} else if other < self {
other
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() {
self
} else {
other
}
} else {
self + other
}
}
#[inline]
fn wasm_mul_add(self, b: f32, c: f32) -> f32 {
#[cfg(feature = "std")]
if !(cfg!(windows) && cfg!(target_env = "gnu")) {
return self.mul_add(b, c);
}
libm::fmaf(self, b, c)
}
}
impl WasmFloat for f64 {
#[inline]
fn wasm_trunc(self) -> f64 {
#[cfg(feature = "std")]
if !cfg!(windows) && !cfg!(target_arch = "riscv64") {
return self.trunc();
}
if self.is_nan() {
return f64::NAN;
}
libm::trunc(self)
}
#[inline]
fn wasm_copysign(self, sign: f64) -> f64 {
#[cfg(feature = "std")]
if true {
return self.copysign(sign);
}
libm::copysign(self, sign)
}
#[inline]
fn wasm_floor(self) -> f64 {
#[cfg(feature = "std")]
if !cfg!(target_arch = "riscv64") {
return self.floor();
}
if self.is_nan() {
return f64::NAN;
}
libm::floor(self)
}
#[inline]
fn wasm_ceil(self) -> f64 {
#[cfg(feature = "std")]
if !cfg!(target_arch = "riscv64") {
return self.ceil();
}
if self.is_nan() {
return f64::NAN;
}
libm::ceil(self)
}
#[inline]
fn wasm_sqrt(self) -> f64 {
#[cfg(feature = "std")]
if true {
return self.sqrt();
}
libm::sqrt(self)
}
#[inline]
fn wasm_abs(self) -> f64 {
#[cfg(feature = "std")]
if true {
return self.abs();
}
libm::fabs(self)
}
#[inline]
fn wasm_nearest(self) -> f64 {
#[cfg(feature = "std")]
if !cfg!(windows) && !cfg!(target_arch = "riscv64") {
return self.round_ties_even();
}
if self.is_nan() {
return f64::NAN;
}
let round = libm::round(self);
if libm::fabs(self - round) != 0.5 {
return round;
}
match round % 2.0 {
1.0 => libm::floor(self),
-1.0 => libm::ceil(self),
_ => round,
}
}
#[inline]
fn wasm_maximum(self, other: f64) -> f64 {
if self > other {
self
} else if other > self {
other
} else if self == other {
if self.is_sign_positive() && other.is_sign_negative() {
self
} else {
other
}
} else {
self + other
}
}
#[inline]
fn wasm_minimum(self, other: f64) -> f64 {
if self < other {
self
} else if other < self {
other
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() {
self
} else {
other
}
} else {
self + other
}
}
#[inline]
fn wasm_mul_add(self, b: f64, c: f64) -> f64 {
#[cfg(feature = "std")]
if !(cfg!(windows) && cfg!(target_env = "gnu")) {
return self.mul_add(b, c);
}
libm::fma(self, b, c)
}
}