impl traits for scalar types
[vector-math.git] / src / traits.rs
1 use core::ops::{
2 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
3 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
4 };
5
6 use crate::f16::F16;
7
8 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
9 macro_rules! make_float_type {
10 (
11 #[u32 = $u32:ident]
12 #[bool = $bool:ident]
13 [
14 $({
15 #[uint]
16 $uint_smaller:ident;
17 #[int]
18 $int_smaller:ident;
19 $(
20 #[float]
21 $float_smaller:ident;
22 )?
23 },)*
24 ],
25 {
26 #[uint]
27 $uint:ident;
28 #[int]
29 $int:ident;
30 #[float(prim = $float_prim:ident $(, scalar = $float_scalar:ident)?)]
31 $float:ident;
32 },
33 [
34 $({
35 #[uint]
36 $uint_larger:ident;
37 #[int]
38 $int_larger:ident;
39 $(
40 #[float]
41 $float_larger:ident;
42 )?
43 },)*
44 ]
45 ) => {
46 type $float: Float<Self::$u32, BitsType = Self::$uint>
47 $(+ From<Self::$float_scalar>)?
48 + Compare<Bool = Self::$bool>
49 + Make<Self, Prim = $float_prim>
50 $(+ ConvertTo<Self::$uint_smaller>)*
51 $(+ ConvertTo<Self::$int_smaller>)*
52 $($(+ ConvertTo<Self::$float_smaller>)?)*
53 + ConvertTo<Self::$uint>
54 + ConvertTo<Self::$int>
55 $(+ ConvertTo<Self::$uint_larger>)*
56 $(+ ConvertTo<Self::$int_larger>)*
57 $($(+ Into<Self::$float_larger>)?)*;
58 };
59 (
60 #[u32 = $u32:ident]
61 #[bool = $bool:ident]
62 [$($smaller:tt,)*],
63 {
64 #[uint]
65 $uint:ident;
66 #[int]
67 $int:ident;
68 },
69 [$($larger:tt,)*]
70 ) => {};
71 }
72
73 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
74 macro_rules! make_uint_int_float_type {
75 (
76 #[u32 = $u32:ident]
77 #[bool = $bool:ident]
78 [
79 $({
80 #[uint($($uint_smaller_traits:tt)*)]
81 $uint_smaller:ident;
82 #[int($($int_smaller_traits:tt)*)]
83 $int_smaller:ident;
84 $(
85 #[float($($float_smaller_traits:tt)*)]
86 $float_smaller:ident;
87 )?
88 },)*
89 ],
90 {
91 #[uint(prim = $uint_prim:ident $(, scalar = $uint_scalar:ident)?)]
92 $uint:ident;
93 #[int(prim = $int_prim:ident $(, scalar = $int_scalar:ident)?)]
94 $int:ident;
95 $(
96 #[float(prim = $float_prim:ident $(, scalar = $float_scalar:ident)?)]
97 $float:ident;
98 )?
99 },
100 [
101 $({
102 #[uint($($uint_larger_traits:tt)*)]
103 $uint_larger:ident;
104 #[int($($int_larger_traits:tt)*)]
105 $int_larger:ident;
106 $(
107 #[float($($float_larger_traits:tt)*)]
108 $float_larger:ident;
109 )?
110 },)*
111 ]
112 ) => {
113 type $uint: UInt<Self::$u32>
114 $(+ From<Self::$uint_scalar>)?
115 + Compare<Bool = Self::$bool>
116 + Make<Self, Prim = $uint_prim>
117 $(+ ConvertTo<Self::$uint_smaller>)*
118 $(+ ConvertTo<Self::$int_smaller>)*
119 $($(+ ConvertTo<Self::$float_smaller>)?)*
120 + ConvertTo<Self::$int>
121 $(+ ConvertTo<Self::$float>)?
122 $(+ Into<Self::$uint_larger>)*
123 $(+ Into<Self::$int_larger>)*
124 $($(+ Into<Self::$float_larger>)?)*;
125 type $int: SInt<Self::$u32>
126 $(+ From<Self::$int_scalar>)?
127 + Compare<Bool = Self::$bool>
128 + Make<Self, Prim = $int_prim>
129 $(+ ConvertTo<Self::$uint_smaller>)*
130 $(+ ConvertTo<Self::$int_smaller>)*
131 $($(+ ConvertTo<Self::$float_smaller>)?)*
132 + ConvertTo<Self::$uint>
133 $(+ ConvertTo<Self::$float>)?
134 $(+ ConvertTo<Self::$uint_larger>)*
135 $(+ Into<Self::$int_larger>)*
136 $($(+ Into<Self::$float_larger>)?)*;
137 make_float_type! {
138 #[u32 = $u32]
139 #[bool = $bool]
140 [
141 $({
142 #[uint]
143 $uint_smaller;
144 #[int]
145 $int_smaller;
146 $(
147 #[float]
148 $float_smaller;
149 )?
150 },)*
151 ],
152 {
153 #[uint]
154 $uint;
155 #[int]
156 $int;
157 $(
158 #[float(prim = $float_prim $(, scalar = $float_scalar)?)]
159 $float;
160 )?
161 },
162 [
163 $({
164 #[uint]
165 $uint_larger;
166 #[int]
167 $int_larger;
168 $(
169 #[float]
170 $float_larger;
171 )?
172 },)*
173 ]
174 }
175 };
176 }
177
178 macro_rules! make_uint_int_float_types {
179 (
180 #[u32 = $u32:ident]
181 #[bool = $bool:ident]
182 [$($smaller:tt,)*],
183 $current:tt,
184 [$first_larger:tt, $($larger:tt,)*]
185 ) => {
186 make_uint_int_float_type! {
187 #[u32 = $u32]
188 #[bool = $bool]
189 [$($smaller,)*],
190 $current,
191 [$first_larger, $($larger,)*]
192 }
193 make_uint_int_float_types! {
194 #[u32 = $u32]
195 #[bool = $bool]
196 [$($smaller,)* $current,],
197 $first_larger,
198 [$($larger,)*]
199 }
200 };
201 (
202 #[u32 = $u32:ident]
203 #[bool = $bool:ident]
204 [$($smaller:tt,)*],
205 $current:tt,
206 []
207 ) => {
208 make_uint_int_float_type! {
209 #[u32 = $u32]
210 #[bool = $bool]
211 [$($smaller,)*],
212 $current,
213 []
214 }
215 };
216 }
217
218 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
219 macro_rules! make_types {
220 (
221 #[bool]
222 $(#[scalar = $ScalarBool:ident])?
223 type $Bool:ident;
224
225 #[u8]
226 $(#[scalar = $ScalarU8:ident])?
227 type $U8:ident;
228
229 #[u16]
230 $(#[scalar = $ScalarU16:ident])?
231 type $U16:ident;
232
233 #[u32]
234 $(#[scalar = $ScalarU32:ident])?
235 type $U32:ident;
236
237 #[u64]
238 $(#[scalar = $ScalarU64:ident])?
239 type $U64:ident;
240
241 #[i8]
242 $(#[scalar = $ScalarI8:ident])?
243 type $I8:ident;
244
245 #[i16]
246 $(#[scalar = $ScalarI16:ident])?
247 type $I16:ident;
248
249 #[i32]
250 $(#[scalar = $ScalarI32:ident])?
251 type $I32:ident;
252
253 #[i64]
254 $(#[scalar = $ScalarI64:ident])?
255 type $I64:ident;
256
257 #[f16]
258 $(#[scalar = $ScalarF16:ident])?
259 type $F16:ident;
260
261 #[f32]
262 $(#[scalar = $ScalarF32:ident])?
263 type $F32:ident;
264
265 #[f64]
266 $(#[scalar = $ScalarF64:ident])?
267 type $F64:ident;
268 ) => {
269 type $Bool: Bool
270 $(+ From<Self::$ScalarBool>)?
271 + Make<Self, Prim = bool>
272 + Select<Self::$Bool>;
273 make_uint_int_float_types! {
274 #[u32 = $U32]
275 #[bool = $Bool]
276 [],
277 {
278 #[uint(prim = u8 $(, scalar = $ScalarU8)?)]
279 $U8;
280 #[int(prim = i8 $(, scalar = $ScalarI8)?)]
281 $I8;
282 },
283 [
284 {
285 #[uint(prim = u16 $(, scalar = $ScalarU16)?)]
286 $U16;
287 #[int(prim = i16 $(, scalar = $ScalarI16)?)]
288 $I16;
289 #[float(prim = F16 $(, scalar = $ScalarF16)?)]
290 $F16;
291 },
292 {
293 #[uint(prim = u32 $(, scalar = $ScalarU32)?)]
294 $U32;
295 #[int(prim = i32 $(, scalar = $ScalarI32)?)]
296 $I32;
297 #[float(prim = f32 $(, scalar = $ScalarF32)?)]
298 $F32;
299 },
300 {
301 #[uint(prim = u64 $(, scalar = $ScalarU64)?)]
302 $U64;
303 #[int(prim = i64 $(, scalar = $ScalarI64)?)]
304 $I64;
305 #[float(prim = f64 $(, scalar = $ScalarF64)?)]
306 $F64;
307 },
308 ]
309 }
310 };
311 }
312
313 /// reference used to build IR for Kazan; an empty type for `core::simd`
314 pub trait Context: Copy {
315 make_types! {
316 #[bool]
317 type Bool;
318
319 #[u8]
320 type U8;
321
322 #[u16]
323 type U16;
324
325 #[u32]
326 type U32;
327
328 #[u64]
329 type U64;
330
331 #[i8]
332 type I8;
333
334 #[i16]
335 type I16;
336
337 #[i32]
338 type I32;
339
340 #[i64]
341 type I64;
342
343 #[f16]
344 type F16;
345
346 #[f32]
347 type F32;
348
349 #[f64]
350 type F64;
351 }
352 make_types! {
353 #[bool]
354 #[scalar = Bool]
355 type VecBool;
356
357 #[u8]
358 #[scalar = U8]
359 type VecU8;
360
361 #[u16]
362 #[scalar = U16]
363 type VecU16;
364
365 #[u32]
366 #[scalar = U32]
367 type VecU32;
368
369 #[u64]
370 #[scalar = U64]
371 type VecU64;
372
373 #[i8]
374 #[scalar = I8]
375 type VecI8;
376
377 #[i16]
378 #[scalar = I16]
379 type VecI16;
380
381 #[i32]
382 #[scalar = I32]
383 type VecI32;
384
385 #[i64]
386 #[scalar = I64]
387 type VecI64;
388
389 #[f16]
390 #[scalar = F16]
391 type VecF16;
392
393 #[f32]
394 #[scalar = F32]
395 type VecF32;
396
397 #[f64]
398 #[scalar = F64]
399 type VecF64;
400 }
401 fn make<T: Make<Self>>(self, v: T::Prim) -> T {
402 T::make(self, v)
403 }
404 }
405
406 pub trait Make<Context>: Sized {
407 type Prim;
408 fn make(ctx: Context, v: Self::Prim) -> Self;
409 }
410
411 pub trait ConvertTo<T> {
412 fn to(self) -> T;
413 }
414
415 macro_rules! impl_convert_to_using_as {
416 ($($src:ident -> [$($dest:ident),*];)*) => {
417 $($(
418 impl ConvertTo<$dest> for $src {
419 fn to(self) -> $dest {
420 self as $dest
421 }
422 }
423 )*)*
424 };
425 ([$($src:ident),*] -> $dest:tt;) => {
426 impl_convert_to_using_as! {
427 $(
428 $src -> $dest;
429 )*
430 }
431 };
432 ([$($src:ident),*];) => {
433 impl_convert_to_using_as! {
434 [$($src),*] -> [$($src),*];
435 }
436 };
437 }
438
439 impl_convert_to_using_as! {
440 [u8, i8, u16, i16, u32, i32, u64, i64, f32, f64];
441 }
442
443 pub trait Number:
444 Compare
445 + Add<Output = Self>
446 + Sub<Output = Self>
447 + Mul<Output = Self>
448 + Div<Output = Self>
449 + Rem<Output = Self>
450 + AddAssign
451 + SubAssign
452 + MulAssign
453 + DivAssign
454 + RemAssign
455 {
456 }
457
458 impl<T> Number for T where
459 T: Compare
460 + Add<Output = Self>
461 + Sub<Output = Self>
462 + Mul<Output = Self>
463 + Div<Output = Self>
464 + Rem<Output = Self>
465 + AddAssign
466 + SubAssign
467 + MulAssign
468 + DivAssign
469 + RemAssign
470 {
471 }
472
473 pub trait BitOps:
474 Copy
475 + BitAnd<Output = Self>
476 + BitOr<Output = Self>
477 + BitXor<Output = Self>
478 + Not<Output = Self>
479 + BitAndAssign
480 + BitOrAssign
481 + BitXorAssign
482 {
483 }
484
485 impl<T> BitOps for T where
486 T: Copy
487 + BitAnd<Output = Self>
488 + BitOr<Output = Self>
489 + BitXor<Output = Self>
490 + Not<Output = Self>
491 + BitAndAssign
492 + BitOrAssign
493 + BitXorAssign
494 {
495 }
496
497 pub trait Int<ShiftRhs>:
498 Number
499 + BitOps
500 + Shl<ShiftRhs, Output = Self>
501 + Shr<ShiftRhs, Output = Self>
502 + ShlAssign<ShiftRhs>
503 + ShrAssign<ShiftRhs>
504 {
505 }
506
507 pub trait UInt<ShiftRhs>: Int<ShiftRhs> {}
508
509 pub trait SInt<ShiftRhs>: Int<ShiftRhs> + Neg<Output = Self> {}
510
511 macro_rules! impl_uint {
512 ($($ty:ident),*) => {
513 $(
514 impl Int<u32> for $ty {}
515 impl UInt<u32> for $ty {}
516 )*
517 };
518 }
519
520 impl_uint![u8, u16, u32, u64];
521
522 macro_rules! impl_int {
523 ($($ty:ident),*) => {
524 $(
525 impl Int<u32> for $ty {}
526 impl SInt<u32> for $ty {}
527 )*
528 };
529 }
530
531 impl_int![i8, i16, i32, i64];
532
533 pub trait Float<BitsShiftRhs>: Number + Neg<Output = Self> {
534 type BitsType: UInt<BitsShiftRhs>;
535 fn abs(self) -> Self;
536 fn trunc(self) -> Self;
537 fn ceil(self) -> Self;
538 fn floor(self) -> Self;
539 fn round(self) -> Self;
540 #[cfg(feature = "fma")]
541 fn fma(self, a: Self, b: Self) -> Self;
542 fn is_nan(self) -> Self::Bool;
543 fn is_infinite(self) -> Self::Bool;
544 fn is_finite(self) -> Self::Bool;
545 fn from_bits(v: Self::BitsType) -> Self;
546 fn to_bits(self) -> Self::BitsType;
547 }
548
549 macro_rules! impl_float {
550 ($ty:ty, $bits:ty) => {
551 impl Float<u32> for $ty {
552 type BitsType = $bits;
553 fn abs(self) -> Self {
554 #[cfg(feature = "std")]
555 return self.abs();
556 #[cfg(not(feature = "std"))]
557 todo!();
558 }
559 fn trunc(self) -> Self {
560 #[cfg(feature = "std")]
561 return self.trunc();
562 #[cfg(not(feature = "std"))]
563 todo!();
564 }
565 fn ceil(self) -> Self {
566 #[cfg(feature = "std")]
567 return self.ceil();
568 #[cfg(not(feature = "std"))]
569 todo!();
570 }
571 fn floor(self) -> Self {
572 #[cfg(feature = "std")]
573 return self.floor();
574 #[cfg(not(feature = "std"))]
575 todo!();
576 }
577 fn round(self) -> Self {
578 #[cfg(feature = "std")]
579 return self.round();
580 #[cfg(not(feature = "std"))]
581 todo!();
582 }
583 #[cfg(feature = "fma")]
584 fn fma(self, a: Self, b: Self) -> Self {
585 self.mul_add(a, b)
586 }
587 fn is_nan(self) -> Self::Bool {
588 self.is_nan()
589 }
590 fn is_infinite(self) -> Self::Bool {
591 self.is_infinite()
592 }
593 fn is_finite(self) -> Self::Bool {
594 self.is_finite()
595 }
596 fn from_bits(v: Self::BitsType) -> Self {
597 <$ty>::from_bits(v)
598 }
599 fn to_bits(self) -> Self::BitsType {
600 self.to_bits()
601 }
602 }
603 };
604 }
605
606 impl_float!(f32, u32);
607 impl_float!(f64, u64);
608
609 pub trait Bool: BitOps {}
610
611 impl Bool for bool {}
612
613 pub trait Select<T>: Bool {
614 fn select(self, true_v: T, false_v: T) -> T;
615 }
616
617 impl<T> Select<T> for bool {
618 fn select(self, true_v: T, false_v: T) -> T {
619 if self {
620 true_v
621 } else {
622 false_v
623 }
624 }
625 }
626 pub trait Compare: Copy {
627 type Bool: Bool + Select<Self>;
628 fn eq(self, rhs: Self) -> Self::Bool;
629 fn ne(self, rhs: Self) -> Self::Bool;
630 fn lt(self, rhs: Self) -> Self::Bool;
631 fn gt(self, rhs: Self) -> Self::Bool;
632 fn le(self, rhs: Self) -> Self::Bool;
633 fn ge(self, rhs: Self) -> Self::Bool;
634 }
635
636 macro_rules! impl_compare_using_partial_cmp {
637 ($($ty:ty),*) => {
638 $(
639 impl Compare for $ty {
640 type Bool = bool;
641 fn eq(self, rhs: Self) -> Self::Bool {
642 self == rhs
643 }
644 fn ne(self, rhs: Self) -> Self::Bool {
645 self != rhs
646 }
647 fn lt(self, rhs: Self) -> Self::Bool {
648 self < rhs
649 }
650 fn gt(self, rhs: Self) -> Self::Bool {
651 self > rhs
652 }
653 fn le(self, rhs: Self) -> Self::Bool {
654 self <= rhs
655 }
656 fn ge(self, rhs: Self) -> Self::Bool {
657 self >= rhs
658 }
659 }
660 )*
661 };
662 }
663
664 impl_compare_using_partial_cmp![u8, i8, u16, i16, F16, u32, i32, f32, u64, i64, f64];