-use crate::traits::{Context, Make};
+use crate::{
+ f16::F16,
+ traits::{Bool, Compare, Context, ConvertFrom, Float, Int, Make, SInt, Select, UInt},
+};
+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,
+};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub struct Scalar;
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
+#[repr(transparent)]
+pub struct Value<T>(pub T);
+
+macro_rules! impl_convert_from {
+ ($first:ident $(, $ty:ident)*) => {
+ $(
+ impl ConvertFrom<Value<$first>> for Value<$ty> {
+ fn cvt_from(v: Value<$first>) -> Self {
+ Value(ConvertFrom::cvt_from(v.0))
+ }
+ }
+ impl ConvertFrom<Value<$ty>> for Value<$first> {
+ fn cvt_from(v: Value<$ty>) -> Self {
+ Value(ConvertFrom::cvt_from(v.0))
+ }
+ }
+ )*
+ impl_convert_from![$($ty),*];
+ };
+ () => {
+ };
+}
+
+impl_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
+
+macro_rules! impl_bit_ops {
+ ($ty:ident) => {
+ impl BitAnd for Value<$ty> {
+ type Output = Self;
+
+ fn bitand(self, rhs: Self) -> Self {
+ Value(self.0 & rhs.0)
+ }
+ }
+
+ impl BitOr for Value<$ty> {
+ type Output = Self;
+
+ fn bitor(self, rhs: Self) -> Self {
+ Value(self.0 | rhs.0)
+ }
+ }
+
+ impl BitXor for Value<$ty> {
+ type Output = Self;
+
+ fn bitxor(self, rhs: Self) -> Self {
+ Value(self.0 ^ rhs.0)
+ }
+ }
+
+ impl Not for Value<$ty> {
+ type Output = Self;
+
+ fn not(self) -> Self {
+ Value(!self.0)
+ }
+ }
+
+ impl BitAndAssign for Value<$ty> {
+ fn bitand_assign(&mut self, rhs: Self) {
+ self.0 &= rhs.0;
+ }
+ }
+
+ impl BitOrAssign for Value<$ty> {
+ fn bitor_assign(&mut self, rhs: Self) {
+ self.0 |= rhs.0;
+ }
+ }
+
+ impl BitXorAssign for Value<$ty> {
+ fn bitxor_assign(&mut self, rhs: Self) {
+ self.0 ^= rhs.0;
+ }
+ }
+ };
+}
+
+macro_rules! impl_wrapping_int_ops {
+ ($ty:ident) => {
+ impl Add for Value<$ty> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_add(rhs.0))
+ }
+ }
+
+ impl Sub for Value<$ty> {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_sub(rhs.0))
+ }
+ }
+
+ impl Mul for Value<$ty> {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_mul(rhs.0))
+ }
+ }
+
+ impl Div for Value<$ty> {
+ type Output = Self;
+
+ fn div(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_div(rhs.0))
+ }
+ }
+
+ impl Rem for Value<$ty> {
+ type Output = Self;
+
+ fn rem(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_rem(rhs.0))
+ }
+ }
+
+ impl Shl for Value<$ty> {
+ type Output = Self;
+
+ fn shl(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_shl(rhs.0 as u32))
+ }
+ }
+
+ impl Shr for Value<$ty> {
+ type Output = Self;
+
+ fn shr(self, rhs: Self) -> Self {
+ Value(self.0.wrapping_shr(rhs.0 as u32))
+ }
+ }
+
+ impl Neg for Value<$ty> {
+ type Output = Self;
+
+ fn neg(self) -> Self {
+ Value(self.0.wrapping_neg())
+ }
+ }
+
+ impl AddAssign for Value<$ty> {
+ fn add_assign(&mut self, rhs: Self) {
+ *self = self.add(rhs);
+ }
+ }
+
+ impl SubAssign for Value<$ty> {
+ fn sub_assign(&mut self, rhs: Self) {
+ *self = self.sub(rhs);
+ }
+ }
+
+ impl MulAssign for Value<$ty> {
+ fn mul_assign(&mut self, rhs: Self) {
+ *self = self.mul(rhs);
+ }
+ }
+
+ impl DivAssign for Value<$ty> {
+ fn div_assign(&mut self, rhs: Self) {
+ *self = self.div(rhs);
+ }
+ }
+
+ impl RemAssign for Value<$ty> {
+ fn rem_assign(&mut self, rhs: Self) {
+ *self = self.rem(rhs);
+ }
+ }
+
+ impl ShlAssign for Value<$ty> {
+ fn shl_assign(&mut self, rhs: Self) {
+ *self = self.shl(rhs);
+ }
+ }
+
+ impl ShrAssign for Value<$ty> {
+ fn shr_assign(&mut self, rhs: Self) {
+ *self = self.shr(rhs);
+ }
+ }
+ };
+}
+macro_rules! impl_int {
+ ($ty:ident) => {
+ impl_bit_ops!($ty);
+ impl_wrapping_int_ops!($ty);
+ impl Int for Value<$ty> {
+ fn leading_zeros(self) -> Self {
+ Value(self.0.leading_zeros() as $ty)
+ }
+ fn leading_ones(self) -> Self {
+ Value(self.0.leading_ones() as $ty)
+ }
+ fn trailing_zeros(self) -> Self {
+ Value(self.0.trailing_zeros() as $ty)
+ }
+ fn trailing_ones(self) -> Self {
+ Value(self.0.trailing_ones() as $ty)
+ }
+ fn count_zeros(self) -> Self {
+ Value(self.0.count_zeros() as $ty)
+ }
+ fn count_ones(self) -> Self {
+ Value(self.0.count_ones() as $ty)
+ }
+ }
+ };
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident),*) => {
+ $(
+ impl_int!($ty);
+ impl UInt for Value<$ty> {}
+ )*
+ };
+}
+
+impl_uint![u8, u16, u32, u64];
+
+macro_rules! impl_sint {
+ ($($ty:ident),*) => {
+ $(
+ impl_int!($ty);
+ impl SInt for Value<$ty> {}
+ )*
+ };
+}
+
+impl_sint![i8, i16, i32, i64];
+
+macro_rules! impl_float_ops {
+ ($ty:ident) => {
+ impl Add for Value<$ty> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ Value(self.0.add(rhs.0))
+ }
+ }
+
+ impl Sub for Value<$ty> {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ Value(self.0.sub(rhs.0))
+ }
+ }
+
+ impl Mul for Value<$ty> {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self {
+ Value(self.0.mul(rhs.0))
+ }
+ }
+
+ impl Div for Value<$ty> {
+ type Output = Self;
+
+ fn div(self, rhs: Self) -> Self {
+ Value(self.0.div(rhs.0))
+ }
+ }
+
+ impl Rem for Value<$ty> {
+ type Output = Self;
+
+ fn rem(self, rhs: Self) -> Self {
+ Value(self.0.rem(rhs.0))
+ }
+ }
+
+ impl Neg for Value<$ty> {
+ type Output = Self;
+
+ fn neg(self) -> Self {
+ Value(self.0.neg())
+ }
+ }
+
+ impl AddAssign for Value<$ty> {
+ fn add_assign(&mut self, rhs: Self) {
+ *self = self.add(rhs);
+ }
+ }
+
+ impl SubAssign for Value<$ty> {
+ fn sub_assign(&mut self, rhs: Self) {
+ *self = self.sub(rhs);
+ }
+ }
+
+ impl MulAssign for Value<$ty> {
+ fn mul_assign(&mut self, rhs: Self) {
+ *self = self.mul(rhs);
+ }
+ }
+
+ impl DivAssign for Value<$ty> {
+ fn div_assign(&mut self, rhs: Self) {
+ *self = self.div(rhs);
+ }
+ }
+
+ impl RemAssign for Value<$ty> {
+ fn rem_assign(&mut self, rhs: Self) {
+ *self = self.rem(rhs);
+ }
+ }
+ };
+}
+
+impl_float_ops!(F16);
+
+macro_rules! impl_float {
+ ($ty:ident, $bits:ty, $signed_bits:ty) => {
+ impl_float_ops!($ty);
+ impl Float for Value<$ty> {
+ type FloatEncoding = $ty;
+ type BitsType = Value<$bits>;
+ type SignedBitsType = Value<$signed_bits>;
+ fn abs(self) -> Self {
+ #[cfg(feature = "std")]
+ return Value(self.0.abs());
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn trunc(self) -> Self {
+ #[cfg(feature = "std")]
+ return Value(self.0.trunc());
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn ceil(self) -> Self {
+ #[cfg(feature = "std")]
+ return Value(self.0.ceil());
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn floor(self) -> Self {
+ #[cfg(feature = "std")]
+ return Value(self.0.floor());
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ fn round(self) -> Self {
+ #[cfg(feature = "std")]
+ return Value(self.0.round());
+ #[cfg(not(feature = "std"))]
+ todo!();
+ }
+ #[cfg(feature = "fma")]
+ fn fma(self, a: Self, b: Self) -> Self {
+ Value(self.0.mul_add(a.0, b.0))
+ }
+ fn is_nan(self) -> Self::Bool {
+ Value(self.0.is_nan())
+ }
+ fn is_infinite(self) -> Self::Bool {
+ Value(self.0.is_infinite())
+ }
+ fn is_finite(self) -> Self::Bool {
+ Value(self.0.is_finite())
+ }
+ fn from_bits(v: Self::BitsType) -> Self {
+ Value(<$ty>::from_bits(v.0))
+ }
+ fn to_bits(self) -> Self::BitsType {
+ Value(self.0.to_bits())
+ }
+ }
+ };
+}
+
+impl_float!(f32, u32, i32);
+impl_float!(f64, u64, i64);
+
+macro_rules! impl_compare_using_partial_cmp {
+ ($($ty:ty),*) => {
+ $(
+ impl Compare for Value<$ty> {
+ type Bool = Value<bool>;
+ fn eq(self, rhs: Self) -> Self::Bool {
+ Value(self == rhs)
+ }
+ fn ne(self, rhs: Self) -> Self::Bool {
+ Value(self != rhs)
+ }
+ fn lt(self, rhs: Self) -> Self::Bool {
+ Value(self < rhs)
+ }
+ fn gt(self, rhs: Self) -> Self::Bool {
+ Value(self > rhs)
+ }
+ fn le(self, rhs: Self) -> Self::Bool {
+ Value(self <= rhs)
+ }
+ fn ge(self, rhs: Self) -> Self::Bool {
+ Value(self >= rhs)
+ }
+ }
+ )*
+ };
+}
+
+impl_compare_using_partial_cmp![bool, u8, i8, u16, i16, F16, u32, i32, f32, u64, i64, f64];
+
+impl Bool for Value<bool> {}
+
+impl_bit_ops!(bool);
+
+impl<T> Select<Value<T>> for Value<bool> {
+ fn select(self, true_v: Value<T>, false_v: Value<T>) -> Value<T> {
+ if self.0 {
+ true_v
+ } else {
+ false_v
+ }
+ }
+}
+
+macro_rules! impl_from {
+ ($src:ident => [$($dest:ident),*]) => {
+ $(
+ impl From<Value<$src>> for Value<$dest> {
+ fn from(v: Value<$src>) -> Self {
+ Value(v.0.into())
+ }
+ }
+ )*
+ };
+}
+
+impl_from!(u8 => [u16, i16, F16, u32, i32, f32, u64, i64, f64]);
+impl_from!(u16 => [u32, i32, f32, u64, i64, f64]);
+impl_from!(u32 => [u64, i64, f64]);
+impl_from!(i8 => [i16, F16, i32, f32, i64, f64]);
+impl_from!(i16 => [i32, f32, i64, f64]);
+impl_from!(i32 => [i64, f64]);
+impl_from!(F16 => [f32, f64]);
+impl_from!(f32 => [f64]);
+
macro_rules! impl_context {
(
impl Context for Scalar {
- $(type $name:ident = $ty:ty;)*
+ $(type $name:ident = Value<$ty:ident>;)*
#[vec]
- $(type $vec_name:ident = $vec_ty:ty;)*
+ $(type $vec_name:ident = Value<$vec_ty:ident>;)*
}
) => {
impl Context for Scalar {
- $(type $name = $ty;)*
- $(type $vec_name = $vec_ty;)*
+ $(type $name = Value<$ty>;)*
+ $(type $vec_name = Value<$vec_ty>;)*
}
$(
- impl Make for $ty {
+ impl Make for Value<$ty> {
type Prim = $ty;
type Context = Scalar;
fn ctx(self) -> Self::Context {
Scalar
}
fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
- v
+ Value(v)
}
}
)*
impl_context! {
impl Context for Scalar {
- type Bool = bool;
- type U8 = u8;
- type I8 = i8;
- type U16 = u16;
- type I16 = i16;
- type F16 = crate::f16::F16;
- type U32 = u32;
- type I32 = i32;
- type F32 = f32;
- type U64 = u64;
- type I64 = i64;
- type F64 = f64;
+ type Bool = Value<bool>;
+ type U8 = Value<u8>;
+ type I8 = Value<i8>;
+ type U16 = Value<u16>;
+ type I16 = Value<i16>;
+ type F16 = Value<F16>;
+ type U32 = Value<u32>;
+ type I32 = Value<i32>;
+ type F32 = Value<f32>;
+ type U64 = Value<u64>;
+ type I64 = Value<i64>;
+ type F64 = Value<f64>;
#[vec]
- type VecBool8 = bool;
- type VecU8 = u8;
- type VecI8 = i8;
- type VecBool16 = bool;
- type VecU16 = u16;
- type VecI16 = i16;
- type VecF16 = crate::f16::F16;
- type VecBool32 = bool;
- type VecU32 = u32;
- type VecI32 = i32;
- type VecF32 = f32;
- type VecBool64 = bool;
- type VecU64 = u64;
- type VecI64 = i64;
- type VecF64 = f64;
+ type VecBool8 = Value<bool>;
+ type VecU8 = Value<u8>;
+ type VecI8 = Value<i8>;
+ type VecBool16 = Value<bool>;
+ type VecU16 = Value<u16>;
+ type VecI16 = Value<i16>;
+ type VecF16 = Value<F16>;
+ type VecBool32 = Value<bool>;
+ type VecU32 = Value<u32>;
+ type VecI32 = Value<i32>;
+ type VecF32 = Value<f32>;
+ type VecBool64 = Value<bool>;
+ type VecU64 = Value<u64>;
+ type VecI64 = Value<i64>;
+ type VecF64 = Value<f64>;
}
}