add sin_pi_f16, cos_pi_f16, and sin_cos_pi_f16
[vector-math.git] / src / scalar.rs
index fb83af695799114ffdd7c31f37f5d77b0bd84144..4eb5b985627f03f3e9a75761437e1923b4f279c8 100644 (file)
-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)
                 }
             }
         )*
@@ -33,33 +490,33 @@ macro_rules! impl_context {
 
 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>;
     }
 }