+use crate::{f16::F16, ieee754::FloatEncoding, scalar::Scalar};
use core::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
};
-use crate::F16;
-
-#[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
-macro_rules! make_types {
- (
- #[bool]
- $(#[scalar = $ScalarBool:ident])?
- type $Bool:ident;
-
- #[u8]
- $(#[scalar = $ScalarU8:ident])?
- type $U8:ident;
-
- #[u16]
- $(#[scalar = $ScalarU16:ident])?
- type $U16:ident;
-
- #[u32]
- $(#[scalar = $ScalarU32:ident])?
- type $U32:ident;
-
- #[u64]
- $(#[scalar = $ScalarU64:ident])?
- type $U64:ident;
-
- #[i8]
- $(#[scalar = $ScalarI8:ident])?
- type $I8:ident;
-
- #[i16]
- $(#[scalar = $ScalarI16:ident])?
- type $I16:ident;
-
- #[i32]
- $(#[scalar = $ScalarI32:ident])?
- type $I32:ident;
-
- #[i64]
- $(#[scalar = $ScalarI64:ident])?
- type $I64:ident;
-
- #[f16]
- $(#[scalar = $ScalarF16:ident])?
- type $F16:ident;
-
- #[f32]
- $(#[scalar = $ScalarF32:ident])?
- type $F32:ident;
-
- #[f64]
- $(#[scalar = $ScalarF64:ident])?
- type $F64:ident;
- ) => {
- type Bool: Bool + Make<Self, Prim = bool> + Select<Self::Bool>;
- type U8: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u8>
- + ConvertTo<Self::I8>
- + Into<Self::U16>
- + Into<Self::I16>
- + Into<Self::F16>
- + Into<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U16: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + Into<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U32: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U64: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::I64>
- + ConvertTo<Self::F64>;
- type I8: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i8>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::U16>
- + Into<Self::I16>
- + Into<Self::F16>
- + ConvertTo<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I16: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I32: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I64: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::F64>;
- type F16: Float<Self::U32, BitsType = Self::U16>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = F16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>
- + Into<Self::F64>;
- type F32: Float<Self::U32, BitsType = Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = f32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>
- + Into<Self::F64>;
- type F64: Float<Self::U32, BitsType = Self::U64>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = f64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>;
- };
-}
-
/// reference used to build IR for Kazan; an empty type for `core::simd`
pub trait Context: Copy {
- make_types! {
- #[bool]
- type Bool;
-
- #[u8]
- type U8;
-
- #[u16]
- type U16;
-
- #[u32]
- type U32;
-
- #[u64]
- type U64;
-
- #[i8]
- type I8;
-
- #[i16]
- type I16;
-
- #[i32]
- type I32;
-
- #[i64]
- type I64;
-
- #[f16]
- type F16;
-
- #[f32]
- type F32;
-
- #[f64]
- type F64;
- }
- make_types! {
- #[bool]
- #[scalar = ScalarBool]
- type Bool;
-
- #[u8]
- #[scalar = ScalarU8]
- type U8;
-
- #[u16]
- #[scalar = ScalarU16]
- type U16;
-
- #[u32]
- #[scalar = ScalarU32]
- type U32;
-
- #[u64]
- #[scalar = ScalarU64]
- type U64;
-
- #[i8]
- #[scalar = ScalarI8]
- type I8;
-
- #[i16]
- #[scalar = ScalarI16]
- type I16;
-
- #[i32]
- #[scalar = ScalarI32]
- type I32;
-
- #[i64]
- #[scalar = ScalarI64]
- type I64;
-
- #[f16]
- #[scalar = ScalarF16]
- type F16;
-
- #[f32]
- #[scalar = ScalarF32]
- type F32;
-
- #[f64]
- #[scalar = ScalarF64]
- type F64;
- }
- type Bool: Bool + Make<Self, Prim = bool> + Select<Self::Bool>;
- type U8: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u8>
- + ConvertTo<Self::I8>
- + Into<Self::U16>
- + Into<Self::I16>
- + Into<Self::F16>
- + Into<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U16: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + Into<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U32: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + Into<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type U64: UInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = u64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::I64>
- + ConvertTo<Self::F64>;
- type I8: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i8>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::U16>
- + Into<Self::I16>
- + Into<Self::F16>
- + ConvertTo<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I16: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + Into<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I32: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + Into<Self::I64>
- + Into<Self::F64>;
- type I64: SInt<Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = i64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::F64>;
- type F16: Float<Self::U32, BitsType = Self::U16>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = F16>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + Into<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>
- + Into<Self::F64>;
- type F32: Float<Self::U32, BitsType = Self::U32>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = f32>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>
- + Into<Self::F64>;
- type F64: Float<Self::U32, BitsType = Self::U64>
- + Compare<Bool = Self::Bool>
- + Make<Self, Prim = f64>
- + ConvertTo<Self::U8>
- + ConvertTo<Self::I8>
- + ConvertTo<Self::U16>
- + ConvertTo<Self::I16>
- + ConvertTo<Self::F16>
- + ConvertTo<Self::U32>
- + ConvertTo<Self::I32>
- + ConvertTo<Self::F32>
- + ConvertTo<Self::U64>
- + ConvertTo<Self::I64>;
- // Vector types
- type VecBool: From<Self::Bool> + Bool + Make<Self, Prim = bool> + Select<Self::VecBool>;
- type VecU8: From<Self::U8>
- + UInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = u8>;
- type VecI8: From<Self::I8>
- + SInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = i8>;
- type VecU16: From<Self::U16>
- + UInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = u16>;
- type VecI16: From<Self::I16>
- + SInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = i16>;
- type VecF16: From<Self::F16> + Float + Compare<Bool = Self::VecBool> + Make<Self, Prim = F16>;
- type VecU32: From<Self::U32>
- + UInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = u32>;
- type VecI32: From<Self::I32>
- + SInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = i32>;
- type VecF32: From<Self::F32> + Float + Compare<Bool = Self::VecBool> + Make<Self, Prim = f32>;
- type VecU64: From<Self::U64>
- + UInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = u64>;
- type VecI64: From<Self::I64>
- + SInt<Self::VecU32>
- + Compare<Bool = Self::VecBool>
- + Make<Self, Prim = i64>;
- type VecF64: From<Self::F64> + Float + Compare<Bool = Self::VecBool> + Make<Self, Prim = f64>;
- fn make<T: Make<Self>>(self, v: T::Prim) -> T {
+ vector_math_proc_macro::make_context_types!();
+ fn make<T: Make<Context = Self>>(self, v: T::Prim) -> T {
T::make(self, v)
}
}
-pub trait Make<Context>: Sized {
- type Prim;
- fn make(ctx: Context, v: Self::Prim) -> Self;
+pub trait Make: Copy {
+ type Prim: Copy;
+ type Context: Context;
+ fn ctx(self) -> Self::Context;
+ fn make(ctx: Self::Context, v: Self::Prim) -> Self;
}
pub trait ConvertTo<T> {
fn to(self) -> T;
}
-impl<T, U: Into<T>> ConvertTo<T> for U {
+impl<T> ConvertTo<T> for T {
fn to(self) -> T {
- self.into()
+ self
}
}
+macro_rules! impl_convert_to_using_as {
+ ($first:ident $(, $ty:ident)*) => {
+ $(
+ impl ConvertTo<$first> for $ty {
+ fn to(self) -> $first {
+ self as $first
+ }
+ }
+ impl ConvertTo<$ty> for $first {
+ fn to(self) -> $ty {
+ self as $ty
+ }
+ }
+ )*
+ impl_convert_to_using_as![$($ty),*];
+ };
+ () => {
+ };
+}
+
+impl_convert_to_using_as![u8, i8, u16, i16, u32, i32, u64, i64, f32, f64];
+
pub trait Number:
Compare
+ Add<Output = Self>
{
}
+impl<T> Number for T where
+ T: Compare
+ + Add<Output = Self>
+ + Sub<Output = Self>
+ + Mul<Output = Self>
+ + Div<Output = Self>
+ + Rem<Output = Self>
+ + AddAssign
+ + SubAssign
+ + MulAssign
+ + DivAssign
+ + RemAssign
+{
+}
+
pub trait BitOps:
Copy
+ BitAnd<Output = Self>
{
}
-pub trait Int<ShiftRhs>:
- Number
- + BitOps
- + Shl<ShiftRhs, Output = Self>
- + Shr<ShiftRhs, Output = Self>
- + ShlAssign<ShiftRhs>
- + ShrAssign<ShiftRhs>
+impl<T> BitOps for T where
+ T: Copy
+ + BitAnd<Output = Self>
+ + BitOr<Output = Self>
+ + BitXor<Output = Self>
+ + Not<Output = Self>
+ + BitAndAssign
+ + BitOrAssign
+ + BitXorAssign
{
}
-pub trait UInt<ShiftRhs>: Int<ShiftRhs> {}
+pub trait Int:
+ Number + BitOps + Shl<Output = Self> + Shr<Output = Self> + ShlAssign + ShrAssign
+{
+ fn leading_zeros(self) -> Self;
+ fn leading_ones(self) -> Self {
+ self.not().leading_zeros()
+ }
+ fn trailing_zeros(self) -> Self;
+ fn trailing_ones(self) -> Self {
+ self.not().trailing_zeros()
+ }
+ fn count_zeros(self) -> Self {
+ self.not().count_ones()
+ }
+ fn count_ones(self) -> Self;
+}
-pub trait SInt<ShiftRhs>: Int<ShiftRhs> + Neg<Output = Self> {}
+pub trait UInt: Int {}
+
+pub trait SInt: Int + Neg<Output = Self> {}
+
+macro_rules! impl_int {
+ ($ty:ident) => {
+ impl Int for $ty {
+ fn leading_zeros(self) -> Self {
+ self.leading_zeros() as Self
+ }
+ fn leading_ones(self) -> Self {
+ self.leading_ones() as Self
+ }
+ fn trailing_zeros(self) -> Self {
+ self.trailing_zeros() as Self
+ }
+ fn trailing_ones(self) -> Self {
+ self.trailing_ones() as Self
+ }
+ fn count_zeros(self) -> Self {
+ self.count_zeros() as Self
+ }
+ fn count_ones(self) -> Self {
+ self.count_ones() as Self
+ }
+ }
+ };
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident),*) => {
+ $(
+ impl_int!($ty);
+ impl UInt for $ty {}
+ )*
+ };
+}
-pub trait Float<BitsShiftRhs>: Number + Neg<Output = Self> {
- type BitsType: UInt<BitsShiftRhs>;
+impl_uint![u8, u16, u32, u64];
+
+macro_rules! impl_sint {
+ ($($ty:ident),*) => {
+ $(
+ impl_int!($ty);
+ impl SInt for $ty {}
+ )*
+ };
+}
+
+impl_sint![i8, i16, i32, i64];
+
+pub trait Float: Number + Neg<Output = Self> {
+ type FloatEncoding: FloatEncoding + Make<Context = Scalar, Prim = <Self as Make>::Prim>;
+ type BitsType: UInt
+ + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float>::BitsType>
+ + ConvertTo<Self::SignedBitsType>
+ + Compare<Bool = Self::Bool>;
+ type SignedBitsType: SInt
+ + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float>::SignedBitsType>
+ + ConvertTo<Self::BitsType>
+ + Compare<Bool = Self::Bool>;
fn abs(self) -> Self;
fn trunc(self) -> Self;
fn ceil(self) -> Self;
fn floor(self) -> Self;
fn round(self) -> Self;
+ #[cfg(feature = "fma")]
fn fma(self, a: Self, b: Self) -> Self;
- fn is_nan(self) -> Self::Bool;
- fn is_infinity(self) -> Self::Bool;
+ fn is_nan(self) -> Self::Bool {
+ self.ne(self)
+ }
+ fn is_infinite(self) -> Self::Bool {
+ self.abs().eq(Self::infinity(self.ctx()))
+ }
+ fn infinity(ctx: Self::Context) -> Self {
+ Self::from_bits(ctx.make(Self::FloatEncoding::INFINITY_BITS))
+ }
+ fn nan(ctx: Self::Context) -> Self {
+ Self::from_bits(ctx.make(Self::FloatEncoding::NAN_BITS))
+ }
fn is_finite(self) -> Self::Bool;
+ fn is_zero_or_subnormal(self) -> Self::Bool {
+ self.extract_exponent_field().eq(self
+ .ctx()
+ .make(Self::FloatEncoding::ZERO_SUBNORMAL_EXPONENT))
+ }
fn from_bits(v: Self::BitsType) -> Self;
fn to_bits(self) -> Self::BitsType;
+ fn extract_exponent_field(self) -> Self::BitsType {
+ let mask = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_MASK);
+ let shift = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_SHIFT);
+ (self.to_bits() & mask) >> shift
+ }
+ fn extract_exponent_unbiased(self) -> Self::SignedBitsType {
+ Self::sub_exponent_bias(self.extract_exponent_field())
+ }
+ fn extract_mantissa_field(self) -> Self::BitsType {
+ let mask = self.ctx().make(Self::FloatEncoding::MANTISSA_FIELD_MASK);
+ self.to_bits() & mask
+ }
+ fn sub_exponent_bias(exponent_field: Self::BitsType) -> Self::SignedBitsType {
+ exponent_field.to()
+ - exponent_field
+ .ctx()
+ .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED)
+ }
+ fn add_exponent_bias(exponent: Self::SignedBitsType) -> Self::BitsType {
+ (exponent
+ + exponent
+ .ctx()
+ .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED))
+ .to()
+ }
}
-pub trait Bool: BitOps {}
+macro_rules! impl_float {
+ ($ty:ty, $bits:ty, $signed_bits:ty) => {
+ impl Float for $ty {
+ type FloatEncoding = $ty;
+ type BitsType = $bits;
+ type SignedBitsType = $signed_bits;
+ fn abs(self) -> Self {
+ #[cfg(feature = "std")]
+ return self.abs();
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn trunc(self) -> Self {
+ #[cfg(feature = "std")]
+ return self.trunc();
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn ceil(self) -> Self {
+ #[cfg(feature = "std")]
+ return self.ceil();
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn floor(self) -> Self {
+ #[cfg(feature = "std")]
+ return self.floor();
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn round(self) -> Self {
+ #[cfg(feature = "std")]
+ return self.round();
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ #[cfg(feature = "fma")]
+ fn fma(self, a: Self, b: Self) -> Self {
+ self.mul_add(a, b)
+ }
+ fn is_nan(self) -> Self::Bool {
+ self.is_nan()
+ }
+ fn is_infinite(self) -> Self::Bool {
+ self.is_infinite()
+ }
+ fn is_finite(self) -> Self::Bool {
+ self.is_finite()
+ }
+ fn from_bits(v: Self::BitsType) -> Self {
+ <$ty>::from_bits(v)
+ }
+ fn to_bits(self) -> Self::BitsType {
+ self.to_bits()
+ }
+ }
+ };
+}
+
+impl_float!(f32, u32, i32);
+impl_float!(f64, u64, i64);
+
+pub trait Bool: Make + BitOps {}
+
+impl Bool for bool {}
pub trait Select<T>: Bool {
fn select(self, true_v: T, false_v: T) -> T;
}
-pub trait Compare: Copy {
+impl<T> Select<T> for bool {
+ fn select(self, true_v: T, false_v: T) -> T {
+ if self {
+ true_v
+ } else {
+ false_v
+ }
+ }
+}
+pub trait Compare: Make {
type Bool: Bool + Select<Self>;
fn eq(self, rhs: Self) -> Self::Bool;
fn ne(self, rhs: Self) -> Self::Bool;
fn le(self, rhs: Self) -> Self::Bool;
fn ge(self, rhs: Self) -> Self::Bool;
}
+
+macro_rules! impl_compare_using_partial_cmp {
+ ($($ty:ty),*) => {
+ $(
+ impl Compare for $ty {
+ type Bool = bool;
+ fn eq(self, rhs: Self) -> Self::Bool {
+ self == rhs
+ }
+ fn ne(self, rhs: Self) -> Self::Bool {
+ self != rhs
+ }
+ fn lt(self, rhs: Self) -> Self::Bool {
+ self < rhs
+ }
+ fn gt(self, rhs: Self) -> Self::Bool {
+ self > rhs
+ }
+ fn le(self, rhs: Self) -> Self::Bool {
+ self <= rhs
+ }
+ fn ge(self, rhs: Self) -> Self::Bool {
+ self >= rhs
+ }
+ }
+ )*
+ };
+}
+
+impl_compare_using_partial_cmp![bool, u8, i8, u16, i16, F16, u32, i32, f32, u64, i64, f64];