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