-use core::ops::{
- Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
+use crate::{
+ prim::PrimFloat,
+ scalar::Value,
+ traits::{ConvertFrom, ConvertTo, Float},
+};
+use core::{
+ fmt,
+ ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
};
-
-use crate::traits::{ConvertTo, Float};
#[cfg(feature = "f16")]
use half::f16 as F16Impl;
#[cfg(not(feature = "f16"))]
type F16Impl = u16;
-#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
+#[derive(Clone, Copy, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct F16(F16Impl);
+#[cfg(not(feature = "f16"))]
+#[track_caller]
+pub(crate) fn panic_f16_feature_disabled() -> ! {
+ panic!("f16 feature is not enabled")
+}
+
#[cfg(feature = "f16")]
macro_rules! f16_impl {
($v:expr, [$($vars:ident),*]) => {
($v:expr, [$($vars:ident),*]) => {
{
$(let _ = $vars;)*
- panic!("f16 feature is not enabled")
+ panic_f16_feature_disabled()
}
};
}
+impl fmt::Display for F16 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f16_impl!(self.0.fmt(f), [f])
+ }
+}
+
+impl fmt::Debug for F16 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f16_impl!(self.0.fmt(f), [f])
+ }
+}
+
+impl Default for F16 {
+ fn default() -> Self {
+ f16_impl!(F16(F16Impl::default()), [])
+ }
+}
+
impl From<F16Impl> for F16 {
fn from(v: F16Impl) -> Self {
F16(v)
}
}
- impl ConvertTo<F16> for $ty {
- fn to(self) -> F16 {
- self.into()
+ impl ConvertFrom<$ty> for F16 {
+ fn cvt_from(v: $ty) -> F16 {
+ v.into()
}
}
)*
}
}
- impl ConvertTo<$ty> for F16 {
- fn to(self) -> $ty {
- self.into()
+ impl ConvertFrom<F16> for $ty {
+ fn cvt_from(v: F16) -> Self {
+ v.into()
}
}
)*
macro_rules! impl_int_to_f16 {
($($int:ident),*) => {
$(
- impl ConvertTo<F16> for $int {
- fn to(self) -> F16 {
+ impl ConvertFrom<$int> for F16 {
+ fn cvt_from(v: $int) -> Self {
// f32 has enough mantissa bits such that f16 overflows to
// infinity before f32 stops being able to properly
// represent integer values, making the below conversion correct.
- (self as f32).to()
+ F16::cvt_from(v as f32)
}
}
)*
macro_rules! impl_f16_to_int {
($($int:ident),*) => {
$(
- impl ConvertTo<$int> for F16 {
- fn to(self) -> $int {
- f32::from(self) as $int
+ impl ConvertFrom<F16> for $int {
+ fn cvt_from(v: F16) -> Self {
+ f32::from(v) as $int
}
}
)*
impl_int_to_f16![i16, u16, i32, u32, i64, u64, i128, u128];
impl_f16_to_int![i8, u8, i16, u16, i32, u32, i64, u64, i128, u128];
-impl ConvertTo<F16> for f32 {
- fn to(self) -> F16 {
- f16_impl!(F16(F16Impl::from_f32(self)), [])
+impl ConvertFrom<f32> for F16 {
+ fn cvt_from(v: f32) -> Self {
+ f16_impl!(F16(F16Impl::from_f32(v)), [v])
}
}
-impl ConvertTo<F16> for f64 {
- fn to(self) -> F16 {
- f16_impl!(F16(F16Impl::from_f64(self)), [])
+impl ConvertFrom<f64> for F16 {
+ fn cvt_from(v: f64) -> Self {
+ f16_impl!(F16(F16Impl::from_f64(v)), [v])
}
}
Rem, rem, RemAssign, rem_assign;
}
-impl Float for F16 {
- type FloatEncoding = F16;
- type BitsType = u16;
- type SignedBitsType = i16;
+impl F16 {
+ pub fn from_bits(v: u16) -> Self {
+ #[cfg(feature = "f16")]
+ return F16(F16Impl::from_bits(v));
+ #[cfg(not(feature = "f16"))]
+ return F16(v);
+ }
+ pub fn to_bits(self) -> u16 {
+ #[cfg(feature = "f16")]
+ return self.0.to_bits();
+ #[cfg(not(feature = "f16"))]
+ return self.0;
+ }
+ pub fn abs(self) -> Self {
+ f16_impl!(Self::from_bits(self.to_bits() & 0x7FFF), [])
+ }
+ pub fn copysign(self, sign: Self) -> Self {
+ f16_impl!(
+ Self::from_bits((self.to_bits() & 0x7FFF) | (sign.to_bits() & 0x8000)),
+ [sign]
+ )
+ }
+ pub fn trunc(self) -> Self {
+ return PrimFloat::trunc(f32::from(self)).to();
+ }
+ pub fn ceil(self) -> Self {
+ return PrimFloat::ceil(f32::from(self)).to();
+ }
+ pub fn floor(self) -> Self {
+ return PrimFloat::floor(f32::from(self)).to();
+ }
+ /// round to nearest, ties to unspecified
+ pub fn round(self) -> Self {
+ return PrimFloat::round(f32::from(self)).to();
+ }
+ #[cfg(feature = "fma")]
+ pub fn fma(self, a: Self, b: Self) -> Self {
+ (f64::from(self) * f64::from(a) + f64::from(b)).to()
+ }
+
+ pub fn is_nan(self) -> bool {
+ f16_impl!(self.0.is_nan(), [])
+ }
+
+ pub fn is_infinite(self) -> bool {
+ f16_impl!(self.0.is_infinite(), [])
+ }
+
+ pub fn is_finite(self) -> bool {
+ f16_impl!(self.0.is_finite(), [])
+ }
+}
+
+impl Float for Value<F16> {
+ type PrimFloat = F16;
+ type BitsType = Value<u16>;
+ type SignedBitsType = Value<i16>;
fn abs(self) -> Self {
- f16_impl!(Self::from_bits(self.to_bits() & 0x7FFF), [])
+ Value(self.0.abs())
}
fn trunc(self) -> Self {
- f32::from(self).trunc().to()
+ Value(self.0.trunc())
}
fn ceil(self) -> Self {
- f32::from(self).ceil().to()
+ Value(self.0.ceil())
}
fn floor(self) -> Self {
- f32::from(self).floor().to()
+ Value(self.0.floor())
}
fn round(self) -> Self {
- f32::from(self).round().to()
+ Value(self.0.round())
}
#[cfg(feature = "fma")]
fn fma(self, a: Self, b: Self) -> Self {
- (f64::from(self) * f64::from(a) + f64::from(b)).to()
+ Value(self.0.fma(a.0, b.0))
}
fn is_nan(self) -> Self::Bool {
- f16_impl!(self.0.is_nan(), [])
+ Value(self.0.is_nan())
}
fn is_infinite(self) -> Self::Bool {
- f16_impl!(self.0.is_infinite(), [])
+ Value(self.0.is_infinite())
}
fn is_finite(self) -> Self::Bool {
- f16_impl!(self.0.is_finite(), [])
+ Value(self.0.is_finite())
}
fn from_bits(v: Self::BitsType) -> Self {
- #[cfg(feature = "f16")]
- return F16(F16Impl::from_bits(v));
- #[cfg(not(feature = "f16"))]
- return F16(v);
+ Value(F16::from_bits(v.0))
}
fn to_bits(self) -> Self::BitsType {
- #[cfg(feature = "f16")]
- return self.0.to_bits();
- #[cfg(not(feature = "f16"))]
- return self.0;
+ Value(self.0.to_bits())
}
}