1877c21f1cb7d1fde0c73114f7170a4f0261d1a8
[vector-math.git] / src / traits.rs
1 use crate::{f16::F16, ieee754::FloatEncoding};
2 use core::ops::{
3 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
4 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
5 };
6
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 {
11 T::make(self, v)
12 }
13 }
14
15 pub trait Make: Copy {
16 type Prim: Copy;
17 type Context: Context;
18 fn ctx(self) -> Self::Context;
19 fn make(ctx: Self::Context, v: Self::Prim) -> Self;
20 }
21
22 pub trait ConvertFrom<T>: Sized {
23 fn cvt_from(v: T) -> Self;
24 }
25
26 impl<T> ConvertFrom<T> for T {
27 fn cvt_from(v: T) -> Self {
28 v
29 }
30 }
31
32 pub trait ConvertTo<T> {
33 fn to(self) -> T;
34 }
35
36 impl<F, T: ConvertFrom<F>> ConvertTo<T> for F {
37 fn to(self) -> T {
38 T::cvt_from(self)
39 }
40 }
41
42 macro_rules! impl_convert_from_using_as {
43 ($first:ident $(, $ty:ident)*) => {
44 $(
45 impl ConvertFrom<$first> for $ty {
46 fn cvt_from(v: $first) -> Self {
47 v as _
48 }
49 }
50 impl ConvertFrom<$ty> for $first {
51 fn cvt_from(v: $ty) -> Self {
52 v as _
53 }
54 }
55 )*
56 impl_convert_from_using_as![$($ty),*];
57 };
58 () => {
59 };
60 }
61
62 impl_convert_from_using_as![u8, i8, u16, i16, u32, i32, u64, i64, f32, f64];
63
64 pub trait Number:
65 Compare
66 + Add<Output = Self>
67 + Sub<Output = Self>
68 + Mul<Output = Self>
69 + Div<Output = Self>
70 + Rem<Output = Self>
71 + AddAssign
72 + SubAssign
73 + MulAssign
74 + DivAssign
75 + RemAssign
76 {
77 }
78
79 impl<T> Number for T where
80 T: Compare
81 + Add<Output = Self>
82 + Sub<Output = Self>
83 + Mul<Output = Self>
84 + Div<Output = Self>
85 + Rem<Output = Self>
86 + AddAssign
87 + SubAssign
88 + MulAssign
89 + DivAssign
90 + RemAssign
91 {
92 }
93
94 pub trait BitOps:
95 Copy
96 + BitAnd<Output = Self>
97 + BitOr<Output = Self>
98 + BitXor<Output = Self>
99 + Not<Output = Self>
100 + BitAndAssign
101 + BitOrAssign
102 + BitXorAssign
103 {
104 }
105
106 impl<T> BitOps for T where
107 T: Copy
108 + BitAnd<Output = Self>
109 + BitOr<Output = Self>
110 + BitXor<Output = Self>
111 + Not<Output = Self>
112 + BitAndAssign
113 + BitOrAssign
114 + BitXorAssign
115 {
116 }
117
118 pub trait Int:
119 Number + BitOps + Shl<Output = Self> + Shr<Output = Self> + ShlAssign + ShrAssign
120 {
121 fn leading_zeros(self) -> Self;
122 fn leading_ones(self) -> Self {
123 self.not().leading_zeros()
124 }
125 fn trailing_zeros(self) -> Self;
126 fn trailing_ones(self) -> Self {
127 self.not().trailing_zeros()
128 }
129 fn count_zeros(self) -> Self {
130 self.not().count_ones()
131 }
132 fn count_ones(self) -> Self;
133 }
134
135 pub trait UInt: Int {}
136
137 pub trait SInt: Int + Neg<Output = Self> {}
138
139 pub trait Float: Number + Neg<Output = Self> {
140 type FloatEncoding: FloatEncoding + From<<Self as Make>::Prim> + Into<<Self as Make>::Prim>;
141 type BitsType: UInt
142 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as FloatEncoding>::BitsType>
143 + ConvertTo<Self::SignedBitsType>
144 + Compare<Bool = Self::Bool>;
145 type SignedBitsType: SInt
146 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as FloatEncoding>::SignedBitsType>
147 + ConvertTo<Self::BitsType>
148 + Compare<Bool = Self::Bool>;
149 fn abs(self) -> Self;
150 fn trunc(self) -> Self;
151 fn ceil(self) -> Self;
152 fn floor(self) -> Self;
153 /// round to nearest integer, unspecified which way half-way cases are rounded
154 fn round(self) -> Self;
155 /// returns `self * a + b` but only rounding once
156 #[cfg(feature = "fma")]
157 fn fma(self, a: Self, b: Self) -> Self;
158 /// returns `self * a + b` either using `fma` or `self * a + b`
159 fn mul_add_fast(self, a: Self, b: Self) -> Self {
160 #[cfg(feature = "fma")]
161 return self.fma(a, b);
162 #[cfg(not(feature = "fma"))]
163 return self * a + b;
164 }
165 fn is_nan(self) -> Self::Bool {
166 self.ne(self)
167 }
168 fn is_infinite(self) -> Self::Bool {
169 self.abs().eq(Self::infinity(self.ctx()))
170 }
171 fn infinity(ctx: Self::Context) -> Self {
172 Self::from_bits(ctx.make(Self::FloatEncoding::INFINITY_BITS))
173 }
174 fn nan(ctx: Self::Context) -> Self {
175 Self::from_bits(ctx.make(Self::FloatEncoding::NAN_BITS))
176 }
177 fn is_finite(self) -> Self::Bool;
178 fn is_zero_or_subnormal(self) -> Self::Bool {
179 self.extract_exponent_field().eq(self
180 .ctx()
181 .make(Self::FloatEncoding::ZERO_SUBNORMAL_EXPONENT))
182 }
183 fn from_bits(v: Self::BitsType) -> Self;
184 fn to_bits(self) -> Self::BitsType;
185 fn extract_exponent_field(self) -> Self::BitsType {
186 let mask = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_MASK);
187 let shift = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_SHIFT);
188 (self.to_bits() & mask) >> shift
189 }
190 fn extract_exponent_unbiased(self) -> Self::SignedBitsType {
191 Self::sub_exponent_bias(self.extract_exponent_field())
192 }
193 fn extract_mantissa_field(self) -> Self::BitsType {
194 let mask = self.ctx().make(Self::FloatEncoding::MANTISSA_FIELD_MASK);
195 self.to_bits() & mask
196 }
197 fn sub_exponent_bias(exponent_field: Self::BitsType) -> Self::SignedBitsType {
198 exponent_field.to()
199 - exponent_field
200 .ctx()
201 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED)
202 }
203 fn add_exponent_bias(exponent: Self::SignedBitsType) -> Self::BitsType {
204 (exponent
205 + exponent
206 .ctx()
207 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED))
208 .to()
209 }
210 }
211
212 pub trait Bool: Make + BitOps {}
213
214 pub trait Select<T>: Bool {
215 fn select(self, true_v: T, false_v: T) -> T;
216 }
217
218 pub trait Compare: Make {
219 type Bool: Bool + Select<Self>;
220 fn eq(self, rhs: Self) -> Self::Bool;
221 fn ne(self, rhs: Self) -> Self::Bool;
222 fn lt(self, rhs: Self) -> Self::Bool;
223 fn gt(self, rhs: Self) -> Self::Bool;
224 fn le(self, rhs: Self) -> Self::Bool;
225 fn ge(self, rhs: Self) -> Self::Bool;
226 }