1 use crate::{f16::F16, ieee754::FloatEncoding, scalar::Scalar};
3 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
4 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
7 /// reference used to build IR for Kazan; an empty type for `core::simd`
8 pub trait Context: Copy {
9 vector_math_proc_macro::make_context_types!();
10 fn make<T: Make<Context = Self>>(self, v: T::Prim) -> T {
15 pub trait Make: Copy {
17 type Context: Context;
18 fn ctx(self) -> Self::Context;
19 fn make(ctx: Self::Context, v: Self::Prim) -> Self;
22 pub trait ConvertTo<T> {
26 impl<T> ConvertTo<T> for T {
32 macro_rules! impl_convert_to_using_as {
33 ($first:ident $(, $ty:ident)*) => {
35 impl ConvertTo<$first> for $ty {
36 fn to(self) -> $first {
40 impl ConvertTo<$ty> for $first {
46 impl_convert_to_using_as![$($ty),*];
52 impl_convert_to_using_as![u8, i8, u16, i16, u32, i32, u64, i64, f32, f64];
69 impl<T> Number for T where
86 + BitAnd<Output = Self>
87 + BitOr<Output = Self>
88 + BitXor<Output = Self>
96 impl<T> BitOps for T where
98 + BitAnd<Output = Self>
99 + BitOr<Output = Self>
100 + BitXor<Output = Self>
109 Number + BitOps + Shl<Output = Self> + Shr<Output = Self> + ShlAssign + ShrAssign
111 fn leading_zeros(self) -> Self;
112 fn leading_ones(self) -> Self {
113 self.not().leading_zeros()
115 fn trailing_zeros(self) -> Self;
116 fn trailing_ones(self) -> Self {
117 self.not().trailing_zeros()
119 fn count_zeros(self) -> Self {
120 self.not().count_ones()
122 fn count_ones(self) -> Self;
125 pub trait UInt: Int {}
127 pub trait SInt: Int + Neg<Output = Self> {}
129 macro_rules! impl_int {
132 fn leading_zeros(self) -> Self {
133 self.leading_zeros() as Self
135 fn leading_ones(self) -> Self {
136 self.leading_ones() as Self
138 fn trailing_zeros(self) -> Self {
139 self.trailing_zeros() as Self
141 fn trailing_ones(self) -> Self {
142 self.trailing_ones() as Self
144 fn count_zeros(self) -> Self {
145 self.count_zeros() as Self
147 fn count_ones(self) -> Self {
148 self.count_ones() as Self
154 macro_rules! impl_uint {
155 ($($ty:ident),*) => {
163 impl_uint![u8, u16, u32, u64];
165 macro_rules! impl_sint {
166 ($($ty:ident),*) => {
174 impl_sint![i8, i16, i32, i64];
176 pub trait Float: Number + Neg<Output = Self> {
177 type FloatEncoding: FloatEncoding + Make<Context = Scalar, Prim = <Self as Make>::Prim>;
179 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float>::BitsType>
180 + ConvertTo<Self::SignedBitsType>
181 + Compare<Bool = Self::Bool>;
182 type SignedBitsType: SInt
183 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float>::SignedBitsType>
184 + ConvertTo<Self::BitsType>
185 + Compare<Bool = Self::Bool>;
186 fn abs(self) -> Self;
187 fn trunc(self) -> Self;
188 fn ceil(self) -> Self;
189 fn floor(self) -> Self;
190 fn round(self) -> Self;
191 #[cfg(feature = "fma")]
192 fn fma(self, a: Self, b: Self) -> Self;
193 fn is_nan(self) -> Self::Bool {
196 fn is_infinite(self) -> Self::Bool {
197 self.abs().eq(Self::infinity(self.ctx()))
199 fn infinity(ctx: Self::Context) -> Self {
200 Self::from_bits(ctx.make(Self::FloatEncoding::INFINITY_BITS))
202 fn nan(ctx: Self::Context) -> Self {
203 Self::from_bits(ctx.make(Self::FloatEncoding::NAN_BITS))
205 fn is_finite(self) -> Self::Bool;
206 fn is_zero_or_subnormal(self) -> Self::Bool {
207 self.extract_exponent_field().eq(self
209 .make(Self::FloatEncoding::ZERO_SUBNORMAL_EXPONENT))
211 fn from_bits(v: Self::BitsType) -> Self;
212 fn to_bits(self) -> Self::BitsType;
213 fn extract_exponent_field(self) -> Self::BitsType {
214 let mask = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_MASK);
215 let shift = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_SHIFT);
216 (self.to_bits() & mask) >> shift
218 fn extract_exponent_unbiased(self) -> Self::SignedBitsType {
219 Self::sub_exponent_bias(self.extract_exponent_field())
221 fn extract_mantissa_field(self) -> Self::BitsType {
222 let mask = self.ctx().make(Self::FloatEncoding::MANTISSA_FIELD_MASK);
223 self.to_bits() & mask
225 fn sub_exponent_bias(exponent_field: Self::BitsType) -> Self::SignedBitsType {
229 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED)
231 fn add_exponent_bias(exponent: Self::SignedBitsType) -> Self::BitsType {
235 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED))
240 macro_rules! impl_float {
241 ($ty:ty, $bits:ty, $signed_bits:ty) => {
243 type FloatEncoding = $ty;
244 type BitsType = $bits;
245 type SignedBitsType = $signed_bits;
246 fn abs(self) -> Self {
247 #[cfg(feature = "std")]
249 #[cfg(not(feature = "std"))]
252 fn trunc(self) -> Self {
253 #[cfg(feature = "std")]
255 #[cfg(not(feature = "std"))]
258 fn ceil(self) -> Self {
259 #[cfg(feature = "std")]
261 #[cfg(not(feature = "std"))]
264 fn floor(self) -> Self {
265 #[cfg(feature = "std")]
267 #[cfg(not(feature = "std"))]
270 fn round(self) -> Self {
271 #[cfg(feature = "std")]
273 #[cfg(not(feature = "std"))]
276 #[cfg(feature = "fma")]
277 fn fma(self, a: Self, b: Self) -> Self {
280 fn is_nan(self) -> Self::Bool {
283 fn is_infinite(self) -> Self::Bool {
286 fn is_finite(self) -> Self::Bool {
289 fn from_bits(v: Self::BitsType) -> Self {
292 fn to_bits(self) -> Self::BitsType {
299 impl_float!(f32, u32, i32);
300 impl_float!(f64, u64, i64);
302 pub trait Bool: Make + BitOps {}
304 impl Bool for bool {}
306 pub trait Select<T>: Bool {
307 fn select(self, true_v: T, false_v: T) -> T;
310 impl<T> Select<T> for bool {
311 fn select(self, true_v: T, false_v: T) -> T {
319 pub trait Compare: Make {
320 type Bool: Bool + Select<Self>;
321 fn eq(self, rhs: Self) -> Self::Bool;
322 fn ne(self, rhs: Self) -> Self::Bool;
323 fn lt(self, rhs: Self) -> Self::Bool;
324 fn gt(self, rhs: Self) -> Self::Bool;
325 fn le(self, rhs: Self) -> Self::Bool;
326 fn ge(self, rhs: Self) -> Self::Bool;
329 macro_rules! impl_compare_using_partial_cmp {
332 impl Compare for $ty {
334 fn eq(self, rhs: Self) -> Self::Bool {
337 fn ne(self, rhs: Self) -> Self::Bool {
340 fn lt(self, rhs: Self) -> Self::Bool {
343 fn gt(self, rhs: Self) -> Self::Bool {
346 fn le(self, rhs: Self) -> Self::Bool {
349 fn ge(self, rhs: Self) -> Self::Bool {
357 impl_compare_using_partial_cmp![bool, u8, i8, u16, i16, F16, u32, i32, f32, u64, i64, f64];