2 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
3 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
6 use crate::{f16::F16, ieee754::FloatEncoding, scalar::Scalar};
8 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
9 macro_rules! make_float_type {
30 #[float(prim = $float_prim:ident $(, scalar = $float_scalar:ident)?)]
46 type $float: Float<Self::$u32, BitsType = Self::$uint, SignedBitsType = Self::$int, FloatEncoding = $float_prim>
47 $(+ From<Self::$float_scalar>)?
48 + Compare<Bool = Self::$bool>
49 + Make<Context = 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> + ConvertTo<Self::$float_larger>)?)*;
73 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
74 macro_rules! make_uint_int_float_type {
80 #[uint($($uint_smaller_traits:tt)*)]
82 #[int($($int_smaller_traits:tt)*)]
85 #[float($($float_smaller_traits:tt)*)]
91 #[uint(prim = $uint_prim:ident $(, scalar = $uint_scalar:ident)?)]
93 #[int(prim = $int_prim:ident $(, scalar = $int_scalar:ident)?)]
96 #[float(prim = $float_prim:ident $(, scalar = $float_scalar:ident)?)]
102 #[uint($($uint_larger_traits:tt)*)]
104 #[int($($int_larger_traits:tt)*)]
107 #[float($($float_larger_traits:tt)*)]
113 type $uint: UInt<Self::$u32>
114 $(+ From<Self::$uint_scalar>)?
115 + Compare<Bool = Self::$bool>
116 + Make<Context = 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> + ConvertTo<Self::$uint_larger>)*
123 $(+ Into<Self::$int_larger> + ConvertTo<Self::$int_larger>)*
124 $($(+ Into<Self::$float_larger> + ConvertTo<Self::$float_larger>)?)*;
125 type $int: SInt<Self::$u32>
126 $(+ From<Self::$int_scalar>)?
127 + Compare<Bool = Self::$bool>
128 + Make<Context = 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> + ConvertTo<Self::$int_larger>)*
136 $($(+ Into<Self::$float_larger> + ConvertTo<Self::$float_larger>)?)*;
158 #[float(prim = $float_prim $(, scalar = $float_scalar)?)]
178 macro_rules! make_uint_int_float_types {
181 #[bool = $bool:ident]
184 [$first_larger:tt, $($larger:tt,)*]
186 make_uint_int_float_type! {
191 [$first_larger, $($larger,)*]
193 make_uint_int_float_types! {
196 [$($smaller,)* $current,],
203 #[bool = $bool:ident]
208 make_uint_int_float_type! {
218 #[rustfmt::skip] // work around for https://github.com/rust-lang/rustfmt/issues/4823
219 macro_rules! make_types {
222 $(#[scalar = $ScalarBool:ident])?
226 $(#[scalar = $ScalarU8:ident])?
230 $(#[scalar = $ScalarU16:ident])?
234 $(#[scalar = $ScalarU32:ident])?
238 $(#[scalar = $ScalarU64:ident])?
242 $(#[scalar = $ScalarI8:ident])?
246 $(#[scalar = $ScalarI16:ident])?
250 $(#[scalar = $ScalarI32:ident])?
254 $(#[scalar = $ScalarI64:ident])?
258 $(#[scalar = $ScalarF16:ident])?
262 $(#[scalar = $ScalarF32:ident])?
266 $(#[scalar = $ScalarF64:ident])?
270 $(+ From<Self::$ScalarBool>)?
271 + Make<Context = Self, Prim = bool>
272 + Select<Self::$Bool>
283 + Select<Self::$F64>;
284 make_uint_int_float_types! {
289 #[uint(prim = u8 $(, scalar = $ScalarU8)?)]
291 #[int(prim = i8 $(, scalar = $ScalarI8)?)]
296 #[uint(prim = u16 $(, scalar = $ScalarU16)?)]
298 #[int(prim = i16 $(, scalar = $ScalarI16)?)]
300 #[float(prim = F16 $(, scalar = $ScalarF16)?)]
304 #[uint(prim = u32 $(, scalar = $ScalarU32)?)]
306 #[int(prim = i32 $(, scalar = $ScalarI32)?)]
308 #[float(prim = f32 $(, scalar = $ScalarF32)?)]
312 #[uint(prim = u64 $(, scalar = $ScalarU64)?)]
314 #[int(prim = i64 $(, scalar = $ScalarI64)?)]
316 #[float(prim = f64 $(, scalar = $ScalarF64)?)]
324 /// reference used to build IR for Kazan; an empty type for `core::simd`
325 pub trait Context: Copy {
412 fn make<T: Make<Context = Self>>(self, v: T::Prim) -> T {
417 pub trait Make: Copy {
419 type Context: Context;
420 fn ctx(self) -> Self::Context;
421 fn make(ctx: Self::Context, v: Self::Prim) -> Self;
424 pub trait ConvertTo<T> {
428 macro_rules! impl_convert_to_using_as {
429 ($($src:ident -> [$($dest:ident),*];)*) => {
431 impl ConvertTo<$dest> for $src {
432 fn to(self) -> $dest {
438 ([$($src:ident),*] -> $dest:tt;) => {
439 impl_convert_to_using_as! {
445 ([$($src:ident),*];) => {
446 impl_convert_to_using_as! {
447 [$($src),*] -> [$($src),*];
452 impl_convert_to_using_as! {
453 [u8, i8, u16, i16, u32, i32, u64, i64, f32, f64];
471 impl<T> Number for T where
488 + BitAnd<Output = Self>
489 + BitOr<Output = Self>
490 + BitXor<Output = Self>
498 impl<T> BitOps for T where
500 + BitAnd<Output = Self>
501 + BitOr<Output = Self>
502 + BitXor<Output = Self>
510 pub trait Int<ShiftRhs>:
513 + Shl<ShiftRhs, Output = Self>
514 + Shr<ShiftRhs, Output = Self>
515 + ShlAssign<ShiftRhs>
516 + ShrAssign<ShiftRhs>
518 fn leading_zeros(self) -> Self;
519 fn leading_ones(self) -> Self {
520 self.not().leading_zeros()
522 fn trailing_zeros(self) -> Self;
523 fn trailing_ones(self) -> Self {
524 self.not().trailing_zeros()
526 fn count_zeros(self) -> Self {
527 self.not().count_ones()
529 fn count_ones(self) -> Self;
532 pub trait UInt<ShiftRhs>: Int<ShiftRhs> {}
534 pub trait SInt<ShiftRhs>: Int<ShiftRhs> + Neg<Output = Self> {}
536 macro_rules! impl_int {
538 impl Int<u32> for $ty {
539 fn leading_zeros(self) -> Self {
540 self.leading_zeros() as Self
542 fn leading_ones(self) -> Self {
543 self.leading_ones() as Self
545 fn trailing_zeros(self) -> Self {
546 self.trailing_zeros() as Self
548 fn trailing_ones(self) -> Self {
549 self.trailing_ones() as Self
551 fn count_zeros(self) -> Self {
552 self.count_zeros() as Self
554 fn count_ones(self) -> Self {
555 self.count_ones() as Self
561 macro_rules! impl_uint {
562 ($($ty:ident),*) => {
565 impl UInt<u32> for $ty {}
570 impl_uint![u8, u16, u32, u64];
572 macro_rules! impl_sint {
573 ($($ty:ident),*) => {
576 impl SInt<u32> for $ty {}
581 impl_sint![i8, i16, i32, i64];
583 pub trait Float<BitsShiftRhs: Make<Context = Self::Context, Prim = u32>>:
584 Number + Neg<Output = Self>
586 type FloatEncoding: FloatEncoding + Make<Context = Scalar, Prim = <Self as Make>::Prim>;
587 type BitsType: UInt<BitsShiftRhs>
588 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float<u32>>::BitsType>
589 + ConvertTo<Self::SignedBitsType>
590 + Compare<Bool = Self::Bool>;
591 type SignedBitsType: SInt<BitsShiftRhs>
592 + Make<Context = Self::Context, Prim = <Self::FloatEncoding as Float<u32>>::SignedBitsType>
593 + ConvertTo<Self::BitsType>
594 + Compare<Bool = Self::Bool>;
595 fn abs(self) -> Self;
596 fn trunc(self) -> Self;
597 fn ceil(self) -> Self;
598 fn floor(self) -> Self;
599 fn round(self) -> Self;
600 #[cfg(feature = "fma")]
601 fn fma(self, a: Self, b: Self) -> Self;
602 fn is_nan(self) -> Self::Bool {
605 fn is_infinite(self) -> Self::Bool {
606 self.abs().eq(Self::infinity(self.ctx()))
608 fn infinity(ctx: Self::Context) -> Self {
609 Self::from_bits(ctx.make(Self::FloatEncoding::INFINITY_BITS))
611 fn nan(ctx: Self::Context) -> Self {
612 Self::from_bits(ctx.make(Self::FloatEncoding::NAN_BITS))
614 fn is_finite(self) -> Self::Bool;
615 fn is_zero_or_subnormal(self) -> Self::Bool {
616 self.extract_exponent_field().eq(self
618 .make(Self::FloatEncoding::ZERO_SUBNORMAL_EXPONENT))
620 fn from_bits(v: Self::BitsType) -> Self;
621 fn to_bits(self) -> Self::BitsType;
622 fn extract_exponent_field(self) -> Self::BitsType {
623 let mask = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_MASK);
624 let shift = self.ctx().make(Self::FloatEncoding::EXPONENT_FIELD_SHIFT);
625 (self.to_bits() & mask) >> shift
627 fn extract_exponent_unbiased(self) -> Self::SignedBitsType {
628 Self::sub_exponent_bias(self.extract_exponent_field())
630 fn extract_mantissa_field(self) -> Self::BitsType {
631 let mask = self.ctx().make(Self::FloatEncoding::MANTISSA_FIELD_MASK);
632 self.to_bits() & mask
634 fn sub_exponent_bias(exponent_field: Self::BitsType) -> Self::SignedBitsType {
638 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED)
640 fn add_exponent_bias(exponent: Self::SignedBitsType) -> Self::BitsType {
644 .make(Self::FloatEncoding::EXPONENT_BIAS_SIGNED))
649 macro_rules! impl_float {
650 ($ty:ty, $bits:ty, $signed_bits:ty) => {
651 impl Float<u32> for $ty {
652 type FloatEncoding = $ty;
653 type BitsType = $bits;
654 type SignedBitsType = $signed_bits;
655 fn abs(self) -> Self {
656 #[cfg(feature = "std")]
658 #[cfg(not(feature = "std"))]
661 fn trunc(self) -> Self {
662 #[cfg(feature = "std")]
664 #[cfg(not(feature = "std"))]
667 fn ceil(self) -> Self {
668 #[cfg(feature = "std")]
670 #[cfg(not(feature = "std"))]
673 fn floor(self) -> Self {
674 #[cfg(feature = "std")]
676 #[cfg(not(feature = "std"))]
679 fn round(self) -> Self {
680 #[cfg(feature = "std")]
682 #[cfg(not(feature = "std"))]
685 #[cfg(feature = "fma")]
686 fn fma(self, a: Self, b: Self) -> Self {
689 fn is_nan(self) -> Self::Bool {
692 fn is_infinite(self) -> Self::Bool {
695 fn is_finite(self) -> Self::Bool {
698 fn from_bits(v: Self::BitsType) -> Self {
701 fn to_bits(self) -> Self::BitsType {
708 impl_float!(f32, u32, i32);
709 impl_float!(f64, u64, i64);
711 pub trait Bool: Make + BitOps {}
713 impl Bool for bool {}
715 pub trait Select<T>: Bool {
716 fn select(self, true_v: T, false_v: T) -> T;
719 impl<T> Select<T> for bool {
720 fn select(self, true_v: T, false_v: T) -> T {
728 pub trait Compare: Make {
729 type Bool: Bool + Select<Self>;
730 fn eq(self, rhs: Self) -> Self::Bool;
731 fn ne(self, rhs: Self) -> Self::Bool;
732 fn lt(self, rhs: Self) -> Self::Bool;
733 fn gt(self, rhs: Self) -> Self::Bool;
734 fn le(self, rhs: Self) -> Self::Bool;
735 fn ge(self, rhs: Self) -> Self::Bool;
738 macro_rules! impl_compare_using_partial_cmp {
741 impl Compare for $ty {
743 fn eq(self, rhs: Self) -> Self::Bool {
746 fn ne(self, rhs: Self) -> Self::Bool {
749 fn lt(self, rhs: Self) -> Self::Bool {
752 fn gt(self, rhs: Self) -> Self::Bool {
755 fn le(self, rhs: Self) -> Self::Bool {
758 fn ge(self, rhs: Self) -> Self::Bool {
766 impl_compare_using_partial_cmp![u8, i8, u16, i16, F16, u32, i32, f32, u64, i64, f64];