diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/half/src/num_traits.rs | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/half/src/num_traits.rs')
-rw-r--r-- | third_party/rust/half/src/num_traits.rs | 1461 |
1 files changed, 1461 insertions, 0 deletions
diff --git a/third_party/rust/half/src/num_traits.rs b/third_party/rust/half/src/num_traits.rs new file mode 100644 index 0000000000..e5ee490a84 --- /dev/null +++ b/third_party/rust/half/src/num_traits.rs @@ -0,0 +1,1461 @@ +use crate::{bf16, f16}; +use core::cmp::Ordering; +use core::{num::FpCategory, ops::Div}; +use num_traits::{ + AsPrimitive, Bounded, FloatConst, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero, +}; + +impl ToPrimitive for f16 { + #[inline] + fn to_i64(&self) -> Option<i64> { + Self::to_f32(*self).to_i64() + } + #[inline] + fn to_u64(&self) -> Option<u64> { + Self::to_f32(*self).to_u64() + } + #[inline] + fn to_i8(&self) -> Option<i8> { + Self::to_f32(*self).to_i8() + } + #[inline] + fn to_u8(&self) -> Option<u8> { + Self::to_f32(*self).to_u8() + } + #[inline] + fn to_i16(&self) -> Option<i16> { + Self::to_f32(*self).to_i16() + } + #[inline] + fn to_u16(&self) -> Option<u16> { + Self::to_f32(*self).to_u16() + } + #[inline] + fn to_i32(&self) -> Option<i32> { + Self::to_f32(*self).to_i32() + } + #[inline] + fn to_u32(&self) -> Option<u32> { + Self::to_f32(*self).to_u32() + } + #[inline] + fn to_f32(&self) -> Option<f32> { + Some(Self::to_f32(*self)) + } + #[inline] + fn to_f64(&self) -> Option<f64> { + Some(Self::to_f64(*self)) + } +} + +impl FromPrimitive for f16 { + #[inline] + fn from_i64(n: i64) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u64(n: u64) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i8(n: i8) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u8(n: u8) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i16(n: i16) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u16(n: u16) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i32(n: i32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u32(n: u32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_f32(n: f32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_f64(n: f64) -> Option<Self> { + n.to_f64().map(Self::from_f64) + } +} + +impl Num for f16 { + type FromStrRadixErr = <f32 as Num>::FromStrRadixErr; + + #[inline] + fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { + Ok(Self::from_f32(f32::from_str_radix(str, radix)?)) + } +} + +impl One for f16 { + #[inline] + fn one() -> Self { + Self::ONE + } +} + +impl Zero for f16 { + #[inline] + fn zero() -> Self { + Self::ZERO + } + + #[inline] + fn is_zero(&self) -> bool { + *self == Self::ZERO + } +} + +impl NumCast for f16 { + #[inline] + fn from<T: ToPrimitive>(n: T) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } +} + +impl num_traits::float::FloatCore for f16 { + #[inline] + fn infinity() -> Self { + Self::INFINITY + } + + #[inline] + fn neg_infinity() -> Self { + Self::NEG_INFINITY + } + + #[inline] + fn nan() -> Self { + Self::NAN + } + + #[inline] + fn neg_zero() -> Self { + Self::NEG_ZERO + } + + #[inline] + fn min_value() -> Self { + Self::MIN + } + + #[inline] + fn min_positive_value() -> Self { + Self::MIN_POSITIVE + } + + #[inline] + fn epsilon() -> Self { + Self::EPSILON + } + + #[inline] + fn max_value() -> Self { + Self::MAX + } + + #[inline] + fn is_nan(self) -> bool { + self.is_nan() + } + + #[inline] + fn is_infinite(self) -> bool { + self.is_infinite() + } + + #[inline] + fn is_finite(self) -> bool { + self.is_finite() + } + + #[inline] + fn is_normal(self) -> bool { + self.is_normal() + } + + #[inline] + fn classify(self) -> FpCategory { + self.classify() + } + + #[inline] + fn floor(self) -> Self { + Self::from_f32(self.to_f32().floor()) + } + + #[inline] + fn ceil(self) -> Self { + Self::from_f32(self.to_f32().ceil()) + } + + #[inline] + fn round(self) -> Self { + Self::from_f32(self.to_f32().round()) + } + + #[inline] + fn trunc(self) -> Self { + Self::from_f32(self.to_f32().trunc()) + } + + #[inline] + fn fract(self) -> Self { + Self::from_f32(self.to_f32().fract()) + } + + #[inline] + fn abs(self) -> Self { + Self::from_bits(self.to_bits() & 0x7FFF) + } + + #[inline] + fn signum(self) -> Self { + self.signum() + } + + #[inline] + fn is_sign_positive(self) -> bool { + self.is_sign_positive() + } + + #[inline] + fn is_sign_negative(self) -> bool { + self.is_sign_negative() + } + + fn min(self, other: Self) -> Self { + match self.partial_cmp(&other) { + None => { + if self.is_nan() { + other + } else { + self + } + } + Some(Ordering::Greater) | Some(Ordering::Equal) => other, + Some(Ordering::Less) => self, + } + } + + fn max(self, other: Self) -> Self { + match self.partial_cmp(&other) { + None => { + if self.is_nan() { + other + } else { + self + } + } + Some(Ordering::Greater) | Some(Ordering::Equal) => self, + Some(Ordering::Less) => other, + } + } + + #[inline] + fn recip(self) -> Self { + Self::from_f32(self.to_f32().recip()) + } + + #[inline] + fn powi(self, exp: i32) -> Self { + Self::from_f32(self.to_f32().powi(exp)) + } + + #[inline] + fn to_degrees(self) -> Self { + Self::from_f32(self.to_f32().to_degrees()) + } + + #[inline] + fn to_radians(self) -> Self { + Self::from_f32(self.to_f32().to_radians()) + } + + #[inline] + fn integer_decode(self) -> (u64, i16, i8) { + num_traits::float::FloatCore::integer_decode(self.to_f32()) + } +} + +impl num_traits::float::Float for f16 { + #[inline] + fn nan() -> Self { + Self::NAN + } + + #[inline] + fn infinity() -> Self { + Self::INFINITY + } + + #[inline] + fn neg_infinity() -> Self { + Self::NEG_INFINITY + } + + #[inline] + fn neg_zero() -> Self { + Self::NEG_ZERO + } + + #[inline] + fn min_value() -> Self { + Self::MIN + } + + #[inline] + fn min_positive_value() -> Self { + Self::MIN_POSITIVE + } + + #[inline] + fn epsilon() -> Self { + Self::EPSILON + } + + #[inline] + fn max_value() -> Self { + Self::MAX + } + + #[inline] + fn is_nan(self) -> bool { + self.is_nan() + } + + #[inline] + fn is_infinite(self) -> bool { + self.is_infinite() + } + + #[inline] + fn is_finite(self) -> bool { + self.is_finite() + } + + #[inline] + fn is_normal(self) -> bool { + self.is_normal() + } + + #[inline] + fn classify(self) -> FpCategory { + self.classify() + } + + #[inline] + fn floor(self) -> Self { + Self::from_f32(self.to_f32().floor()) + } + + #[inline] + fn ceil(self) -> Self { + Self::from_f32(self.to_f32().ceil()) + } + + #[inline] + fn round(self) -> Self { + Self::from_f32(self.to_f32().round()) + } + + #[inline] + fn trunc(self) -> Self { + Self::from_f32(self.to_f32().trunc()) + } + + #[inline] + fn fract(self) -> Self { + Self::from_f32(self.to_f32().fract()) + } + + #[inline] + fn abs(self) -> Self { + Self::from_f32(self.to_f32().abs()) + } + + #[inline] + fn signum(self) -> Self { + Self::from_f32(self.to_f32().signum()) + } + + #[inline] + fn is_sign_positive(self) -> bool { + self.is_sign_positive() + } + + #[inline] + fn is_sign_negative(self) -> bool { + self.is_sign_negative() + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + Self::from_f32(self.to_f32().mul_add(a.to_f32(), b.to_f32())) + } + + #[inline] + fn recip(self) -> Self { + Self::from_f32(self.to_f32().recip()) + } + + #[inline] + fn powi(self, n: i32) -> Self { + Self::from_f32(self.to_f32().powi(n)) + } + + #[inline] + fn powf(self, n: Self) -> Self { + Self::from_f32(self.to_f32().powf(n.to_f32())) + } + + #[inline] + fn sqrt(self) -> Self { + Self::from_f32(self.to_f32().sqrt()) + } + + #[inline] + fn exp(self) -> Self { + Self::from_f32(self.to_f32().exp()) + } + + #[inline] + fn exp2(self) -> Self { + Self::from_f32(self.to_f32().exp2()) + } + + #[inline] + fn ln(self) -> Self { + Self::from_f32(self.to_f32().ln()) + } + + #[inline] + fn log(self, base: Self) -> Self { + Self::from_f32(self.to_f32().log(base.to_f32())) + } + + #[inline] + fn log2(self) -> Self { + Self::from_f32(self.to_f32().log2()) + } + + #[inline] + fn log10(self) -> Self { + Self::from_f32(self.to_f32().log10()) + } + + #[inline] + fn to_degrees(self) -> Self { + Self::from_f32(self.to_f32().to_degrees()) + } + + #[inline] + fn to_radians(self) -> Self { + Self::from_f32(self.to_f32().to_radians()) + } + + #[inline] + fn max(self, other: Self) -> Self { + self.max(other) + } + + #[inline] + fn min(self, other: Self) -> Self { + self.min(other) + } + + #[inline] + fn abs_sub(self, other: Self) -> Self { + Self::from_f32((self.to_f32() - other.to_f32()).max(0.0)) + } + + #[inline] + fn cbrt(self) -> Self { + Self::from_f32(self.to_f32().cbrt()) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + Self::from_f32(self.to_f32().hypot(other.to_f32())) + } + + #[inline] + fn sin(self) -> Self { + Self::from_f32(self.to_f32().sin()) + } + + #[inline] + fn cos(self) -> Self { + Self::from_f32(self.to_f32().cos()) + } + + #[inline] + fn tan(self) -> Self { + Self::from_f32(self.to_f32().tan()) + } + + #[inline] + fn asin(self) -> Self { + Self::from_f32(self.to_f32().asin()) + } + + #[inline] + fn acos(self) -> Self { + Self::from_f32(self.to_f32().acos()) + } + + #[inline] + fn atan(self) -> Self { + Self::from_f32(self.to_f32().atan()) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + Self::from_f32(self.to_f32().atan2(other.to_f32())) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + let (sin, cos) = self.to_f32().sin_cos(); + (Self::from_f32(sin), Self::from_f32(cos)) + } + + #[inline] + fn exp_m1(self) -> Self { + Self::from_f32(self.to_f32().exp_m1()) + } + + #[inline] + fn ln_1p(self) -> Self { + Self::from_f32(self.to_f32().ln_1p()) + } + + #[inline] + fn sinh(self) -> Self { + Self::from_f32(self.to_f32().sinh()) + } + + #[inline] + fn cosh(self) -> Self { + Self::from_f32(self.to_f32().cosh()) + } + + #[inline] + fn tanh(self) -> Self { + Self::from_f32(self.to_f32().tanh()) + } + + #[inline] + fn asinh(self) -> Self { + Self::from_f32(self.to_f32().asinh()) + } + + #[inline] + fn acosh(self) -> Self { + Self::from_f32(self.to_f32().acosh()) + } + + #[inline] + fn atanh(self) -> Self { + Self::from_f32(self.to_f32().atanh()) + } + + #[inline] + fn integer_decode(self) -> (u64, i16, i8) { + num_traits::float::Float::integer_decode(self.to_f32()) + } +} + +impl FloatConst for f16 { + #[inline] + fn E() -> Self { + Self::E + } + + #[inline] + fn FRAC_1_PI() -> Self { + Self::FRAC_1_PI + } + + #[inline] + fn FRAC_1_SQRT_2() -> Self { + Self::FRAC_1_SQRT_2 + } + + #[inline] + fn FRAC_2_PI() -> Self { + Self::FRAC_2_PI + } + + #[inline] + fn FRAC_2_SQRT_PI() -> Self { + Self::FRAC_2_SQRT_PI + } + + #[inline] + fn FRAC_PI_2() -> Self { + Self::FRAC_PI_2 + } + + #[inline] + fn FRAC_PI_3() -> Self { + Self::FRAC_PI_3 + } + + #[inline] + fn FRAC_PI_4() -> Self { + Self::FRAC_PI_4 + } + + #[inline] + fn FRAC_PI_6() -> Self { + Self::FRAC_PI_6 + } + + #[inline] + fn FRAC_PI_8() -> Self { + Self::FRAC_PI_8 + } + + #[inline] + fn LN_10() -> Self { + Self::LN_10 + } + + #[inline] + fn LN_2() -> Self { + Self::LN_2 + } + + #[inline] + fn LOG10_E() -> Self { + Self::LOG10_E + } + + #[inline] + fn LOG2_E() -> Self { + Self::LOG2_E + } + + #[inline] + fn PI() -> Self { + Self::PI + } + + fn SQRT_2() -> Self { + Self::SQRT_2 + } + + #[inline] + fn LOG10_2() -> Self + where + Self: Sized + Div<Self, Output = Self>, + { + Self::LOG10_2 + } + + #[inline] + fn LOG2_10() -> Self + where + Self: Sized + Div<Self, Output = Self>, + { + Self::LOG2_10 + } +} + +impl Bounded for f16 { + #[inline] + fn min_value() -> Self { + f16::MIN + } + + #[inline] + fn max_value() -> Self { + f16::MAX + } +} + +macro_rules! impl_as_primitive_to_f16 { + ($ty:ty, $meth:ident) => { + impl AsPrimitive<$ty> for f16 { + #[inline] + fn as_(self) -> $ty { + self.$meth().as_() + } + } + }; +} + +impl_as_primitive_to_f16!(i64, to_f32); +impl_as_primitive_to_f16!(u64, to_f32); +impl_as_primitive_to_f16!(i8, to_f32); +impl_as_primitive_to_f16!(u8, to_f32); +impl_as_primitive_to_f16!(i16, to_f32); +impl_as_primitive_to_f16!(u16, to_f32); +impl_as_primitive_to_f16!(i32, to_f32); +impl_as_primitive_to_f16!(u32, to_f32); +impl_as_primitive_to_f16!(f32, to_f32); +impl_as_primitive_to_f16!(f64, to_f64); + +macro_rules! impl_as_primitive_f16_from { + ($ty:ty, $meth:ident) => { + impl AsPrimitive<f16> for $ty { + #[inline] + fn as_(self) -> f16 { + f16::$meth(self.as_()) + } + } + }; +} + +impl_as_primitive_f16_from!(i64, from_f32); +impl_as_primitive_f16_from!(u64, from_f32); +impl_as_primitive_f16_from!(i8, from_f32); +impl_as_primitive_f16_from!(u8, from_f32); +impl_as_primitive_f16_from!(i16, from_f32); +impl_as_primitive_f16_from!(u16, from_f32); +impl_as_primitive_f16_from!(i32, from_f32); +impl_as_primitive_f16_from!(u32, from_f32); +impl_as_primitive_f16_from!(f32, from_f32); +impl_as_primitive_f16_from!(f64, from_f64); + +impl ToPrimitive for bf16 { + #[inline] + fn to_i64(&self) -> Option<i64> { + Self::to_f32(*self).to_i64() + } + #[inline] + fn to_u64(&self) -> Option<u64> { + Self::to_f32(*self).to_u64() + } + #[inline] + fn to_i8(&self) -> Option<i8> { + Self::to_f32(*self).to_i8() + } + #[inline] + fn to_u8(&self) -> Option<u8> { + Self::to_f32(*self).to_u8() + } + #[inline] + fn to_i16(&self) -> Option<i16> { + Self::to_f32(*self).to_i16() + } + #[inline] + fn to_u16(&self) -> Option<u16> { + Self::to_f32(*self).to_u16() + } + #[inline] + fn to_i32(&self) -> Option<i32> { + Self::to_f32(*self).to_i32() + } + #[inline] + fn to_u32(&self) -> Option<u32> { + Self::to_f32(*self).to_u32() + } + #[inline] + fn to_f32(&self) -> Option<f32> { + Some(Self::to_f32(*self)) + } + #[inline] + fn to_f64(&self) -> Option<f64> { + Some(Self::to_f64(*self)) + } +} + +impl FromPrimitive for bf16 { + #[inline] + fn from_i64(n: i64) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u64(n: u64) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i8(n: i8) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u8(n: u8) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i16(n: i16) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u16(n: u16) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_i32(n: i32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_u32(n: u32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_f32(n: f32) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } + #[inline] + fn from_f64(n: f64) -> Option<Self> { + n.to_f64().map(Self::from_f64) + } +} + +impl Num for bf16 { + type FromStrRadixErr = <f32 as Num>::FromStrRadixErr; + + #[inline] + fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { + Ok(Self::from_f32(f32::from_str_radix(str, radix)?)) + } +} + +impl One for bf16 { + #[inline] + fn one() -> Self { + Self::ONE + } +} + +impl Zero for bf16 { + #[inline] + fn zero() -> Self { + Self::ZERO + } + + #[inline] + fn is_zero(&self) -> bool { + *self == Self::ZERO + } +} + +impl NumCast for bf16 { + #[inline] + fn from<T: ToPrimitive>(n: T) -> Option<Self> { + n.to_f32().map(Self::from_f32) + } +} + +impl num_traits::float::FloatCore for bf16 { + #[inline] + fn infinity() -> Self { + Self::INFINITY + } + + #[inline] + fn neg_infinity() -> Self { + Self::NEG_INFINITY + } + + #[inline] + fn nan() -> Self { + Self::NAN + } + + #[inline] + fn neg_zero() -> Self { + Self::NEG_ZERO + } + + #[inline] + fn min_value() -> Self { + Self::MIN + } + + #[inline] + fn min_positive_value() -> Self { + Self::MIN_POSITIVE + } + + #[inline] + fn epsilon() -> Self { + Self::EPSILON + } + + #[inline] + fn max_value() -> Self { + Self::MAX + } + + #[inline] + fn is_nan(self) -> bool { + self.is_nan() + } + + #[inline] + fn is_infinite(self) -> bool { + self.is_infinite() + } + + #[inline] + fn is_finite(self) -> bool { + self.is_finite() + } + + #[inline] + fn is_normal(self) -> bool { + self.is_normal() + } + + #[inline] + fn classify(self) -> FpCategory { + self.classify() + } + + #[inline] + fn floor(self) -> Self { + Self::from_f32(self.to_f32().floor()) + } + + #[inline] + fn ceil(self) -> Self { + Self::from_f32(self.to_f32().ceil()) + } + + #[inline] + fn round(self) -> Self { + Self::from_f32(self.to_f32().round()) + } + + #[inline] + fn trunc(self) -> Self { + Self::from_f32(self.to_f32().trunc()) + } + + #[inline] + fn fract(self) -> Self { + Self::from_f32(self.to_f32().fract()) + } + + #[inline] + fn abs(self) -> Self { + Self::from_bits(self.to_bits() & 0x7FFF) + } + + #[inline] + fn signum(self) -> Self { + self.signum() + } + + #[inline] + fn is_sign_positive(self) -> bool { + self.is_sign_positive() + } + + #[inline] + fn is_sign_negative(self) -> bool { + self.is_sign_negative() + } + + fn min(self, other: Self) -> Self { + match self.partial_cmp(&other) { + None => { + if self.is_nan() { + other + } else { + self + } + } + Some(Ordering::Greater) | Some(Ordering::Equal) => other, + Some(Ordering::Less) => self, + } + } + + fn max(self, other: Self) -> Self { + match self.partial_cmp(&other) { + None => { + if self.is_nan() { + other + } else { + self + } + } + Some(Ordering::Greater) | Some(Ordering::Equal) => self, + Some(Ordering::Less) => other, + } + } + + #[inline] + fn recip(self) -> Self { + Self::from_f32(self.to_f32().recip()) + } + + #[inline] + fn powi(self, exp: i32) -> Self { + Self::from_f32(self.to_f32().powi(exp)) + } + + #[inline] + fn to_degrees(self) -> Self { + Self::from_f32(self.to_f32().to_degrees()) + } + + #[inline] + fn to_radians(self) -> Self { + Self::from_f32(self.to_f32().to_radians()) + } + + #[inline] + fn integer_decode(self) -> (u64, i16, i8) { + num_traits::float::FloatCore::integer_decode(self.to_f32()) + } +} + +impl num_traits::float::Float for bf16 { + #[inline] + fn nan() -> Self { + Self::NAN + } + + #[inline] + fn infinity() -> Self { + Self::INFINITY + } + + #[inline] + fn neg_infinity() -> Self { + Self::NEG_INFINITY + } + + #[inline] + fn neg_zero() -> Self { + Self::NEG_ZERO + } + + #[inline] + fn min_value() -> Self { + Self::MIN + } + + #[inline] + fn min_positive_value() -> Self { + Self::MIN_POSITIVE + } + + #[inline] + fn epsilon() -> Self { + Self::EPSILON + } + + #[inline] + fn max_value() -> Self { + Self::MAX + } + + #[inline] + fn is_nan(self) -> bool { + self.is_nan() + } + + #[inline] + fn is_infinite(self) -> bool { + self.is_infinite() + } + + #[inline] + fn is_finite(self) -> bool { + self.is_finite() + } + + #[inline] + fn is_normal(self) -> bool { + self.is_normal() + } + + #[inline] + fn classify(self) -> FpCategory { + self.classify() + } + + #[inline] + fn floor(self) -> Self { + Self::from_f32(self.to_f32().floor()) + } + + #[inline] + fn ceil(self) -> Self { + Self::from_f32(self.to_f32().ceil()) + } + + #[inline] + fn round(self) -> Self { + Self::from_f32(self.to_f32().round()) + } + + #[inline] + fn trunc(self) -> Self { + Self::from_f32(self.to_f32().trunc()) + } + + #[inline] + fn fract(self) -> Self { + Self::from_f32(self.to_f32().fract()) + } + + #[inline] + fn abs(self) -> Self { + Self::from_f32(self.to_f32().abs()) + } + + #[inline] + fn signum(self) -> Self { + Self::from_f32(self.to_f32().signum()) + } + + #[inline] + fn is_sign_positive(self) -> bool { + self.is_sign_positive() + } + + #[inline] + fn is_sign_negative(self) -> bool { + self.is_sign_negative() + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + Self::from_f32(self.to_f32().mul_add(a.to_f32(), b.to_f32())) + } + + #[inline] + fn recip(self) -> Self { + Self::from_f32(self.to_f32().recip()) + } + + #[inline] + fn powi(self, n: i32) -> Self { + Self::from_f32(self.to_f32().powi(n)) + } + + #[inline] + fn powf(self, n: Self) -> Self { + Self::from_f32(self.to_f32().powf(n.to_f32())) + } + + #[inline] + fn sqrt(self) -> Self { + Self::from_f32(self.to_f32().sqrt()) + } + + #[inline] + fn exp(self) -> Self { + Self::from_f32(self.to_f32().exp()) + } + + #[inline] + fn exp2(self) -> Self { + Self::from_f32(self.to_f32().exp2()) + } + + #[inline] + fn ln(self) -> Self { + Self::from_f32(self.to_f32().ln()) + } + + #[inline] + fn log(self, base: Self) -> Self { + Self::from_f32(self.to_f32().log(base.to_f32())) + } + + #[inline] + fn log2(self) -> Self { + Self::from_f32(self.to_f32().log2()) + } + + #[inline] + fn log10(self) -> Self { + Self::from_f32(self.to_f32().log10()) + } + + #[inline] + fn to_degrees(self) -> Self { + Self::from_f32(self.to_f32().to_degrees()) + } + + #[inline] + fn to_radians(self) -> Self { + Self::from_f32(self.to_f32().to_radians()) + } + + #[inline] + fn max(self, other: Self) -> Self { + self.max(other) + } + + #[inline] + fn min(self, other: Self) -> Self { + self.min(other) + } + + #[inline] + fn abs_sub(self, other: Self) -> Self { + Self::from_f32((self.to_f32() - other.to_f32()).max(0.0)) + } + + #[inline] + fn cbrt(self) -> Self { + Self::from_f32(self.to_f32().cbrt()) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + Self::from_f32(self.to_f32().hypot(other.to_f32())) + } + + #[inline] + fn sin(self) -> Self { + Self::from_f32(self.to_f32().sin()) + } + + #[inline] + fn cos(self) -> Self { + Self::from_f32(self.to_f32().cos()) + } + + #[inline] + fn tan(self) -> Self { + Self::from_f32(self.to_f32().tan()) + } + + #[inline] + fn asin(self) -> Self { + Self::from_f32(self.to_f32().asin()) + } + + #[inline] + fn acos(self) -> Self { + Self::from_f32(self.to_f32().acos()) + } + + #[inline] + fn atan(self) -> Self { + Self::from_f32(self.to_f32().atan()) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + Self::from_f32(self.to_f32().atan2(other.to_f32())) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + let (sin, cos) = self.to_f32().sin_cos(); + (Self::from_f32(sin), Self::from_f32(cos)) + } + + #[inline] + fn exp_m1(self) -> Self { + Self::from_f32(self.to_f32().exp_m1()) + } + + #[inline] + fn ln_1p(self) -> Self { + Self::from_f32(self.to_f32().ln_1p()) + } + + #[inline] + fn sinh(self) -> Self { + Self::from_f32(self.to_f32().sinh()) + } + + #[inline] + fn cosh(self) -> Self { + Self::from_f32(self.to_f32().cosh()) + } + + #[inline] + fn tanh(self) -> Self { + Self::from_f32(self.to_f32().tanh()) + } + + #[inline] + fn asinh(self) -> Self { + Self::from_f32(self.to_f32().asinh()) + } + + #[inline] + fn acosh(self) -> Self { + Self::from_f32(self.to_f32().acosh()) + } + + #[inline] + fn atanh(self) -> Self { + Self::from_f32(self.to_f32().atanh()) + } + + #[inline] + fn integer_decode(self) -> (u64, i16, i8) { + num_traits::float::Float::integer_decode(self.to_f32()) + } +} + +impl FloatConst for bf16 { + #[inline] + fn E() -> Self { + Self::E + } + + #[inline] + fn FRAC_1_PI() -> Self { + Self::FRAC_1_PI + } + + #[inline] + fn FRAC_1_SQRT_2() -> Self { + Self::FRAC_1_SQRT_2 + } + + #[inline] + fn FRAC_2_PI() -> Self { + Self::FRAC_2_PI + } + + #[inline] + fn FRAC_2_SQRT_PI() -> Self { + Self::FRAC_2_SQRT_PI + } + + #[inline] + fn FRAC_PI_2() -> Self { + Self::FRAC_PI_2 + } + + #[inline] + fn FRAC_PI_3() -> Self { + Self::FRAC_PI_3 + } + + #[inline] + fn FRAC_PI_4() -> Self { + Self::FRAC_PI_4 + } + + #[inline] + fn FRAC_PI_6() -> Self { + Self::FRAC_PI_6 + } + + #[inline] + fn FRAC_PI_8() -> Self { + Self::FRAC_PI_8 + } + + #[inline] + fn LN_10() -> Self { + Self::LN_10 + } + + #[inline] + fn LN_2() -> Self { + Self::LN_2 + } + + #[inline] + fn LOG10_E() -> Self { + Self::LOG10_E + } + + #[inline] + fn LOG2_E() -> Self { + Self::LOG2_E + } + + #[inline] + fn PI() -> Self { + Self::PI + } + + #[inline] + fn SQRT_2() -> Self { + Self::SQRT_2 + } + + #[inline] + fn LOG10_2() -> Self + where + Self: Sized + Div<Self, Output = Self>, + { + Self::LOG10_2 + } + + #[inline] + fn LOG2_10() -> Self + where + Self: Sized + Div<Self, Output = Self>, + { + Self::LOG2_10 + } +} + +impl Bounded for bf16 { + #[inline] + fn min_value() -> Self { + bf16::MIN + } + + #[inline] + fn max_value() -> Self { + bf16::MAX + } +} + +macro_rules! impl_as_primitive_to_bf16 { + ($ty:ty, $meth:ident) => { + impl AsPrimitive<$ty> for bf16 { + #[inline] + fn as_(self) -> $ty { + self.$meth().as_() + } + } + }; +} + +impl_as_primitive_to_bf16!(i64, to_f32); +impl_as_primitive_to_bf16!(u64, to_f32); +impl_as_primitive_to_bf16!(i8, to_f32); +impl_as_primitive_to_bf16!(u8, to_f32); +impl_as_primitive_to_bf16!(i16, to_f32); +impl_as_primitive_to_bf16!(u16, to_f32); +impl_as_primitive_to_bf16!(i32, to_f32); +impl_as_primitive_to_bf16!(u32, to_f32); +impl_as_primitive_to_bf16!(f32, to_f32); +impl_as_primitive_to_bf16!(f64, to_f64); + +macro_rules! impl_as_primitive_bf16_from { + ($ty:ty, $meth:ident) => { + impl AsPrimitive<bf16> for $ty { + #[inline] + fn as_(self) -> bf16 { + bf16::$meth(self.as_()) + } + } + }; +} + +impl_as_primitive_bf16_from!(i64, from_f32); +impl_as_primitive_bf16_from!(u64, from_f32); +impl_as_primitive_bf16_from!(i8, from_f32); +impl_as_primitive_bf16_from!(u8, from_f32); +impl_as_primitive_bf16_from!(i16, from_f32); +impl_as_primitive_bf16_from!(u16, from_f32); +impl_as_primitive_bf16_from!(i32, from_f32); +impl_as_primitive_bf16_from!(u32, from_f32); +impl_as_primitive_bf16_from!(f32, from_f32); +impl_as_primitive_bf16_from!(f64, from_f64); |