]> git.lizzy.rs Git - rust.git/blob - crates/core_simd/src/vector/float.rs
6371f88a40a21deef428d16ea527a1360841ee56
[rust.git] / crates / core_simd / src / vector / float.rs
1 #![allow(non_camel_case_types)]
2
3 /// Implements inherent methods for a float vector `$name` containing multiple
4 /// `$lanes` of float `$type`, which uses `$bits_ty` as its binary
5 /// representation. Called from `define_float_vector!`.
6 macro_rules! impl_float_vector {
7     { $name:ident, $type:ty, $bits_ty:ident, $mask_ty:ident, $mask_impl_ty:ident } => {
8         impl_vector! { $name, $type }
9         impl_float_reductions! { $name, $type }
10
11         impl<const LANES: usize> $name<LANES>
12         where
13             Self: crate::LanesAtMost32,
14             crate::$bits_ty<LANES>: crate::LanesAtMost32,
15         {
16             /// Raw transmutation to an unsigned integer vector type with the
17             /// same size and number of lanes.
18             #[inline]
19             pub fn to_bits(self) -> crate::$bits_ty<LANES> {
20                 assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<crate::$bits_ty<LANES>>());
21                 unsafe { core::mem::transmute_copy(&self) }
22             }
23
24             /// Raw transmutation from an unsigned integer vector type with the
25             /// same size and number of lanes.
26             #[inline]
27             pub fn from_bits(bits: crate::$bits_ty<LANES>) -> Self {
28                 assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<crate::$bits_ty<LANES>>());
29                 unsafe { core::mem::transmute_copy(&bits) }
30             }
31
32             /// Produces a vector where every lane has the absolute value of the
33             /// equivalently-indexed lane in `self`.
34             #[inline]
35             pub fn abs(self) -> Self {
36                 unsafe { crate::intrinsics::simd_fabs(self) }
37             }
38         }
39
40         impl<const LANES: usize> $name<LANES>
41         where
42             Self: crate::LanesAtMost32,
43             crate::$bits_ty<LANES>: crate::LanesAtMost32,
44             crate::$mask_impl_ty<LANES>: crate::LanesAtMost32,
45             crate::$mask_ty<LANES>: crate::Mask,
46         {
47             /// Returns true for each lane if it has a positive sign, including
48             /// `+0.0`, `NaN`s with positive sign bit and positive infinity.
49             #[inline]
50             pub fn is_sign_positive(self) -> crate::$mask_ty<LANES> {
51                 !self.is_sign_negative()
52             }
53
54             /// Returns true for each lane if it has a negative sign, including
55             /// `-0.0`, `NaN`s with negative sign bit and negative infinity.
56             #[inline]
57             pub fn is_sign_negative(self) -> crate::$mask_ty<LANES> {
58                 let sign_bits = self.to_bits() & crate::$bits_ty::splat((!0 >> 1) + 1);
59                 sign_bits.lanes_gt(crate::$bits_ty::splat(0))
60             }
61
62             /// Returns true for each lane if its value is `NaN`.
63             #[inline]
64             pub fn is_nan(self) -> crate::$mask_ty<LANES> {
65                 self.lanes_ne(self)
66             }
67
68             /// Returns true for each lane if its value is positive infinity or negative infinity.
69             #[inline]
70             pub fn is_infinite(self) -> crate::$mask_ty<LANES> {
71                 self.abs().lanes_eq(Self::splat(<$type>::INFINITY))
72             }
73
74             /// Returns true for each lane if its value is neither infinite nor `NaN`.
75             #[inline]
76             pub fn is_finite(self) -> crate::$mask_ty<LANES> {
77                 self.abs().lanes_lt(Self::splat(<$type>::INFINITY))
78             }
79
80             /// Returns true for each lane if its value is subnormal.
81             #[inline]
82             pub fn is_subnormal(self) -> crate::$mask_ty<LANES> {
83                 self.abs().lanes_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(<$type>::INFINITY).to_bits()).lanes_eq(crate::$bits_ty::splat(0))
84             }
85
86             /// Returns true for each lane if its value is neither neither zero, infinite,
87             /// subnormal, or `NaN`.
88             #[inline]
89             pub fn is_normal(self) -> crate::$mask_ty<LANES> {
90                 !(self.abs().lanes_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite())
91             }
92         }
93     };
94 }
95
96 /// A SIMD vector of containing `LANES` `f32` values.
97 #[repr(simd)]
98 pub struct SimdF32<const LANES: usize>([f32; LANES])
99 where
100     Self: crate::LanesAtMost32;
101
102 impl_float_vector! { SimdF32, f32, SimdU32, Mask32, SimdI32 }
103
104 from_transmute_x86! { unsafe f32x4 => __m128 }
105 from_transmute_x86! { unsafe f32x8 => __m256 }
106 //from_transmute_x86! { unsafe f32x16 => __m512 }
107
108 /// A SIMD vector of containing `LANES` `f64` values.
109 #[repr(simd)]
110 pub struct SimdF64<const LANES: usize>([f64; LANES])
111 where
112     Self: crate::LanesAtMost32;
113
114 impl_float_vector! { SimdF64, f64, SimdU64, Mask64, SimdI64 }
115
116 from_transmute_x86! { unsafe f64x2 => __m128d }
117 from_transmute_x86! { unsafe f64x4 => __m256d }
118 //from_transmute_x86! { unsafe f64x8 => __m512d }
119
120 /// Vector of two `f32` values
121 pub type f32x2 = SimdF32<2>;
122
123 /// Vector of four `f32` values
124 pub type f32x4 = SimdF32<4>;
125
126 /// Vector of eight `f32` values
127 pub type f32x8 = SimdF32<8>;
128
129 /// Vector of 16 `f32` values
130 pub type f32x16 = SimdF32<16>;
131
132 /// Vector of two `f64` values
133 pub type f64x2 = SimdF64<2>;
134
135 /// Vector of four `f64` values
136 pub type f64x4 = SimdF64<4>;
137
138 /// Vector of eight `f64` values
139 pub type f64x8 = SimdF64<8>;