1use crate::{
7 Bytes, ExtractToken, Level, MaskNarrow, MaskWiden, Select, SimdCvtFloat, SimdCvtTruncate,
8 SimdElement, SimdFloatElement, SimdFrom, SimdIntElement, SimdIntWiden, SimdInto, SimdNarrow,
9 SimdWiden, seal::Seal,
10};
11use crate::{
12 f32x4, f32x8, f32x16, f64x2, f64x4, f64x8, i8x16, i8x32, i8x64, i16x8, i16x16, i16x32, i32x4,
13 i32x8, i32x16, i64x2, i64x4, i64x8, mask8x16, mask8x32, mask8x64, mask16x8, mask16x16,
14 mask16x32, mask32x4, mask32x8, mask32x16, mask64x2, mask64x4, mask64x8, u8x16, u8x32, u8x64,
15 u16x8, u16x16, u16x32, u32x4, u32x8, u32x16, u64x2, u64x4, u64x8,
16};
17use core::fmt::Debug;
18#[doc = r" The main SIMD trait, implemented by all SIMD token types."]
19#[doc = r""]
20#[doc = r#" Each implementor of this trait (e.g. `Avx2`, `Sse4_2`, `Sse2`, `Neon`, `Fallback`) is a zero-sized "token" type"#]
21#[doc = r" representing a specific SIMD instruction set. These tokens are obtained at runtime via [`Level`] and the"]
22#[doc = r" [`dispatch!`](crate::dispatch) macro, which selects the best available backend for the current CPU."]
23#[doc = r""]
24#[doc = r" This trait defines all the low-level SIMD operations (e.g. [`add_f32x4`](Simd::add_f32x4),"]
25#[doc = r" [`mul_u32x4`](Simd::mul_u32x4)) that are implemented by each token type using platform-specific intrinsics."]
26#[doc = r" However, you typically won't call these methods directly. Instead, you'll probably be using the methods"]
27#[doc = r" defined on the vector types themselves, such as [`f32x4`] or [`u32x4`]."]
28#[doc = r""]
29#[doc = r" # Associated Types"]
30#[doc = r""]
31#[doc = r#" The trait defines associated types for the highest "native" vector width of each scalar type (e.g. `f32s`,"#]
32#[doc = r" `u32s`). These are always at least 128 bits, but may be larger. Currently, they are 128 bits on the"]
33#[doc = r" fallback, NEON, WASM, SSE2, and SSE4.2 backends, 256 bits on AVX2, and 512 bits on AVX-512."]
34#[doc = r""]
35#[doc = r" # Example"]
36#[doc = r""]
37#[doc = r" ```"]
38#[doc = r" # use fearless_simd::{prelude::*, f32x4, dispatch, Level};"]
39#[doc = r""]
40#[doc = r" #[inline(always)]"]
41#[doc = r" fn add_vectors<S: Simd>(simd: S, a: f32x4<S>, b: f32x4<S>) -> f32x4<S> {"]
42#[doc = r" a + b // Uses operator overloading, which calls simd.add_f32x4 internally"]
43#[doc = r" }"]
44#[doc = r""]
45#[doc = r" let level = Level::new();"]
46#[doc = r" dispatch!(level, simd => {"]
47#[doc = r" let a = [1.0, 2.0, 3.0, 4.0].simd_into(simd);"]
48#[doc = r" let b = [5.0, 6.0, 7.0, 8.0].simd_into(simd);"]
49#[doc = r" let result = add_vectors(simd, a, b);"]
50#[doc = r" # assert_eq!(*result, [6.0, 8.0, 10.0, 12.0]);"]
51#[doc = r" });"]
52#[doc = r" ```"]
53pub trait Simd:
54 ExtractToken<S = Self>
55 + Sized
56 + Clone
57 + Copy
58 + Send
59 + Sync
60 + Debug
61 + Seal
62 + arch_types::ArchTypes
63 + 'static
64{
65 #[doc = r" A native-width SIMD vector of [`f32`]s."]
66 type f32s: SimdFloat<
67 Self,
68 Element = f32,
69 Block = f32x4<Self>,
70 Mask = Self::mask32s,
71 ByteVector = Self::u8s,
72 > + SimdCvtFloat<Self::u32s>
73 + SimdCvtFloat<Self::i32s>
74 + SimdWiden<Self, Widened = Self::f64s>;
75 #[doc = r" A native-width SIMD vector of [`f64`]s."]
76 type f64s: SimdFloat<
77 Self,
78 Element = f64,
79 Block = f64x2<Self>,
80 Mask = Self::mask64s,
81 ByteVector = Self::u8s,
82 > + SimdCvtFloat<Self::u64s>
83 + SimdCvtFloat<Self::i64s>
84 + SimdNarrow<Self, Narrowed = Self::f32s>;
85 #[doc = r" A native-width SIMD vector of [`u8`]s."]
86 type u8s: SimdInt<
87 Self,
88 Element = u8,
89 Block = u8x16<Self>,
90 Mask = Self::mask8s,
91 ByteVector = Self::u8s,
92 > + SimdIntWiden<Self, Widened = Self::u16s>;
93 #[doc = r" A native-width SIMD vector of [`i8`]s."]
94 type i8s: SimdInt<
95 Self,
96 Element = i8,
97 Block = i8x16<Self>,
98 Mask = Self::mask8s,
99 ByteVector = Self::u8s,
100 > + SimdIntWiden<Self, Widened = Self::i16s>
101 + core::ops::Neg<Output = Self::i8s>;
102 #[doc = r" A native-width SIMD vector of [`u16`]s."]
103 type u16s: SimdInt<
104 Self,
105 Element = u16,
106 Block = u16x8<Self>,
107 Mask = Self::mask16s,
108 ByteVector = Self::u8s,
109 > + SimdNarrow<Self, Narrowed = Self::u8s>
110 + SimdIntWiden<Self, Widened = Self::u32s>;
111 #[doc = r" A native-width SIMD vector of [`i16`]s."]
112 type i16s: SimdInt<
113 Self,
114 Element = i16,
115 Block = i16x8<Self>,
116 Mask = Self::mask16s,
117 ByteVector = Self::u8s,
118 > + SimdNarrow<Self, Narrowed = Self::i8s>
119 + SimdIntWiden<Self, Widened = Self::i32s>
120 + core::ops::Neg<Output = Self::i16s>;
121 #[doc = r" A native-width SIMD vector of [`u32`]s."]
122 type u32s: SimdInt<
123 Self,
124 Element = u32,
125 Block = u32x4<Self>,
126 Mask = Self::mask32s,
127 ByteVector = Self::u8s,
128 > + SimdCvtTruncate<Self::f32s>
129 + SimdNarrow<Self, Narrowed = Self::u16s>
130 + SimdIntWiden<Self, Widened = Self::u64s>;
131 #[doc = r" A native-width SIMD vector of [`i32`]s."]
132 type i32s: SimdInt<
133 Self,
134 Element = i32,
135 Block = i32x4<Self>,
136 Mask = Self::mask32s,
137 ByteVector = Self::u8s,
138 > + SimdCvtTruncate<Self::f32s>
139 + SimdNarrow<Self, Narrowed = Self::i16s>
140 + SimdIntWiden<Self, Widened = Self::i64s>
141 + core::ops::Neg<Output = Self::i32s>;
142 #[doc = r" A native-width SIMD vector of [`u64`]s."]
143 type u64s: SimdInt<
144 Self,
145 Element = u64,
146 Block = u64x2<Self>,
147 Mask = Self::mask64s,
148 ByteVector = Self::u8s,
149 > + SimdCvtTruncate<Self::f64s>
150 + SimdNarrow<Self, Narrowed = Self::u32s>;
151 #[doc = r" A native-width SIMD vector of [`i64`]s."]
152 type i64s: SimdInt<
153 Self,
154 Element = i64,
155 Block = i64x2<Self>,
156 Mask = Self::mask64s,
157 ByteVector = Self::u8s,
158 > + SimdCvtTruncate<Self::f64s>
159 + SimdNarrow<Self, Narrowed = Self::i32s>
160 + core::ops::Neg<Output = Self::i64s>;
161 #[doc = r" A native-width SIMD mask with 8-bit lanes."]
162 type mask8s: SimdMask<Self, Element = i8, Ints = Self::i8s>
163 + Select<Self::u8s>
164 + Select<Self::i8s>
165 + Select<Self::mask8s>
166 + MaskWiden<Self, Widened = Self::mask16s>;
167 #[doc = r" A native-width SIMD mask with 16-bit lanes."]
168 type mask16s: SimdMask<Self, Element = i16, Ints = Self::i16s>
169 + Select<Self::u16s>
170 + Select<Self::i16s>
171 + Select<Self::mask16s>
172 + MaskNarrow<Self, Narrowed = Self::mask8s>
173 + MaskWiden<Self, Widened = Self::mask32s>;
174 #[doc = r" A native-width SIMD mask with 32-bit lanes."]
175 type mask32s: SimdMask<Self, Element = i32, Ints = Self::i32s>
176 + Select<Self::f32s>
177 + Select<Self::u32s>
178 + Select<Self::i32s>
179 + Select<Self::mask32s>
180 + MaskNarrow<Self, Narrowed = Self::mask16s>
181 + MaskWiden<Self, Widened = Self::mask64s>;
182 #[doc = r" A native-width SIMD mask with 64-bit lanes."]
183 type mask64s: SimdMask<Self, Element = i64, Ints = Self::i64s>
184 + Select<Self::f64s>
185 + Select<Self::u64s>
186 + Select<Self::i64s>
187 + Select<Self::mask64s>
188 + MaskNarrow<Self, Narrowed = Self::mask32s>;
189 #[doc = r" This SIMD token's feature level."]
190 fn level(self) -> Level;
191 #[doc = r" Call a closure with the instructions for this SIMD level enabled."]
192 #[doc = r""]
193 #[doc = r" `vectorize()` establishes the correct `#[target_feature]` context. The provided"]
194 #[doc = r" closure should be `#[inline(always)]` so that its body is incorporated into that"]
195 #[doc = r" context and can use all instructions supported by this SIMD level."]
196 #[doc = r""]
197 #[doc = r" The small wrappers used by `vectorize()` are eligible for inlining when the caller"]
198 #[doc = r" has a compatible target-feature context. A function containing the call does not"]
199 #[doc = r" itself need an `#[inline(always)]` annotation; a target-feature boundary is retained"]
200 #[doc = r" whenever one is required."]
201 #[doc = r""]
202 #[doc = r" The [`#[simd]`](https://docs.rs/fearless_simd_macros/latest/fearless_simd_macros/attr.simd.html)"]
203 #[doc = r" attribute from the separate `fearless_simd_macros` crate establishes this context"]
204 #[doc = r" automatically, passing ordinary function arguments separately to reduce capture"]
205 #[doc = r" overhead. Calling `vectorize()` manually avoids the procedural-macro dependency."]
206 #[doc = r""]
207 #[doc = r" # Example"]
208 #[doc = r""]
209 #[doc = r" `double_u32s` does not need to be marked `#[inline(always)]`; only the closure passed"]
210 #[doc = r" to `vectorize()` does."]
211 #[doc = r""]
212 #[doc = r" ```"]
213 #[doc = r" use fearless_simd::{dispatch, prelude::*, Level};"]
214 #[doc = r""]
215 #[doc = r" fn double_u32s<S: Simd>(simd: S, values: &mut [u32]) {"]
216 #[doc = r" simd.vectorize("]
217 #[doc = r" #[inline(always)]"]
218 #[doc = r" || {"]
219 #[doc = r" let mut chunks = values.chunks_exact_mut(S::u32s::LEN);"]
220 #[doc = r" for chunk in &mut chunks {"]
221 #[doc = r" let value = S::u32s::from_slice(simd, chunk);"]
222 #[doc = r" (value * 2).store_slice(chunk);"]
223 #[doc = r" }"]
224 #[doc = r" for value in chunks.into_remainder() {"]
225 #[doc = r" *value *= 2;"]
226 #[doc = r" }"]
227 #[doc = r" },"]
228 #[doc = r" );"]
229 #[doc = r" }"]
230 #[doc = r""]
231 #[doc = r" let mut values = [1, 2, 3, 4, 5];"]
232 #[doc = r" let level = Level::new();"]
233 #[doc = r" dispatch!(level, simd => double_u32s(simd, &mut values));"]
234 #[doc = r" assert_eq!(values, [2, 4, 6, 8, 10]);"]
235 #[doc = r" ```"]
236 fn vectorize<F: FnOnce() -> R, R>(self, f: F) -> R;
237 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
238 fn abs_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
239 #[doc = "Create a SIMD vector with all elements set to the given value."]
240 fn splat_f32x4(self, val: f32) -> f32x4<Self>;
241 #[doc = "Reverse the order of the vector's elements."]
242 fn reverse_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
243 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
244 fn slide_f32x4<const SHIFT: usize>(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
245 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
246 #[inline(always)]
247 fn slide_within_blocks_f32x4<const SHIFT: usize>(
248 self,
249 a: f32x4<Self>,
250 b: f32x4<Self>,
251 ) -> f32x4<Self> {
252 self.slide_f32x4::<SHIFT>(a, b)
253 }
254 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
255 #[inline(always)]
256 fn swizzle_dyn_within_blocks_f32x4(self, a: f32x4<Self>, indices: u8x16<Self>) -> f32x4<Self> {
257 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
258 }
259 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
260 #[inline(always)]
261 fn swizzle_dyn_f32x4(self, a: f32x4<Self>, indices: u8x16<Self>) -> f32x4<Self> {
262 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
263 }
264 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
265 #[inline(always)]
266 fn swizzle_dyn_precise_f32x4(self, a: f32x4<Self>, indices: u8x16<Self>) -> f32x4<Self> {
267 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
268 }
269 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
270 #[inline(always)]
271 fn concat_swizzle_dyn_f32x4(
272 self,
273 a: f32x4<Self>,
274 b: f32x4<Self>,
275 indices: u8x16<Self>,
276 ) -> f32x4<Self> {
277 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
278 Bytes::to_bytes(a),
279 Bytes::to_bytes(b),
280 indices,
281 ))
282 }
283 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
284 #[inline(always)]
285 fn concat_swizzle_dyn_precise_f32x4(
286 self,
287 a: f32x4<Self>,
288 b: f32x4<Self>,
289 indices: u8x16<Self>,
290 ) -> f32x4<Self> {
291 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
292 Bytes::to_bytes(a),
293 Bytes::to_bytes(b),
294 indices,
295 ))
296 }
297 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
298 fn compress_f32x4(self, values: f32x4<Self>, mask: mask32x4<Self>) -> f32x4<Self>;
299 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
300 fn compress_merge_f32x4(
301 self,
302 values: f32x4<Self>,
303 mask: mask32x4<Self>,
304 merge: f32x4<Self>,
305 ) -> f32x4<Self>;
306 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
307 fn expand_f32x4(self, values: f32x4<Self>, mask: mask32x4<Self>) -> f32x4<Self>;
308 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
309 fn expand_merge_f32x4(
310 self,
311 values: f32x4<Self>,
312 mask: mask32x4<Self>,
313 merge: f32x4<Self>,
314 ) -> f32x4<Self>;
315 #[doc = "Negate each element of the vector."]
316 fn neg_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
317 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
318 fn sqrt_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
319 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
320 fn approximate_recip_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
321 #[doc = "Add two vectors element-wise."]
322 fn add_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
323 #[doc = "Subtract two vectors element-wise."]
324 fn sub_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
325 #[doc = "Multiply two vectors element-wise."]
326 fn mul_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
327 #[doc = "Divide two vectors element-wise."]
328 fn div_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
329 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
330 fn copysign_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
331 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
332 fn reduce_max_f32x4(self, a: f32x4<Self>) -> f32;
333 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
334 fn reduce_min_f32x4(self, a: f32x4<Self>) -> f32;
335 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
336 fn reduce_max_precise_f32x4(self, a: f32x4<Self>) -> f32;
337 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
338 fn reduce_min_precise_f32x4(self, a: f32x4<Self>) -> f32;
339 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
340 fn reduce_sum_f32x4(self, a: f32x4<Self>) -> f32;
341 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
342 fn reduce_product_f32x4(self, a: f32x4<Self>) -> f32;
343 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
344 fn max_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
345 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
346 fn min_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
347 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
348 fn max_precise_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
349 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
350 fn min_precise_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
351 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
352 fn clamp_f32x4(self, a: f32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
353 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
354 fn simd_eq_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self>;
355 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
356 #[inline(always)]
357 fn simd_ne_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self> {
358 self.not_mask32x4(self.simd_eq_f32x4(a, b))
359 }
360 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
361 fn simd_lt_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self>;
362 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
363 fn simd_le_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self>;
364 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
365 #[inline(always)]
366 fn simd_ge_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self> {
367 self.simd_le_f32x4(b, a)
368 }
369 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
370 #[inline(always)]
371 fn simd_gt_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> mask32x4<Self> {
372 self.simd_lt_f32x4(b, a)
373 }
374 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
375 fn zip_low_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
376 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
377 fn zip_high_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
378 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
379 fn unzip_low_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
380 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
381 fn unzip_high_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x4<Self>;
382 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
383 fn interleave_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> (f32x4<Self>, f32x4<Self>);
384 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
385 fn deinterleave_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> (f32x4<Self>, f32x4<Self>);
386 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
387 fn mul_add_f32x4(self, a: f32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
388 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
389 fn mul_add_precise_f32x4(self, a: f32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
390 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
391 fn mul_sub_f32x4(self, a: f32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
392 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
393 fn mul_sub_precise_f32x4(self, a: f32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
394 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
395 fn floor_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
396 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
397 fn ceil_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
398 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
399 fn round_ties_even_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
400 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
401 fn round_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
402 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
403 fn fract_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
404 #[doc = "Return the integer part of each element, rounding towards zero."]
405 fn trunc_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
406 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
407 fn to_degrees_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
408 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
409 fn to_radians_f32x4(self, a: f32x4<Self>) -> f32x4<Self>;
410 #[doc = "Return a mask indicating which elements are NaN."]
411 fn is_nan_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
412 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
413 fn is_infinite_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
414 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
415 fn is_finite_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
416 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
417 fn is_subnormal_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
418 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
419 fn is_normal_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
420 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
421 fn is_sign_positive_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
422 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
423 fn is_sign_negative_f32x4(self, a: f32x4<Self>) -> mask32x4<Self>;
424 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
425 fn select_f32x4(self, a: mask32x4<Self>, b: f32x4<Self>, c: f32x4<Self>) -> f32x4<Self>;
426 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
427 fn combine_f32x4(self, a: f32x4<Self>, b: f32x4<Self>) -> f32x8<Self>;
428 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
429 #[doc(alias = "load_interleaved")]
430 fn load_four_interleaved_f32x4(self, src: &[f32; 16usize]) -> [f32x4<Self>; 4usize];
431 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
432 #[doc(alias = "store_interleaved")]
433 fn store_four_interleaved_f32x4(
434 self,
435 vectors: [f32x4<Self>; 4usize],
436 dest: &mut [f32; 16usize],
437 ) -> ();
438 #[doc = "Widen every `f32` lane exactly into two same-width `f64` vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
439 fn widen_f32x4(self, a: f32x4<Self>) -> (f64x2<Self>, f64x2<Self>);
440 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results.\n\nOn x86 platforms below AVX-512, this operation will still be slower than converting to `i32`, because there is no native instruction for converting to `u32`.\nIf you know your values fit within range of an `i32`, you should convert to an `i32` and cast to your desired datatype afterwards."]
441 fn cvt_u32_f32x4(self, a: f32x4<Self>) -> u32x4<Self>;
442 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
443 fn cvt_u32_precise_f32x4(self, a: f32x4<Self>) -> u32x4<Self>;
444 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
445 fn cvt_i32_f32x4(self, a: f32x4<Self>) -> i32x4<Self>;
446 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
447 fn cvt_i32_precise_f32x4(self, a: f32x4<Self>) -> i32x4<Self>;
448 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
449 fn abs_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
450 #[doc = "Create a SIMD vector with all elements set to the given value."]
451 fn splat_i8x16(self, val: i8) -> i8x16<Self>;
452 #[doc = "Reverse the order of the vector's elements."]
453 fn reverse_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
454 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
455 fn slide_i8x16<const SHIFT: usize>(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
456 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
457 #[inline(always)]
458 fn slide_within_blocks_i8x16<const SHIFT: usize>(
459 self,
460 a: i8x16<Self>,
461 b: i8x16<Self>,
462 ) -> i8x16<Self> {
463 self.slide_i8x16::<SHIFT>(a, b)
464 }
465 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
466 #[inline(always)]
467 fn swizzle_dyn_within_blocks_i8x16(self, a: i8x16<Self>, indices: u8x16<Self>) -> i8x16<Self> {
468 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
469 }
470 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
471 #[inline(always)]
472 fn swizzle_dyn_i8x16(self, a: i8x16<Self>, indices: u8x16<Self>) -> i8x16<Self> {
473 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
474 }
475 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
476 #[inline(always)]
477 fn swizzle_dyn_precise_i8x16(self, a: i8x16<Self>, indices: u8x16<Self>) -> i8x16<Self> {
478 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
479 }
480 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
481 #[inline(always)]
482 fn concat_swizzle_dyn_i8x16(
483 self,
484 a: i8x16<Self>,
485 b: i8x16<Self>,
486 indices: u8x16<Self>,
487 ) -> i8x16<Self> {
488 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
489 Bytes::to_bytes(a),
490 Bytes::to_bytes(b),
491 indices,
492 ))
493 }
494 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
495 #[inline(always)]
496 fn concat_swizzle_dyn_precise_i8x16(
497 self,
498 a: i8x16<Self>,
499 b: i8x16<Self>,
500 indices: u8x16<Self>,
501 ) -> i8x16<Self> {
502 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
503 Bytes::to_bytes(a),
504 Bytes::to_bytes(b),
505 indices,
506 ))
507 }
508 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
509 fn compress_i8x16(self, values: i8x16<Self>, mask: mask8x16<Self>) -> i8x16<Self>;
510 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
511 fn compress_merge_i8x16(
512 self,
513 values: i8x16<Self>,
514 mask: mask8x16<Self>,
515 merge: i8x16<Self>,
516 ) -> i8x16<Self>;
517 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
518 fn expand_i8x16(self, values: i8x16<Self>, mask: mask8x16<Self>) -> i8x16<Self>;
519 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
520 fn expand_merge_i8x16(
521 self,
522 values: i8x16<Self>,
523 mask: mask8x16<Self>,
524 merge: i8x16<Self>,
525 ) -> i8x16<Self>;
526 #[doc = "Return the number of ones in the binary representation of each element."]
527 fn count_ones_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
528 #[doc = "Return the number of zeros in the binary representation of each element."]
529 fn count_zeros_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
530 #[doc = "Add two vectors element-wise, wrapping on overflow."]
531 fn add_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
532 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
533 fn saturating_add_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
534 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
535 fn sub_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
536 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
537 fn saturating_sub_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
538 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
539 fn mul_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
540 #[doc = "Compute the bitwise AND of two vectors."]
541 fn and_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
542 #[doc = "Compute the bitwise OR of two vectors."]
543 fn or_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
544 #[doc = "Compute the bitwise XOR of two vectors."]
545 fn xor_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
546 #[doc = "Compute the bitwise NOT of the vector."]
547 fn not_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
548 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
549 fn shl_i8x16(self, a: i8x16<Self>, shift: u32) -> i8x16<Self>;
550 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
551 fn shlv_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
552 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
553 fn shr_i8x16(self, a: i8x16<Self>, shift: u32) -> i8x16<Self>;
554 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
555 fn shrv_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
556 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
557 fn reduce_max_i8x16(self, a: i8x16<Self>) -> i8;
558 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
559 fn reduce_min_i8x16(self, a: i8x16<Self>) -> i8;
560 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
561 fn reduce_sum_i8x16(self, a: i8x16<Self>) -> i8;
562 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
563 fn reduce_product_i8x16(self, a: i8x16<Self>) -> i8;
564 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
565 fn max_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
566 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
567 fn min_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
568 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
569 fn clamp_i8x16(self, a: i8x16<Self>, b: i8x16<Self>, c: i8x16<Self>) -> i8x16<Self>;
570 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
571 fn simd_eq_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self>;
572 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
573 #[inline(always)]
574 fn simd_ne_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self> {
575 self.not_mask8x16(self.simd_eq_i8x16(a, b))
576 }
577 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
578 fn simd_lt_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self>;
579 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
580 fn simd_le_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self>;
581 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
582 #[inline(always)]
583 fn simd_ge_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self> {
584 self.simd_le_i8x16(b, a)
585 }
586 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
587 #[inline(always)]
588 fn simd_gt_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> mask8x16<Self> {
589 self.simd_lt_i8x16(b, a)
590 }
591 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
592 fn zip_low_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
593 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
594 fn zip_high_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
595 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
596 fn unzip_low_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
597 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
598 fn unzip_high_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x16<Self>;
599 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
600 fn interleave_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> (i8x16<Self>, i8x16<Self>);
601 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
602 fn deinterleave_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> (i8x16<Self>, i8x16<Self>);
603 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
604 fn select_i8x16(self, a: mask8x16<Self>, b: i8x16<Self>, c: i8x16<Self>) -> i8x16<Self>;
605 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
606 fn combine_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i8x32<Self>;
607 #[doc = "Negate each element of the vector, wrapping on overflow."]
608 fn neg_i8x16(self, a: i8x16<Self>) -> i8x16<Self>;
609 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
610 #[doc(alias = "load_interleaved")]
611 fn load_four_interleaved_i8x16(self, src: &[i8; 64usize]) -> [i8x16<Self>; 4usize];
612 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
613 #[doc(alias = "store_interleaved")]
614 fn store_four_interleaved_i8x16(
615 self,
616 vectors: [i8x16<Self>; 4usize],
617 dest: &mut [i8; 64usize],
618 ) -> ();
619 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
620 fn widen_i8x16(self, a: i8x16<Self>) -> (i16x8<Self>, i16x8<Self>);
621 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
622 fn widening_mul_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> (i16x8<Self>, i16x8<Self>);
623 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
624 fn widening_add_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> (i16x8<Self>, i16x8<Self>);
625 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
626 fn pairwise_widening_add_i8x16(self, a: i8x16<Self>) -> i16x8<Self>;
627 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
628 fn pairwise_dot_product_i8x16(self, a: i8x16<Self>, b: i8x16<Self>) -> i16x8<Self>;
629 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
630 #[inline(always)]
631 fn abs_u8x16(self, a: u8x16<Self>) -> u8x16<Self> {
632 a
633 }
634 #[doc = "Create a SIMD vector with all elements set to the given value."]
635 fn splat_u8x16(self, val: u8) -> u8x16<Self>;
636 #[doc = "Reverse the order of the vector's elements."]
637 fn reverse_u8x16(self, a: u8x16<Self>) -> u8x16<Self>;
638 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
639 fn slide_u8x16<const SHIFT: usize>(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
640 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
641 #[inline(always)]
642 fn slide_within_blocks_u8x16<const SHIFT: usize>(
643 self,
644 a: u8x16<Self>,
645 b: u8x16<Self>,
646 ) -> u8x16<Self> {
647 self.slide_u8x16::<SHIFT>(a, b)
648 }
649 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
650 fn swizzle_dyn_within_blocks_u8x16(self, a: u8x16<Self>, indices: u8x16<Self>) -> u8x16<Self>;
651 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
652 fn swizzle_dyn_u8x16(self, a: u8x16<Self>, indices: u8x16<Self>) -> u8x16<Self>;
653 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
654 fn swizzle_dyn_precise_u8x16(self, a: u8x16<Self>, indices: u8x16<Self>) -> u8x16<Self>;
655 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
656 fn concat_swizzle_dyn_u8x16(
657 self,
658 a: u8x16<Self>,
659 b: u8x16<Self>,
660 indices: u8x16<Self>,
661 ) -> u8x16<Self>;
662 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
663 fn concat_swizzle_dyn_precise_u8x16(
664 self,
665 a: u8x16<Self>,
666 b: u8x16<Self>,
667 indices: u8x16<Self>,
668 ) -> u8x16<Self>;
669 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
670 fn compress_u8x16(self, values: u8x16<Self>, mask: mask8x16<Self>) -> u8x16<Self>;
671 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
672 fn compress_merge_u8x16(
673 self,
674 values: u8x16<Self>,
675 mask: mask8x16<Self>,
676 merge: u8x16<Self>,
677 ) -> u8x16<Self>;
678 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
679 fn expand_u8x16(self, values: u8x16<Self>, mask: mask8x16<Self>) -> u8x16<Self>;
680 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
681 fn expand_merge_u8x16(
682 self,
683 values: u8x16<Self>,
684 mask: mask8x16<Self>,
685 merge: u8x16<Self>,
686 ) -> u8x16<Self>;
687 #[doc = "Return the number of ones in the binary representation of each element."]
688 fn count_ones_u8x16(self, a: u8x16<Self>) -> u8x16<Self>;
689 #[doc = "Return the number of zeros in the binary representation of each element."]
690 fn count_zeros_u8x16(self, a: u8x16<Self>) -> u8x16<Self>;
691 #[doc = "Add two vectors element-wise, wrapping on overflow."]
692 fn add_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
693 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
694 fn saturating_add_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
695 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
696 fn sub_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
697 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
698 fn saturating_sub_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
699 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
700 fn mul_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
701 #[doc = "Compute the bitwise AND of two vectors."]
702 fn and_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
703 #[doc = "Compute the bitwise OR of two vectors."]
704 fn or_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
705 #[doc = "Compute the bitwise XOR of two vectors."]
706 fn xor_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
707 #[doc = "Compute the bitwise NOT of the vector."]
708 fn not_u8x16(self, a: u8x16<Self>) -> u8x16<Self>;
709 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
710 fn shl_u8x16(self, a: u8x16<Self>, shift: u32) -> u8x16<Self>;
711 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
712 fn shlv_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
713 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
714 fn shr_u8x16(self, a: u8x16<Self>, shift: u32) -> u8x16<Self>;
715 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
716 fn shrv_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
717 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
718 fn reduce_max_u8x16(self, a: u8x16<Self>) -> u8;
719 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
720 fn reduce_min_u8x16(self, a: u8x16<Self>) -> u8;
721 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
722 fn reduce_sum_u8x16(self, a: u8x16<Self>) -> u8;
723 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
724 fn reduce_product_u8x16(self, a: u8x16<Self>) -> u8;
725 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
726 fn max_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
727 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
728 fn min_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
729 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
730 fn clamp_u8x16(self, a: u8x16<Self>, b: u8x16<Self>, c: u8x16<Self>) -> u8x16<Self>;
731 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
732 fn simd_eq_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self>;
733 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
734 #[inline(always)]
735 fn simd_ne_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self> {
736 self.not_mask8x16(self.simd_eq_u8x16(a, b))
737 }
738 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
739 fn simd_lt_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self>;
740 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
741 fn simd_le_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self>;
742 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
743 #[inline(always)]
744 fn simd_ge_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self> {
745 self.simd_le_u8x16(b, a)
746 }
747 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
748 #[inline(always)]
749 fn simd_gt_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> mask8x16<Self> {
750 self.simd_lt_u8x16(b, a)
751 }
752 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
753 fn zip_low_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
754 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
755 fn zip_high_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
756 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
757 fn unzip_low_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
758 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
759 fn unzip_high_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x16<Self>;
760 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
761 fn interleave_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> (u8x16<Self>, u8x16<Self>);
762 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
763 fn deinterleave_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> (u8x16<Self>, u8x16<Self>);
764 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
765 fn select_u8x16(self, a: mask8x16<Self>, b: u8x16<Self>, c: u8x16<Self>) -> u8x16<Self>;
766 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
767 fn combine_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u8x32<Self>;
768 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
769 #[doc(alias = "load_interleaved")]
770 fn load_four_interleaved_u8x16(self, src: &[u8; 64usize]) -> [u8x16<Self>; 4usize];
771 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
772 #[doc(alias = "store_interleaved")]
773 fn store_four_interleaved_u8x16(
774 self,
775 vectors: [u8x16<Self>; 4usize],
776 dest: &mut [u8; 64usize],
777 ) -> ();
778 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
779 fn widen_u8x16(self, a: u8x16<Self>) -> (u16x8<Self>, u16x8<Self>);
780 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
781 fn widening_mul_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> (u16x8<Self>, u16x8<Self>);
782 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
783 fn widening_add_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> (u16x8<Self>, u16x8<Self>);
784 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
785 fn pairwise_widening_add_u8x16(self, a: u8x16<Self>) -> u16x8<Self>;
786 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
787 fn pairwise_dot_product_u8x16(self, a: u8x16<Self>, b: u8x16<Self>) -> u16x8<Self>;
788 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
789 fn splat_mask8x16(self, val: bool) -> mask8x16<Self>;
790 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
791 fn from_bitmask_mask8x16(self, bits: u64) -> mask8x16<Self>;
792 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
793 fn to_bitmask_mask8x16(self, a: mask8x16<Self>) -> u64;
794 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
795 fn from_vector_mask8x16(self, vector: i8x16<Self>) -> mask8x16<Self>;
796 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
797 fn to_vector_mask8x16(self, a: mask8x16<Self>) -> i8x16<Self>;
798 #[doc = "Set one logical lane of a SIMD mask."]
799 fn set_mask8x16(self, a: &mut mask8x16<Self>, index: usize, value: bool) -> ();
800 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
801 fn rotate_elements_left_mask8x16<const OFFSET: usize>(
802 self,
803 a: mask8x16<Self>,
804 ) -> mask8x16<Self>;
805 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
806 fn rotate_elements_right_mask8x16<const OFFSET: usize>(
807 self,
808 a: mask8x16<Self>,
809 ) -> mask8x16<Self>;
810 #[doc = "Compute the logical AND of two masks."]
811 fn and_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x16<Self>;
812 #[doc = "Compute the logical OR of two masks."]
813 fn or_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x16<Self>;
814 #[doc = "Compute the logical XOR of two masks."]
815 fn xor_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x16<Self>;
816 #[doc = "Compute the logical NOT of the mask."]
817 fn not_mask8x16(self, a: mask8x16<Self>) -> mask8x16<Self>;
818 #[doc = "Reverse the order of the mask's logical lanes."]
819 fn reverse_mask8x16(self, a: mask8x16<Self>) -> mask8x16<Self>;
820 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
821 fn select_mask8x16(
822 self,
823 a: mask8x16<Self>,
824 b: mask8x16<Self>,
825 c: mask8x16<Self>,
826 ) -> mask8x16<Self>;
827 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
828 fn simd_eq_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x16<Self>;
829 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
830 #[inline(always)]
831 fn simd_ne_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x16<Self> {
832 self.not_mask8x16(self.simd_eq_mask8x16(a, b))
833 }
834 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
835 fn any_true_mask8x16(self, a: mask8x16<Self>) -> bool;
836 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
837 fn all_true_mask8x16(self, a: mask8x16<Self>) -> bool;
838 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
839 fn any_false_mask8x16(self, a: mask8x16<Self>) -> bool;
840 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
841 fn all_false_mask8x16(self, a: mask8x16<Self>) -> bool;
842 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
843 fn combine_mask8x16(self, a: mask8x16<Self>, b: mask8x16<Self>) -> mask8x32<Self>;
844 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
845 fn widen_mask8x16(self, a: mask8x16<Self>) -> (mask16x8<Self>, mask16x8<Self>);
846 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
847 fn abs_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
848 #[doc = "Create a SIMD vector with all elements set to the given value."]
849 fn splat_i16x8(self, val: i16) -> i16x8<Self>;
850 #[doc = "Reverse the order of the vector's elements."]
851 fn reverse_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
852 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
853 fn slide_i16x8<const SHIFT: usize>(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
854 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
855 #[inline(always)]
856 fn slide_within_blocks_i16x8<const SHIFT: usize>(
857 self,
858 a: i16x8<Self>,
859 b: i16x8<Self>,
860 ) -> i16x8<Self> {
861 self.slide_i16x8::<SHIFT>(a, b)
862 }
863 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
864 #[inline(always)]
865 fn swizzle_dyn_within_blocks_i16x8(self, a: i16x8<Self>, indices: u8x16<Self>) -> i16x8<Self> {
866 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
867 }
868 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
869 #[inline(always)]
870 fn swizzle_dyn_i16x8(self, a: i16x8<Self>, indices: u8x16<Self>) -> i16x8<Self> {
871 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
872 }
873 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
874 #[inline(always)]
875 fn swizzle_dyn_precise_i16x8(self, a: i16x8<Self>, indices: u8x16<Self>) -> i16x8<Self> {
876 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
877 }
878 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
879 #[inline(always)]
880 fn concat_swizzle_dyn_i16x8(
881 self,
882 a: i16x8<Self>,
883 b: i16x8<Self>,
884 indices: u8x16<Self>,
885 ) -> i16x8<Self> {
886 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
887 Bytes::to_bytes(a),
888 Bytes::to_bytes(b),
889 indices,
890 ))
891 }
892 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
893 #[inline(always)]
894 fn concat_swizzle_dyn_precise_i16x8(
895 self,
896 a: i16x8<Self>,
897 b: i16x8<Self>,
898 indices: u8x16<Self>,
899 ) -> i16x8<Self> {
900 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
901 Bytes::to_bytes(a),
902 Bytes::to_bytes(b),
903 indices,
904 ))
905 }
906 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
907 fn compress_i16x8(self, values: i16x8<Self>, mask: mask16x8<Self>) -> i16x8<Self>;
908 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
909 fn compress_merge_i16x8(
910 self,
911 values: i16x8<Self>,
912 mask: mask16x8<Self>,
913 merge: i16x8<Self>,
914 ) -> i16x8<Self>;
915 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
916 fn expand_i16x8(self, values: i16x8<Self>, mask: mask16x8<Self>) -> i16x8<Self>;
917 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
918 fn expand_merge_i16x8(
919 self,
920 values: i16x8<Self>,
921 mask: mask16x8<Self>,
922 merge: i16x8<Self>,
923 ) -> i16x8<Self>;
924 #[doc = "Return the number of ones in the binary representation of each element."]
925 fn count_ones_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
926 #[doc = "Return the number of zeros in the binary representation of each element."]
927 fn count_zeros_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
928 #[doc = "Add two vectors element-wise, wrapping on overflow."]
929 fn add_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
930 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
931 fn saturating_add_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
932 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
933 fn sub_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
934 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
935 fn saturating_sub_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
936 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
937 fn mul_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
938 #[doc = "Compute the bitwise AND of two vectors."]
939 fn and_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
940 #[doc = "Compute the bitwise OR of two vectors."]
941 fn or_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
942 #[doc = "Compute the bitwise XOR of two vectors."]
943 fn xor_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
944 #[doc = "Compute the bitwise NOT of the vector."]
945 fn not_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
946 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
947 fn shl_i16x8(self, a: i16x8<Self>, shift: u32) -> i16x8<Self>;
948 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
949 fn shlv_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
950 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
951 fn shr_i16x8(self, a: i16x8<Self>, shift: u32) -> i16x8<Self>;
952 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
953 fn shrv_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
954 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
955 fn reduce_max_i16x8(self, a: i16x8<Self>) -> i16;
956 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
957 fn reduce_min_i16x8(self, a: i16x8<Self>) -> i16;
958 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
959 fn reduce_sum_i16x8(self, a: i16x8<Self>) -> i16;
960 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
961 fn reduce_product_i16x8(self, a: i16x8<Self>) -> i16;
962 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
963 fn max_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
964 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
965 fn min_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
966 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
967 fn clamp_i16x8(self, a: i16x8<Self>, b: i16x8<Self>, c: i16x8<Self>) -> i16x8<Self>;
968 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
969 fn simd_eq_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self>;
970 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
971 #[inline(always)]
972 fn simd_ne_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self> {
973 self.not_mask16x8(self.simd_eq_i16x8(a, b))
974 }
975 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
976 fn simd_lt_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self>;
977 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
978 fn simd_le_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self>;
979 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
980 #[inline(always)]
981 fn simd_ge_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self> {
982 self.simd_le_i16x8(b, a)
983 }
984 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
985 #[inline(always)]
986 fn simd_gt_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> mask16x8<Self> {
987 self.simd_lt_i16x8(b, a)
988 }
989 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
990 fn zip_low_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
991 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
992 fn zip_high_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
993 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
994 fn unzip_low_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
995 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
996 fn unzip_high_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x8<Self>;
997 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
998 fn interleave_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> (i16x8<Self>, i16x8<Self>);
999 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
1000 fn deinterleave_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> (i16x8<Self>, i16x8<Self>);
1001 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1002 fn select_i16x8(self, a: mask16x8<Self>, b: i16x8<Self>, c: i16x8<Self>) -> i16x8<Self>;
1003 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1004 fn combine_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i16x16<Self>;
1005 #[doc = "Negate each element of the vector, wrapping on overflow."]
1006 fn neg_i16x8(self, a: i16x8<Self>) -> i16x8<Self>;
1007 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
1008 #[doc(alias = "load_interleaved")]
1009 fn load_four_interleaved_i16x8(self, src: &[i16; 32usize]) -> [i16x8<Self>; 4usize];
1010 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
1011 #[doc(alias = "store_interleaved")]
1012 fn store_four_interleaved_i16x8(
1013 self,
1014 vectors: [i16x8<Self>; 4usize],
1015 dest: &mut [i16; 32usize],
1016 ) -> ();
1017 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
1018 fn widen_i16x8(self, a: i16x8<Self>) -> (i32x4<Self>, i32x4<Self>);
1019 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1020 fn widening_mul_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> (i32x4<Self>, i32x4<Self>);
1021 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1022 fn widening_add_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> (i32x4<Self>, i32x4<Self>);
1023 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
1024 fn pairwise_widening_add_i16x8(self, a: i16x8<Self>) -> i32x4<Self>;
1025 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
1026 fn pairwise_dot_product_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i32x4<Self>;
1027 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1028 fn narrow_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i8x16<Self>;
1029 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1030 fn saturating_narrow_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i8x16<Self>;
1031 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1032 fn relaxed_narrow_i16x8(self, a: i16x8<Self>, b: i16x8<Self>) -> i8x16<Self>;
1033 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
1034 #[inline(always)]
1035 fn abs_u16x8(self, a: u16x8<Self>) -> u16x8<Self> {
1036 a
1037 }
1038 #[doc = "Create a SIMD vector with all elements set to the given value."]
1039 fn splat_u16x8(self, val: u16) -> u16x8<Self>;
1040 #[doc = "Reverse the order of the vector's elements."]
1041 fn reverse_u16x8(self, a: u16x8<Self>) -> u16x8<Self>;
1042 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
1043 fn slide_u16x8<const SHIFT: usize>(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1044 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
1045 #[inline(always)]
1046 fn slide_within_blocks_u16x8<const SHIFT: usize>(
1047 self,
1048 a: u16x8<Self>,
1049 b: u16x8<Self>,
1050 ) -> u16x8<Self> {
1051 self.slide_u16x8::<SHIFT>(a, b)
1052 }
1053 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
1054 #[inline(always)]
1055 fn swizzle_dyn_within_blocks_u16x8(self, a: u16x8<Self>, indices: u8x16<Self>) -> u16x8<Self> {
1056 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
1057 }
1058 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1059 #[inline(always)]
1060 fn swizzle_dyn_u16x8(self, a: u16x8<Self>, indices: u8x16<Self>) -> u16x8<Self> {
1061 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
1062 }
1063 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
1064 #[inline(always)]
1065 fn swizzle_dyn_precise_u16x8(self, a: u16x8<Self>, indices: u8x16<Self>) -> u16x8<Self> {
1066 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
1067 }
1068 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1069 #[inline(always)]
1070 fn concat_swizzle_dyn_u16x8(
1071 self,
1072 a: u16x8<Self>,
1073 b: u16x8<Self>,
1074 indices: u8x16<Self>,
1075 ) -> u16x8<Self> {
1076 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
1077 Bytes::to_bytes(a),
1078 Bytes::to_bytes(b),
1079 indices,
1080 ))
1081 }
1082 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
1083 #[inline(always)]
1084 fn concat_swizzle_dyn_precise_u16x8(
1085 self,
1086 a: u16x8<Self>,
1087 b: u16x8<Self>,
1088 indices: u8x16<Self>,
1089 ) -> u16x8<Self> {
1090 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
1091 Bytes::to_bytes(a),
1092 Bytes::to_bytes(b),
1093 indices,
1094 ))
1095 }
1096 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
1097 fn compress_u16x8(self, values: u16x8<Self>, mask: mask16x8<Self>) -> u16x8<Self>;
1098 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
1099 fn compress_merge_u16x8(
1100 self,
1101 values: u16x8<Self>,
1102 mask: mask16x8<Self>,
1103 merge: u16x8<Self>,
1104 ) -> u16x8<Self>;
1105 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
1106 fn expand_u16x8(self, values: u16x8<Self>, mask: mask16x8<Self>) -> u16x8<Self>;
1107 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
1108 fn expand_merge_u16x8(
1109 self,
1110 values: u16x8<Self>,
1111 mask: mask16x8<Self>,
1112 merge: u16x8<Self>,
1113 ) -> u16x8<Self>;
1114 #[doc = "Return the number of ones in the binary representation of each element."]
1115 fn count_ones_u16x8(self, a: u16x8<Self>) -> u16x8<Self>;
1116 #[doc = "Return the number of zeros in the binary representation of each element."]
1117 fn count_zeros_u16x8(self, a: u16x8<Self>) -> u16x8<Self>;
1118 #[doc = "Add two vectors element-wise, wrapping on overflow."]
1119 fn add_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1120 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
1121 fn saturating_add_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1122 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
1123 fn sub_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1124 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
1125 fn saturating_sub_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1126 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
1127 fn mul_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1128 #[doc = "Compute the bitwise AND of two vectors."]
1129 fn and_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1130 #[doc = "Compute the bitwise OR of two vectors."]
1131 fn or_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1132 #[doc = "Compute the bitwise XOR of two vectors."]
1133 fn xor_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1134 #[doc = "Compute the bitwise NOT of the vector."]
1135 fn not_u16x8(self, a: u16x8<Self>) -> u16x8<Self>;
1136 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1137 fn shl_u16x8(self, a: u16x8<Self>, shift: u32) -> u16x8<Self>;
1138 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1139 fn shlv_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1140 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1141 fn shr_u16x8(self, a: u16x8<Self>, shift: u32) -> u16x8<Self>;
1142 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1143 fn shrv_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1144 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1145 fn reduce_max_u16x8(self, a: u16x8<Self>) -> u16;
1146 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1147 fn reduce_min_u16x8(self, a: u16x8<Self>) -> u16;
1148 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
1149 fn reduce_sum_u16x8(self, a: u16x8<Self>) -> u16;
1150 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
1151 fn reduce_product_u16x8(self, a: u16x8<Self>) -> u16;
1152 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1153 fn max_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1154 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1155 fn min_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1156 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
1157 fn clamp_u16x8(self, a: u16x8<Self>, b: u16x8<Self>, c: u16x8<Self>) -> u16x8<Self>;
1158 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1159 fn simd_eq_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self>;
1160 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1161 #[inline(always)]
1162 fn simd_ne_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self> {
1163 self.not_mask16x8(self.simd_eq_u16x8(a, b))
1164 }
1165 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
1166 fn simd_lt_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self>;
1167 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
1168 fn simd_le_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self>;
1169 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
1170 #[inline(always)]
1171 fn simd_ge_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self> {
1172 self.simd_le_u16x8(b, a)
1173 }
1174 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
1175 #[inline(always)]
1176 fn simd_gt_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> mask16x8<Self> {
1177 self.simd_lt_u16x8(b, a)
1178 }
1179 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1180 fn zip_low_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1181 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1182 fn zip_high_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1183 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1184 fn unzip_low_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1185 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1186 fn unzip_high_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x8<Self>;
1187 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
1188 fn interleave_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> (u16x8<Self>, u16x8<Self>);
1189 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
1190 fn deinterleave_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> (u16x8<Self>, u16x8<Self>);
1191 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1192 fn select_u16x8(self, a: mask16x8<Self>, b: u16x8<Self>, c: u16x8<Self>) -> u16x8<Self>;
1193 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1194 fn combine_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u16x16<Self>;
1195 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
1196 #[doc(alias = "load_interleaved")]
1197 fn load_four_interleaved_u16x8(self, src: &[u16; 32usize]) -> [u16x8<Self>; 4usize];
1198 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
1199 #[doc(alias = "store_interleaved")]
1200 fn store_four_interleaved_u16x8(
1201 self,
1202 vectors: [u16x8<Self>; 4usize],
1203 dest: &mut [u16; 32usize],
1204 ) -> ();
1205 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
1206 fn widen_u16x8(self, a: u16x8<Self>) -> (u32x4<Self>, u32x4<Self>);
1207 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1208 fn widening_mul_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> (u32x4<Self>, u32x4<Self>);
1209 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1210 fn widening_add_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> (u32x4<Self>, u32x4<Self>);
1211 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
1212 fn pairwise_widening_add_u16x8(self, a: u16x8<Self>) -> u32x4<Self>;
1213 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
1214 fn pairwise_dot_product_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u32x4<Self>;
1215 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1216 fn narrow_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u8x16<Self>;
1217 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1218 fn saturating_narrow_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u8x16<Self>;
1219 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1220 fn relaxed_narrow_u16x8(self, a: u16x8<Self>, b: u16x8<Self>) -> u8x16<Self>;
1221 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
1222 fn splat_mask16x8(self, val: bool) -> mask16x8<Self>;
1223 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
1224 fn from_bitmask_mask16x8(self, bits: u64) -> mask16x8<Self>;
1225 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
1226 fn to_bitmask_mask16x8(self, a: mask16x8<Self>) -> u64;
1227 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
1228 fn from_vector_mask16x8(self, vector: i16x8<Self>) -> mask16x8<Self>;
1229 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
1230 fn to_vector_mask16x8(self, a: mask16x8<Self>) -> i16x8<Self>;
1231 #[doc = "Set one logical lane of a SIMD mask."]
1232 fn set_mask16x8(self, a: &mut mask16x8<Self>, index: usize, value: bool) -> ();
1233 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
1234 fn rotate_elements_left_mask16x8<const OFFSET: usize>(
1235 self,
1236 a: mask16x8<Self>,
1237 ) -> mask16x8<Self>;
1238 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
1239 fn rotate_elements_right_mask16x8<const OFFSET: usize>(
1240 self,
1241 a: mask16x8<Self>,
1242 ) -> mask16x8<Self>;
1243 #[doc = "Compute the logical AND of two masks."]
1244 fn and_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x8<Self>;
1245 #[doc = "Compute the logical OR of two masks."]
1246 fn or_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x8<Self>;
1247 #[doc = "Compute the logical XOR of two masks."]
1248 fn xor_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x8<Self>;
1249 #[doc = "Compute the logical NOT of the mask."]
1250 fn not_mask16x8(self, a: mask16x8<Self>) -> mask16x8<Self>;
1251 #[doc = "Reverse the order of the mask's logical lanes."]
1252 fn reverse_mask16x8(self, a: mask16x8<Self>) -> mask16x8<Self>;
1253 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1254 fn select_mask16x8(
1255 self,
1256 a: mask16x8<Self>,
1257 b: mask16x8<Self>,
1258 c: mask16x8<Self>,
1259 ) -> mask16x8<Self>;
1260 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1261 fn simd_eq_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x8<Self>;
1262 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1263 #[inline(always)]
1264 fn simd_ne_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x8<Self> {
1265 self.not_mask16x8(self.simd_eq_mask16x8(a, b))
1266 }
1267 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1268 fn any_true_mask16x8(self, a: mask16x8<Self>) -> bool;
1269 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1270 fn all_true_mask16x8(self, a: mask16x8<Self>) -> bool;
1271 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1272 fn any_false_mask16x8(self, a: mask16x8<Self>) -> bool;
1273 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1274 fn all_false_mask16x8(self, a: mask16x8<Self>) -> bool;
1275 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1276 fn combine_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask16x16<Self>;
1277 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
1278 fn widen_mask16x8(self, a: mask16x8<Self>) -> (mask32x4<Self>, mask32x4<Self>);
1279 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
1280 fn narrow_mask16x8(self, a: mask16x8<Self>, b: mask16x8<Self>) -> mask8x16<Self>;
1281 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
1282 fn abs_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1283 #[doc = "Create a SIMD vector with all elements set to the given value."]
1284 fn splat_i32x4(self, val: i32) -> i32x4<Self>;
1285 #[doc = "Reverse the order of the vector's elements."]
1286 fn reverse_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1287 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
1288 fn slide_i32x4<const SHIFT: usize>(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1289 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
1290 #[inline(always)]
1291 fn slide_within_blocks_i32x4<const SHIFT: usize>(
1292 self,
1293 a: i32x4<Self>,
1294 b: i32x4<Self>,
1295 ) -> i32x4<Self> {
1296 self.slide_i32x4::<SHIFT>(a, b)
1297 }
1298 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
1299 #[inline(always)]
1300 fn swizzle_dyn_within_blocks_i32x4(self, a: i32x4<Self>, indices: u8x16<Self>) -> i32x4<Self> {
1301 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
1302 }
1303 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1304 #[inline(always)]
1305 fn swizzle_dyn_i32x4(self, a: i32x4<Self>, indices: u8x16<Self>) -> i32x4<Self> {
1306 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
1307 }
1308 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
1309 #[inline(always)]
1310 fn swizzle_dyn_precise_i32x4(self, a: i32x4<Self>, indices: u8x16<Self>) -> i32x4<Self> {
1311 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
1312 }
1313 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1314 #[inline(always)]
1315 fn concat_swizzle_dyn_i32x4(
1316 self,
1317 a: i32x4<Self>,
1318 b: i32x4<Self>,
1319 indices: u8x16<Self>,
1320 ) -> i32x4<Self> {
1321 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
1322 Bytes::to_bytes(a),
1323 Bytes::to_bytes(b),
1324 indices,
1325 ))
1326 }
1327 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
1328 #[inline(always)]
1329 fn concat_swizzle_dyn_precise_i32x4(
1330 self,
1331 a: i32x4<Self>,
1332 b: i32x4<Self>,
1333 indices: u8x16<Self>,
1334 ) -> i32x4<Self> {
1335 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
1336 Bytes::to_bytes(a),
1337 Bytes::to_bytes(b),
1338 indices,
1339 ))
1340 }
1341 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
1342 fn compress_i32x4(self, values: i32x4<Self>, mask: mask32x4<Self>) -> i32x4<Self>;
1343 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
1344 fn compress_merge_i32x4(
1345 self,
1346 values: i32x4<Self>,
1347 mask: mask32x4<Self>,
1348 merge: i32x4<Self>,
1349 ) -> i32x4<Self>;
1350 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
1351 fn expand_i32x4(self, values: i32x4<Self>, mask: mask32x4<Self>) -> i32x4<Self>;
1352 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
1353 fn expand_merge_i32x4(
1354 self,
1355 values: i32x4<Self>,
1356 mask: mask32x4<Self>,
1357 merge: i32x4<Self>,
1358 ) -> i32x4<Self>;
1359 #[doc = "Return the number of ones in the binary representation of each element."]
1360 fn count_ones_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1361 #[doc = "Return the number of zeros in the binary representation of each element."]
1362 fn count_zeros_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1363 #[doc = "Add two vectors element-wise, wrapping on overflow."]
1364 fn add_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1365 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
1366 fn saturating_add_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1367 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
1368 fn sub_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1369 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
1370 fn saturating_sub_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1371 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
1372 fn mul_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1373 #[doc = "Compute the bitwise AND of two vectors."]
1374 fn and_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1375 #[doc = "Compute the bitwise OR of two vectors."]
1376 fn or_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1377 #[doc = "Compute the bitwise XOR of two vectors."]
1378 fn xor_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1379 #[doc = "Compute the bitwise NOT of the vector."]
1380 fn not_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1381 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1382 fn shl_i32x4(self, a: i32x4<Self>, shift: u32) -> i32x4<Self>;
1383 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1384 fn shlv_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1385 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1386 fn shr_i32x4(self, a: i32x4<Self>, shift: u32) -> i32x4<Self>;
1387 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1388 fn shrv_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1389 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1390 fn reduce_max_i32x4(self, a: i32x4<Self>) -> i32;
1391 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1392 fn reduce_min_i32x4(self, a: i32x4<Self>) -> i32;
1393 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
1394 fn reduce_sum_i32x4(self, a: i32x4<Self>) -> i32;
1395 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
1396 fn reduce_product_i32x4(self, a: i32x4<Self>) -> i32;
1397 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1398 fn max_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1399 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1400 fn min_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1401 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
1402 fn clamp_i32x4(self, a: i32x4<Self>, b: i32x4<Self>, c: i32x4<Self>) -> i32x4<Self>;
1403 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1404 fn simd_eq_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self>;
1405 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1406 #[inline(always)]
1407 fn simd_ne_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self> {
1408 self.not_mask32x4(self.simd_eq_i32x4(a, b))
1409 }
1410 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
1411 fn simd_lt_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self>;
1412 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
1413 fn simd_le_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self>;
1414 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
1415 #[inline(always)]
1416 fn simd_ge_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self> {
1417 self.simd_le_i32x4(b, a)
1418 }
1419 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
1420 #[inline(always)]
1421 fn simd_gt_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> mask32x4<Self> {
1422 self.simd_lt_i32x4(b, a)
1423 }
1424 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1425 fn zip_low_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1426 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1427 fn zip_high_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1428 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1429 fn unzip_low_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1430 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1431 fn unzip_high_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x4<Self>;
1432 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
1433 fn interleave_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> (i32x4<Self>, i32x4<Self>);
1434 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
1435 fn deinterleave_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> (i32x4<Self>, i32x4<Self>);
1436 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1437 fn select_i32x4(self, a: mask32x4<Self>, b: i32x4<Self>, c: i32x4<Self>) -> i32x4<Self>;
1438 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1439 fn combine_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i32x8<Self>;
1440 #[doc = "Negate each element of the vector, wrapping on overflow."]
1441 fn neg_i32x4(self, a: i32x4<Self>) -> i32x4<Self>;
1442 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
1443 #[doc(alias = "load_interleaved")]
1444 fn load_four_interleaved_i32x4(self, src: &[i32; 16usize]) -> [i32x4<Self>; 4usize];
1445 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
1446 #[doc(alias = "store_interleaved")]
1447 fn store_four_interleaved_i32x4(
1448 self,
1449 vectors: [i32x4<Self>; 4usize],
1450 dest: &mut [i32; 16usize],
1451 ) -> ();
1452 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
1453 fn widen_i32x4(self, a: i32x4<Self>) -> (i64x2<Self>, i64x2<Self>);
1454 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1455 fn widening_mul_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> (i64x2<Self>, i64x2<Self>);
1456 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1457 fn widening_add_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> (i64x2<Self>, i64x2<Self>);
1458 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
1459 fn pairwise_widening_add_i32x4(self, a: i32x4<Self>) -> i64x2<Self>;
1460 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
1461 fn pairwise_dot_product_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i64x2<Self>;
1462 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1463 fn narrow_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i16x8<Self>;
1464 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1465 fn saturating_narrow_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i16x8<Self>;
1466 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1467 fn relaxed_narrow_i32x4(self, a: i32x4<Self>, b: i32x4<Self>) -> i16x8<Self>;
1468 #[doc = "Convert each signed 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
1469 fn cvt_f32_i32x4(self, a: i32x4<Self>) -> f32x4<Self>;
1470 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
1471 #[inline(always)]
1472 fn abs_u32x4(self, a: u32x4<Self>) -> u32x4<Self> {
1473 a
1474 }
1475 #[doc = "Create a SIMD vector with all elements set to the given value."]
1476 fn splat_u32x4(self, val: u32) -> u32x4<Self>;
1477 #[doc = "Reverse the order of the vector's elements."]
1478 fn reverse_u32x4(self, a: u32x4<Self>) -> u32x4<Self>;
1479 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
1480 fn slide_u32x4<const SHIFT: usize>(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1481 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
1482 #[inline(always)]
1483 fn slide_within_blocks_u32x4<const SHIFT: usize>(
1484 self,
1485 a: u32x4<Self>,
1486 b: u32x4<Self>,
1487 ) -> u32x4<Self> {
1488 self.slide_u32x4::<SHIFT>(a, b)
1489 }
1490 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
1491 #[inline(always)]
1492 fn swizzle_dyn_within_blocks_u32x4(self, a: u32x4<Self>, indices: u8x16<Self>) -> u32x4<Self> {
1493 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
1494 }
1495 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1496 #[inline(always)]
1497 fn swizzle_dyn_u32x4(self, a: u32x4<Self>, indices: u8x16<Self>) -> u32x4<Self> {
1498 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
1499 }
1500 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
1501 #[inline(always)]
1502 fn swizzle_dyn_precise_u32x4(self, a: u32x4<Self>, indices: u8x16<Self>) -> u32x4<Self> {
1503 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
1504 }
1505 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1506 #[inline(always)]
1507 fn concat_swizzle_dyn_u32x4(
1508 self,
1509 a: u32x4<Self>,
1510 b: u32x4<Self>,
1511 indices: u8x16<Self>,
1512 ) -> u32x4<Self> {
1513 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
1514 Bytes::to_bytes(a),
1515 Bytes::to_bytes(b),
1516 indices,
1517 ))
1518 }
1519 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
1520 #[inline(always)]
1521 fn concat_swizzle_dyn_precise_u32x4(
1522 self,
1523 a: u32x4<Self>,
1524 b: u32x4<Self>,
1525 indices: u8x16<Self>,
1526 ) -> u32x4<Self> {
1527 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
1528 Bytes::to_bytes(a),
1529 Bytes::to_bytes(b),
1530 indices,
1531 ))
1532 }
1533 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
1534 fn compress_u32x4(self, values: u32x4<Self>, mask: mask32x4<Self>) -> u32x4<Self>;
1535 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
1536 fn compress_merge_u32x4(
1537 self,
1538 values: u32x4<Self>,
1539 mask: mask32x4<Self>,
1540 merge: u32x4<Self>,
1541 ) -> u32x4<Self>;
1542 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
1543 fn expand_u32x4(self, values: u32x4<Self>, mask: mask32x4<Self>) -> u32x4<Self>;
1544 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
1545 fn expand_merge_u32x4(
1546 self,
1547 values: u32x4<Self>,
1548 mask: mask32x4<Self>,
1549 merge: u32x4<Self>,
1550 ) -> u32x4<Self>;
1551 #[doc = "Return the number of ones in the binary representation of each element."]
1552 fn count_ones_u32x4(self, a: u32x4<Self>) -> u32x4<Self>;
1553 #[doc = "Return the number of zeros in the binary representation of each element."]
1554 fn count_zeros_u32x4(self, a: u32x4<Self>) -> u32x4<Self>;
1555 #[doc = "Add two vectors element-wise, wrapping on overflow."]
1556 fn add_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1557 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
1558 fn saturating_add_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1559 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
1560 fn sub_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1561 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
1562 fn saturating_sub_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1563 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
1564 fn mul_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1565 #[doc = "Compute the bitwise AND of two vectors."]
1566 fn and_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1567 #[doc = "Compute the bitwise OR of two vectors."]
1568 fn or_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1569 #[doc = "Compute the bitwise XOR of two vectors."]
1570 fn xor_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1571 #[doc = "Compute the bitwise NOT of the vector."]
1572 fn not_u32x4(self, a: u32x4<Self>) -> u32x4<Self>;
1573 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1574 fn shl_u32x4(self, a: u32x4<Self>, shift: u32) -> u32x4<Self>;
1575 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1576 fn shlv_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1577 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
1578 fn shr_u32x4(self, a: u32x4<Self>, shift: u32) -> u32x4<Self>;
1579 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
1580 fn shrv_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1581 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1582 fn reduce_max_u32x4(self, a: u32x4<Self>) -> u32;
1583 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1584 fn reduce_min_u32x4(self, a: u32x4<Self>) -> u32;
1585 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
1586 fn reduce_sum_u32x4(self, a: u32x4<Self>) -> u32;
1587 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
1588 fn reduce_product_u32x4(self, a: u32x4<Self>) -> u32;
1589 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1590 fn max_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1591 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1592 fn min_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1593 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
1594 fn clamp_u32x4(self, a: u32x4<Self>, b: u32x4<Self>, c: u32x4<Self>) -> u32x4<Self>;
1595 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1596 fn simd_eq_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self>;
1597 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1598 #[inline(always)]
1599 fn simd_ne_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self> {
1600 self.not_mask32x4(self.simd_eq_u32x4(a, b))
1601 }
1602 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
1603 fn simd_lt_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self>;
1604 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
1605 fn simd_le_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self>;
1606 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
1607 #[inline(always)]
1608 fn simd_ge_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self> {
1609 self.simd_le_u32x4(b, a)
1610 }
1611 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
1612 #[inline(always)]
1613 fn simd_gt_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> mask32x4<Self> {
1614 self.simd_lt_u32x4(b, a)
1615 }
1616 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1617 fn zip_low_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1618 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1619 fn zip_high_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1620 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1621 fn unzip_low_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1622 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1623 fn unzip_high_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x4<Self>;
1624 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
1625 fn interleave_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> (u32x4<Self>, u32x4<Self>);
1626 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
1627 fn deinterleave_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> (u32x4<Self>, u32x4<Self>);
1628 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1629 fn select_u32x4(self, a: mask32x4<Self>, b: u32x4<Self>, c: u32x4<Self>) -> u32x4<Self>;
1630 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1631 fn combine_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u32x8<Self>;
1632 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
1633 #[doc(alias = "load_interleaved")]
1634 fn load_four_interleaved_u32x4(self, src: &[u32; 16usize]) -> [u32x4<Self>; 4usize];
1635 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
1636 #[doc(alias = "store_interleaved")]
1637 fn store_four_interleaved_u32x4(
1638 self,
1639 vectors: [u32x4<Self>; 4usize],
1640 dest: &mut [u32; 16usize],
1641 ) -> ();
1642 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
1643 fn widen_u32x4(self, a: u32x4<Self>) -> (u64x2<Self>, u64x2<Self>);
1644 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1645 fn widening_mul_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> (u64x2<Self>, u64x2<Self>);
1646 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
1647 fn widening_add_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> (u64x2<Self>, u64x2<Self>);
1648 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
1649 fn pairwise_widening_add_u32x4(self, a: u32x4<Self>) -> u64x2<Self>;
1650 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
1651 fn pairwise_dot_product_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u64x2<Self>;
1652 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1653 fn narrow_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u16x8<Self>;
1654 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
1655 fn saturating_narrow_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u16x8<Self>;
1656 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1657 fn relaxed_narrow_u32x4(self, a: u32x4<Self>, b: u32x4<Self>) -> u16x8<Self>;
1658 #[doc = "Convert each unsigned 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
1659 fn cvt_f32_u32x4(self, a: u32x4<Self>) -> f32x4<Self>;
1660 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
1661 fn splat_mask32x4(self, val: bool) -> mask32x4<Self>;
1662 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
1663 fn from_bitmask_mask32x4(self, bits: u64) -> mask32x4<Self>;
1664 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
1665 fn to_bitmask_mask32x4(self, a: mask32x4<Self>) -> u64;
1666 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
1667 fn from_vector_mask32x4(self, vector: i32x4<Self>) -> mask32x4<Self>;
1668 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
1669 fn to_vector_mask32x4(self, a: mask32x4<Self>) -> i32x4<Self>;
1670 #[doc = "Set one logical lane of a SIMD mask."]
1671 fn set_mask32x4(self, a: &mut mask32x4<Self>, index: usize, value: bool) -> ();
1672 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
1673 fn rotate_elements_left_mask32x4<const OFFSET: usize>(
1674 self,
1675 a: mask32x4<Self>,
1676 ) -> mask32x4<Self>;
1677 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
1678 fn rotate_elements_right_mask32x4<const OFFSET: usize>(
1679 self,
1680 a: mask32x4<Self>,
1681 ) -> mask32x4<Self>;
1682 #[doc = "Compute the logical AND of two masks."]
1683 fn and_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x4<Self>;
1684 #[doc = "Compute the logical OR of two masks."]
1685 fn or_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x4<Self>;
1686 #[doc = "Compute the logical XOR of two masks."]
1687 fn xor_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x4<Self>;
1688 #[doc = "Compute the logical NOT of the mask."]
1689 fn not_mask32x4(self, a: mask32x4<Self>) -> mask32x4<Self>;
1690 #[doc = "Reverse the order of the mask's logical lanes."]
1691 fn reverse_mask32x4(self, a: mask32x4<Self>) -> mask32x4<Self>;
1692 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1693 fn select_mask32x4(
1694 self,
1695 a: mask32x4<Self>,
1696 b: mask32x4<Self>,
1697 c: mask32x4<Self>,
1698 ) -> mask32x4<Self>;
1699 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1700 fn simd_eq_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x4<Self>;
1701 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1702 #[inline(always)]
1703 fn simd_ne_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x4<Self> {
1704 self.not_mask32x4(self.simd_eq_mask32x4(a, b))
1705 }
1706 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1707 fn any_true_mask32x4(self, a: mask32x4<Self>) -> bool;
1708 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1709 fn all_true_mask32x4(self, a: mask32x4<Self>) -> bool;
1710 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1711 fn any_false_mask32x4(self, a: mask32x4<Self>) -> bool;
1712 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
1713 fn all_false_mask32x4(self, a: mask32x4<Self>) -> bool;
1714 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1715 fn combine_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask32x8<Self>;
1716 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
1717 fn widen_mask32x4(self, a: mask32x4<Self>) -> (mask64x2<Self>, mask64x2<Self>);
1718 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
1719 fn narrow_mask32x4(self, a: mask32x4<Self>, b: mask32x4<Self>) -> mask16x8<Self>;
1720 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
1721 fn abs_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1722 #[doc = "Create a SIMD vector with all elements set to the given value."]
1723 fn splat_f64x2(self, val: f64) -> f64x2<Self>;
1724 #[doc = "Reverse the order of the vector's elements."]
1725 fn reverse_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1726 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
1727 fn slide_f64x2<const SHIFT: usize>(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1728 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
1729 #[inline(always)]
1730 fn slide_within_blocks_f64x2<const SHIFT: usize>(
1731 self,
1732 a: f64x2<Self>,
1733 b: f64x2<Self>,
1734 ) -> f64x2<Self> {
1735 self.slide_f64x2::<SHIFT>(a, b)
1736 }
1737 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
1738 #[inline(always)]
1739 fn swizzle_dyn_within_blocks_f64x2(self, a: f64x2<Self>, indices: u8x16<Self>) -> f64x2<Self> {
1740 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
1741 }
1742 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1743 #[inline(always)]
1744 fn swizzle_dyn_f64x2(self, a: f64x2<Self>, indices: u8x16<Self>) -> f64x2<Self> {
1745 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
1746 }
1747 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
1748 #[inline(always)]
1749 fn swizzle_dyn_precise_f64x2(self, a: f64x2<Self>, indices: u8x16<Self>) -> f64x2<Self> {
1750 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
1751 }
1752 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1753 #[inline(always)]
1754 fn concat_swizzle_dyn_f64x2(
1755 self,
1756 a: f64x2<Self>,
1757 b: f64x2<Self>,
1758 indices: u8x16<Self>,
1759 ) -> f64x2<Self> {
1760 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
1761 Bytes::to_bytes(a),
1762 Bytes::to_bytes(b),
1763 indices,
1764 ))
1765 }
1766 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
1767 #[inline(always)]
1768 fn concat_swizzle_dyn_precise_f64x2(
1769 self,
1770 a: f64x2<Self>,
1771 b: f64x2<Self>,
1772 indices: u8x16<Self>,
1773 ) -> f64x2<Self> {
1774 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
1775 Bytes::to_bytes(a),
1776 Bytes::to_bytes(b),
1777 indices,
1778 ))
1779 }
1780 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
1781 fn compress_f64x2(self, values: f64x2<Self>, mask: mask64x2<Self>) -> f64x2<Self>;
1782 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
1783 fn compress_merge_f64x2(
1784 self,
1785 values: f64x2<Self>,
1786 mask: mask64x2<Self>,
1787 merge: f64x2<Self>,
1788 ) -> f64x2<Self>;
1789 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
1790 fn expand_f64x2(self, values: f64x2<Self>, mask: mask64x2<Self>) -> f64x2<Self>;
1791 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
1792 fn expand_merge_f64x2(
1793 self,
1794 values: f64x2<Self>,
1795 mask: mask64x2<Self>,
1796 merge: f64x2<Self>,
1797 ) -> f64x2<Self>;
1798 #[doc = "Negate each element of the vector."]
1799 fn neg_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1800 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
1801 fn sqrt_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1802 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
1803 fn approximate_recip_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1804 #[doc = "Add two vectors element-wise."]
1805 fn add_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1806 #[doc = "Subtract two vectors element-wise."]
1807 fn sub_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1808 #[doc = "Multiply two vectors element-wise."]
1809 fn mul_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1810 #[doc = "Divide two vectors element-wise."]
1811 fn div_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1812 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
1813 fn copysign_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1814 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1815 fn reduce_max_f64x2(self, a: f64x2<Self>) -> f64;
1816 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
1817 fn reduce_min_f64x2(self, a: f64x2<Self>) -> f64;
1818 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
1819 fn reduce_max_precise_f64x2(self, a: f64x2<Self>) -> f64;
1820 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
1821 fn reduce_min_precise_f64x2(self, a: f64x2<Self>) -> f64;
1822 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
1823 fn reduce_sum_f64x2(self, a: f64x2<Self>) -> f64;
1824 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
1825 fn reduce_product_f64x2(self, a: f64x2<Self>) -> f64;
1826 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1827 fn max_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1828 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
1829 fn min_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1830 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
1831 fn max_precise_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1832 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
1833 fn min_precise_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1834 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
1835 fn clamp_f64x2(self, a: f64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1836 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
1837 fn simd_eq_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self>;
1838 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
1839 #[inline(always)]
1840 fn simd_ne_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self> {
1841 self.not_mask64x2(self.simd_eq_f64x2(a, b))
1842 }
1843 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
1844 fn simd_lt_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self>;
1845 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
1846 fn simd_le_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self>;
1847 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
1848 #[inline(always)]
1849 fn simd_ge_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self> {
1850 self.simd_le_f64x2(b, a)
1851 }
1852 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
1853 #[inline(always)]
1854 fn simd_gt_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> mask64x2<Self> {
1855 self.simd_lt_f64x2(b, a)
1856 }
1857 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1858 fn zip_low_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1859 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
1860 fn zip_high_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1861 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1862 fn unzip_low_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1863 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
1864 fn unzip_high_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x2<Self>;
1865 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
1866 fn interleave_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> (f64x2<Self>, f64x2<Self>);
1867 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
1868 fn deinterleave_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> (f64x2<Self>, f64x2<Self>);
1869 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
1870 fn mul_add_f64x2(self, a: f64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1871 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
1872 fn mul_add_precise_f64x2(self, a: f64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1873 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
1874 fn mul_sub_f64x2(self, a: f64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1875 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
1876 fn mul_sub_precise_f64x2(self, a: f64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1877 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
1878 fn floor_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1879 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
1880 fn ceil_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1881 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
1882 fn round_ties_even_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1883 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
1884 fn round_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1885 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
1886 fn fract_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1887 #[doc = "Return the integer part of each element, rounding towards zero."]
1888 fn trunc_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1889 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
1890 fn to_degrees_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1891 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
1892 fn to_radians_f64x2(self, a: f64x2<Self>) -> f64x2<Self>;
1893 #[doc = "Return a mask indicating which elements are NaN."]
1894 fn is_nan_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1895 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
1896 fn is_infinite_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1897 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
1898 fn is_finite_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1899 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
1900 fn is_subnormal_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1901 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
1902 fn is_normal_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1903 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
1904 fn is_sign_positive_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1905 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
1906 fn is_sign_negative_f64x2(self, a: f64x2<Self>) -> mask64x2<Self>;
1907 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
1908 fn select_f64x2(self, a: mask64x2<Self>, b: f64x2<Self>, c: f64x2<Self>) -> f64x2<Self>;
1909 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
1910 fn combine_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f64x4<Self>;
1911 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
1912 #[doc(alias = "load_interleaved")]
1913 fn load_four_interleaved_f64x2(self, src: &[f64; 8usize]) -> [f64x2<Self>; 4usize];
1914 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
1915 #[doc(alias = "store_interleaved")]
1916 fn store_four_interleaved_f64x2(
1917 self,
1918 vectors: [f64x2<Self>; 4usize],
1919 dest: &mut [f64; 8usize],
1920 ) -> ();
1921 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nValues are rounded to the nearest representable `f32`, with ties resolved to even; overflow produces signed infinity.This is the same as the `as` operator, and follows the IEEE 754 narrowing behavior in round-to-even mode.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1922 fn narrow_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f32x4<Self>;
1923 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1924 fn saturating_narrow_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f32x4<Self>;
1925 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
1926 fn relaxed_narrow_f64x2(self, a: f64x2<Self>, b: f64x2<Self>) -> f32x4<Self>;
1927 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
1928 fn cvt_u64_f64x2(self, a: f64x2<Self>) -> u64x2<Self>;
1929 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
1930 fn cvt_u64_precise_f64x2(self, a: f64x2<Self>) -> u64x2<Self>;
1931 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
1932 fn cvt_i64_f64x2(self, a: f64x2<Self>) -> i64x2<Self>;
1933 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
1934 fn cvt_i64_precise_f64x2(self, a: f64x2<Self>) -> i64x2<Self>;
1935 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
1936 fn abs_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
1937 #[doc = "Create a SIMD vector with all elements set to the given value."]
1938 fn splat_i64x2(self, val: i64) -> i64x2<Self>;
1939 #[doc = "Reverse the order of the vector's elements."]
1940 fn reverse_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
1941 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
1942 fn slide_i64x2<const SHIFT: usize>(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
1943 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
1944 #[inline(always)]
1945 fn slide_within_blocks_i64x2<const SHIFT: usize>(
1946 self,
1947 a: i64x2<Self>,
1948 b: i64x2<Self>,
1949 ) -> i64x2<Self> {
1950 self.slide_i64x2::<SHIFT>(a, b)
1951 }
1952 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
1953 #[inline(always)]
1954 fn swizzle_dyn_within_blocks_i64x2(self, a: i64x2<Self>, indices: u8x16<Self>) -> i64x2<Self> {
1955 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
1956 }
1957 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1958 #[inline(always)]
1959 fn swizzle_dyn_i64x2(self, a: i64x2<Self>, indices: u8x16<Self>) -> i64x2<Self> {
1960 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
1961 }
1962 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
1963 #[inline(always)]
1964 fn swizzle_dyn_precise_i64x2(self, a: i64x2<Self>, indices: u8x16<Self>) -> i64x2<Self> {
1965 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
1966 }
1967 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
1968 #[inline(always)]
1969 fn concat_swizzle_dyn_i64x2(
1970 self,
1971 a: i64x2<Self>,
1972 b: i64x2<Self>,
1973 indices: u8x16<Self>,
1974 ) -> i64x2<Self> {
1975 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
1976 Bytes::to_bytes(a),
1977 Bytes::to_bytes(b),
1978 indices,
1979 ))
1980 }
1981 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
1982 #[inline(always)]
1983 fn concat_swizzle_dyn_precise_i64x2(
1984 self,
1985 a: i64x2<Self>,
1986 b: i64x2<Self>,
1987 indices: u8x16<Self>,
1988 ) -> i64x2<Self> {
1989 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
1990 Bytes::to_bytes(a),
1991 Bytes::to_bytes(b),
1992 indices,
1993 ))
1994 }
1995 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
1996 fn compress_i64x2(self, values: i64x2<Self>, mask: mask64x2<Self>) -> i64x2<Self>;
1997 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
1998 fn compress_merge_i64x2(
1999 self,
2000 values: i64x2<Self>,
2001 mask: mask64x2<Self>,
2002 merge: i64x2<Self>,
2003 ) -> i64x2<Self>;
2004 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
2005 fn expand_i64x2(self, values: i64x2<Self>, mask: mask64x2<Self>) -> i64x2<Self>;
2006 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
2007 fn expand_merge_i64x2(
2008 self,
2009 values: i64x2<Self>,
2010 mask: mask64x2<Self>,
2011 merge: i64x2<Self>,
2012 ) -> i64x2<Self>;
2013 #[doc = "Return the number of ones in the binary representation of each element."]
2014 fn count_ones_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
2015 #[doc = "Return the number of zeros in the binary representation of each element."]
2016 fn count_zeros_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
2017 #[doc = "Add two vectors element-wise, wrapping on overflow."]
2018 fn add_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2019 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
2020 fn saturating_add_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2021 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
2022 fn sub_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2023 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
2024 fn saturating_sub_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2025 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
2026 fn mul_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2027 #[doc = "Compute the bitwise AND of two vectors."]
2028 fn and_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2029 #[doc = "Compute the bitwise OR of two vectors."]
2030 fn or_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2031 #[doc = "Compute the bitwise XOR of two vectors."]
2032 fn xor_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2033 #[doc = "Compute the bitwise NOT of the vector."]
2034 fn not_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
2035 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
2036 fn shl_i64x2(self, a: i64x2<Self>, shift: u32) -> i64x2<Self>;
2037 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
2038 fn shlv_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2039 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
2040 fn shr_i64x2(self, a: i64x2<Self>, shift: u32) -> i64x2<Self>;
2041 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
2042 fn shrv_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2043 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2044 fn reduce_max_i64x2(self, a: i64x2<Self>) -> i64;
2045 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2046 fn reduce_min_i64x2(self, a: i64x2<Self>) -> i64;
2047 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
2048 fn reduce_sum_i64x2(self, a: i64x2<Self>) -> i64;
2049 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
2050 fn reduce_product_i64x2(self, a: i64x2<Self>) -> i64;
2051 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2052 fn max_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2053 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2054 fn min_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2055 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
2056 fn clamp_i64x2(self, a: i64x2<Self>, b: i64x2<Self>, c: i64x2<Self>) -> i64x2<Self>;
2057 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
2058 fn simd_eq_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self>;
2059 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
2060 #[inline(always)]
2061 fn simd_ne_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self> {
2062 self.not_mask64x2(self.simd_eq_i64x2(a, b))
2063 }
2064 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
2065 fn simd_lt_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self>;
2066 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
2067 fn simd_le_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self>;
2068 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
2069 #[inline(always)]
2070 fn simd_ge_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self> {
2071 self.simd_le_i64x2(b, a)
2072 }
2073 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
2074 #[inline(always)]
2075 fn simd_gt_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> mask64x2<Self> {
2076 self.simd_lt_i64x2(b, a)
2077 }
2078 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2079 fn zip_low_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2080 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2081 fn zip_high_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2082 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2083 fn unzip_low_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2084 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2085 fn unzip_high_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x2<Self>;
2086 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
2087 fn interleave_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> (i64x2<Self>, i64x2<Self>);
2088 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
2089 fn deinterleave_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> (i64x2<Self>, i64x2<Self>);
2090 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
2091 fn select_i64x2(self, a: mask64x2<Self>, b: i64x2<Self>, c: i64x2<Self>) -> i64x2<Self>;
2092 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
2093 fn combine_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i64x4<Self>;
2094 #[doc = "Negate each element of the vector, wrapping on overflow."]
2095 fn neg_i64x2(self, a: i64x2<Self>) -> i64x2<Self>;
2096 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
2097 #[doc(alias = "load_interleaved")]
2098 fn load_four_interleaved_i64x2(self, src: &[i64; 8usize]) -> [i64x2<Self>; 4usize];
2099 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
2100 #[doc(alias = "store_interleaved")]
2101 fn store_four_interleaved_i64x2(
2102 self,
2103 vectors: [i64x2<Self>; 4usize],
2104 dest: &mut [i64; 8usize],
2105 ) -> ();
2106 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
2107 fn narrow_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i32x4<Self>;
2108 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
2109 fn saturating_narrow_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i32x4<Self>;
2110 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
2111 fn relaxed_narrow_i64x2(self, a: i64x2<Self>, b: i64x2<Self>) -> i32x4<Self>;
2112 #[doc = "Convert each signed 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
2113 fn cvt_f64_i64x2(self, a: i64x2<Self>) -> f64x2<Self>;
2114 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
2115 #[inline(always)]
2116 fn abs_u64x2(self, a: u64x2<Self>) -> u64x2<Self> {
2117 a
2118 }
2119 #[doc = "Create a SIMD vector with all elements set to the given value."]
2120 fn splat_u64x2(self, val: u64) -> u64x2<Self>;
2121 #[doc = "Reverse the order of the vector's elements."]
2122 fn reverse_u64x2(self, a: u64x2<Self>) -> u64x2<Self>;
2123 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
2124 fn slide_u64x2<const SHIFT: usize>(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2125 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
2126 #[inline(always)]
2127 fn slide_within_blocks_u64x2<const SHIFT: usize>(
2128 self,
2129 a: u64x2<Self>,
2130 b: u64x2<Self>,
2131 ) -> u64x2<Self> {
2132 self.slide_u64x2::<SHIFT>(a, b)
2133 }
2134 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
2135 #[inline(always)]
2136 fn swizzle_dyn_within_blocks_u64x2(self, a: u64x2<Self>, indices: u8x16<Self>) -> u64x2<Self> {
2137 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x16(Bytes::to_bytes(a), indices))
2138 }
2139 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2140 #[inline(always)]
2141 fn swizzle_dyn_u64x2(self, a: u64x2<Self>, indices: u8x16<Self>) -> u64x2<Self> {
2142 Bytes::from_bytes(self.swizzle_dyn_u8x16(Bytes::to_bytes(a), indices))
2143 }
2144 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
2145 #[inline(always)]
2146 fn swizzle_dyn_precise_u64x2(self, a: u64x2<Self>, indices: u8x16<Self>) -> u64x2<Self> {
2147 Bytes::from_bytes(self.swizzle_dyn_precise_u8x16(Bytes::to_bytes(a), indices))
2148 }
2149 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2150 #[inline(always)]
2151 fn concat_swizzle_dyn_u64x2(
2152 self,
2153 a: u64x2<Self>,
2154 b: u64x2<Self>,
2155 indices: u8x16<Self>,
2156 ) -> u64x2<Self> {
2157 Bytes::from_bytes(self.concat_swizzle_dyn_u8x16(
2158 Bytes::to_bytes(a),
2159 Bytes::to_bytes(b),
2160 indices,
2161 ))
2162 }
2163 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
2164 #[inline(always)]
2165 fn concat_swizzle_dyn_precise_u64x2(
2166 self,
2167 a: u64x2<Self>,
2168 b: u64x2<Self>,
2169 indices: u8x16<Self>,
2170 ) -> u64x2<Self> {
2171 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x16(
2172 Bytes::to_bytes(a),
2173 Bytes::to_bytes(b),
2174 indices,
2175 ))
2176 }
2177 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
2178 fn compress_u64x2(self, values: u64x2<Self>, mask: mask64x2<Self>) -> u64x2<Self>;
2179 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
2180 fn compress_merge_u64x2(
2181 self,
2182 values: u64x2<Self>,
2183 mask: mask64x2<Self>,
2184 merge: u64x2<Self>,
2185 ) -> u64x2<Self>;
2186 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
2187 fn expand_u64x2(self, values: u64x2<Self>, mask: mask64x2<Self>) -> u64x2<Self>;
2188 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
2189 fn expand_merge_u64x2(
2190 self,
2191 values: u64x2<Self>,
2192 mask: mask64x2<Self>,
2193 merge: u64x2<Self>,
2194 ) -> u64x2<Self>;
2195 #[doc = "Return the number of ones in the binary representation of each element."]
2196 fn count_ones_u64x2(self, a: u64x2<Self>) -> u64x2<Self>;
2197 #[doc = "Return the number of zeros in the binary representation of each element."]
2198 fn count_zeros_u64x2(self, a: u64x2<Self>) -> u64x2<Self>;
2199 #[doc = "Add two vectors element-wise, wrapping on overflow."]
2200 fn add_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2201 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
2202 fn saturating_add_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2203 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
2204 fn sub_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2205 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
2206 fn saturating_sub_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2207 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
2208 fn mul_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2209 #[doc = "Compute the bitwise AND of two vectors."]
2210 fn and_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2211 #[doc = "Compute the bitwise OR of two vectors."]
2212 fn or_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2213 #[doc = "Compute the bitwise XOR of two vectors."]
2214 fn xor_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2215 #[doc = "Compute the bitwise NOT of the vector."]
2216 fn not_u64x2(self, a: u64x2<Self>) -> u64x2<Self>;
2217 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
2218 fn shl_u64x2(self, a: u64x2<Self>, shift: u32) -> u64x2<Self>;
2219 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
2220 fn shlv_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2221 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
2222 fn shr_u64x2(self, a: u64x2<Self>, shift: u32) -> u64x2<Self>;
2223 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
2224 fn shrv_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2225 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2226 fn reduce_max_u64x2(self, a: u64x2<Self>) -> u64;
2227 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2228 fn reduce_min_u64x2(self, a: u64x2<Self>) -> u64;
2229 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
2230 fn reduce_sum_u64x2(self, a: u64x2<Self>) -> u64;
2231 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
2232 fn reduce_product_u64x2(self, a: u64x2<Self>) -> u64;
2233 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2234 fn max_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2235 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2236 fn min_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2237 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
2238 fn clamp_u64x2(self, a: u64x2<Self>, b: u64x2<Self>, c: u64x2<Self>) -> u64x2<Self>;
2239 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
2240 fn simd_eq_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self>;
2241 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
2242 #[inline(always)]
2243 fn simd_ne_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self> {
2244 self.not_mask64x2(self.simd_eq_u64x2(a, b))
2245 }
2246 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
2247 fn simd_lt_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self>;
2248 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
2249 fn simd_le_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self>;
2250 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
2251 #[inline(always)]
2252 fn simd_ge_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self> {
2253 self.simd_le_u64x2(b, a)
2254 }
2255 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
2256 #[inline(always)]
2257 fn simd_gt_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> mask64x2<Self> {
2258 self.simd_lt_u64x2(b, a)
2259 }
2260 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2261 fn zip_low_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2262 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2263 fn zip_high_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2264 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2265 fn unzip_low_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2266 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2267 fn unzip_high_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x2<Self>;
2268 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
2269 fn interleave_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> (u64x2<Self>, u64x2<Self>);
2270 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
2271 fn deinterleave_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> (u64x2<Self>, u64x2<Self>);
2272 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
2273 fn select_u64x2(self, a: mask64x2<Self>, b: u64x2<Self>, c: u64x2<Self>) -> u64x2<Self>;
2274 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
2275 fn combine_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u64x4<Self>;
2276 #[doc = "Load four 128-bit vectors from an array with 4-way interleaving.\n\nThis is useful e.g. in image processing to turn interleaved RGBA pixels into vectors of each color component.\n\nFor example, with 32-bit lanes, memory laid out as`[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]` loads as`[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]`."]
2277 #[doc(alias = "load_interleaved")]
2278 fn load_four_interleaved_u64x2(self, src: &[u64; 8usize]) -> [u64x2<Self>; 4usize];
2279 #[doc = "Store four 128-bit vectors to an array with 4-way interleaving.\n\nThis is the inverse of `load_four_interleaved`.\n\nThis is useful e.g. in image processing to turn vectors of each color component into interleaved RGBA pixels.\n\nFor example, with 32-bit lanes, vectors containing `[[r0, r1, r2, r3], [g0, g1, g2, g3], [b0, b1, b2, b3], [a0, a1, a2, a3]]` get stored as `[r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3]`."]
2280 #[doc(alias = "store_interleaved")]
2281 fn store_four_interleaved_u64x2(
2282 self,
2283 vectors: [u64x2<Self>; 4usize],
2284 dest: &mut [u64; 8usize],
2285 ) -> ();
2286 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
2287 fn narrow_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u32x4<Self>;
2288 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
2289 fn saturating_narrow_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u32x4<Self>;
2290 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
2291 fn relaxed_narrow_u64x2(self, a: u64x2<Self>, b: u64x2<Self>) -> u32x4<Self>;
2292 #[doc = "Convert each unsigned 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
2293 fn cvt_f64_u64x2(self, a: u64x2<Self>) -> f64x2<Self>;
2294 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
2295 fn splat_mask64x2(self, val: bool) -> mask64x2<Self>;
2296 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
2297 fn from_bitmask_mask64x2(self, bits: u64) -> mask64x2<Self>;
2298 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
2299 fn to_bitmask_mask64x2(self, a: mask64x2<Self>) -> u64;
2300 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
2301 fn from_vector_mask64x2(self, vector: i64x2<Self>) -> mask64x2<Self>;
2302 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
2303 fn to_vector_mask64x2(self, a: mask64x2<Self>) -> i64x2<Self>;
2304 #[doc = "Set one logical lane of a SIMD mask."]
2305 fn set_mask64x2(self, a: &mut mask64x2<Self>, index: usize, value: bool) -> ();
2306 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
2307 fn rotate_elements_left_mask64x2<const OFFSET: usize>(
2308 self,
2309 a: mask64x2<Self>,
2310 ) -> mask64x2<Self>;
2311 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
2312 fn rotate_elements_right_mask64x2<const OFFSET: usize>(
2313 self,
2314 a: mask64x2<Self>,
2315 ) -> mask64x2<Self>;
2316 #[doc = "Compute the logical AND of two masks."]
2317 fn and_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x2<Self>;
2318 #[doc = "Compute the logical OR of two masks."]
2319 fn or_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x2<Self>;
2320 #[doc = "Compute the logical XOR of two masks."]
2321 fn xor_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x2<Self>;
2322 #[doc = "Compute the logical NOT of the mask."]
2323 fn not_mask64x2(self, a: mask64x2<Self>) -> mask64x2<Self>;
2324 #[doc = "Reverse the order of the mask's logical lanes."]
2325 fn reverse_mask64x2(self, a: mask64x2<Self>) -> mask64x2<Self>;
2326 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
2327 fn select_mask64x2(
2328 self,
2329 a: mask64x2<Self>,
2330 b: mask64x2<Self>,
2331 c: mask64x2<Self>,
2332 ) -> mask64x2<Self>;
2333 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
2334 fn simd_eq_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x2<Self>;
2335 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
2336 #[inline(always)]
2337 fn simd_ne_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x2<Self> {
2338 self.not_mask64x2(self.simd_eq_mask64x2(a, b))
2339 }
2340 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
2341 fn any_true_mask64x2(self, a: mask64x2<Self>) -> bool;
2342 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
2343 fn all_true_mask64x2(self, a: mask64x2<Self>) -> bool;
2344 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
2345 fn any_false_mask64x2(self, a: mask64x2<Self>) -> bool;
2346 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
2347 fn all_false_mask64x2(self, a: mask64x2<Self>) -> bool;
2348 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
2349 fn combine_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask64x4<Self>;
2350 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
2351 fn narrow_mask64x2(self, a: mask64x2<Self>, b: mask64x2<Self>) -> mask32x4<Self>;
2352 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
2353 #[inline(always)]
2354 fn abs_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2355 let (a0, a1) = self.split_f32x8(a);
2356 self.combine_f32x4(self.abs_f32x4(a0), self.abs_f32x4(a1))
2357 }
2358 #[doc = "Create a SIMD vector with all elements set to the given value."]
2359 #[inline(always)]
2360 fn splat_f32x8(self, val: f32) -> f32x8<Self> {
2361 let half = self.splat_f32x4(val);
2362 self.combine_f32x4(half, half)
2363 }
2364 #[doc = "Reverse the order of the vector's elements."]
2365 #[inline(always)]
2366 fn reverse_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2367 let (a0, a1) = self.split_f32x8(a);
2368 self.combine_f32x4(self.reverse_f32x4(a1), self.reverse_f32x4(a0))
2369 }
2370 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
2371 fn slide_f32x8<const SHIFT: usize>(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self>;
2372 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
2373 #[inline(always)]
2374 fn slide_within_blocks_f32x8<const SHIFT: usize>(
2375 self,
2376 a: f32x8<Self>,
2377 b: f32x8<Self>,
2378 ) -> f32x8<Self> {
2379 let (a0, a1) = self.split_f32x8(a);
2380 let (b0, b1) = self.split_f32x8(b);
2381 self.combine_f32x4(
2382 self.slide_within_blocks_f32x4::<SHIFT>(a0, b0),
2383 self.slide_within_blocks_f32x4::<SHIFT>(a1, b1),
2384 )
2385 }
2386 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
2387 #[inline(always)]
2388 fn swizzle_dyn_within_blocks_f32x8(self, a: f32x8<Self>, indices: u8x32<Self>) -> f32x8<Self> {
2389 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
2390 }
2391 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2392 #[inline(always)]
2393 fn swizzle_dyn_f32x8(self, a: f32x8<Self>, indices: u8x32<Self>) -> f32x8<Self> {
2394 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
2395 }
2396 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
2397 #[inline(always)]
2398 fn swizzle_dyn_precise_f32x8(self, a: f32x8<Self>, indices: u8x32<Self>) -> f32x8<Self> {
2399 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
2400 }
2401 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2402 #[inline(always)]
2403 fn concat_swizzle_dyn_f32x8(
2404 self,
2405 a: f32x8<Self>,
2406 b: f32x8<Self>,
2407 indices: u8x32<Self>,
2408 ) -> f32x8<Self> {
2409 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
2410 Bytes::to_bytes(a),
2411 Bytes::to_bytes(b),
2412 indices,
2413 ))
2414 }
2415 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
2416 #[inline(always)]
2417 fn concat_swizzle_dyn_precise_f32x8(
2418 self,
2419 a: f32x8<Self>,
2420 b: f32x8<Self>,
2421 indices: u8x32<Self>,
2422 ) -> f32x8<Self> {
2423 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
2424 Bytes::to_bytes(a),
2425 Bytes::to_bytes(b),
2426 indices,
2427 ))
2428 }
2429 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
2430 fn compress_f32x8(self, values: f32x8<Self>, mask: mask32x8<Self>) -> f32x8<Self>;
2431 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
2432 fn compress_merge_f32x8(
2433 self,
2434 values: f32x8<Self>,
2435 mask: mask32x8<Self>,
2436 merge: f32x8<Self>,
2437 ) -> f32x8<Self>;
2438 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
2439 fn expand_f32x8(self, values: f32x8<Self>, mask: mask32x8<Self>) -> f32x8<Self>;
2440 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
2441 fn expand_merge_f32x8(
2442 self,
2443 values: f32x8<Self>,
2444 mask: mask32x8<Self>,
2445 merge: f32x8<Self>,
2446 ) -> f32x8<Self>;
2447 #[doc = "Negate each element of the vector."]
2448 #[inline(always)]
2449 fn neg_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2450 let (a0, a1) = self.split_f32x8(a);
2451 self.combine_f32x4(self.neg_f32x4(a0), self.neg_f32x4(a1))
2452 }
2453 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
2454 #[inline(always)]
2455 fn sqrt_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2456 let (a0, a1) = self.split_f32x8(a);
2457 self.combine_f32x4(self.sqrt_f32x4(a0), self.sqrt_f32x4(a1))
2458 }
2459 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
2460 #[inline(always)]
2461 fn approximate_recip_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2462 let (a0, a1) = self.split_f32x8(a);
2463 self.combine_f32x4(
2464 self.approximate_recip_f32x4(a0),
2465 self.approximate_recip_f32x4(a1),
2466 )
2467 }
2468 #[doc = "Add two vectors element-wise."]
2469 #[inline(always)]
2470 fn add_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2471 let (a0, a1) = self.split_f32x8(a);
2472 let (b0, b1) = self.split_f32x8(b);
2473 self.combine_f32x4(self.add_f32x4(a0, b0), self.add_f32x4(a1, b1))
2474 }
2475 #[doc = "Subtract two vectors element-wise."]
2476 #[inline(always)]
2477 fn sub_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2478 let (a0, a1) = self.split_f32x8(a);
2479 let (b0, b1) = self.split_f32x8(b);
2480 self.combine_f32x4(self.sub_f32x4(a0, b0), self.sub_f32x4(a1, b1))
2481 }
2482 #[doc = "Multiply two vectors element-wise."]
2483 #[inline(always)]
2484 fn mul_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2485 let (a0, a1) = self.split_f32x8(a);
2486 let (b0, b1) = self.split_f32x8(b);
2487 self.combine_f32x4(self.mul_f32x4(a0, b0), self.mul_f32x4(a1, b1))
2488 }
2489 #[doc = "Divide two vectors element-wise."]
2490 #[inline(always)]
2491 fn div_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2492 let (a0, a1) = self.split_f32x8(a);
2493 let (b0, b1) = self.split_f32x8(b);
2494 self.combine_f32x4(self.div_f32x4(a0, b0), self.div_f32x4(a1, b1))
2495 }
2496 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
2497 #[inline(always)]
2498 fn copysign_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2499 let (a0, a1) = self.split_f32x8(a);
2500 let (b0, b1) = self.split_f32x8(b);
2501 self.combine_f32x4(self.copysign_f32x4(a0, b0), self.copysign_f32x4(a1, b1))
2502 }
2503 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2504 #[inline(always)]
2505 fn reduce_max_f32x8(self, a: f32x8<Self>) -> f32 {
2506 let (a0, a1) = self.split_f32x8(a);
2507 self.reduce_max_f32x4(self.max_f32x4(a0, a1))
2508 }
2509 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
2510 #[inline(always)]
2511 fn reduce_min_f32x8(self, a: f32x8<Self>) -> f32 {
2512 let (a0, a1) = self.split_f32x8(a);
2513 self.reduce_min_f32x4(self.min_f32x4(a0, a1))
2514 }
2515 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
2516 #[inline(always)]
2517 fn reduce_max_precise_f32x8(self, a: f32x8<Self>) -> f32 {
2518 let (a0, a1) = self.split_f32x8(a);
2519 self.reduce_max_precise_f32x4(self.max_precise_f32x4(a0, a1))
2520 }
2521 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
2522 #[inline(always)]
2523 fn reduce_min_precise_f32x8(self, a: f32x8<Self>) -> f32 {
2524 let (a0, a1) = self.split_f32x8(a);
2525 self.reduce_min_precise_f32x4(self.min_precise_f32x4(a0, a1))
2526 }
2527 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
2528 #[inline(always)]
2529 fn reduce_sum_f32x8(self, a: f32x8<Self>) -> f32 {
2530 let (a0, a1) = self.split_f32x8(a);
2531 self.reduce_sum_f32x4(self.add_f32x4(a0, a1))
2532 }
2533 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
2534 #[inline(always)]
2535 fn reduce_product_f32x8(self, a: f32x8<Self>) -> f32 {
2536 let (a0, a1) = self.split_f32x8(a);
2537 self.reduce_product_f32x4(self.mul_f32x4(a0, a1))
2538 }
2539 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2540 #[inline(always)]
2541 fn max_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2542 let (a0, a1) = self.split_f32x8(a);
2543 let (b0, b1) = self.split_f32x8(b);
2544 self.combine_f32x4(self.max_f32x4(a0, b0), self.max_f32x4(a1, b1))
2545 }
2546 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
2547 #[inline(always)]
2548 fn min_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2549 let (a0, a1) = self.split_f32x8(a);
2550 let (b0, b1) = self.split_f32x8(b);
2551 self.combine_f32x4(self.min_f32x4(a0, b0), self.min_f32x4(a1, b1))
2552 }
2553 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
2554 #[inline(always)]
2555 fn max_precise_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2556 let (a0, a1) = self.split_f32x8(a);
2557 let (b0, b1) = self.split_f32x8(b);
2558 self.combine_f32x4(
2559 self.max_precise_f32x4(a0, b0),
2560 self.max_precise_f32x4(a1, b1),
2561 )
2562 }
2563 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
2564 #[inline(always)]
2565 fn min_precise_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2566 let (a0, a1) = self.split_f32x8(a);
2567 let (b0, b1) = self.split_f32x8(b);
2568 self.combine_f32x4(
2569 self.min_precise_f32x4(a0, b0),
2570 self.min_precise_f32x4(a1, b1),
2571 )
2572 }
2573 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
2574 #[inline(always)]
2575 fn clamp_f32x8(self, a: f32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2576 let (a0, a1) = self.split_f32x8(a);
2577 let (b0, b1) = self.split_f32x8(b);
2578 let (c0, c1) = self.split_f32x8(c);
2579 self.combine_f32x4(self.clamp_f32x4(a0, b0, c0), self.clamp_f32x4(a1, b1, c1))
2580 }
2581 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
2582 #[inline(always)]
2583 fn simd_eq_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2584 let (a0, a1) = self.split_f32x8(a);
2585 let (b0, b1) = self.split_f32x8(b);
2586 self.combine_mask32x4(self.simd_eq_f32x4(a0, b0), self.simd_eq_f32x4(a1, b1))
2587 }
2588 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
2589 #[inline(always)]
2590 fn simd_ne_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2591 self.not_mask32x8(self.simd_eq_f32x8(a, b))
2592 }
2593 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
2594 #[inline(always)]
2595 fn simd_lt_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2596 let (a0, a1) = self.split_f32x8(a);
2597 let (b0, b1) = self.split_f32x8(b);
2598 self.combine_mask32x4(self.simd_lt_f32x4(a0, b0), self.simd_lt_f32x4(a1, b1))
2599 }
2600 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
2601 #[inline(always)]
2602 fn simd_le_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2603 let (a0, a1) = self.split_f32x8(a);
2604 let (b0, b1) = self.split_f32x8(b);
2605 self.combine_mask32x4(self.simd_le_f32x4(a0, b0), self.simd_le_f32x4(a1, b1))
2606 }
2607 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
2608 #[inline(always)]
2609 fn simd_ge_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2610 self.simd_le_f32x8(b, a)
2611 }
2612 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
2613 #[inline(always)]
2614 fn simd_gt_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> mask32x8<Self> {
2615 self.simd_lt_f32x8(b, a)
2616 }
2617 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2618 #[inline(always)]
2619 fn zip_low_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2620 let (a0, _) = self.split_f32x8(a);
2621 let (b0, _) = self.split_f32x8(b);
2622 self.combine_f32x4(self.zip_low_f32x4(a0, b0), self.zip_high_f32x4(a0, b0))
2623 }
2624 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
2625 #[inline(always)]
2626 fn zip_high_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2627 let (_, a1) = self.split_f32x8(a);
2628 let (_, b1) = self.split_f32x8(b);
2629 self.combine_f32x4(self.zip_low_f32x4(a1, b1), self.zip_high_f32x4(a1, b1))
2630 }
2631 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2632 #[inline(always)]
2633 fn unzip_low_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2634 let (a0, a1) = self.split_f32x8(a);
2635 let (b0, b1) = self.split_f32x8(b);
2636 self.combine_f32x4(self.unzip_low_f32x4(a0, a1), self.unzip_low_f32x4(b0, b1))
2637 }
2638 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
2639 #[inline(always)]
2640 fn unzip_high_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x8<Self> {
2641 let (a0, a1) = self.split_f32x8(a);
2642 let (b0, b1) = self.split_f32x8(b);
2643 self.combine_f32x4(self.unzip_high_f32x4(a0, a1), self.unzip_high_f32x4(b0, b1))
2644 }
2645 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
2646 #[inline(always)]
2647 fn interleave_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> (f32x8<Self>, f32x8<Self>) {
2648 let (a0, a1) = self.split_f32x8(a);
2649 let (b0, b1) = self.split_f32x8(b);
2650 let lo_lo = self.zip_low_f32x4(a0, b0);
2651 let lo_hi = self.zip_high_f32x4(a0, b0);
2652 let hi_lo = self.zip_low_f32x4(a1, b1);
2653 let hi_hi = self.zip_high_f32x4(a1, b1);
2654 (
2655 self.combine_f32x4(lo_lo, lo_hi),
2656 self.combine_f32x4(hi_lo, hi_hi),
2657 )
2658 }
2659 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
2660 #[inline(always)]
2661 fn deinterleave_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> (f32x8<Self>, f32x8<Self>) {
2662 let (a0, a1) = self.split_f32x8(a);
2663 let (b0, b1) = self.split_f32x8(b);
2664 let lo_even = self.unzip_low_f32x4(a0, a1);
2665 let lo_odd = self.unzip_high_f32x4(a0, a1);
2666 let hi_even = self.unzip_low_f32x4(b0, b1);
2667 let hi_odd = self.unzip_high_f32x4(b0, b1);
2668 (
2669 self.combine_f32x4(lo_even, hi_even),
2670 self.combine_f32x4(lo_odd, hi_odd),
2671 )
2672 }
2673 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
2674 #[inline(always)]
2675 fn mul_add_f32x8(self, a: f32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2676 let (a0, a1) = self.split_f32x8(a);
2677 let (b0, b1) = self.split_f32x8(b);
2678 let (c0, c1) = self.split_f32x8(c);
2679 self.combine_f32x4(
2680 self.mul_add_f32x4(a0, b0, c0),
2681 self.mul_add_f32x4(a1, b1, c1),
2682 )
2683 }
2684 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
2685 #[inline(always)]
2686 fn mul_add_precise_f32x8(self, a: f32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2687 let (a0, a1) = self.split_f32x8(a);
2688 let (b0, b1) = self.split_f32x8(b);
2689 let (c0, c1) = self.split_f32x8(c);
2690 self.combine_f32x4(
2691 self.mul_add_precise_f32x4(a0, b0, c0),
2692 self.mul_add_precise_f32x4(a1, b1, c1),
2693 )
2694 }
2695 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
2696 #[inline(always)]
2697 fn mul_sub_f32x8(self, a: f32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2698 let (a0, a1) = self.split_f32x8(a);
2699 let (b0, b1) = self.split_f32x8(b);
2700 let (c0, c1) = self.split_f32x8(c);
2701 self.combine_f32x4(
2702 self.mul_sub_f32x4(a0, b0, c0),
2703 self.mul_sub_f32x4(a1, b1, c1),
2704 )
2705 }
2706 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
2707 #[inline(always)]
2708 fn mul_sub_precise_f32x8(self, a: f32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2709 let (a0, a1) = self.split_f32x8(a);
2710 let (b0, b1) = self.split_f32x8(b);
2711 let (c0, c1) = self.split_f32x8(c);
2712 self.combine_f32x4(
2713 self.mul_sub_precise_f32x4(a0, b0, c0),
2714 self.mul_sub_precise_f32x4(a1, b1, c1),
2715 )
2716 }
2717 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
2718 #[inline(always)]
2719 fn floor_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2720 let (a0, a1) = self.split_f32x8(a);
2721 self.combine_f32x4(self.floor_f32x4(a0), self.floor_f32x4(a1))
2722 }
2723 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
2724 #[inline(always)]
2725 fn ceil_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2726 let (a0, a1) = self.split_f32x8(a);
2727 self.combine_f32x4(self.ceil_f32x4(a0), self.ceil_f32x4(a1))
2728 }
2729 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
2730 #[inline(always)]
2731 fn round_ties_even_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2732 let (a0, a1) = self.split_f32x8(a);
2733 self.combine_f32x4(
2734 self.round_ties_even_f32x4(a0),
2735 self.round_ties_even_f32x4(a1),
2736 )
2737 }
2738 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
2739 #[inline(always)]
2740 fn round_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2741 let (a0, a1) = self.split_f32x8(a);
2742 self.combine_f32x4(self.round_f32x4(a0), self.round_f32x4(a1))
2743 }
2744 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
2745 #[inline(always)]
2746 fn fract_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2747 let (a0, a1) = self.split_f32x8(a);
2748 self.combine_f32x4(self.fract_f32x4(a0), self.fract_f32x4(a1))
2749 }
2750 #[doc = "Return the integer part of each element, rounding towards zero."]
2751 #[inline(always)]
2752 fn trunc_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2753 let (a0, a1) = self.split_f32x8(a);
2754 self.combine_f32x4(self.trunc_f32x4(a0), self.trunc_f32x4(a1))
2755 }
2756 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
2757 #[inline(always)]
2758 fn to_degrees_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2759 let (a0, a1) = self.split_f32x8(a);
2760 self.combine_f32x4(self.to_degrees_f32x4(a0), self.to_degrees_f32x4(a1))
2761 }
2762 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
2763 #[inline(always)]
2764 fn to_radians_f32x8(self, a: f32x8<Self>) -> f32x8<Self> {
2765 let (a0, a1) = self.split_f32x8(a);
2766 self.combine_f32x4(self.to_radians_f32x4(a0), self.to_radians_f32x4(a1))
2767 }
2768 #[doc = "Return a mask indicating which elements are NaN."]
2769 fn is_nan_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2770 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
2771 fn is_infinite_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2772 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
2773 fn is_finite_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2774 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
2775 fn is_subnormal_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2776 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
2777 fn is_normal_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2778 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
2779 fn is_sign_positive_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2780 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
2781 fn is_sign_negative_f32x8(self, a: f32x8<Self>) -> mask32x8<Self>;
2782 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
2783 #[inline(always)]
2784 fn select_f32x8(self, a: mask32x8<Self>, b: f32x8<Self>, c: f32x8<Self>) -> f32x8<Self> {
2785 let (a0, a1) = self.split_mask32x8(a);
2786 let (b0, b1) = self.split_f32x8(b);
2787 let (c0, c1) = self.split_f32x8(c);
2788 self.combine_f32x4(self.select_f32x4(a0, b0, c0), self.select_f32x4(a1, b1, c1))
2789 }
2790 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
2791 fn combine_f32x8(self, a: f32x8<Self>, b: f32x8<Self>) -> f32x16<Self>;
2792 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
2793 fn split_f32x8(self, a: f32x8<Self>) -> (f32x4<Self>, f32x4<Self>);
2794 #[doc = "Widen every `f32` lane exactly into two same-width `f64` vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
2795 #[inline(always)]
2796 fn widen_f32x8(self, a: f32x8<Self>) -> (f64x4<Self>, f64x4<Self>) {
2797 let (a0, a1) = self.split_f32x8(a);
2798 let (a00, a01) = self.widen_f32x4(a0);
2799 let (a10, a11) = self.widen_f32x4(a1);
2800 (self.combine_f64x2(a00, a01), self.combine_f64x2(a10, a11))
2801 }
2802 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results.\n\nOn x86 platforms below AVX-512, this operation will still be slower than converting to `i32`, because there is no native instruction for converting to `u32`.\nIf you know your values fit within range of an `i32`, you should convert to an `i32` and cast to your desired datatype afterwards."]
2803 #[inline(always)]
2804 fn cvt_u32_f32x8(self, a: f32x8<Self>) -> u32x8<Self> {
2805 let (a0, a1) = self.split_f32x8(a);
2806 self.combine_u32x4(self.cvt_u32_f32x4(a0), self.cvt_u32_f32x4(a1))
2807 }
2808 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
2809 #[inline(always)]
2810 fn cvt_u32_precise_f32x8(self, a: f32x8<Self>) -> u32x8<Self> {
2811 let (a0, a1) = self.split_f32x8(a);
2812 self.combine_u32x4(
2813 self.cvt_u32_precise_f32x4(a0),
2814 self.cvt_u32_precise_f32x4(a1),
2815 )
2816 }
2817 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
2818 #[inline(always)]
2819 fn cvt_i32_f32x8(self, a: f32x8<Self>) -> i32x8<Self> {
2820 let (a0, a1) = self.split_f32x8(a);
2821 self.combine_i32x4(self.cvt_i32_f32x4(a0), self.cvt_i32_f32x4(a1))
2822 }
2823 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
2824 #[inline(always)]
2825 fn cvt_i32_precise_f32x8(self, a: f32x8<Self>) -> i32x8<Self> {
2826 let (a0, a1) = self.split_f32x8(a);
2827 self.combine_i32x4(
2828 self.cvt_i32_precise_f32x4(a0),
2829 self.cvt_i32_precise_f32x4(a1),
2830 )
2831 }
2832 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
2833 #[inline(always)]
2834 fn abs_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
2835 let (a0, a1) = self.split_i8x32(a);
2836 self.combine_i8x16(self.abs_i8x16(a0), self.abs_i8x16(a1))
2837 }
2838 #[doc = "Create a SIMD vector with all elements set to the given value."]
2839 #[inline(always)]
2840 fn splat_i8x32(self, val: i8) -> i8x32<Self> {
2841 let half = self.splat_i8x16(val);
2842 self.combine_i8x16(half, half)
2843 }
2844 #[doc = "Reverse the order of the vector's elements."]
2845 #[inline(always)]
2846 fn reverse_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
2847 let (a0, a1) = self.split_i8x32(a);
2848 self.combine_i8x16(self.reverse_i8x16(a1), self.reverse_i8x16(a0))
2849 }
2850 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
2851 fn slide_i8x32<const SHIFT: usize>(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self>;
2852 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
2853 #[inline(always)]
2854 fn slide_within_blocks_i8x32<const SHIFT: usize>(
2855 self,
2856 a: i8x32<Self>,
2857 b: i8x32<Self>,
2858 ) -> i8x32<Self> {
2859 let (a0, a1) = self.split_i8x32(a);
2860 let (b0, b1) = self.split_i8x32(b);
2861 self.combine_i8x16(
2862 self.slide_within_blocks_i8x16::<SHIFT>(a0, b0),
2863 self.slide_within_blocks_i8x16::<SHIFT>(a1, b1),
2864 )
2865 }
2866 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
2867 #[inline(always)]
2868 fn swizzle_dyn_within_blocks_i8x32(self, a: i8x32<Self>, indices: u8x32<Self>) -> i8x32<Self> {
2869 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
2870 }
2871 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2872 #[inline(always)]
2873 fn swizzle_dyn_i8x32(self, a: i8x32<Self>, indices: u8x32<Self>) -> i8x32<Self> {
2874 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
2875 }
2876 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
2877 #[inline(always)]
2878 fn swizzle_dyn_precise_i8x32(self, a: i8x32<Self>, indices: u8x32<Self>) -> i8x32<Self> {
2879 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
2880 }
2881 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
2882 #[inline(always)]
2883 fn concat_swizzle_dyn_i8x32(
2884 self,
2885 a: i8x32<Self>,
2886 b: i8x32<Self>,
2887 indices: u8x32<Self>,
2888 ) -> i8x32<Self> {
2889 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
2890 Bytes::to_bytes(a),
2891 Bytes::to_bytes(b),
2892 indices,
2893 ))
2894 }
2895 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
2896 #[inline(always)]
2897 fn concat_swizzle_dyn_precise_i8x32(
2898 self,
2899 a: i8x32<Self>,
2900 b: i8x32<Self>,
2901 indices: u8x32<Self>,
2902 ) -> i8x32<Self> {
2903 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
2904 Bytes::to_bytes(a),
2905 Bytes::to_bytes(b),
2906 indices,
2907 ))
2908 }
2909 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
2910 fn compress_i8x32(self, values: i8x32<Self>, mask: mask8x32<Self>) -> i8x32<Self>;
2911 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
2912 fn compress_merge_i8x32(
2913 self,
2914 values: i8x32<Self>,
2915 mask: mask8x32<Self>,
2916 merge: i8x32<Self>,
2917 ) -> i8x32<Self>;
2918 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
2919 fn expand_i8x32(self, values: i8x32<Self>, mask: mask8x32<Self>) -> i8x32<Self>;
2920 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
2921 fn expand_merge_i8x32(
2922 self,
2923 values: i8x32<Self>,
2924 mask: mask8x32<Self>,
2925 merge: i8x32<Self>,
2926 ) -> i8x32<Self>;
2927 #[doc = "Return the number of ones in the binary representation of each element."]
2928 #[inline(always)]
2929 fn count_ones_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
2930 let (a0, a1) = self.split_i8x32(a);
2931 self.combine_i8x16(self.count_ones_i8x16(a0), self.count_ones_i8x16(a1))
2932 }
2933 #[doc = "Return the number of zeros in the binary representation of each element."]
2934 #[inline(always)]
2935 fn count_zeros_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
2936 let (a0, a1) = self.split_i8x32(a);
2937 self.combine_i8x16(self.count_zeros_i8x16(a0), self.count_zeros_i8x16(a1))
2938 }
2939 #[doc = "Add two vectors element-wise, wrapping on overflow."]
2940 #[inline(always)]
2941 fn add_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2942 let (a0, a1) = self.split_i8x32(a);
2943 let (b0, b1) = self.split_i8x32(b);
2944 self.combine_i8x16(self.add_i8x16(a0, b0), self.add_i8x16(a1, b1))
2945 }
2946 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
2947 #[inline(always)]
2948 fn saturating_add_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2949 let (a0, a1) = self.split_i8x32(a);
2950 let (b0, b1) = self.split_i8x32(b);
2951 self.combine_i8x16(
2952 self.saturating_add_i8x16(a0, b0),
2953 self.saturating_add_i8x16(a1, b1),
2954 )
2955 }
2956 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
2957 #[inline(always)]
2958 fn sub_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2959 let (a0, a1) = self.split_i8x32(a);
2960 let (b0, b1) = self.split_i8x32(b);
2961 self.combine_i8x16(self.sub_i8x16(a0, b0), self.sub_i8x16(a1, b1))
2962 }
2963 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
2964 #[inline(always)]
2965 fn saturating_sub_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2966 let (a0, a1) = self.split_i8x32(a);
2967 let (b0, b1) = self.split_i8x32(b);
2968 self.combine_i8x16(
2969 self.saturating_sub_i8x16(a0, b0),
2970 self.saturating_sub_i8x16(a1, b1),
2971 )
2972 }
2973 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
2974 #[inline(always)]
2975 fn mul_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2976 let (a0, a1) = self.split_i8x32(a);
2977 let (b0, b1) = self.split_i8x32(b);
2978 self.combine_i8x16(self.mul_i8x16(a0, b0), self.mul_i8x16(a1, b1))
2979 }
2980 #[doc = "Compute the bitwise AND of two vectors."]
2981 #[inline(always)]
2982 fn and_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2983 let (a0, a1) = self.split_i8x32(a);
2984 let (b0, b1) = self.split_i8x32(b);
2985 self.combine_i8x16(self.and_i8x16(a0, b0), self.and_i8x16(a1, b1))
2986 }
2987 #[doc = "Compute the bitwise OR of two vectors."]
2988 #[inline(always)]
2989 fn or_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2990 let (a0, a1) = self.split_i8x32(a);
2991 let (b0, b1) = self.split_i8x32(b);
2992 self.combine_i8x16(self.or_i8x16(a0, b0), self.or_i8x16(a1, b1))
2993 }
2994 #[doc = "Compute the bitwise XOR of two vectors."]
2995 #[inline(always)]
2996 fn xor_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
2997 let (a0, a1) = self.split_i8x32(a);
2998 let (b0, b1) = self.split_i8x32(b);
2999 self.combine_i8x16(self.xor_i8x16(a0, b0), self.xor_i8x16(a1, b1))
3000 }
3001 #[doc = "Compute the bitwise NOT of the vector."]
3002 #[inline(always)]
3003 fn not_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
3004 let (a0, a1) = self.split_i8x32(a);
3005 self.combine_i8x16(self.not_i8x16(a0), self.not_i8x16(a1))
3006 }
3007 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3008 #[inline(always)]
3009 fn shl_i8x32(self, a: i8x32<Self>, shift: u32) -> i8x32<Self> {
3010 let (a0, a1) = self.split_i8x32(a);
3011 self.combine_i8x16(self.shl_i8x16(a0, shift), self.shl_i8x16(a1, shift))
3012 }
3013 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3014 #[inline(always)]
3015 fn shlv_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3016 let (a0, a1) = self.split_i8x32(a);
3017 let (b0, b1) = self.split_i8x32(b);
3018 self.combine_i8x16(self.shlv_i8x16(a0, b0), self.shlv_i8x16(a1, b1))
3019 }
3020 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3021 #[inline(always)]
3022 fn shr_i8x32(self, a: i8x32<Self>, shift: u32) -> i8x32<Self> {
3023 let (a0, a1) = self.split_i8x32(a);
3024 self.combine_i8x16(self.shr_i8x16(a0, shift), self.shr_i8x16(a1, shift))
3025 }
3026 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3027 #[inline(always)]
3028 fn shrv_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3029 let (a0, a1) = self.split_i8x32(a);
3030 let (b0, b1) = self.split_i8x32(b);
3031 self.combine_i8x16(self.shrv_i8x16(a0, b0), self.shrv_i8x16(a1, b1))
3032 }
3033 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3034 #[inline(always)]
3035 fn reduce_max_i8x32(self, a: i8x32<Self>) -> i8 {
3036 let (a0, a1) = self.split_i8x32(a);
3037 self.reduce_max_i8x16(self.max_i8x16(a0, a1))
3038 }
3039 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3040 #[inline(always)]
3041 fn reduce_min_i8x32(self, a: i8x32<Self>) -> i8 {
3042 let (a0, a1) = self.split_i8x32(a);
3043 self.reduce_min_i8x16(self.min_i8x16(a0, a1))
3044 }
3045 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
3046 #[inline(always)]
3047 fn reduce_sum_i8x32(self, a: i8x32<Self>) -> i8 {
3048 let (a0, a1) = self.split_i8x32(a);
3049 self.reduce_sum_i8x16(self.add_i8x16(a0, a1))
3050 }
3051 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
3052 #[inline(always)]
3053 fn reduce_product_i8x32(self, a: i8x32<Self>) -> i8 {
3054 let (a0, a1) = self.split_i8x32(a);
3055 self.reduce_product_i8x16(self.mul_i8x16(a0, a1))
3056 }
3057 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
3058 #[inline(always)]
3059 fn max_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3060 let (a0, a1) = self.split_i8x32(a);
3061 let (b0, b1) = self.split_i8x32(b);
3062 self.combine_i8x16(self.max_i8x16(a0, b0), self.max_i8x16(a1, b1))
3063 }
3064 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
3065 #[inline(always)]
3066 fn min_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3067 let (a0, a1) = self.split_i8x32(a);
3068 let (b0, b1) = self.split_i8x32(b);
3069 self.combine_i8x16(self.min_i8x16(a0, b0), self.min_i8x16(a1, b1))
3070 }
3071 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
3072 #[inline(always)]
3073 fn clamp_i8x32(self, a: i8x32<Self>, b: i8x32<Self>, c: i8x32<Self>) -> i8x32<Self> {
3074 let (a0, a1) = self.split_i8x32(a);
3075 let (b0, b1) = self.split_i8x32(b);
3076 let (c0, c1) = self.split_i8x32(c);
3077 self.combine_i8x16(self.clamp_i8x16(a0, b0, c0), self.clamp_i8x16(a1, b1, c1))
3078 }
3079 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
3080 #[inline(always)]
3081 fn simd_eq_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3082 let (a0, a1) = self.split_i8x32(a);
3083 let (b0, b1) = self.split_i8x32(b);
3084 self.combine_mask8x16(self.simd_eq_i8x16(a0, b0), self.simd_eq_i8x16(a1, b1))
3085 }
3086 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
3087 #[inline(always)]
3088 fn simd_ne_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3089 self.not_mask8x32(self.simd_eq_i8x32(a, b))
3090 }
3091 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
3092 #[inline(always)]
3093 fn simd_lt_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3094 let (a0, a1) = self.split_i8x32(a);
3095 let (b0, b1) = self.split_i8x32(b);
3096 self.combine_mask8x16(self.simd_lt_i8x16(a0, b0), self.simd_lt_i8x16(a1, b1))
3097 }
3098 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
3099 #[inline(always)]
3100 fn simd_le_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3101 let (a0, a1) = self.split_i8x32(a);
3102 let (b0, b1) = self.split_i8x32(b);
3103 self.combine_mask8x16(self.simd_le_i8x16(a0, b0), self.simd_le_i8x16(a1, b1))
3104 }
3105 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
3106 #[inline(always)]
3107 fn simd_ge_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3108 self.simd_le_i8x32(b, a)
3109 }
3110 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
3111 #[inline(always)]
3112 fn simd_gt_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> mask8x32<Self> {
3113 self.simd_lt_i8x32(b, a)
3114 }
3115 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
3116 #[inline(always)]
3117 fn zip_low_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3118 let (a0, _) = self.split_i8x32(a);
3119 let (b0, _) = self.split_i8x32(b);
3120 self.combine_i8x16(self.zip_low_i8x16(a0, b0), self.zip_high_i8x16(a0, b0))
3121 }
3122 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
3123 #[inline(always)]
3124 fn zip_high_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3125 let (_, a1) = self.split_i8x32(a);
3126 let (_, b1) = self.split_i8x32(b);
3127 self.combine_i8x16(self.zip_low_i8x16(a1, b1), self.zip_high_i8x16(a1, b1))
3128 }
3129 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
3130 #[inline(always)]
3131 fn unzip_low_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3132 let (a0, a1) = self.split_i8x32(a);
3133 let (b0, b1) = self.split_i8x32(b);
3134 self.combine_i8x16(self.unzip_low_i8x16(a0, a1), self.unzip_low_i8x16(b0, b1))
3135 }
3136 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
3137 #[inline(always)]
3138 fn unzip_high_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x32<Self> {
3139 let (a0, a1) = self.split_i8x32(a);
3140 let (b0, b1) = self.split_i8x32(b);
3141 self.combine_i8x16(self.unzip_high_i8x16(a0, a1), self.unzip_high_i8x16(b0, b1))
3142 }
3143 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
3144 #[inline(always)]
3145 fn interleave_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> (i8x32<Self>, i8x32<Self>) {
3146 let (a0, a1) = self.split_i8x32(a);
3147 let (b0, b1) = self.split_i8x32(b);
3148 let lo_lo = self.zip_low_i8x16(a0, b0);
3149 let lo_hi = self.zip_high_i8x16(a0, b0);
3150 let hi_lo = self.zip_low_i8x16(a1, b1);
3151 let hi_hi = self.zip_high_i8x16(a1, b1);
3152 (
3153 self.combine_i8x16(lo_lo, lo_hi),
3154 self.combine_i8x16(hi_lo, hi_hi),
3155 )
3156 }
3157 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
3158 #[inline(always)]
3159 fn deinterleave_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> (i8x32<Self>, i8x32<Self>) {
3160 let (a0, a1) = self.split_i8x32(a);
3161 let (b0, b1) = self.split_i8x32(b);
3162 let lo_even = self.unzip_low_i8x16(a0, a1);
3163 let lo_odd = self.unzip_high_i8x16(a0, a1);
3164 let hi_even = self.unzip_low_i8x16(b0, b1);
3165 let hi_odd = self.unzip_high_i8x16(b0, b1);
3166 (
3167 self.combine_i8x16(lo_even, hi_even),
3168 self.combine_i8x16(lo_odd, hi_odd),
3169 )
3170 }
3171 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
3172 #[inline(always)]
3173 fn select_i8x32(self, a: mask8x32<Self>, b: i8x32<Self>, c: i8x32<Self>) -> i8x32<Self> {
3174 let (a0, a1) = self.split_mask8x32(a);
3175 let (b0, b1) = self.split_i8x32(b);
3176 let (c0, c1) = self.split_i8x32(c);
3177 self.combine_i8x16(self.select_i8x16(a0, b0, c0), self.select_i8x16(a1, b1, c1))
3178 }
3179 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
3180 fn combine_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i8x64<Self>;
3181 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
3182 fn split_i8x32(self, a: i8x32<Self>) -> (i8x16<Self>, i8x16<Self>);
3183 #[doc = "Negate each element of the vector, wrapping on overflow."]
3184 #[inline(always)]
3185 fn neg_i8x32(self, a: i8x32<Self>) -> i8x32<Self> {
3186 let (a0, a1) = self.split_i8x32(a);
3187 self.combine_i8x16(self.neg_i8x16(a0), self.neg_i8x16(a1))
3188 }
3189 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
3190 #[inline(always)]
3191 fn widen_i8x32(self, a: i8x32<Self>) -> (i16x16<Self>, i16x16<Self>) {
3192 let (a0, a1) = self.split_i8x32(a);
3193 let (a00, a01) = self.widen_i8x16(a0);
3194 let (a10, a11) = self.widen_i8x16(a1);
3195 (self.combine_i16x8(a00, a01), self.combine_i16x8(a10, a11))
3196 }
3197 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
3198 #[inline(always)]
3199 fn widening_mul_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> (i16x16<Self>, i16x16<Self>) {
3200 let (a0, a1) = self.split_i8x32(a);
3201 let (b0, b1) = self.split_i8x32(b);
3202 let (low0, low1) = self.widening_mul_i8x16(a0, b0);
3203 let (high0, high1) = self.widening_mul_i8x16(a1, b1);
3204 (
3205 self.combine_i16x8(low0, low1),
3206 self.combine_i16x8(high0, high1),
3207 )
3208 }
3209 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
3210 #[inline(always)]
3211 fn widening_add_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> (i16x16<Self>, i16x16<Self>) {
3212 let (a0, a1) = self.split_i8x32(a);
3213 let (b0, b1) = self.split_i8x32(b);
3214 let (low0, low1) = self.widening_add_i8x16(a0, b0);
3215 let (high0, high1) = self.widening_add_i8x16(a1, b1);
3216 (
3217 self.combine_i16x8(low0, low1),
3218 self.combine_i16x8(high0, high1),
3219 )
3220 }
3221 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
3222 #[inline(always)]
3223 fn pairwise_widening_add_i8x32(self, a: i8x32<Self>) -> i16x16<Self> {
3224 let (a0, a1) = self.split_i8x32(a);
3225 self.combine_i16x8(
3226 self.pairwise_widening_add_i8x16(a0),
3227 self.pairwise_widening_add_i8x16(a1),
3228 )
3229 }
3230 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
3231 #[inline(always)]
3232 fn pairwise_dot_product_i8x32(self, a: i8x32<Self>, b: i8x32<Self>) -> i16x16<Self> {
3233 let (a0, a1) = self.split_i8x32(a);
3234 let (b0, b1) = self.split_i8x32(b);
3235 self.combine_i16x8(
3236 self.pairwise_dot_product_i8x16(a0, b0),
3237 self.pairwise_dot_product_i8x16(a1, b1),
3238 )
3239 }
3240 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
3241 #[inline(always)]
3242 fn abs_u8x32(self, a: u8x32<Self>) -> u8x32<Self> {
3243 a
3244 }
3245 #[doc = "Create a SIMD vector with all elements set to the given value."]
3246 #[inline(always)]
3247 fn splat_u8x32(self, val: u8) -> u8x32<Self> {
3248 let half = self.splat_u8x16(val);
3249 self.combine_u8x16(half, half)
3250 }
3251 #[doc = "Reverse the order of the vector's elements."]
3252 #[inline(always)]
3253 fn reverse_u8x32(self, a: u8x32<Self>) -> u8x32<Self> {
3254 let (a0, a1) = self.split_u8x32(a);
3255 self.combine_u8x16(self.reverse_u8x16(a1), self.reverse_u8x16(a0))
3256 }
3257 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
3258 fn slide_u8x32<const SHIFT: usize>(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self>;
3259 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
3260 #[inline(always)]
3261 fn slide_within_blocks_u8x32<const SHIFT: usize>(
3262 self,
3263 a: u8x32<Self>,
3264 b: u8x32<Self>,
3265 ) -> u8x32<Self> {
3266 let (a0, a1) = self.split_u8x32(a);
3267 let (b0, b1) = self.split_u8x32(b);
3268 self.combine_u8x16(
3269 self.slide_within_blocks_u8x16::<SHIFT>(a0, b0),
3270 self.slide_within_blocks_u8x16::<SHIFT>(a1, b1),
3271 )
3272 }
3273 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
3274 #[inline(always)]
3275 fn swizzle_dyn_within_blocks_u8x32(self, a: u8x32<Self>, indices: u8x32<Self>) -> u8x32<Self> {
3276 let (a0, a1) = self.split_u8x32(a);
3277 let (indices0, indices1) = self.split_u8x32(indices);
3278 self.combine_u8x16(
3279 self.swizzle_dyn_within_blocks_u8x16(a0, indices0),
3280 self.swizzle_dyn_within_blocks_u8x16(a1, indices1),
3281 )
3282 }
3283 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
3284 fn swizzle_dyn_u8x32(self, a: u8x32<Self>, indices: u8x32<Self>) -> u8x32<Self>;
3285 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
3286 fn swizzle_dyn_precise_u8x32(self, a: u8x32<Self>, indices: u8x32<Self>) -> u8x32<Self>;
3287 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
3288 fn concat_swizzle_dyn_u8x32(
3289 self,
3290 a: u8x32<Self>,
3291 b: u8x32<Self>,
3292 indices: u8x32<Self>,
3293 ) -> u8x32<Self>;
3294 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
3295 fn concat_swizzle_dyn_precise_u8x32(
3296 self,
3297 a: u8x32<Self>,
3298 b: u8x32<Self>,
3299 indices: u8x32<Self>,
3300 ) -> u8x32<Self>;
3301 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
3302 fn compress_u8x32(self, values: u8x32<Self>, mask: mask8x32<Self>) -> u8x32<Self>;
3303 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
3304 fn compress_merge_u8x32(
3305 self,
3306 values: u8x32<Self>,
3307 mask: mask8x32<Self>,
3308 merge: u8x32<Self>,
3309 ) -> u8x32<Self>;
3310 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
3311 fn expand_u8x32(self, values: u8x32<Self>, mask: mask8x32<Self>) -> u8x32<Self>;
3312 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
3313 fn expand_merge_u8x32(
3314 self,
3315 values: u8x32<Self>,
3316 mask: mask8x32<Self>,
3317 merge: u8x32<Self>,
3318 ) -> u8x32<Self>;
3319 #[doc = "Return the number of ones in the binary representation of each element."]
3320 #[inline(always)]
3321 fn count_ones_u8x32(self, a: u8x32<Self>) -> u8x32<Self> {
3322 let (a0, a1) = self.split_u8x32(a);
3323 self.combine_u8x16(self.count_ones_u8x16(a0), self.count_ones_u8x16(a1))
3324 }
3325 #[doc = "Return the number of zeros in the binary representation of each element."]
3326 #[inline(always)]
3327 fn count_zeros_u8x32(self, a: u8x32<Self>) -> u8x32<Self> {
3328 let (a0, a1) = self.split_u8x32(a);
3329 self.combine_u8x16(self.count_zeros_u8x16(a0), self.count_zeros_u8x16(a1))
3330 }
3331 #[doc = "Add two vectors element-wise, wrapping on overflow."]
3332 #[inline(always)]
3333 fn add_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3334 let (a0, a1) = self.split_u8x32(a);
3335 let (b0, b1) = self.split_u8x32(b);
3336 self.combine_u8x16(self.add_u8x16(a0, b0), self.add_u8x16(a1, b1))
3337 }
3338 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
3339 #[inline(always)]
3340 fn saturating_add_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3341 let (a0, a1) = self.split_u8x32(a);
3342 let (b0, b1) = self.split_u8x32(b);
3343 self.combine_u8x16(
3344 self.saturating_add_u8x16(a0, b0),
3345 self.saturating_add_u8x16(a1, b1),
3346 )
3347 }
3348 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
3349 #[inline(always)]
3350 fn sub_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3351 let (a0, a1) = self.split_u8x32(a);
3352 let (b0, b1) = self.split_u8x32(b);
3353 self.combine_u8x16(self.sub_u8x16(a0, b0), self.sub_u8x16(a1, b1))
3354 }
3355 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
3356 #[inline(always)]
3357 fn saturating_sub_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3358 let (a0, a1) = self.split_u8x32(a);
3359 let (b0, b1) = self.split_u8x32(b);
3360 self.combine_u8x16(
3361 self.saturating_sub_u8x16(a0, b0),
3362 self.saturating_sub_u8x16(a1, b1),
3363 )
3364 }
3365 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
3366 #[inline(always)]
3367 fn mul_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3368 let (a0, a1) = self.split_u8x32(a);
3369 let (b0, b1) = self.split_u8x32(b);
3370 self.combine_u8x16(self.mul_u8x16(a0, b0), self.mul_u8x16(a1, b1))
3371 }
3372 #[doc = "Compute the bitwise AND of two vectors."]
3373 #[inline(always)]
3374 fn and_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3375 let (a0, a1) = self.split_u8x32(a);
3376 let (b0, b1) = self.split_u8x32(b);
3377 self.combine_u8x16(self.and_u8x16(a0, b0), self.and_u8x16(a1, b1))
3378 }
3379 #[doc = "Compute the bitwise OR of two vectors."]
3380 #[inline(always)]
3381 fn or_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3382 let (a0, a1) = self.split_u8x32(a);
3383 let (b0, b1) = self.split_u8x32(b);
3384 self.combine_u8x16(self.or_u8x16(a0, b0), self.or_u8x16(a1, b1))
3385 }
3386 #[doc = "Compute the bitwise XOR of two vectors."]
3387 #[inline(always)]
3388 fn xor_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3389 let (a0, a1) = self.split_u8x32(a);
3390 let (b0, b1) = self.split_u8x32(b);
3391 self.combine_u8x16(self.xor_u8x16(a0, b0), self.xor_u8x16(a1, b1))
3392 }
3393 #[doc = "Compute the bitwise NOT of the vector."]
3394 #[inline(always)]
3395 fn not_u8x32(self, a: u8x32<Self>) -> u8x32<Self> {
3396 let (a0, a1) = self.split_u8x32(a);
3397 self.combine_u8x16(self.not_u8x16(a0), self.not_u8x16(a1))
3398 }
3399 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3400 #[inline(always)]
3401 fn shl_u8x32(self, a: u8x32<Self>, shift: u32) -> u8x32<Self> {
3402 let (a0, a1) = self.split_u8x32(a);
3403 self.combine_u8x16(self.shl_u8x16(a0, shift), self.shl_u8x16(a1, shift))
3404 }
3405 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3406 #[inline(always)]
3407 fn shlv_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3408 let (a0, a1) = self.split_u8x32(a);
3409 let (b0, b1) = self.split_u8x32(b);
3410 self.combine_u8x16(self.shlv_u8x16(a0, b0), self.shlv_u8x16(a1, b1))
3411 }
3412 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3413 #[inline(always)]
3414 fn shr_u8x32(self, a: u8x32<Self>, shift: u32) -> u8x32<Self> {
3415 let (a0, a1) = self.split_u8x32(a);
3416 self.combine_u8x16(self.shr_u8x16(a0, shift), self.shr_u8x16(a1, shift))
3417 }
3418 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3419 #[inline(always)]
3420 fn shrv_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3421 let (a0, a1) = self.split_u8x32(a);
3422 let (b0, b1) = self.split_u8x32(b);
3423 self.combine_u8x16(self.shrv_u8x16(a0, b0), self.shrv_u8x16(a1, b1))
3424 }
3425 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3426 #[inline(always)]
3427 fn reduce_max_u8x32(self, a: u8x32<Self>) -> u8 {
3428 let (a0, a1) = self.split_u8x32(a);
3429 self.reduce_max_u8x16(self.max_u8x16(a0, a1))
3430 }
3431 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3432 #[inline(always)]
3433 fn reduce_min_u8x32(self, a: u8x32<Self>) -> u8 {
3434 let (a0, a1) = self.split_u8x32(a);
3435 self.reduce_min_u8x16(self.min_u8x16(a0, a1))
3436 }
3437 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
3438 #[inline(always)]
3439 fn reduce_sum_u8x32(self, a: u8x32<Self>) -> u8 {
3440 let (a0, a1) = self.split_u8x32(a);
3441 self.reduce_sum_u8x16(self.add_u8x16(a0, a1))
3442 }
3443 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
3444 #[inline(always)]
3445 fn reduce_product_u8x32(self, a: u8x32<Self>) -> u8 {
3446 let (a0, a1) = self.split_u8x32(a);
3447 self.reduce_product_u8x16(self.mul_u8x16(a0, a1))
3448 }
3449 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
3450 #[inline(always)]
3451 fn max_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3452 let (a0, a1) = self.split_u8x32(a);
3453 let (b0, b1) = self.split_u8x32(b);
3454 self.combine_u8x16(self.max_u8x16(a0, b0), self.max_u8x16(a1, b1))
3455 }
3456 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
3457 #[inline(always)]
3458 fn min_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3459 let (a0, a1) = self.split_u8x32(a);
3460 let (b0, b1) = self.split_u8x32(b);
3461 self.combine_u8x16(self.min_u8x16(a0, b0), self.min_u8x16(a1, b1))
3462 }
3463 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
3464 #[inline(always)]
3465 fn clamp_u8x32(self, a: u8x32<Self>, b: u8x32<Self>, c: u8x32<Self>) -> u8x32<Self> {
3466 let (a0, a1) = self.split_u8x32(a);
3467 let (b0, b1) = self.split_u8x32(b);
3468 let (c0, c1) = self.split_u8x32(c);
3469 self.combine_u8x16(self.clamp_u8x16(a0, b0, c0), self.clamp_u8x16(a1, b1, c1))
3470 }
3471 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
3472 #[inline(always)]
3473 fn simd_eq_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3474 let (a0, a1) = self.split_u8x32(a);
3475 let (b0, b1) = self.split_u8x32(b);
3476 self.combine_mask8x16(self.simd_eq_u8x16(a0, b0), self.simd_eq_u8x16(a1, b1))
3477 }
3478 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
3479 #[inline(always)]
3480 fn simd_ne_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3481 self.not_mask8x32(self.simd_eq_u8x32(a, b))
3482 }
3483 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
3484 #[inline(always)]
3485 fn simd_lt_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3486 let (a0, a1) = self.split_u8x32(a);
3487 let (b0, b1) = self.split_u8x32(b);
3488 self.combine_mask8x16(self.simd_lt_u8x16(a0, b0), self.simd_lt_u8x16(a1, b1))
3489 }
3490 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
3491 #[inline(always)]
3492 fn simd_le_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3493 let (a0, a1) = self.split_u8x32(a);
3494 let (b0, b1) = self.split_u8x32(b);
3495 self.combine_mask8x16(self.simd_le_u8x16(a0, b0), self.simd_le_u8x16(a1, b1))
3496 }
3497 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
3498 #[inline(always)]
3499 fn simd_ge_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3500 self.simd_le_u8x32(b, a)
3501 }
3502 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
3503 #[inline(always)]
3504 fn simd_gt_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> mask8x32<Self> {
3505 self.simd_lt_u8x32(b, a)
3506 }
3507 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
3508 #[inline(always)]
3509 fn zip_low_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3510 let (a0, _) = self.split_u8x32(a);
3511 let (b0, _) = self.split_u8x32(b);
3512 self.combine_u8x16(self.zip_low_u8x16(a0, b0), self.zip_high_u8x16(a0, b0))
3513 }
3514 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
3515 #[inline(always)]
3516 fn zip_high_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3517 let (_, a1) = self.split_u8x32(a);
3518 let (_, b1) = self.split_u8x32(b);
3519 self.combine_u8x16(self.zip_low_u8x16(a1, b1), self.zip_high_u8x16(a1, b1))
3520 }
3521 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
3522 #[inline(always)]
3523 fn unzip_low_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3524 let (a0, a1) = self.split_u8x32(a);
3525 let (b0, b1) = self.split_u8x32(b);
3526 self.combine_u8x16(self.unzip_low_u8x16(a0, a1), self.unzip_low_u8x16(b0, b1))
3527 }
3528 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
3529 #[inline(always)]
3530 fn unzip_high_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x32<Self> {
3531 let (a0, a1) = self.split_u8x32(a);
3532 let (b0, b1) = self.split_u8x32(b);
3533 self.combine_u8x16(self.unzip_high_u8x16(a0, a1), self.unzip_high_u8x16(b0, b1))
3534 }
3535 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
3536 #[inline(always)]
3537 fn interleave_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> (u8x32<Self>, u8x32<Self>) {
3538 let (a0, a1) = self.split_u8x32(a);
3539 let (b0, b1) = self.split_u8x32(b);
3540 let lo_lo = self.zip_low_u8x16(a0, b0);
3541 let lo_hi = self.zip_high_u8x16(a0, b0);
3542 let hi_lo = self.zip_low_u8x16(a1, b1);
3543 let hi_hi = self.zip_high_u8x16(a1, b1);
3544 (
3545 self.combine_u8x16(lo_lo, lo_hi),
3546 self.combine_u8x16(hi_lo, hi_hi),
3547 )
3548 }
3549 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
3550 #[inline(always)]
3551 fn deinterleave_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> (u8x32<Self>, u8x32<Self>) {
3552 let (a0, a1) = self.split_u8x32(a);
3553 let (b0, b1) = self.split_u8x32(b);
3554 let lo_even = self.unzip_low_u8x16(a0, a1);
3555 let lo_odd = self.unzip_high_u8x16(a0, a1);
3556 let hi_even = self.unzip_low_u8x16(b0, b1);
3557 let hi_odd = self.unzip_high_u8x16(b0, b1);
3558 (
3559 self.combine_u8x16(lo_even, hi_even),
3560 self.combine_u8x16(lo_odd, hi_odd),
3561 )
3562 }
3563 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
3564 #[inline(always)]
3565 fn select_u8x32(self, a: mask8x32<Self>, b: u8x32<Self>, c: u8x32<Self>) -> u8x32<Self> {
3566 let (a0, a1) = self.split_mask8x32(a);
3567 let (b0, b1) = self.split_u8x32(b);
3568 let (c0, c1) = self.split_u8x32(c);
3569 self.combine_u8x16(self.select_u8x16(a0, b0, c0), self.select_u8x16(a1, b1, c1))
3570 }
3571 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
3572 fn combine_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u8x64<Self>;
3573 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
3574 fn split_u8x32(self, a: u8x32<Self>) -> (u8x16<Self>, u8x16<Self>);
3575 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
3576 #[inline(always)]
3577 fn widen_u8x32(self, a: u8x32<Self>) -> (u16x16<Self>, u16x16<Self>) {
3578 let (a0, a1) = self.split_u8x32(a);
3579 let (a00, a01) = self.widen_u8x16(a0);
3580 let (a10, a11) = self.widen_u8x16(a1);
3581 (self.combine_u16x8(a00, a01), self.combine_u16x8(a10, a11))
3582 }
3583 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
3584 #[inline(always)]
3585 fn widening_mul_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> (u16x16<Self>, u16x16<Self>) {
3586 let (a0, a1) = self.split_u8x32(a);
3587 let (b0, b1) = self.split_u8x32(b);
3588 let (low0, low1) = self.widening_mul_u8x16(a0, b0);
3589 let (high0, high1) = self.widening_mul_u8x16(a1, b1);
3590 (
3591 self.combine_u16x8(low0, low1),
3592 self.combine_u16x8(high0, high1),
3593 )
3594 }
3595 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
3596 #[inline(always)]
3597 fn widening_add_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> (u16x16<Self>, u16x16<Self>) {
3598 let (a0, a1) = self.split_u8x32(a);
3599 let (b0, b1) = self.split_u8x32(b);
3600 let (low0, low1) = self.widening_add_u8x16(a0, b0);
3601 let (high0, high1) = self.widening_add_u8x16(a1, b1);
3602 (
3603 self.combine_u16x8(low0, low1),
3604 self.combine_u16x8(high0, high1),
3605 )
3606 }
3607 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
3608 #[inline(always)]
3609 fn pairwise_widening_add_u8x32(self, a: u8x32<Self>) -> u16x16<Self> {
3610 let (a0, a1) = self.split_u8x32(a);
3611 self.combine_u16x8(
3612 self.pairwise_widening_add_u8x16(a0),
3613 self.pairwise_widening_add_u8x16(a1),
3614 )
3615 }
3616 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
3617 #[inline(always)]
3618 fn pairwise_dot_product_u8x32(self, a: u8x32<Self>, b: u8x32<Self>) -> u16x16<Self> {
3619 let (a0, a1) = self.split_u8x32(a);
3620 let (b0, b1) = self.split_u8x32(b);
3621 self.combine_u16x8(
3622 self.pairwise_dot_product_u8x16(a0, b0),
3623 self.pairwise_dot_product_u8x16(a1, b1),
3624 )
3625 }
3626 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
3627 #[inline(always)]
3628 fn splat_mask8x32(self, val: bool) -> mask8x32<Self> {
3629 let half = self.splat_mask8x16(val);
3630 self.combine_mask8x16(half, half)
3631 }
3632 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
3633 #[inline(always)]
3634 fn from_bitmask_mask8x32(self, bits: u64) -> mask8x32<Self> {
3635 let lo = self.from_bitmask_mask8x16(bits);
3636 let hi = self.from_bitmask_mask8x16(bits >> 16usize);
3637 self.combine_mask8x16(lo, hi)
3638 }
3639 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
3640 #[inline(always)]
3641 fn to_bitmask_mask8x32(self, a: mask8x32<Self>) -> u64 {
3642 let (lo, hi) = self.split_mask8x32(a);
3643 let lo = self.to_bitmask_mask8x16(lo);
3644 let hi = self.to_bitmask_mask8x16(hi);
3645 lo | (hi << 16usize)
3646 }
3647 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
3648 fn from_vector_mask8x32(self, vector: i8x32<Self>) -> mask8x32<Self>;
3649 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
3650 fn to_vector_mask8x32(self, a: mask8x32<Self>) -> i8x32<Self>;
3651 #[doc = "Set one logical lane of a SIMD mask."]
3652 fn set_mask8x32(self, a: &mut mask8x32<Self>, index: usize, value: bool) -> ();
3653 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
3654 fn rotate_elements_left_mask8x32<const OFFSET: usize>(
3655 self,
3656 a: mask8x32<Self>,
3657 ) -> mask8x32<Self>;
3658 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
3659 fn rotate_elements_right_mask8x32<const OFFSET: usize>(
3660 self,
3661 a: mask8x32<Self>,
3662 ) -> mask8x32<Self>;
3663 #[doc = "Compute the logical AND of two masks."]
3664 #[inline(always)]
3665 fn and_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x32<Self> {
3666 let (a0, a1) = self.split_mask8x32(a);
3667 let (b0, b1) = self.split_mask8x32(b);
3668 self.combine_mask8x16(self.and_mask8x16(a0, b0), self.and_mask8x16(a1, b1))
3669 }
3670 #[doc = "Compute the logical OR of two masks."]
3671 #[inline(always)]
3672 fn or_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x32<Self> {
3673 let (a0, a1) = self.split_mask8x32(a);
3674 let (b0, b1) = self.split_mask8x32(b);
3675 self.combine_mask8x16(self.or_mask8x16(a0, b0), self.or_mask8x16(a1, b1))
3676 }
3677 #[doc = "Compute the logical XOR of two masks."]
3678 #[inline(always)]
3679 fn xor_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x32<Self> {
3680 let (a0, a1) = self.split_mask8x32(a);
3681 let (b0, b1) = self.split_mask8x32(b);
3682 self.combine_mask8x16(self.xor_mask8x16(a0, b0), self.xor_mask8x16(a1, b1))
3683 }
3684 #[doc = "Compute the logical NOT of the mask."]
3685 #[inline(always)]
3686 fn not_mask8x32(self, a: mask8x32<Self>) -> mask8x32<Self> {
3687 let (a0, a1) = self.split_mask8x32(a);
3688 self.combine_mask8x16(self.not_mask8x16(a0), self.not_mask8x16(a1))
3689 }
3690 #[doc = "Reverse the order of the mask's logical lanes."]
3691 #[inline(always)]
3692 fn reverse_mask8x32(self, a: mask8x32<Self>) -> mask8x32<Self> {
3693 let (a0, a1) = self.split_mask8x32(a);
3694 self.combine_mask8x16(self.reverse_mask8x16(a1), self.reverse_mask8x16(a0))
3695 }
3696 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
3697 #[inline(always)]
3698 fn select_mask8x32(
3699 self,
3700 a: mask8x32<Self>,
3701 b: mask8x32<Self>,
3702 c: mask8x32<Self>,
3703 ) -> mask8x32<Self> {
3704 let (a0, a1) = self.split_mask8x32(a);
3705 let (b0, b1) = self.split_mask8x32(b);
3706 let (c0, c1) = self.split_mask8x32(c);
3707 self.combine_mask8x16(
3708 self.select_mask8x16(a0, b0, c0),
3709 self.select_mask8x16(a1, b1, c1),
3710 )
3711 }
3712 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
3713 #[inline(always)]
3714 fn simd_eq_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x32<Self> {
3715 let (a0, a1) = self.split_mask8x32(a);
3716 let (b0, b1) = self.split_mask8x32(b);
3717 self.combine_mask8x16(self.simd_eq_mask8x16(a0, b0), self.simd_eq_mask8x16(a1, b1))
3718 }
3719 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
3720 #[inline(always)]
3721 fn simd_ne_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x32<Self> {
3722 self.not_mask8x32(self.simd_eq_mask8x32(a, b))
3723 }
3724 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
3725 #[inline(always)]
3726 fn any_true_mask8x32(self, a: mask8x32<Self>) -> bool {
3727 let (a0, a1) = self.split_mask8x32(a);
3728 self.any_true_mask8x16(self.or_mask8x16(a0, a1))
3729 }
3730 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
3731 #[inline(always)]
3732 fn all_true_mask8x32(self, a: mask8x32<Self>) -> bool {
3733 let (a0, a1) = self.split_mask8x32(a);
3734 self.all_true_mask8x16(self.and_mask8x16(a0, a1))
3735 }
3736 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
3737 #[inline(always)]
3738 fn any_false_mask8x32(self, a: mask8x32<Self>) -> bool {
3739 let (a0, a1) = self.split_mask8x32(a);
3740 self.any_false_mask8x16(self.and_mask8x16(a0, a1))
3741 }
3742 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
3743 #[inline(always)]
3744 fn all_false_mask8x32(self, a: mask8x32<Self>) -> bool {
3745 let (a0, a1) = self.split_mask8x32(a);
3746 self.all_false_mask8x16(self.or_mask8x16(a0, a1))
3747 }
3748 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
3749 fn combine_mask8x32(self, a: mask8x32<Self>, b: mask8x32<Self>) -> mask8x64<Self>;
3750 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
3751 fn split_mask8x32(self, a: mask8x32<Self>) -> (mask8x16<Self>, mask8x16<Self>);
3752 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
3753 #[inline(always)]
3754 fn widen_mask8x32(self, a: mask8x32<Self>) -> (mask16x16<Self>, mask16x16<Self>) {
3755 let (a0, a1) = self.split_mask8x32(a);
3756 let (a00, a01) = self.widen_mask8x16(a0);
3757 let (a10, a11) = self.widen_mask8x16(a1);
3758 (
3759 self.combine_mask16x8(a00, a01),
3760 self.combine_mask16x8(a10, a11),
3761 )
3762 }
3763 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
3764 #[inline(always)]
3765 fn abs_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
3766 let (a0, a1) = self.split_i16x16(a);
3767 self.combine_i16x8(self.abs_i16x8(a0), self.abs_i16x8(a1))
3768 }
3769 #[doc = "Create a SIMD vector with all elements set to the given value."]
3770 #[inline(always)]
3771 fn splat_i16x16(self, val: i16) -> i16x16<Self> {
3772 let half = self.splat_i16x8(val);
3773 self.combine_i16x8(half, half)
3774 }
3775 #[doc = "Reverse the order of the vector's elements."]
3776 #[inline(always)]
3777 fn reverse_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
3778 let (a0, a1) = self.split_i16x16(a);
3779 self.combine_i16x8(self.reverse_i16x8(a1), self.reverse_i16x8(a0))
3780 }
3781 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
3782 fn slide_i16x16<const SHIFT: usize>(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self>;
3783 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
3784 #[inline(always)]
3785 fn slide_within_blocks_i16x16<const SHIFT: usize>(
3786 self,
3787 a: i16x16<Self>,
3788 b: i16x16<Self>,
3789 ) -> i16x16<Self> {
3790 let (a0, a1) = self.split_i16x16(a);
3791 let (b0, b1) = self.split_i16x16(b);
3792 self.combine_i16x8(
3793 self.slide_within_blocks_i16x8::<SHIFT>(a0, b0),
3794 self.slide_within_blocks_i16x8::<SHIFT>(a1, b1),
3795 )
3796 }
3797 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
3798 #[inline(always)]
3799 fn swizzle_dyn_within_blocks_i16x16(
3800 self,
3801 a: i16x16<Self>,
3802 indices: u8x32<Self>,
3803 ) -> i16x16<Self> {
3804 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
3805 }
3806 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
3807 #[inline(always)]
3808 fn swizzle_dyn_i16x16(self, a: i16x16<Self>, indices: u8x32<Self>) -> i16x16<Self> {
3809 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
3810 }
3811 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
3812 #[inline(always)]
3813 fn swizzle_dyn_precise_i16x16(self, a: i16x16<Self>, indices: u8x32<Self>) -> i16x16<Self> {
3814 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
3815 }
3816 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
3817 #[inline(always)]
3818 fn concat_swizzle_dyn_i16x16(
3819 self,
3820 a: i16x16<Self>,
3821 b: i16x16<Self>,
3822 indices: u8x32<Self>,
3823 ) -> i16x16<Self> {
3824 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
3825 Bytes::to_bytes(a),
3826 Bytes::to_bytes(b),
3827 indices,
3828 ))
3829 }
3830 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
3831 #[inline(always)]
3832 fn concat_swizzle_dyn_precise_i16x16(
3833 self,
3834 a: i16x16<Self>,
3835 b: i16x16<Self>,
3836 indices: u8x32<Self>,
3837 ) -> i16x16<Self> {
3838 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
3839 Bytes::to_bytes(a),
3840 Bytes::to_bytes(b),
3841 indices,
3842 ))
3843 }
3844 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
3845 fn compress_i16x16(self, values: i16x16<Self>, mask: mask16x16<Self>) -> i16x16<Self>;
3846 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
3847 fn compress_merge_i16x16(
3848 self,
3849 values: i16x16<Self>,
3850 mask: mask16x16<Self>,
3851 merge: i16x16<Self>,
3852 ) -> i16x16<Self>;
3853 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
3854 fn expand_i16x16(self, values: i16x16<Self>, mask: mask16x16<Self>) -> i16x16<Self>;
3855 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
3856 fn expand_merge_i16x16(
3857 self,
3858 values: i16x16<Self>,
3859 mask: mask16x16<Self>,
3860 merge: i16x16<Self>,
3861 ) -> i16x16<Self>;
3862 #[doc = "Return the number of ones in the binary representation of each element."]
3863 #[inline(always)]
3864 fn count_ones_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
3865 let (a0, a1) = self.split_i16x16(a);
3866 self.combine_i16x8(self.count_ones_i16x8(a0), self.count_ones_i16x8(a1))
3867 }
3868 #[doc = "Return the number of zeros in the binary representation of each element."]
3869 #[inline(always)]
3870 fn count_zeros_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
3871 let (a0, a1) = self.split_i16x16(a);
3872 self.combine_i16x8(self.count_zeros_i16x8(a0), self.count_zeros_i16x8(a1))
3873 }
3874 #[doc = "Add two vectors element-wise, wrapping on overflow."]
3875 #[inline(always)]
3876 fn add_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3877 let (a0, a1) = self.split_i16x16(a);
3878 let (b0, b1) = self.split_i16x16(b);
3879 self.combine_i16x8(self.add_i16x8(a0, b0), self.add_i16x8(a1, b1))
3880 }
3881 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
3882 #[inline(always)]
3883 fn saturating_add_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3884 let (a0, a1) = self.split_i16x16(a);
3885 let (b0, b1) = self.split_i16x16(b);
3886 self.combine_i16x8(
3887 self.saturating_add_i16x8(a0, b0),
3888 self.saturating_add_i16x8(a1, b1),
3889 )
3890 }
3891 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
3892 #[inline(always)]
3893 fn sub_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3894 let (a0, a1) = self.split_i16x16(a);
3895 let (b0, b1) = self.split_i16x16(b);
3896 self.combine_i16x8(self.sub_i16x8(a0, b0), self.sub_i16x8(a1, b1))
3897 }
3898 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
3899 #[inline(always)]
3900 fn saturating_sub_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3901 let (a0, a1) = self.split_i16x16(a);
3902 let (b0, b1) = self.split_i16x16(b);
3903 self.combine_i16x8(
3904 self.saturating_sub_i16x8(a0, b0),
3905 self.saturating_sub_i16x8(a1, b1),
3906 )
3907 }
3908 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
3909 #[inline(always)]
3910 fn mul_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3911 let (a0, a1) = self.split_i16x16(a);
3912 let (b0, b1) = self.split_i16x16(b);
3913 self.combine_i16x8(self.mul_i16x8(a0, b0), self.mul_i16x8(a1, b1))
3914 }
3915 #[doc = "Compute the bitwise AND of two vectors."]
3916 #[inline(always)]
3917 fn and_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3918 let (a0, a1) = self.split_i16x16(a);
3919 let (b0, b1) = self.split_i16x16(b);
3920 self.combine_i16x8(self.and_i16x8(a0, b0), self.and_i16x8(a1, b1))
3921 }
3922 #[doc = "Compute the bitwise OR of two vectors."]
3923 #[inline(always)]
3924 fn or_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3925 let (a0, a1) = self.split_i16x16(a);
3926 let (b0, b1) = self.split_i16x16(b);
3927 self.combine_i16x8(self.or_i16x8(a0, b0), self.or_i16x8(a1, b1))
3928 }
3929 #[doc = "Compute the bitwise XOR of two vectors."]
3930 #[inline(always)]
3931 fn xor_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3932 let (a0, a1) = self.split_i16x16(a);
3933 let (b0, b1) = self.split_i16x16(b);
3934 self.combine_i16x8(self.xor_i16x8(a0, b0), self.xor_i16x8(a1, b1))
3935 }
3936 #[doc = "Compute the bitwise NOT of the vector."]
3937 #[inline(always)]
3938 fn not_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
3939 let (a0, a1) = self.split_i16x16(a);
3940 self.combine_i16x8(self.not_i16x8(a0), self.not_i16x8(a1))
3941 }
3942 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3943 #[inline(always)]
3944 fn shl_i16x16(self, a: i16x16<Self>, shift: u32) -> i16x16<Self> {
3945 let (a0, a1) = self.split_i16x16(a);
3946 self.combine_i16x8(self.shl_i16x8(a0, shift), self.shl_i16x8(a1, shift))
3947 }
3948 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3949 #[inline(always)]
3950 fn shlv_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3951 let (a0, a1) = self.split_i16x16(a);
3952 let (b0, b1) = self.split_i16x16(b);
3953 self.combine_i16x8(self.shlv_i16x8(a0, b0), self.shlv_i16x8(a1, b1))
3954 }
3955 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
3956 #[inline(always)]
3957 fn shr_i16x16(self, a: i16x16<Self>, shift: u32) -> i16x16<Self> {
3958 let (a0, a1) = self.split_i16x16(a);
3959 self.combine_i16x8(self.shr_i16x8(a0, shift), self.shr_i16x8(a1, shift))
3960 }
3961 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
3962 #[inline(always)]
3963 fn shrv_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3964 let (a0, a1) = self.split_i16x16(a);
3965 let (b0, b1) = self.split_i16x16(b);
3966 self.combine_i16x8(self.shrv_i16x8(a0, b0), self.shrv_i16x8(a1, b1))
3967 }
3968 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3969 #[inline(always)]
3970 fn reduce_max_i16x16(self, a: i16x16<Self>) -> i16 {
3971 let (a0, a1) = self.split_i16x16(a);
3972 self.reduce_max_i16x8(self.max_i16x8(a0, a1))
3973 }
3974 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
3975 #[inline(always)]
3976 fn reduce_min_i16x16(self, a: i16x16<Self>) -> i16 {
3977 let (a0, a1) = self.split_i16x16(a);
3978 self.reduce_min_i16x8(self.min_i16x8(a0, a1))
3979 }
3980 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
3981 #[inline(always)]
3982 fn reduce_sum_i16x16(self, a: i16x16<Self>) -> i16 {
3983 let (a0, a1) = self.split_i16x16(a);
3984 self.reduce_sum_i16x8(self.add_i16x8(a0, a1))
3985 }
3986 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
3987 #[inline(always)]
3988 fn reduce_product_i16x16(self, a: i16x16<Self>) -> i16 {
3989 let (a0, a1) = self.split_i16x16(a);
3990 self.reduce_product_i16x8(self.mul_i16x8(a0, a1))
3991 }
3992 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
3993 #[inline(always)]
3994 fn max_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
3995 let (a0, a1) = self.split_i16x16(a);
3996 let (b0, b1) = self.split_i16x16(b);
3997 self.combine_i16x8(self.max_i16x8(a0, b0), self.max_i16x8(a1, b1))
3998 }
3999 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
4000 #[inline(always)]
4001 fn min_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
4002 let (a0, a1) = self.split_i16x16(a);
4003 let (b0, b1) = self.split_i16x16(b);
4004 self.combine_i16x8(self.min_i16x8(a0, b0), self.min_i16x8(a1, b1))
4005 }
4006 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
4007 #[inline(always)]
4008 fn clamp_i16x16(self, a: i16x16<Self>, b: i16x16<Self>, c: i16x16<Self>) -> i16x16<Self> {
4009 let (a0, a1) = self.split_i16x16(a);
4010 let (b0, b1) = self.split_i16x16(b);
4011 let (c0, c1) = self.split_i16x16(c);
4012 self.combine_i16x8(self.clamp_i16x8(a0, b0, c0), self.clamp_i16x8(a1, b1, c1))
4013 }
4014 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
4015 #[inline(always)]
4016 fn simd_eq_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4017 let (a0, a1) = self.split_i16x16(a);
4018 let (b0, b1) = self.split_i16x16(b);
4019 self.combine_mask16x8(self.simd_eq_i16x8(a0, b0), self.simd_eq_i16x8(a1, b1))
4020 }
4021 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
4022 #[inline(always)]
4023 fn simd_ne_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4024 self.not_mask16x16(self.simd_eq_i16x16(a, b))
4025 }
4026 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
4027 #[inline(always)]
4028 fn simd_lt_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4029 let (a0, a1) = self.split_i16x16(a);
4030 let (b0, b1) = self.split_i16x16(b);
4031 self.combine_mask16x8(self.simd_lt_i16x8(a0, b0), self.simd_lt_i16x8(a1, b1))
4032 }
4033 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
4034 #[inline(always)]
4035 fn simd_le_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4036 let (a0, a1) = self.split_i16x16(a);
4037 let (b0, b1) = self.split_i16x16(b);
4038 self.combine_mask16x8(self.simd_le_i16x8(a0, b0), self.simd_le_i16x8(a1, b1))
4039 }
4040 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
4041 #[inline(always)]
4042 fn simd_ge_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4043 self.simd_le_i16x16(b, a)
4044 }
4045 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
4046 #[inline(always)]
4047 fn simd_gt_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> mask16x16<Self> {
4048 self.simd_lt_i16x16(b, a)
4049 }
4050 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
4051 #[inline(always)]
4052 fn zip_low_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
4053 let (a0, _) = self.split_i16x16(a);
4054 let (b0, _) = self.split_i16x16(b);
4055 self.combine_i16x8(self.zip_low_i16x8(a0, b0), self.zip_high_i16x8(a0, b0))
4056 }
4057 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
4058 #[inline(always)]
4059 fn zip_high_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
4060 let (_, a1) = self.split_i16x16(a);
4061 let (_, b1) = self.split_i16x16(b);
4062 self.combine_i16x8(self.zip_low_i16x8(a1, b1), self.zip_high_i16x8(a1, b1))
4063 }
4064 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
4065 #[inline(always)]
4066 fn unzip_low_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
4067 let (a0, a1) = self.split_i16x16(a);
4068 let (b0, b1) = self.split_i16x16(b);
4069 self.combine_i16x8(self.unzip_low_i16x8(a0, a1), self.unzip_low_i16x8(b0, b1))
4070 }
4071 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
4072 #[inline(always)]
4073 fn unzip_high_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x16<Self> {
4074 let (a0, a1) = self.split_i16x16(a);
4075 let (b0, b1) = self.split_i16x16(b);
4076 self.combine_i16x8(self.unzip_high_i16x8(a0, a1), self.unzip_high_i16x8(b0, b1))
4077 }
4078 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
4079 #[inline(always)]
4080 fn interleave_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> (i16x16<Self>, i16x16<Self>) {
4081 let (a0, a1) = self.split_i16x16(a);
4082 let (b0, b1) = self.split_i16x16(b);
4083 let lo_lo = self.zip_low_i16x8(a0, b0);
4084 let lo_hi = self.zip_high_i16x8(a0, b0);
4085 let hi_lo = self.zip_low_i16x8(a1, b1);
4086 let hi_hi = self.zip_high_i16x8(a1, b1);
4087 (
4088 self.combine_i16x8(lo_lo, lo_hi),
4089 self.combine_i16x8(hi_lo, hi_hi),
4090 )
4091 }
4092 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
4093 #[inline(always)]
4094 fn deinterleave_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> (i16x16<Self>, i16x16<Self>) {
4095 let (a0, a1) = self.split_i16x16(a);
4096 let (b0, b1) = self.split_i16x16(b);
4097 let lo_even = self.unzip_low_i16x8(a0, a1);
4098 let lo_odd = self.unzip_high_i16x8(a0, a1);
4099 let hi_even = self.unzip_low_i16x8(b0, b1);
4100 let hi_odd = self.unzip_high_i16x8(b0, b1);
4101 (
4102 self.combine_i16x8(lo_even, hi_even),
4103 self.combine_i16x8(lo_odd, hi_odd),
4104 )
4105 }
4106 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
4107 #[inline(always)]
4108 fn select_i16x16(self, a: mask16x16<Self>, b: i16x16<Self>, c: i16x16<Self>) -> i16x16<Self> {
4109 let (a0, a1) = self.split_mask16x16(a);
4110 let (b0, b1) = self.split_i16x16(b);
4111 let (c0, c1) = self.split_i16x16(c);
4112 self.combine_i16x8(self.select_i16x8(a0, b0, c0), self.select_i16x8(a1, b1, c1))
4113 }
4114 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
4115 fn combine_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i16x32<Self>;
4116 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
4117 fn split_i16x16(self, a: i16x16<Self>) -> (i16x8<Self>, i16x8<Self>);
4118 #[doc = "Negate each element of the vector, wrapping on overflow."]
4119 #[inline(always)]
4120 fn neg_i16x16(self, a: i16x16<Self>) -> i16x16<Self> {
4121 let (a0, a1) = self.split_i16x16(a);
4122 self.combine_i16x8(self.neg_i16x8(a0), self.neg_i16x8(a1))
4123 }
4124 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
4125 #[inline(always)]
4126 fn widen_i16x16(self, a: i16x16<Self>) -> (i32x8<Self>, i32x8<Self>) {
4127 let (a0, a1) = self.split_i16x16(a);
4128 let (a00, a01) = self.widen_i16x8(a0);
4129 let (a10, a11) = self.widen_i16x8(a1);
4130 (self.combine_i32x4(a00, a01), self.combine_i32x4(a10, a11))
4131 }
4132 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
4133 #[inline(always)]
4134 fn widening_mul_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> (i32x8<Self>, i32x8<Self>) {
4135 let (a0, a1) = self.split_i16x16(a);
4136 let (b0, b1) = self.split_i16x16(b);
4137 let (low0, low1) = self.widening_mul_i16x8(a0, b0);
4138 let (high0, high1) = self.widening_mul_i16x8(a1, b1);
4139 (
4140 self.combine_i32x4(low0, low1),
4141 self.combine_i32x4(high0, high1),
4142 )
4143 }
4144 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
4145 #[inline(always)]
4146 fn widening_add_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> (i32x8<Self>, i32x8<Self>) {
4147 let (a0, a1) = self.split_i16x16(a);
4148 let (b0, b1) = self.split_i16x16(b);
4149 let (low0, low1) = self.widening_add_i16x8(a0, b0);
4150 let (high0, high1) = self.widening_add_i16x8(a1, b1);
4151 (
4152 self.combine_i32x4(low0, low1),
4153 self.combine_i32x4(high0, high1),
4154 )
4155 }
4156 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
4157 #[inline(always)]
4158 fn pairwise_widening_add_i16x16(self, a: i16x16<Self>) -> i32x8<Self> {
4159 let (a0, a1) = self.split_i16x16(a);
4160 self.combine_i32x4(
4161 self.pairwise_widening_add_i16x8(a0),
4162 self.pairwise_widening_add_i16x8(a1),
4163 )
4164 }
4165 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
4166 #[inline(always)]
4167 fn pairwise_dot_product_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i32x8<Self> {
4168 let (a0, a1) = self.split_i16x16(a);
4169 let (b0, b1) = self.split_i16x16(b);
4170 self.combine_i32x4(
4171 self.pairwise_dot_product_i16x8(a0, b0),
4172 self.pairwise_dot_product_i16x8(a1, b1),
4173 )
4174 }
4175 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
4176 #[inline(always)]
4177 fn narrow_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i8x32<Self> {
4178 let (a0, a1) = self.split_i16x16(a);
4179 let (b0, b1) = self.split_i16x16(b);
4180 self.combine_i8x16(self.narrow_i16x8(a0, a1), self.narrow_i16x8(b0, b1))
4181 }
4182 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
4183 #[inline(always)]
4184 fn saturating_narrow_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i8x32<Self> {
4185 let (a0, a1) = self.split_i16x16(a);
4186 let (b0, b1) = self.split_i16x16(b);
4187 self.combine_i8x16(
4188 self.saturating_narrow_i16x8(a0, a1),
4189 self.saturating_narrow_i16x8(b0, b1),
4190 )
4191 }
4192 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
4193 #[inline(always)]
4194 fn relaxed_narrow_i16x16(self, a: i16x16<Self>, b: i16x16<Self>) -> i8x32<Self> {
4195 let (a0, a1) = self.split_i16x16(a);
4196 let (b0, b1) = self.split_i16x16(b);
4197 self.combine_i8x16(
4198 self.relaxed_narrow_i16x8(a0, a1),
4199 self.relaxed_narrow_i16x8(b0, b1),
4200 )
4201 }
4202 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
4203 #[inline(always)]
4204 fn abs_u16x16(self, a: u16x16<Self>) -> u16x16<Self> {
4205 a
4206 }
4207 #[doc = "Create a SIMD vector with all elements set to the given value."]
4208 #[inline(always)]
4209 fn splat_u16x16(self, val: u16) -> u16x16<Self> {
4210 let half = self.splat_u16x8(val);
4211 self.combine_u16x8(half, half)
4212 }
4213 #[doc = "Reverse the order of the vector's elements."]
4214 #[inline(always)]
4215 fn reverse_u16x16(self, a: u16x16<Self>) -> u16x16<Self> {
4216 let (a0, a1) = self.split_u16x16(a);
4217 self.combine_u16x8(self.reverse_u16x8(a1), self.reverse_u16x8(a0))
4218 }
4219 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
4220 fn slide_u16x16<const SHIFT: usize>(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self>;
4221 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
4222 #[inline(always)]
4223 fn slide_within_blocks_u16x16<const SHIFT: usize>(
4224 self,
4225 a: u16x16<Self>,
4226 b: u16x16<Self>,
4227 ) -> u16x16<Self> {
4228 let (a0, a1) = self.split_u16x16(a);
4229 let (b0, b1) = self.split_u16x16(b);
4230 self.combine_u16x8(
4231 self.slide_within_blocks_u16x8::<SHIFT>(a0, b0),
4232 self.slide_within_blocks_u16x8::<SHIFT>(a1, b1),
4233 )
4234 }
4235 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
4236 #[inline(always)]
4237 fn swizzle_dyn_within_blocks_u16x16(
4238 self,
4239 a: u16x16<Self>,
4240 indices: u8x32<Self>,
4241 ) -> u16x16<Self> {
4242 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
4243 }
4244 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
4245 #[inline(always)]
4246 fn swizzle_dyn_u16x16(self, a: u16x16<Self>, indices: u8x32<Self>) -> u16x16<Self> {
4247 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
4248 }
4249 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
4250 #[inline(always)]
4251 fn swizzle_dyn_precise_u16x16(self, a: u16x16<Self>, indices: u8x32<Self>) -> u16x16<Self> {
4252 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
4253 }
4254 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
4255 #[inline(always)]
4256 fn concat_swizzle_dyn_u16x16(
4257 self,
4258 a: u16x16<Self>,
4259 b: u16x16<Self>,
4260 indices: u8x32<Self>,
4261 ) -> u16x16<Self> {
4262 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
4263 Bytes::to_bytes(a),
4264 Bytes::to_bytes(b),
4265 indices,
4266 ))
4267 }
4268 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
4269 #[inline(always)]
4270 fn concat_swizzle_dyn_precise_u16x16(
4271 self,
4272 a: u16x16<Self>,
4273 b: u16x16<Self>,
4274 indices: u8x32<Self>,
4275 ) -> u16x16<Self> {
4276 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
4277 Bytes::to_bytes(a),
4278 Bytes::to_bytes(b),
4279 indices,
4280 ))
4281 }
4282 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
4283 fn compress_u16x16(self, values: u16x16<Self>, mask: mask16x16<Self>) -> u16x16<Self>;
4284 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
4285 fn compress_merge_u16x16(
4286 self,
4287 values: u16x16<Self>,
4288 mask: mask16x16<Self>,
4289 merge: u16x16<Self>,
4290 ) -> u16x16<Self>;
4291 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
4292 fn expand_u16x16(self, values: u16x16<Self>, mask: mask16x16<Self>) -> u16x16<Self>;
4293 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
4294 fn expand_merge_u16x16(
4295 self,
4296 values: u16x16<Self>,
4297 mask: mask16x16<Self>,
4298 merge: u16x16<Self>,
4299 ) -> u16x16<Self>;
4300 #[doc = "Return the number of ones in the binary representation of each element."]
4301 #[inline(always)]
4302 fn count_ones_u16x16(self, a: u16x16<Self>) -> u16x16<Self> {
4303 let (a0, a1) = self.split_u16x16(a);
4304 self.combine_u16x8(self.count_ones_u16x8(a0), self.count_ones_u16x8(a1))
4305 }
4306 #[doc = "Return the number of zeros in the binary representation of each element."]
4307 #[inline(always)]
4308 fn count_zeros_u16x16(self, a: u16x16<Self>) -> u16x16<Self> {
4309 let (a0, a1) = self.split_u16x16(a);
4310 self.combine_u16x8(self.count_zeros_u16x8(a0), self.count_zeros_u16x8(a1))
4311 }
4312 #[doc = "Add two vectors element-wise, wrapping on overflow."]
4313 #[inline(always)]
4314 fn add_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4315 let (a0, a1) = self.split_u16x16(a);
4316 let (b0, b1) = self.split_u16x16(b);
4317 self.combine_u16x8(self.add_u16x8(a0, b0), self.add_u16x8(a1, b1))
4318 }
4319 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
4320 #[inline(always)]
4321 fn saturating_add_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4322 let (a0, a1) = self.split_u16x16(a);
4323 let (b0, b1) = self.split_u16x16(b);
4324 self.combine_u16x8(
4325 self.saturating_add_u16x8(a0, b0),
4326 self.saturating_add_u16x8(a1, b1),
4327 )
4328 }
4329 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
4330 #[inline(always)]
4331 fn sub_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4332 let (a0, a1) = self.split_u16x16(a);
4333 let (b0, b1) = self.split_u16x16(b);
4334 self.combine_u16x8(self.sub_u16x8(a0, b0), self.sub_u16x8(a1, b1))
4335 }
4336 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
4337 #[inline(always)]
4338 fn saturating_sub_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4339 let (a0, a1) = self.split_u16x16(a);
4340 let (b0, b1) = self.split_u16x16(b);
4341 self.combine_u16x8(
4342 self.saturating_sub_u16x8(a0, b0),
4343 self.saturating_sub_u16x8(a1, b1),
4344 )
4345 }
4346 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
4347 #[inline(always)]
4348 fn mul_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4349 let (a0, a1) = self.split_u16x16(a);
4350 let (b0, b1) = self.split_u16x16(b);
4351 self.combine_u16x8(self.mul_u16x8(a0, b0), self.mul_u16x8(a1, b1))
4352 }
4353 #[doc = "Compute the bitwise AND of two vectors."]
4354 #[inline(always)]
4355 fn and_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4356 let (a0, a1) = self.split_u16x16(a);
4357 let (b0, b1) = self.split_u16x16(b);
4358 self.combine_u16x8(self.and_u16x8(a0, b0), self.and_u16x8(a1, b1))
4359 }
4360 #[doc = "Compute the bitwise OR of two vectors."]
4361 #[inline(always)]
4362 fn or_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4363 let (a0, a1) = self.split_u16x16(a);
4364 let (b0, b1) = self.split_u16x16(b);
4365 self.combine_u16x8(self.or_u16x8(a0, b0), self.or_u16x8(a1, b1))
4366 }
4367 #[doc = "Compute the bitwise XOR of two vectors."]
4368 #[inline(always)]
4369 fn xor_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4370 let (a0, a1) = self.split_u16x16(a);
4371 let (b0, b1) = self.split_u16x16(b);
4372 self.combine_u16x8(self.xor_u16x8(a0, b0), self.xor_u16x8(a1, b1))
4373 }
4374 #[doc = "Compute the bitwise NOT of the vector."]
4375 #[inline(always)]
4376 fn not_u16x16(self, a: u16x16<Self>) -> u16x16<Self> {
4377 let (a0, a1) = self.split_u16x16(a);
4378 self.combine_u16x8(self.not_u16x8(a0), self.not_u16x8(a1))
4379 }
4380 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
4381 #[inline(always)]
4382 fn shl_u16x16(self, a: u16x16<Self>, shift: u32) -> u16x16<Self> {
4383 let (a0, a1) = self.split_u16x16(a);
4384 self.combine_u16x8(self.shl_u16x8(a0, shift), self.shl_u16x8(a1, shift))
4385 }
4386 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
4387 #[inline(always)]
4388 fn shlv_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4389 let (a0, a1) = self.split_u16x16(a);
4390 let (b0, b1) = self.split_u16x16(b);
4391 self.combine_u16x8(self.shlv_u16x8(a0, b0), self.shlv_u16x8(a1, b1))
4392 }
4393 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
4394 #[inline(always)]
4395 fn shr_u16x16(self, a: u16x16<Self>, shift: u32) -> u16x16<Self> {
4396 let (a0, a1) = self.split_u16x16(a);
4397 self.combine_u16x8(self.shr_u16x8(a0, shift), self.shr_u16x8(a1, shift))
4398 }
4399 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
4400 #[inline(always)]
4401 fn shrv_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4402 let (a0, a1) = self.split_u16x16(a);
4403 let (b0, b1) = self.split_u16x16(b);
4404 self.combine_u16x8(self.shrv_u16x8(a0, b0), self.shrv_u16x8(a1, b1))
4405 }
4406 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
4407 #[inline(always)]
4408 fn reduce_max_u16x16(self, a: u16x16<Self>) -> u16 {
4409 let (a0, a1) = self.split_u16x16(a);
4410 self.reduce_max_u16x8(self.max_u16x8(a0, a1))
4411 }
4412 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
4413 #[inline(always)]
4414 fn reduce_min_u16x16(self, a: u16x16<Self>) -> u16 {
4415 let (a0, a1) = self.split_u16x16(a);
4416 self.reduce_min_u16x8(self.min_u16x8(a0, a1))
4417 }
4418 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
4419 #[inline(always)]
4420 fn reduce_sum_u16x16(self, a: u16x16<Self>) -> u16 {
4421 let (a0, a1) = self.split_u16x16(a);
4422 self.reduce_sum_u16x8(self.add_u16x8(a0, a1))
4423 }
4424 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
4425 #[inline(always)]
4426 fn reduce_product_u16x16(self, a: u16x16<Self>) -> u16 {
4427 let (a0, a1) = self.split_u16x16(a);
4428 self.reduce_product_u16x8(self.mul_u16x8(a0, a1))
4429 }
4430 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
4431 #[inline(always)]
4432 fn max_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4433 let (a0, a1) = self.split_u16x16(a);
4434 let (b0, b1) = self.split_u16x16(b);
4435 self.combine_u16x8(self.max_u16x8(a0, b0), self.max_u16x8(a1, b1))
4436 }
4437 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
4438 #[inline(always)]
4439 fn min_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4440 let (a0, a1) = self.split_u16x16(a);
4441 let (b0, b1) = self.split_u16x16(b);
4442 self.combine_u16x8(self.min_u16x8(a0, b0), self.min_u16x8(a1, b1))
4443 }
4444 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
4445 #[inline(always)]
4446 fn clamp_u16x16(self, a: u16x16<Self>, b: u16x16<Self>, c: u16x16<Self>) -> u16x16<Self> {
4447 let (a0, a1) = self.split_u16x16(a);
4448 let (b0, b1) = self.split_u16x16(b);
4449 let (c0, c1) = self.split_u16x16(c);
4450 self.combine_u16x8(self.clamp_u16x8(a0, b0, c0), self.clamp_u16x8(a1, b1, c1))
4451 }
4452 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
4453 #[inline(always)]
4454 fn simd_eq_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4455 let (a0, a1) = self.split_u16x16(a);
4456 let (b0, b1) = self.split_u16x16(b);
4457 self.combine_mask16x8(self.simd_eq_u16x8(a0, b0), self.simd_eq_u16x8(a1, b1))
4458 }
4459 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
4460 #[inline(always)]
4461 fn simd_ne_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4462 self.not_mask16x16(self.simd_eq_u16x16(a, b))
4463 }
4464 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
4465 #[inline(always)]
4466 fn simd_lt_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4467 let (a0, a1) = self.split_u16x16(a);
4468 let (b0, b1) = self.split_u16x16(b);
4469 self.combine_mask16x8(self.simd_lt_u16x8(a0, b0), self.simd_lt_u16x8(a1, b1))
4470 }
4471 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
4472 #[inline(always)]
4473 fn simd_le_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4474 let (a0, a1) = self.split_u16x16(a);
4475 let (b0, b1) = self.split_u16x16(b);
4476 self.combine_mask16x8(self.simd_le_u16x8(a0, b0), self.simd_le_u16x8(a1, b1))
4477 }
4478 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
4479 #[inline(always)]
4480 fn simd_ge_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4481 self.simd_le_u16x16(b, a)
4482 }
4483 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
4484 #[inline(always)]
4485 fn simd_gt_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> mask16x16<Self> {
4486 self.simd_lt_u16x16(b, a)
4487 }
4488 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
4489 #[inline(always)]
4490 fn zip_low_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4491 let (a0, _) = self.split_u16x16(a);
4492 let (b0, _) = self.split_u16x16(b);
4493 self.combine_u16x8(self.zip_low_u16x8(a0, b0), self.zip_high_u16x8(a0, b0))
4494 }
4495 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
4496 #[inline(always)]
4497 fn zip_high_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4498 let (_, a1) = self.split_u16x16(a);
4499 let (_, b1) = self.split_u16x16(b);
4500 self.combine_u16x8(self.zip_low_u16x8(a1, b1), self.zip_high_u16x8(a1, b1))
4501 }
4502 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
4503 #[inline(always)]
4504 fn unzip_low_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4505 let (a0, a1) = self.split_u16x16(a);
4506 let (b0, b1) = self.split_u16x16(b);
4507 self.combine_u16x8(self.unzip_low_u16x8(a0, a1), self.unzip_low_u16x8(b0, b1))
4508 }
4509 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
4510 #[inline(always)]
4511 fn unzip_high_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x16<Self> {
4512 let (a0, a1) = self.split_u16x16(a);
4513 let (b0, b1) = self.split_u16x16(b);
4514 self.combine_u16x8(self.unzip_high_u16x8(a0, a1), self.unzip_high_u16x8(b0, b1))
4515 }
4516 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
4517 #[inline(always)]
4518 fn interleave_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> (u16x16<Self>, u16x16<Self>) {
4519 let (a0, a1) = self.split_u16x16(a);
4520 let (b0, b1) = self.split_u16x16(b);
4521 let lo_lo = self.zip_low_u16x8(a0, b0);
4522 let lo_hi = self.zip_high_u16x8(a0, b0);
4523 let hi_lo = self.zip_low_u16x8(a1, b1);
4524 let hi_hi = self.zip_high_u16x8(a1, b1);
4525 (
4526 self.combine_u16x8(lo_lo, lo_hi),
4527 self.combine_u16x8(hi_lo, hi_hi),
4528 )
4529 }
4530 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
4531 #[inline(always)]
4532 fn deinterleave_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> (u16x16<Self>, u16x16<Self>) {
4533 let (a0, a1) = self.split_u16x16(a);
4534 let (b0, b1) = self.split_u16x16(b);
4535 let lo_even = self.unzip_low_u16x8(a0, a1);
4536 let lo_odd = self.unzip_high_u16x8(a0, a1);
4537 let hi_even = self.unzip_low_u16x8(b0, b1);
4538 let hi_odd = self.unzip_high_u16x8(b0, b1);
4539 (
4540 self.combine_u16x8(lo_even, hi_even),
4541 self.combine_u16x8(lo_odd, hi_odd),
4542 )
4543 }
4544 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
4545 #[inline(always)]
4546 fn select_u16x16(self, a: mask16x16<Self>, b: u16x16<Self>, c: u16x16<Self>) -> u16x16<Self> {
4547 let (a0, a1) = self.split_mask16x16(a);
4548 let (b0, b1) = self.split_u16x16(b);
4549 let (c0, c1) = self.split_u16x16(c);
4550 self.combine_u16x8(self.select_u16x8(a0, b0, c0), self.select_u16x8(a1, b1, c1))
4551 }
4552 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
4553 fn combine_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u16x32<Self>;
4554 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
4555 fn split_u16x16(self, a: u16x16<Self>) -> (u16x8<Self>, u16x8<Self>);
4556 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
4557 #[inline(always)]
4558 fn widen_u16x16(self, a: u16x16<Self>) -> (u32x8<Self>, u32x8<Self>) {
4559 let (a0, a1) = self.split_u16x16(a);
4560 let (a00, a01) = self.widen_u16x8(a0);
4561 let (a10, a11) = self.widen_u16x8(a1);
4562 (self.combine_u32x4(a00, a01), self.combine_u32x4(a10, a11))
4563 }
4564 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
4565 #[inline(always)]
4566 fn widening_mul_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> (u32x8<Self>, u32x8<Self>) {
4567 let (a0, a1) = self.split_u16x16(a);
4568 let (b0, b1) = self.split_u16x16(b);
4569 let (low0, low1) = self.widening_mul_u16x8(a0, b0);
4570 let (high0, high1) = self.widening_mul_u16x8(a1, b1);
4571 (
4572 self.combine_u32x4(low0, low1),
4573 self.combine_u32x4(high0, high1),
4574 )
4575 }
4576 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
4577 #[inline(always)]
4578 fn widening_add_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> (u32x8<Self>, u32x8<Self>) {
4579 let (a0, a1) = self.split_u16x16(a);
4580 let (b0, b1) = self.split_u16x16(b);
4581 let (low0, low1) = self.widening_add_u16x8(a0, b0);
4582 let (high0, high1) = self.widening_add_u16x8(a1, b1);
4583 (
4584 self.combine_u32x4(low0, low1),
4585 self.combine_u32x4(high0, high1),
4586 )
4587 }
4588 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
4589 #[inline(always)]
4590 fn pairwise_widening_add_u16x16(self, a: u16x16<Self>) -> u32x8<Self> {
4591 let (a0, a1) = self.split_u16x16(a);
4592 self.combine_u32x4(
4593 self.pairwise_widening_add_u16x8(a0),
4594 self.pairwise_widening_add_u16x8(a1),
4595 )
4596 }
4597 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
4598 #[inline(always)]
4599 fn pairwise_dot_product_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u32x8<Self> {
4600 let (a0, a1) = self.split_u16x16(a);
4601 let (b0, b1) = self.split_u16x16(b);
4602 self.combine_u32x4(
4603 self.pairwise_dot_product_u16x8(a0, b0),
4604 self.pairwise_dot_product_u16x8(a1, b1),
4605 )
4606 }
4607 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
4608 #[inline(always)]
4609 fn narrow_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u8x32<Self> {
4610 let (a0, a1) = self.split_u16x16(a);
4611 let (b0, b1) = self.split_u16x16(b);
4612 self.combine_u8x16(self.narrow_u16x8(a0, a1), self.narrow_u16x8(b0, b1))
4613 }
4614 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
4615 #[inline(always)]
4616 fn saturating_narrow_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u8x32<Self> {
4617 let (a0, a1) = self.split_u16x16(a);
4618 let (b0, b1) = self.split_u16x16(b);
4619 self.combine_u8x16(
4620 self.saturating_narrow_u16x8(a0, a1),
4621 self.saturating_narrow_u16x8(b0, b1),
4622 )
4623 }
4624 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
4625 #[inline(always)]
4626 fn relaxed_narrow_u16x16(self, a: u16x16<Self>, b: u16x16<Self>) -> u8x32<Self> {
4627 let (a0, a1) = self.split_u16x16(a);
4628 let (b0, b1) = self.split_u16x16(b);
4629 self.combine_u8x16(
4630 self.relaxed_narrow_u16x8(a0, a1),
4631 self.relaxed_narrow_u16x8(b0, b1),
4632 )
4633 }
4634 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
4635 #[inline(always)]
4636 fn splat_mask16x16(self, val: bool) -> mask16x16<Self> {
4637 let half = self.splat_mask16x8(val);
4638 self.combine_mask16x8(half, half)
4639 }
4640 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
4641 #[inline(always)]
4642 fn from_bitmask_mask16x16(self, bits: u64) -> mask16x16<Self> {
4643 let lo = self.from_bitmask_mask16x8(bits);
4644 let hi = self.from_bitmask_mask16x8(bits >> 8usize);
4645 self.combine_mask16x8(lo, hi)
4646 }
4647 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
4648 #[inline(always)]
4649 fn to_bitmask_mask16x16(self, a: mask16x16<Self>) -> u64 {
4650 let (lo, hi) = self.split_mask16x16(a);
4651 let lo = self.to_bitmask_mask16x8(lo);
4652 let hi = self.to_bitmask_mask16x8(hi);
4653 lo | (hi << 8usize)
4654 }
4655 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
4656 fn from_vector_mask16x16(self, vector: i16x16<Self>) -> mask16x16<Self>;
4657 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
4658 fn to_vector_mask16x16(self, a: mask16x16<Self>) -> i16x16<Self>;
4659 #[doc = "Set one logical lane of a SIMD mask."]
4660 fn set_mask16x16(self, a: &mut mask16x16<Self>, index: usize, value: bool) -> ();
4661 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
4662 fn rotate_elements_left_mask16x16<const OFFSET: usize>(
4663 self,
4664 a: mask16x16<Self>,
4665 ) -> mask16x16<Self>;
4666 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
4667 fn rotate_elements_right_mask16x16<const OFFSET: usize>(
4668 self,
4669 a: mask16x16<Self>,
4670 ) -> mask16x16<Self>;
4671 #[doc = "Compute the logical AND of two masks."]
4672 #[inline(always)]
4673 fn and_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x16<Self> {
4674 let (a0, a1) = self.split_mask16x16(a);
4675 let (b0, b1) = self.split_mask16x16(b);
4676 self.combine_mask16x8(self.and_mask16x8(a0, b0), self.and_mask16x8(a1, b1))
4677 }
4678 #[doc = "Compute the logical OR of two masks."]
4679 #[inline(always)]
4680 fn or_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x16<Self> {
4681 let (a0, a1) = self.split_mask16x16(a);
4682 let (b0, b1) = self.split_mask16x16(b);
4683 self.combine_mask16x8(self.or_mask16x8(a0, b0), self.or_mask16x8(a1, b1))
4684 }
4685 #[doc = "Compute the logical XOR of two masks."]
4686 #[inline(always)]
4687 fn xor_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x16<Self> {
4688 let (a0, a1) = self.split_mask16x16(a);
4689 let (b0, b1) = self.split_mask16x16(b);
4690 self.combine_mask16x8(self.xor_mask16x8(a0, b0), self.xor_mask16x8(a1, b1))
4691 }
4692 #[doc = "Compute the logical NOT of the mask."]
4693 #[inline(always)]
4694 fn not_mask16x16(self, a: mask16x16<Self>) -> mask16x16<Self> {
4695 let (a0, a1) = self.split_mask16x16(a);
4696 self.combine_mask16x8(self.not_mask16x8(a0), self.not_mask16x8(a1))
4697 }
4698 #[doc = "Reverse the order of the mask's logical lanes."]
4699 #[inline(always)]
4700 fn reverse_mask16x16(self, a: mask16x16<Self>) -> mask16x16<Self> {
4701 let (a0, a1) = self.split_mask16x16(a);
4702 self.combine_mask16x8(self.reverse_mask16x8(a1), self.reverse_mask16x8(a0))
4703 }
4704 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
4705 #[inline(always)]
4706 fn select_mask16x16(
4707 self,
4708 a: mask16x16<Self>,
4709 b: mask16x16<Self>,
4710 c: mask16x16<Self>,
4711 ) -> mask16x16<Self> {
4712 let (a0, a1) = self.split_mask16x16(a);
4713 let (b0, b1) = self.split_mask16x16(b);
4714 let (c0, c1) = self.split_mask16x16(c);
4715 self.combine_mask16x8(
4716 self.select_mask16x8(a0, b0, c0),
4717 self.select_mask16x8(a1, b1, c1),
4718 )
4719 }
4720 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
4721 #[inline(always)]
4722 fn simd_eq_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x16<Self> {
4723 let (a0, a1) = self.split_mask16x16(a);
4724 let (b0, b1) = self.split_mask16x16(b);
4725 self.combine_mask16x8(self.simd_eq_mask16x8(a0, b0), self.simd_eq_mask16x8(a1, b1))
4726 }
4727 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
4728 #[inline(always)]
4729 fn simd_ne_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x16<Self> {
4730 self.not_mask16x16(self.simd_eq_mask16x16(a, b))
4731 }
4732 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
4733 #[inline(always)]
4734 fn any_true_mask16x16(self, a: mask16x16<Self>) -> bool {
4735 let (a0, a1) = self.split_mask16x16(a);
4736 self.any_true_mask16x8(self.or_mask16x8(a0, a1))
4737 }
4738 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
4739 #[inline(always)]
4740 fn all_true_mask16x16(self, a: mask16x16<Self>) -> bool {
4741 let (a0, a1) = self.split_mask16x16(a);
4742 self.all_true_mask16x8(self.and_mask16x8(a0, a1))
4743 }
4744 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
4745 #[inline(always)]
4746 fn any_false_mask16x16(self, a: mask16x16<Self>) -> bool {
4747 let (a0, a1) = self.split_mask16x16(a);
4748 self.any_false_mask16x8(self.and_mask16x8(a0, a1))
4749 }
4750 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
4751 #[inline(always)]
4752 fn all_false_mask16x16(self, a: mask16x16<Self>) -> bool {
4753 let (a0, a1) = self.split_mask16x16(a);
4754 self.all_false_mask16x8(self.or_mask16x8(a0, a1))
4755 }
4756 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
4757 fn combine_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask16x32<Self>;
4758 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
4759 fn split_mask16x16(self, a: mask16x16<Self>) -> (mask16x8<Self>, mask16x8<Self>);
4760 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
4761 #[inline(always)]
4762 fn widen_mask16x16(self, a: mask16x16<Self>) -> (mask32x8<Self>, mask32x8<Self>) {
4763 let (a0, a1) = self.split_mask16x16(a);
4764 let (a00, a01) = self.widen_mask16x8(a0);
4765 let (a10, a11) = self.widen_mask16x8(a1);
4766 (
4767 self.combine_mask32x4(a00, a01),
4768 self.combine_mask32x4(a10, a11),
4769 )
4770 }
4771 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
4772 #[inline(always)]
4773 fn narrow_mask16x16(self, a: mask16x16<Self>, b: mask16x16<Self>) -> mask8x32<Self> {
4774 let (a0, a1) = self.split_mask16x16(a);
4775 let (b0, b1) = self.split_mask16x16(b);
4776 self.combine_mask8x16(self.narrow_mask16x8(a0, a1), self.narrow_mask16x8(b0, b1))
4777 }
4778 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
4779 #[inline(always)]
4780 fn abs_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
4781 let (a0, a1) = self.split_i32x8(a);
4782 self.combine_i32x4(self.abs_i32x4(a0), self.abs_i32x4(a1))
4783 }
4784 #[doc = "Create a SIMD vector with all elements set to the given value."]
4785 #[inline(always)]
4786 fn splat_i32x8(self, val: i32) -> i32x8<Self> {
4787 let half = self.splat_i32x4(val);
4788 self.combine_i32x4(half, half)
4789 }
4790 #[doc = "Reverse the order of the vector's elements."]
4791 #[inline(always)]
4792 fn reverse_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
4793 let (a0, a1) = self.split_i32x8(a);
4794 self.combine_i32x4(self.reverse_i32x4(a1), self.reverse_i32x4(a0))
4795 }
4796 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
4797 fn slide_i32x8<const SHIFT: usize>(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self>;
4798 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
4799 #[inline(always)]
4800 fn slide_within_blocks_i32x8<const SHIFT: usize>(
4801 self,
4802 a: i32x8<Self>,
4803 b: i32x8<Self>,
4804 ) -> i32x8<Self> {
4805 let (a0, a1) = self.split_i32x8(a);
4806 let (b0, b1) = self.split_i32x8(b);
4807 self.combine_i32x4(
4808 self.slide_within_blocks_i32x4::<SHIFT>(a0, b0),
4809 self.slide_within_blocks_i32x4::<SHIFT>(a1, b1),
4810 )
4811 }
4812 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
4813 #[inline(always)]
4814 fn swizzle_dyn_within_blocks_i32x8(self, a: i32x8<Self>, indices: u8x32<Self>) -> i32x8<Self> {
4815 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
4816 }
4817 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
4818 #[inline(always)]
4819 fn swizzle_dyn_i32x8(self, a: i32x8<Self>, indices: u8x32<Self>) -> i32x8<Self> {
4820 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
4821 }
4822 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
4823 #[inline(always)]
4824 fn swizzle_dyn_precise_i32x8(self, a: i32x8<Self>, indices: u8x32<Self>) -> i32x8<Self> {
4825 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
4826 }
4827 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
4828 #[inline(always)]
4829 fn concat_swizzle_dyn_i32x8(
4830 self,
4831 a: i32x8<Self>,
4832 b: i32x8<Self>,
4833 indices: u8x32<Self>,
4834 ) -> i32x8<Self> {
4835 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
4836 Bytes::to_bytes(a),
4837 Bytes::to_bytes(b),
4838 indices,
4839 ))
4840 }
4841 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
4842 #[inline(always)]
4843 fn concat_swizzle_dyn_precise_i32x8(
4844 self,
4845 a: i32x8<Self>,
4846 b: i32x8<Self>,
4847 indices: u8x32<Self>,
4848 ) -> i32x8<Self> {
4849 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
4850 Bytes::to_bytes(a),
4851 Bytes::to_bytes(b),
4852 indices,
4853 ))
4854 }
4855 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
4856 fn compress_i32x8(self, values: i32x8<Self>, mask: mask32x8<Self>) -> i32x8<Self>;
4857 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
4858 fn compress_merge_i32x8(
4859 self,
4860 values: i32x8<Self>,
4861 mask: mask32x8<Self>,
4862 merge: i32x8<Self>,
4863 ) -> i32x8<Self>;
4864 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
4865 fn expand_i32x8(self, values: i32x8<Self>, mask: mask32x8<Self>) -> i32x8<Self>;
4866 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
4867 fn expand_merge_i32x8(
4868 self,
4869 values: i32x8<Self>,
4870 mask: mask32x8<Self>,
4871 merge: i32x8<Self>,
4872 ) -> i32x8<Self>;
4873 #[doc = "Return the number of ones in the binary representation of each element."]
4874 #[inline(always)]
4875 fn count_ones_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
4876 let (a0, a1) = self.split_i32x8(a);
4877 self.combine_i32x4(self.count_ones_i32x4(a0), self.count_ones_i32x4(a1))
4878 }
4879 #[doc = "Return the number of zeros in the binary representation of each element."]
4880 #[inline(always)]
4881 fn count_zeros_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
4882 let (a0, a1) = self.split_i32x8(a);
4883 self.combine_i32x4(self.count_zeros_i32x4(a0), self.count_zeros_i32x4(a1))
4884 }
4885 #[doc = "Add two vectors element-wise, wrapping on overflow."]
4886 #[inline(always)]
4887 fn add_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4888 let (a0, a1) = self.split_i32x8(a);
4889 let (b0, b1) = self.split_i32x8(b);
4890 self.combine_i32x4(self.add_i32x4(a0, b0), self.add_i32x4(a1, b1))
4891 }
4892 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
4893 #[inline(always)]
4894 fn saturating_add_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4895 let (a0, a1) = self.split_i32x8(a);
4896 let (b0, b1) = self.split_i32x8(b);
4897 self.combine_i32x4(
4898 self.saturating_add_i32x4(a0, b0),
4899 self.saturating_add_i32x4(a1, b1),
4900 )
4901 }
4902 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
4903 #[inline(always)]
4904 fn sub_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4905 let (a0, a1) = self.split_i32x8(a);
4906 let (b0, b1) = self.split_i32x8(b);
4907 self.combine_i32x4(self.sub_i32x4(a0, b0), self.sub_i32x4(a1, b1))
4908 }
4909 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
4910 #[inline(always)]
4911 fn saturating_sub_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4912 let (a0, a1) = self.split_i32x8(a);
4913 let (b0, b1) = self.split_i32x8(b);
4914 self.combine_i32x4(
4915 self.saturating_sub_i32x4(a0, b0),
4916 self.saturating_sub_i32x4(a1, b1),
4917 )
4918 }
4919 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
4920 #[inline(always)]
4921 fn mul_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4922 let (a0, a1) = self.split_i32x8(a);
4923 let (b0, b1) = self.split_i32x8(b);
4924 self.combine_i32x4(self.mul_i32x4(a0, b0), self.mul_i32x4(a1, b1))
4925 }
4926 #[doc = "Compute the bitwise AND of two vectors."]
4927 #[inline(always)]
4928 fn and_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4929 let (a0, a1) = self.split_i32x8(a);
4930 let (b0, b1) = self.split_i32x8(b);
4931 self.combine_i32x4(self.and_i32x4(a0, b0), self.and_i32x4(a1, b1))
4932 }
4933 #[doc = "Compute the bitwise OR of two vectors."]
4934 #[inline(always)]
4935 fn or_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4936 let (a0, a1) = self.split_i32x8(a);
4937 let (b0, b1) = self.split_i32x8(b);
4938 self.combine_i32x4(self.or_i32x4(a0, b0), self.or_i32x4(a1, b1))
4939 }
4940 #[doc = "Compute the bitwise XOR of two vectors."]
4941 #[inline(always)]
4942 fn xor_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4943 let (a0, a1) = self.split_i32x8(a);
4944 let (b0, b1) = self.split_i32x8(b);
4945 self.combine_i32x4(self.xor_i32x4(a0, b0), self.xor_i32x4(a1, b1))
4946 }
4947 #[doc = "Compute the bitwise NOT of the vector."]
4948 #[inline(always)]
4949 fn not_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
4950 let (a0, a1) = self.split_i32x8(a);
4951 self.combine_i32x4(self.not_i32x4(a0), self.not_i32x4(a1))
4952 }
4953 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
4954 #[inline(always)]
4955 fn shl_i32x8(self, a: i32x8<Self>, shift: u32) -> i32x8<Self> {
4956 let (a0, a1) = self.split_i32x8(a);
4957 self.combine_i32x4(self.shl_i32x4(a0, shift), self.shl_i32x4(a1, shift))
4958 }
4959 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
4960 #[inline(always)]
4961 fn shlv_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4962 let (a0, a1) = self.split_i32x8(a);
4963 let (b0, b1) = self.split_i32x8(b);
4964 self.combine_i32x4(self.shlv_i32x4(a0, b0), self.shlv_i32x4(a1, b1))
4965 }
4966 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
4967 #[inline(always)]
4968 fn shr_i32x8(self, a: i32x8<Self>, shift: u32) -> i32x8<Self> {
4969 let (a0, a1) = self.split_i32x8(a);
4970 self.combine_i32x4(self.shr_i32x4(a0, shift), self.shr_i32x4(a1, shift))
4971 }
4972 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
4973 #[inline(always)]
4974 fn shrv_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
4975 let (a0, a1) = self.split_i32x8(a);
4976 let (b0, b1) = self.split_i32x8(b);
4977 self.combine_i32x4(self.shrv_i32x4(a0, b0), self.shrv_i32x4(a1, b1))
4978 }
4979 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
4980 #[inline(always)]
4981 fn reduce_max_i32x8(self, a: i32x8<Self>) -> i32 {
4982 let (a0, a1) = self.split_i32x8(a);
4983 self.reduce_max_i32x4(self.max_i32x4(a0, a1))
4984 }
4985 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
4986 #[inline(always)]
4987 fn reduce_min_i32x8(self, a: i32x8<Self>) -> i32 {
4988 let (a0, a1) = self.split_i32x8(a);
4989 self.reduce_min_i32x4(self.min_i32x4(a0, a1))
4990 }
4991 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
4992 #[inline(always)]
4993 fn reduce_sum_i32x8(self, a: i32x8<Self>) -> i32 {
4994 let (a0, a1) = self.split_i32x8(a);
4995 self.reduce_sum_i32x4(self.add_i32x4(a0, a1))
4996 }
4997 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
4998 #[inline(always)]
4999 fn reduce_product_i32x8(self, a: i32x8<Self>) -> i32 {
5000 let (a0, a1) = self.split_i32x8(a);
5001 self.reduce_product_i32x4(self.mul_i32x4(a0, a1))
5002 }
5003 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5004 #[inline(always)]
5005 fn max_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5006 let (a0, a1) = self.split_i32x8(a);
5007 let (b0, b1) = self.split_i32x8(b);
5008 self.combine_i32x4(self.max_i32x4(a0, b0), self.max_i32x4(a1, b1))
5009 }
5010 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5011 #[inline(always)]
5012 fn min_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5013 let (a0, a1) = self.split_i32x8(a);
5014 let (b0, b1) = self.split_i32x8(b);
5015 self.combine_i32x4(self.min_i32x4(a0, b0), self.min_i32x4(a1, b1))
5016 }
5017 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
5018 #[inline(always)]
5019 fn clamp_i32x8(self, a: i32x8<Self>, b: i32x8<Self>, c: i32x8<Self>) -> i32x8<Self> {
5020 let (a0, a1) = self.split_i32x8(a);
5021 let (b0, b1) = self.split_i32x8(b);
5022 let (c0, c1) = self.split_i32x8(c);
5023 self.combine_i32x4(self.clamp_i32x4(a0, b0, c0), self.clamp_i32x4(a1, b1, c1))
5024 }
5025 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
5026 #[inline(always)]
5027 fn simd_eq_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5028 let (a0, a1) = self.split_i32x8(a);
5029 let (b0, b1) = self.split_i32x8(b);
5030 self.combine_mask32x4(self.simd_eq_i32x4(a0, b0), self.simd_eq_i32x4(a1, b1))
5031 }
5032 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
5033 #[inline(always)]
5034 fn simd_ne_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5035 self.not_mask32x8(self.simd_eq_i32x8(a, b))
5036 }
5037 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
5038 #[inline(always)]
5039 fn simd_lt_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5040 let (a0, a1) = self.split_i32x8(a);
5041 let (b0, b1) = self.split_i32x8(b);
5042 self.combine_mask32x4(self.simd_lt_i32x4(a0, b0), self.simd_lt_i32x4(a1, b1))
5043 }
5044 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
5045 #[inline(always)]
5046 fn simd_le_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5047 let (a0, a1) = self.split_i32x8(a);
5048 let (b0, b1) = self.split_i32x8(b);
5049 self.combine_mask32x4(self.simd_le_i32x4(a0, b0), self.simd_le_i32x4(a1, b1))
5050 }
5051 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
5052 #[inline(always)]
5053 fn simd_ge_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5054 self.simd_le_i32x8(b, a)
5055 }
5056 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
5057 #[inline(always)]
5058 fn simd_gt_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> mask32x8<Self> {
5059 self.simd_lt_i32x8(b, a)
5060 }
5061 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
5062 #[inline(always)]
5063 fn zip_low_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5064 let (a0, _) = self.split_i32x8(a);
5065 let (b0, _) = self.split_i32x8(b);
5066 self.combine_i32x4(self.zip_low_i32x4(a0, b0), self.zip_high_i32x4(a0, b0))
5067 }
5068 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
5069 #[inline(always)]
5070 fn zip_high_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5071 let (_, a1) = self.split_i32x8(a);
5072 let (_, b1) = self.split_i32x8(b);
5073 self.combine_i32x4(self.zip_low_i32x4(a1, b1), self.zip_high_i32x4(a1, b1))
5074 }
5075 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
5076 #[inline(always)]
5077 fn unzip_low_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5078 let (a0, a1) = self.split_i32x8(a);
5079 let (b0, b1) = self.split_i32x8(b);
5080 self.combine_i32x4(self.unzip_low_i32x4(a0, a1), self.unzip_low_i32x4(b0, b1))
5081 }
5082 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
5083 #[inline(always)]
5084 fn unzip_high_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x8<Self> {
5085 let (a0, a1) = self.split_i32x8(a);
5086 let (b0, b1) = self.split_i32x8(b);
5087 self.combine_i32x4(self.unzip_high_i32x4(a0, a1), self.unzip_high_i32x4(b0, b1))
5088 }
5089 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
5090 #[inline(always)]
5091 fn interleave_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> (i32x8<Self>, i32x8<Self>) {
5092 let (a0, a1) = self.split_i32x8(a);
5093 let (b0, b1) = self.split_i32x8(b);
5094 let lo_lo = self.zip_low_i32x4(a0, b0);
5095 let lo_hi = self.zip_high_i32x4(a0, b0);
5096 let hi_lo = self.zip_low_i32x4(a1, b1);
5097 let hi_hi = self.zip_high_i32x4(a1, b1);
5098 (
5099 self.combine_i32x4(lo_lo, lo_hi),
5100 self.combine_i32x4(hi_lo, hi_hi),
5101 )
5102 }
5103 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
5104 #[inline(always)]
5105 fn deinterleave_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> (i32x8<Self>, i32x8<Self>) {
5106 let (a0, a1) = self.split_i32x8(a);
5107 let (b0, b1) = self.split_i32x8(b);
5108 let lo_even = self.unzip_low_i32x4(a0, a1);
5109 let lo_odd = self.unzip_high_i32x4(a0, a1);
5110 let hi_even = self.unzip_low_i32x4(b0, b1);
5111 let hi_odd = self.unzip_high_i32x4(b0, b1);
5112 (
5113 self.combine_i32x4(lo_even, hi_even),
5114 self.combine_i32x4(lo_odd, hi_odd),
5115 )
5116 }
5117 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
5118 #[inline(always)]
5119 fn select_i32x8(self, a: mask32x8<Self>, b: i32x8<Self>, c: i32x8<Self>) -> i32x8<Self> {
5120 let (a0, a1) = self.split_mask32x8(a);
5121 let (b0, b1) = self.split_i32x8(b);
5122 let (c0, c1) = self.split_i32x8(c);
5123 self.combine_i32x4(self.select_i32x4(a0, b0, c0), self.select_i32x4(a1, b1, c1))
5124 }
5125 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
5126 fn combine_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i32x16<Self>;
5127 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
5128 fn split_i32x8(self, a: i32x8<Self>) -> (i32x4<Self>, i32x4<Self>);
5129 #[doc = "Negate each element of the vector, wrapping on overflow."]
5130 #[inline(always)]
5131 fn neg_i32x8(self, a: i32x8<Self>) -> i32x8<Self> {
5132 let (a0, a1) = self.split_i32x8(a);
5133 self.combine_i32x4(self.neg_i32x4(a0), self.neg_i32x4(a1))
5134 }
5135 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
5136 #[inline(always)]
5137 fn widen_i32x8(self, a: i32x8<Self>) -> (i64x4<Self>, i64x4<Self>) {
5138 let (a0, a1) = self.split_i32x8(a);
5139 let (a00, a01) = self.widen_i32x4(a0);
5140 let (a10, a11) = self.widen_i32x4(a1);
5141 (self.combine_i64x2(a00, a01), self.combine_i64x2(a10, a11))
5142 }
5143 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
5144 #[inline(always)]
5145 fn widening_mul_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> (i64x4<Self>, i64x4<Self>) {
5146 let (a0, a1) = self.split_i32x8(a);
5147 let (b0, b1) = self.split_i32x8(b);
5148 let (low0, low1) = self.widening_mul_i32x4(a0, b0);
5149 let (high0, high1) = self.widening_mul_i32x4(a1, b1);
5150 (
5151 self.combine_i64x2(low0, low1),
5152 self.combine_i64x2(high0, high1),
5153 )
5154 }
5155 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
5156 #[inline(always)]
5157 fn widening_add_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> (i64x4<Self>, i64x4<Self>) {
5158 let (a0, a1) = self.split_i32x8(a);
5159 let (b0, b1) = self.split_i32x8(b);
5160 let (low0, low1) = self.widening_add_i32x4(a0, b0);
5161 let (high0, high1) = self.widening_add_i32x4(a1, b1);
5162 (
5163 self.combine_i64x2(low0, low1),
5164 self.combine_i64x2(high0, high1),
5165 )
5166 }
5167 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
5168 #[inline(always)]
5169 fn pairwise_widening_add_i32x8(self, a: i32x8<Self>) -> i64x4<Self> {
5170 let (a0, a1) = self.split_i32x8(a);
5171 self.combine_i64x2(
5172 self.pairwise_widening_add_i32x4(a0),
5173 self.pairwise_widening_add_i32x4(a1),
5174 )
5175 }
5176 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
5177 #[inline(always)]
5178 fn pairwise_dot_product_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i64x4<Self> {
5179 let (a0, a1) = self.split_i32x8(a);
5180 let (b0, b1) = self.split_i32x8(b);
5181 self.combine_i64x2(
5182 self.pairwise_dot_product_i32x4(a0, b0),
5183 self.pairwise_dot_product_i32x4(a1, b1),
5184 )
5185 }
5186 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
5187 #[inline(always)]
5188 fn narrow_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i16x16<Self> {
5189 let (a0, a1) = self.split_i32x8(a);
5190 let (b0, b1) = self.split_i32x8(b);
5191 self.combine_i16x8(self.narrow_i32x4(a0, a1), self.narrow_i32x4(b0, b1))
5192 }
5193 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
5194 #[inline(always)]
5195 fn saturating_narrow_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i16x16<Self> {
5196 let (a0, a1) = self.split_i32x8(a);
5197 let (b0, b1) = self.split_i32x8(b);
5198 self.combine_i16x8(
5199 self.saturating_narrow_i32x4(a0, a1),
5200 self.saturating_narrow_i32x4(b0, b1),
5201 )
5202 }
5203 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
5204 #[inline(always)]
5205 fn relaxed_narrow_i32x8(self, a: i32x8<Self>, b: i32x8<Self>) -> i16x16<Self> {
5206 let (a0, a1) = self.split_i32x8(a);
5207 let (b0, b1) = self.split_i32x8(b);
5208 self.combine_i16x8(
5209 self.relaxed_narrow_i32x4(a0, a1),
5210 self.relaxed_narrow_i32x4(b0, b1),
5211 )
5212 }
5213 #[doc = "Convert each signed 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
5214 #[inline(always)]
5215 fn cvt_f32_i32x8(self, a: i32x8<Self>) -> f32x8<Self> {
5216 let (a0, a1) = self.split_i32x8(a);
5217 self.combine_f32x4(self.cvt_f32_i32x4(a0), self.cvt_f32_i32x4(a1))
5218 }
5219 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
5220 #[inline(always)]
5221 fn abs_u32x8(self, a: u32x8<Self>) -> u32x8<Self> {
5222 a
5223 }
5224 #[doc = "Create a SIMD vector with all elements set to the given value."]
5225 #[inline(always)]
5226 fn splat_u32x8(self, val: u32) -> u32x8<Self> {
5227 let half = self.splat_u32x4(val);
5228 self.combine_u32x4(half, half)
5229 }
5230 #[doc = "Reverse the order of the vector's elements."]
5231 #[inline(always)]
5232 fn reverse_u32x8(self, a: u32x8<Self>) -> u32x8<Self> {
5233 let (a0, a1) = self.split_u32x8(a);
5234 self.combine_u32x4(self.reverse_u32x4(a1), self.reverse_u32x4(a0))
5235 }
5236 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
5237 fn slide_u32x8<const SHIFT: usize>(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self>;
5238 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
5239 #[inline(always)]
5240 fn slide_within_blocks_u32x8<const SHIFT: usize>(
5241 self,
5242 a: u32x8<Self>,
5243 b: u32x8<Self>,
5244 ) -> u32x8<Self> {
5245 let (a0, a1) = self.split_u32x8(a);
5246 let (b0, b1) = self.split_u32x8(b);
5247 self.combine_u32x4(
5248 self.slide_within_blocks_u32x4::<SHIFT>(a0, b0),
5249 self.slide_within_blocks_u32x4::<SHIFT>(a1, b1),
5250 )
5251 }
5252 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
5253 #[inline(always)]
5254 fn swizzle_dyn_within_blocks_u32x8(self, a: u32x8<Self>, indices: u8x32<Self>) -> u32x8<Self> {
5255 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
5256 }
5257 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
5258 #[inline(always)]
5259 fn swizzle_dyn_u32x8(self, a: u32x8<Self>, indices: u8x32<Self>) -> u32x8<Self> {
5260 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
5261 }
5262 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
5263 #[inline(always)]
5264 fn swizzle_dyn_precise_u32x8(self, a: u32x8<Self>, indices: u8x32<Self>) -> u32x8<Self> {
5265 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
5266 }
5267 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
5268 #[inline(always)]
5269 fn concat_swizzle_dyn_u32x8(
5270 self,
5271 a: u32x8<Self>,
5272 b: u32x8<Self>,
5273 indices: u8x32<Self>,
5274 ) -> u32x8<Self> {
5275 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
5276 Bytes::to_bytes(a),
5277 Bytes::to_bytes(b),
5278 indices,
5279 ))
5280 }
5281 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
5282 #[inline(always)]
5283 fn concat_swizzle_dyn_precise_u32x8(
5284 self,
5285 a: u32x8<Self>,
5286 b: u32x8<Self>,
5287 indices: u8x32<Self>,
5288 ) -> u32x8<Self> {
5289 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
5290 Bytes::to_bytes(a),
5291 Bytes::to_bytes(b),
5292 indices,
5293 ))
5294 }
5295 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
5296 fn compress_u32x8(self, values: u32x8<Self>, mask: mask32x8<Self>) -> u32x8<Self>;
5297 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
5298 fn compress_merge_u32x8(
5299 self,
5300 values: u32x8<Self>,
5301 mask: mask32x8<Self>,
5302 merge: u32x8<Self>,
5303 ) -> u32x8<Self>;
5304 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
5305 fn expand_u32x8(self, values: u32x8<Self>, mask: mask32x8<Self>) -> u32x8<Self>;
5306 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
5307 fn expand_merge_u32x8(
5308 self,
5309 values: u32x8<Self>,
5310 mask: mask32x8<Self>,
5311 merge: u32x8<Self>,
5312 ) -> u32x8<Self>;
5313 #[doc = "Return the number of ones in the binary representation of each element."]
5314 #[inline(always)]
5315 fn count_ones_u32x8(self, a: u32x8<Self>) -> u32x8<Self> {
5316 let (a0, a1) = self.split_u32x8(a);
5317 self.combine_u32x4(self.count_ones_u32x4(a0), self.count_ones_u32x4(a1))
5318 }
5319 #[doc = "Return the number of zeros in the binary representation of each element."]
5320 #[inline(always)]
5321 fn count_zeros_u32x8(self, a: u32x8<Self>) -> u32x8<Self> {
5322 let (a0, a1) = self.split_u32x8(a);
5323 self.combine_u32x4(self.count_zeros_u32x4(a0), self.count_zeros_u32x4(a1))
5324 }
5325 #[doc = "Add two vectors element-wise, wrapping on overflow."]
5326 #[inline(always)]
5327 fn add_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5328 let (a0, a1) = self.split_u32x8(a);
5329 let (b0, b1) = self.split_u32x8(b);
5330 self.combine_u32x4(self.add_u32x4(a0, b0), self.add_u32x4(a1, b1))
5331 }
5332 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
5333 #[inline(always)]
5334 fn saturating_add_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5335 let (a0, a1) = self.split_u32x8(a);
5336 let (b0, b1) = self.split_u32x8(b);
5337 self.combine_u32x4(
5338 self.saturating_add_u32x4(a0, b0),
5339 self.saturating_add_u32x4(a1, b1),
5340 )
5341 }
5342 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
5343 #[inline(always)]
5344 fn sub_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5345 let (a0, a1) = self.split_u32x8(a);
5346 let (b0, b1) = self.split_u32x8(b);
5347 self.combine_u32x4(self.sub_u32x4(a0, b0), self.sub_u32x4(a1, b1))
5348 }
5349 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
5350 #[inline(always)]
5351 fn saturating_sub_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5352 let (a0, a1) = self.split_u32x8(a);
5353 let (b0, b1) = self.split_u32x8(b);
5354 self.combine_u32x4(
5355 self.saturating_sub_u32x4(a0, b0),
5356 self.saturating_sub_u32x4(a1, b1),
5357 )
5358 }
5359 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
5360 #[inline(always)]
5361 fn mul_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5362 let (a0, a1) = self.split_u32x8(a);
5363 let (b0, b1) = self.split_u32x8(b);
5364 self.combine_u32x4(self.mul_u32x4(a0, b0), self.mul_u32x4(a1, b1))
5365 }
5366 #[doc = "Compute the bitwise AND of two vectors."]
5367 #[inline(always)]
5368 fn and_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5369 let (a0, a1) = self.split_u32x8(a);
5370 let (b0, b1) = self.split_u32x8(b);
5371 self.combine_u32x4(self.and_u32x4(a0, b0), self.and_u32x4(a1, b1))
5372 }
5373 #[doc = "Compute the bitwise OR of two vectors."]
5374 #[inline(always)]
5375 fn or_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5376 let (a0, a1) = self.split_u32x8(a);
5377 let (b0, b1) = self.split_u32x8(b);
5378 self.combine_u32x4(self.or_u32x4(a0, b0), self.or_u32x4(a1, b1))
5379 }
5380 #[doc = "Compute the bitwise XOR of two vectors."]
5381 #[inline(always)]
5382 fn xor_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5383 let (a0, a1) = self.split_u32x8(a);
5384 let (b0, b1) = self.split_u32x8(b);
5385 self.combine_u32x4(self.xor_u32x4(a0, b0), self.xor_u32x4(a1, b1))
5386 }
5387 #[doc = "Compute the bitwise NOT of the vector."]
5388 #[inline(always)]
5389 fn not_u32x8(self, a: u32x8<Self>) -> u32x8<Self> {
5390 let (a0, a1) = self.split_u32x8(a);
5391 self.combine_u32x4(self.not_u32x4(a0), self.not_u32x4(a1))
5392 }
5393 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
5394 #[inline(always)]
5395 fn shl_u32x8(self, a: u32x8<Self>, shift: u32) -> u32x8<Self> {
5396 let (a0, a1) = self.split_u32x8(a);
5397 self.combine_u32x4(self.shl_u32x4(a0, shift), self.shl_u32x4(a1, shift))
5398 }
5399 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
5400 #[inline(always)]
5401 fn shlv_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5402 let (a0, a1) = self.split_u32x8(a);
5403 let (b0, b1) = self.split_u32x8(b);
5404 self.combine_u32x4(self.shlv_u32x4(a0, b0), self.shlv_u32x4(a1, b1))
5405 }
5406 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
5407 #[inline(always)]
5408 fn shr_u32x8(self, a: u32x8<Self>, shift: u32) -> u32x8<Self> {
5409 let (a0, a1) = self.split_u32x8(a);
5410 self.combine_u32x4(self.shr_u32x4(a0, shift), self.shr_u32x4(a1, shift))
5411 }
5412 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
5413 #[inline(always)]
5414 fn shrv_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5415 let (a0, a1) = self.split_u32x8(a);
5416 let (b0, b1) = self.split_u32x8(b);
5417 self.combine_u32x4(self.shrv_u32x4(a0, b0), self.shrv_u32x4(a1, b1))
5418 }
5419 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
5420 #[inline(always)]
5421 fn reduce_max_u32x8(self, a: u32x8<Self>) -> u32 {
5422 let (a0, a1) = self.split_u32x8(a);
5423 self.reduce_max_u32x4(self.max_u32x4(a0, a1))
5424 }
5425 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
5426 #[inline(always)]
5427 fn reduce_min_u32x8(self, a: u32x8<Self>) -> u32 {
5428 let (a0, a1) = self.split_u32x8(a);
5429 self.reduce_min_u32x4(self.min_u32x4(a0, a1))
5430 }
5431 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
5432 #[inline(always)]
5433 fn reduce_sum_u32x8(self, a: u32x8<Self>) -> u32 {
5434 let (a0, a1) = self.split_u32x8(a);
5435 self.reduce_sum_u32x4(self.add_u32x4(a0, a1))
5436 }
5437 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
5438 #[inline(always)]
5439 fn reduce_product_u32x8(self, a: u32x8<Self>) -> u32 {
5440 let (a0, a1) = self.split_u32x8(a);
5441 self.reduce_product_u32x4(self.mul_u32x4(a0, a1))
5442 }
5443 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5444 #[inline(always)]
5445 fn max_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5446 let (a0, a1) = self.split_u32x8(a);
5447 let (b0, b1) = self.split_u32x8(b);
5448 self.combine_u32x4(self.max_u32x4(a0, b0), self.max_u32x4(a1, b1))
5449 }
5450 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5451 #[inline(always)]
5452 fn min_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5453 let (a0, a1) = self.split_u32x8(a);
5454 let (b0, b1) = self.split_u32x8(b);
5455 self.combine_u32x4(self.min_u32x4(a0, b0), self.min_u32x4(a1, b1))
5456 }
5457 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
5458 #[inline(always)]
5459 fn clamp_u32x8(self, a: u32x8<Self>, b: u32x8<Self>, c: u32x8<Self>) -> u32x8<Self> {
5460 let (a0, a1) = self.split_u32x8(a);
5461 let (b0, b1) = self.split_u32x8(b);
5462 let (c0, c1) = self.split_u32x8(c);
5463 self.combine_u32x4(self.clamp_u32x4(a0, b0, c0), self.clamp_u32x4(a1, b1, c1))
5464 }
5465 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
5466 #[inline(always)]
5467 fn simd_eq_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5468 let (a0, a1) = self.split_u32x8(a);
5469 let (b0, b1) = self.split_u32x8(b);
5470 self.combine_mask32x4(self.simd_eq_u32x4(a0, b0), self.simd_eq_u32x4(a1, b1))
5471 }
5472 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
5473 #[inline(always)]
5474 fn simd_ne_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5475 self.not_mask32x8(self.simd_eq_u32x8(a, b))
5476 }
5477 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
5478 #[inline(always)]
5479 fn simd_lt_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5480 let (a0, a1) = self.split_u32x8(a);
5481 let (b0, b1) = self.split_u32x8(b);
5482 self.combine_mask32x4(self.simd_lt_u32x4(a0, b0), self.simd_lt_u32x4(a1, b1))
5483 }
5484 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
5485 #[inline(always)]
5486 fn simd_le_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5487 let (a0, a1) = self.split_u32x8(a);
5488 let (b0, b1) = self.split_u32x8(b);
5489 self.combine_mask32x4(self.simd_le_u32x4(a0, b0), self.simd_le_u32x4(a1, b1))
5490 }
5491 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
5492 #[inline(always)]
5493 fn simd_ge_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5494 self.simd_le_u32x8(b, a)
5495 }
5496 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
5497 #[inline(always)]
5498 fn simd_gt_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> mask32x8<Self> {
5499 self.simd_lt_u32x8(b, a)
5500 }
5501 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
5502 #[inline(always)]
5503 fn zip_low_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5504 let (a0, _) = self.split_u32x8(a);
5505 let (b0, _) = self.split_u32x8(b);
5506 self.combine_u32x4(self.zip_low_u32x4(a0, b0), self.zip_high_u32x4(a0, b0))
5507 }
5508 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
5509 #[inline(always)]
5510 fn zip_high_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5511 let (_, a1) = self.split_u32x8(a);
5512 let (_, b1) = self.split_u32x8(b);
5513 self.combine_u32x4(self.zip_low_u32x4(a1, b1), self.zip_high_u32x4(a1, b1))
5514 }
5515 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
5516 #[inline(always)]
5517 fn unzip_low_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5518 let (a0, a1) = self.split_u32x8(a);
5519 let (b0, b1) = self.split_u32x8(b);
5520 self.combine_u32x4(self.unzip_low_u32x4(a0, a1), self.unzip_low_u32x4(b0, b1))
5521 }
5522 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
5523 #[inline(always)]
5524 fn unzip_high_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x8<Self> {
5525 let (a0, a1) = self.split_u32x8(a);
5526 let (b0, b1) = self.split_u32x8(b);
5527 self.combine_u32x4(self.unzip_high_u32x4(a0, a1), self.unzip_high_u32x4(b0, b1))
5528 }
5529 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
5530 #[inline(always)]
5531 fn interleave_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> (u32x8<Self>, u32x8<Self>) {
5532 let (a0, a1) = self.split_u32x8(a);
5533 let (b0, b1) = self.split_u32x8(b);
5534 let lo_lo = self.zip_low_u32x4(a0, b0);
5535 let lo_hi = self.zip_high_u32x4(a0, b0);
5536 let hi_lo = self.zip_low_u32x4(a1, b1);
5537 let hi_hi = self.zip_high_u32x4(a1, b1);
5538 (
5539 self.combine_u32x4(lo_lo, lo_hi),
5540 self.combine_u32x4(hi_lo, hi_hi),
5541 )
5542 }
5543 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
5544 #[inline(always)]
5545 fn deinterleave_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> (u32x8<Self>, u32x8<Self>) {
5546 let (a0, a1) = self.split_u32x8(a);
5547 let (b0, b1) = self.split_u32x8(b);
5548 let lo_even = self.unzip_low_u32x4(a0, a1);
5549 let lo_odd = self.unzip_high_u32x4(a0, a1);
5550 let hi_even = self.unzip_low_u32x4(b0, b1);
5551 let hi_odd = self.unzip_high_u32x4(b0, b1);
5552 (
5553 self.combine_u32x4(lo_even, hi_even),
5554 self.combine_u32x4(lo_odd, hi_odd),
5555 )
5556 }
5557 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
5558 #[inline(always)]
5559 fn select_u32x8(self, a: mask32x8<Self>, b: u32x8<Self>, c: u32x8<Self>) -> u32x8<Self> {
5560 let (a0, a1) = self.split_mask32x8(a);
5561 let (b0, b1) = self.split_u32x8(b);
5562 let (c0, c1) = self.split_u32x8(c);
5563 self.combine_u32x4(self.select_u32x4(a0, b0, c0), self.select_u32x4(a1, b1, c1))
5564 }
5565 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
5566 fn combine_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u32x16<Self>;
5567 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
5568 fn split_u32x8(self, a: u32x8<Self>) -> (u32x4<Self>, u32x4<Self>);
5569 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
5570 #[inline(always)]
5571 fn widen_u32x8(self, a: u32x8<Self>) -> (u64x4<Self>, u64x4<Self>) {
5572 let (a0, a1) = self.split_u32x8(a);
5573 let (a00, a01) = self.widen_u32x4(a0);
5574 let (a10, a11) = self.widen_u32x4(a1);
5575 (self.combine_u64x2(a00, a01), self.combine_u64x2(a10, a11))
5576 }
5577 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
5578 #[inline(always)]
5579 fn widening_mul_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> (u64x4<Self>, u64x4<Self>) {
5580 let (a0, a1) = self.split_u32x8(a);
5581 let (b0, b1) = self.split_u32x8(b);
5582 let (low0, low1) = self.widening_mul_u32x4(a0, b0);
5583 let (high0, high1) = self.widening_mul_u32x4(a1, b1);
5584 (
5585 self.combine_u64x2(low0, low1),
5586 self.combine_u64x2(high0, high1),
5587 )
5588 }
5589 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
5590 #[inline(always)]
5591 fn widening_add_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> (u64x4<Self>, u64x4<Self>) {
5592 let (a0, a1) = self.split_u32x8(a);
5593 let (b0, b1) = self.split_u32x8(b);
5594 let (low0, low1) = self.widening_add_u32x4(a0, b0);
5595 let (high0, high1) = self.widening_add_u32x4(a1, b1);
5596 (
5597 self.combine_u64x2(low0, low1),
5598 self.combine_u64x2(high0, high1),
5599 )
5600 }
5601 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
5602 #[inline(always)]
5603 fn pairwise_widening_add_u32x8(self, a: u32x8<Self>) -> u64x4<Self> {
5604 let (a0, a1) = self.split_u32x8(a);
5605 self.combine_u64x2(
5606 self.pairwise_widening_add_u32x4(a0),
5607 self.pairwise_widening_add_u32x4(a1),
5608 )
5609 }
5610 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
5611 #[inline(always)]
5612 fn pairwise_dot_product_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u64x4<Self> {
5613 let (a0, a1) = self.split_u32x8(a);
5614 let (b0, b1) = self.split_u32x8(b);
5615 self.combine_u64x2(
5616 self.pairwise_dot_product_u32x4(a0, b0),
5617 self.pairwise_dot_product_u32x4(a1, b1),
5618 )
5619 }
5620 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
5621 #[inline(always)]
5622 fn narrow_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u16x16<Self> {
5623 let (a0, a1) = self.split_u32x8(a);
5624 let (b0, b1) = self.split_u32x8(b);
5625 self.combine_u16x8(self.narrow_u32x4(a0, a1), self.narrow_u32x4(b0, b1))
5626 }
5627 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
5628 #[inline(always)]
5629 fn saturating_narrow_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u16x16<Self> {
5630 let (a0, a1) = self.split_u32x8(a);
5631 let (b0, b1) = self.split_u32x8(b);
5632 self.combine_u16x8(
5633 self.saturating_narrow_u32x4(a0, a1),
5634 self.saturating_narrow_u32x4(b0, b1),
5635 )
5636 }
5637 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
5638 #[inline(always)]
5639 fn relaxed_narrow_u32x8(self, a: u32x8<Self>, b: u32x8<Self>) -> u16x16<Self> {
5640 let (a0, a1) = self.split_u32x8(a);
5641 let (b0, b1) = self.split_u32x8(b);
5642 self.combine_u16x8(
5643 self.relaxed_narrow_u32x4(a0, a1),
5644 self.relaxed_narrow_u32x4(b0, b1),
5645 )
5646 }
5647 #[doc = "Convert each unsigned 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
5648 #[inline(always)]
5649 fn cvt_f32_u32x8(self, a: u32x8<Self>) -> f32x8<Self> {
5650 let (a0, a1) = self.split_u32x8(a);
5651 self.combine_f32x4(self.cvt_f32_u32x4(a0), self.cvt_f32_u32x4(a1))
5652 }
5653 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
5654 #[inline(always)]
5655 fn splat_mask32x8(self, val: bool) -> mask32x8<Self> {
5656 let half = self.splat_mask32x4(val);
5657 self.combine_mask32x4(half, half)
5658 }
5659 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
5660 #[inline(always)]
5661 fn from_bitmask_mask32x8(self, bits: u64) -> mask32x8<Self> {
5662 let lo = self.from_bitmask_mask32x4(bits);
5663 let hi = self.from_bitmask_mask32x4(bits >> 4usize);
5664 self.combine_mask32x4(lo, hi)
5665 }
5666 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
5667 #[inline(always)]
5668 fn to_bitmask_mask32x8(self, a: mask32x8<Self>) -> u64 {
5669 let (lo, hi) = self.split_mask32x8(a);
5670 let lo = self.to_bitmask_mask32x4(lo);
5671 let hi = self.to_bitmask_mask32x4(hi);
5672 lo | (hi << 4usize)
5673 }
5674 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
5675 fn from_vector_mask32x8(self, vector: i32x8<Self>) -> mask32x8<Self>;
5676 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
5677 fn to_vector_mask32x8(self, a: mask32x8<Self>) -> i32x8<Self>;
5678 #[doc = "Set one logical lane of a SIMD mask."]
5679 fn set_mask32x8(self, a: &mut mask32x8<Self>, index: usize, value: bool) -> ();
5680 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
5681 fn rotate_elements_left_mask32x8<const OFFSET: usize>(
5682 self,
5683 a: mask32x8<Self>,
5684 ) -> mask32x8<Self>;
5685 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
5686 fn rotate_elements_right_mask32x8<const OFFSET: usize>(
5687 self,
5688 a: mask32x8<Self>,
5689 ) -> mask32x8<Self>;
5690 #[doc = "Compute the logical AND of two masks."]
5691 #[inline(always)]
5692 fn and_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x8<Self> {
5693 let (a0, a1) = self.split_mask32x8(a);
5694 let (b0, b1) = self.split_mask32x8(b);
5695 self.combine_mask32x4(self.and_mask32x4(a0, b0), self.and_mask32x4(a1, b1))
5696 }
5697 #[doc = "Compute the logical OR of two masks."]
5698 #[inline(always)]
5699 fn or_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x8<Self> {
5700 let (a0, a1) = self.split_mask32x8(a);
5701 let (b0, b1) = self.split_mask32x8(b);
5702 self.combine_mask32x4(self.or_mask32x4(a0, b0), self.or_mask32x4(a1, b1))
5703 }
5704 #[doc = "Compute the logical XOR of two masks."]
5705 #[inline(always)]
5706 fn xor_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x8<Self> {
5707 let (a0, a1) = self.split_mask32x8(a);
5708 let (b0, b1) = self.split_mask32x8(b);
5709 self.combine_mask32x4(self.xor_mask32x4(a0, b0), self.xor_mask32x4(a1, b1))
5710 }
5711 #[doc = "Compute the logical NOT of the mask."]
5712 #[inline(always)]
5713 fn not_mask32x8(self, a: mask32x8<Self>) -> mask32x8<Self> {
5714 let (a0, a1) = self.split_mask32x8(a);
5715 self.combine_mask32x4(self.not_mask32x4(a0), self.not_mask32x4(a1))
5716 }
5717 #[doc = "Reverse the order of the mask's logical lanes."]
5718 #[inline(always)]
5719 fn reverse_mask32x8(self, a: mask32x8<Self>) -> mask32x8<Self> {
5720 let (a0, a1) = self.split_mask32x8(a);
5721 self.combine_mask32x4(self.reverse_mask32x4(a1), self.reverse_mask32x4(a0))
5722 }
5723 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
5724 #[inline(always)]
5725 fn select_mask32x8(
5726 self,
5727 a: mask32x8<Self>,
5728 b: mask32x8<Self>,
5729 c: mask32x8<Self>,
5730 ) -> mask32x8<Self> {
5731 let (a0, a1) = self.split_mask32x8(a);
5732 let (b0, b1) = self.split_mask32x8(b);
5733 let (c0, c1) = self.split_mask32x8(c);
5734 self.combine_mask32x4(
5735 self.select_mask32x4(a0, b0, c0),
5736 self.select_mask32x4(a1, b1, c1),
5737 )
5738 }
5739 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
5740 #[inline(always)]
5741 fn simd_eq_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x8<Self> {
5742 let (a0, a1) = self.split_mask32x8(a);
5743 let (b0, b1) = self.split_mask32x8(b);
5744 self.combine_mask32x4(self.simd_eq_mask32x4(a0, b0), self.simd_eq_mask32x4(a1, b1))
5745 }
5746 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
5747 #[inline(always)]
5748 fn simd_ne_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x8<Self> {
5749 self.not_mask32x8(self.simd_eq_mask32x8(a, b))
5750 }
5751 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
5752 #[inline(always)]
5753 fn any_true_mask32x8(self, a: mask32x8<Self>) -> bool {
5754 let (a0, a1) = self.split_mask32x8(a);
5755 self.any_true_mask32x4(self.or_mask32x4(a0, a1))
5756 }
5757 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
5758 #[inline(always)]
5759 fn all_true_mask32x8(self, a: mask32x8<Self>) -> bool {
5760 let (a0, a1) = self.split_mask32x8(a);
5761 self.all_true_mask32x4(self.and_mask32x4(a0, a1))
5762 }
5763 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
5764 #[inline(always)]
5765 fn any_false_mask32x8(self, a: mask32x8<Self>) -> bool {
5766 let (a0, a1) = self.split_mask32x8(a);
5767 self.any_false_mask32x4(self.and_mask32x4(a0, a1))
5768 }
5769 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
5770 #[inline(always)]
5771 fn all_false_mask32x8(self, a: mask32x8<Self>) -> bool {
5772 let (a0, a1) = self.split_mask32x8(a);
5773 self.all_false_mask32x4(self.or_mask32x4(a0, a1))
5774 }
5775 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
5776 fn combine_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask32x16<Self>;
5777 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
5778 fn split_mask32x8(self, a: mask32x8<Self>) -> (mask32x4<Self>, mask32x4<Self>);
5779 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
5780 #[inline(always)]
5781 fn widen_mask32x8(self, a: mask32x8<Self>) -> (mask64x4<Self>, mask64x4<Self>) {
5782 let (a0, a1) = self.split_mask32x8(a);
5783 let (a00, a01) = self.widen_mask32x4(a0);
5784 let (a10, a11) = self.widen_mask32x4(a1);
5785 (
5786 self.combine_mask64x2(a00, a01),
5787 self.combine_mask64x2(a10, a11),
5788 )
5789 }
5790 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
5791 #[inline(always)]
5792 fn narrow_mask32x8(self, a: mask32x8<Self>, b: mask32x8<Self>) -> mask16x16<Self> {
5793 let (a0, a1) = self.split_mask32x8(a);
5794 let (b0, b1) = self.split_mask32x8(b);
5795 self.combine_mask16x8(self.narrow_mask32x4(a0, a1), self.narrow_mask32x4(b0, b1))
5796 }
5797 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
5798 #[inline(always)]
5799 fn abs_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
5800 let (a0, a1) = self.split_f64x4(a);
5801 self.combine_f64x2(self.abs_f64x2(a0), self.abs_f64x2(a1))
5802 }
5803 #[doc = "Create a SIMD vector with all elements set to the given value."]
5804 #[inline(always)]
5805 fn splat_f64x4(self, val: f64) -> f64x4<Self> {
5806 let half = self.splat_f64x2(val);
5807 self.combine_f64x2(half, half)
5808 }
5809 #[doc = "Reverse the order of the vector's elements."]
5810 #[inline(always)]
5811 fn reverse_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
5812 let (a0, a1) = self.split_f64x4(a);
5813 self.combine_f64x2(self.reverse_f64x2(a1), self.reverse_f64x2(a0))
5814 }
5815 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
5816 fn slide_f64x4<const SHIFT: usize>(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self>;
5817 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
5818 #[inline(always)]
5819 fn slide_within_blocks_f64x4<const SHIFT: usize>(
5820 self,
5821 a: f64x4<Self>,
5822 b: f64x4<Self>,
5823 ) -> f64x4<Self> {
5824 let (a0, a1) = self.split_f64x4(a);
5825 let (b0, b1) = self.split_f64x4(b);
5826 self.combine_f64x2(
5827 self.slide_within_blocks_f64x2::<SHIFT>(a0, b0),
5828 self.slide_within_blocks_f64x2::<SHIFT>(a1, b1),
5829 )
5830 }
5831 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
5832 #[inline(always)]
5833 fn swizzle_dyn_within_blocks_f64x4(self, a: f64x4<Self>, indices: u8x32<Self>) -> f64x4<Self> {
5834 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
5835 }
5836 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
5837 #[inline(always)]
5838 fn swizzle_dyn_f64x4(self, a: f64x4<Self>, indices: u8x32<Self>) -> f64x4<Self> {
5839 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
5840 }
5841 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
5842 #[inline(always)]
5843 fn swizzle_dyn_precise_f64x4(self, a: f64x4<Self>, indices: u8x32<Self>) -> f64x4<Self> {
5844 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
5845 }
5846 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
5847 #[inline(always)]
5848 fn concat_swizzle_dyn_f64x4(
5849 self,
5850 a: f64x4<Self>,
5851 b: f64x4<Self>,
5852 indices: u8x32<Self>,
5853 ) -> f64x4<Self> {
5854 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
5855 Bytes::to_bytes(a),
5856 Bytes::to_bytes(b),
5857 indices,
5858 ))
5859 }
5860 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
5861 #[inline(always)]
5862 fn concat_swizzle_dyn_precise_f64x4(
5863 self,
5864 a: f64x4<Self>,
5865 b: f64x4<Self>,
5866 indices: u8x32<Self>,
5867 ) -> f64x4<Self> {
5868 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
5869 Bytes::to_bytes(a),
5870 Bytes::to_bytes(b),
5871 indices,
5872 ))
5873 }
5874 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
5875 fn compress_f64x4(self, values: f64x4<Self>, mask: mask64x4<Self>) -> f64x4<Self>;
5876 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
5877 fn compress_merge_f64x4(
5878 self,
5879 values: f64x4<Self>,
5880 mask: mask64x4<Self>,
5881 merge: f64x4<Self>,
5882 ) -> f64x4<Self>;
5883 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
5884 fn expand_f64x4(self, values: f64x4<Self>, mask: mask64x4<Self>) -> f64x4<Self>;
5885 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
5886 fn expand_merge_f64x4(
5887 self,
5888 values: f64x4<Self>,
5889 mask: mask64x4<Self>,
5890 merge: f64x4<Self>,
5891 ) -> f64x4<Self>;
5892 #[doc = "Negate each element of the vector."]
5893 #[inline(always)]
5894 fn neg_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
5895 let (a0, a1) = self.split_f64x4(a);
5896 self.combine_f64x2(self.neg_f64x2(a0), self.neg_f64x2(a1))
5897 }
5898 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
5899 #[inline(always)]
5900 fn sqrt_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
5901 let (a0, a1) = self.split_f64x4(a);
5902 self.combine_f64x2(self.sqrt_f64x2(a0), self.sqrt_f64x2(a1))
5903 }
5904 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
5905 #[inline(always)]
5906 fn approximate_recip_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
5907 let (a0, a1) = self.split_f64x4(a);
5908 self.combine_f64x2(
5909 self.approximate_recip_f64x2(a0),
5910 self.approximate_recip_f64x2(a1),
5911 )
5912 }
5913 #[doc = "Add two vectors element-wise."]
5914 #[inline(always)]
5915 fn add_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5916 let (a0, a1) = self.split_f64x4(a);
5917 let (b0, b1) = self.split_f64x4(b);
5918 self.combine_f64x2(self.add_f64x2(a0, b0), self.add_f64x2(a1, b1))
5919 }
5920 #[doc = "Subtract two vectors element-wise."]
5921 #[inline(always)]
5922 fn sub_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5923 let (a0, a1) = self.split_f64x4(a);
5924 let (b0, b1) = self.split_f64x4(b);
5925 self.combine_f64x2(self.sub_f64x2(a0, b0), self.sub_f64x2(a1, b1))
5926 }
5927 #[doc = "Multiply two vectors element-wise."]
5928 #[inline(always)]
5929 fn mul_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5930 let (a0, a1) = self.split_f64x4(a);
5931 let (b0, b1) = self.split_f64x4(b);
5932 self.combine_f64x2(self.mul_f64x2(a0, b0), self.mul_f64x2(a1, b1))
5933 }
5934 #[doc = "Divide two vectors element-wise."]
5935 #[inline(always)]
5936 fn div_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5937 let (a0, a1) = self.split_f64x4(a);
5938 let (b0, b1) = self.split_f64x4(b);
5939 self.combine_f64x2(self.div_f64x2(a0, b0), self.div_f64x2(a1, b1))
5940 }
5941 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
5942 #[inline(always)]
5943 fn copysign_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5944 let (a0, a1) = self.split_f64x4(a);
5945 let (b0, b1) = self.split_f64x4(b);
5946 self.combine_f64x2(self.copysign_f64x2(a0, b0), self.copysign_f64x2(a1, b1))
5947 }
5948 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
5949 #[inline(always)]
5950 fn reduce_max_f64x4(self, a: f64x4<Self>) -> f64 {
5951 let (a0, a1) = self.split_f64x4(a);
5952 self.reduce_max_f64x2(self.max_f64x2(a0, a1))
5953 }
5954 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
5955 #[inline(always)]
5956 fn reduce_min_f64x4(self, a: f64x4<Self>) -> f64 {
5957 let (a0, a1) = self.split_f64x4(a);
5958 self.reduce_min_f64x2(self.min_f64x2(a0, a1))
5959 }
5960 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
5961 #[inline(always)]
5962 fn reduce_max_precise_f64x4(self, a: f64x4<Self>) -> f64 {
5963 let (a0, a1) = self.split_f64x4(a);
5964 self.reduce_max_precise_f64x2(self.max_precise_f64x2(a0, a1))
5965 }
5966 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
5967 #[inline(always)]
5968 fn reduce_min_precise_f64x4(self, a: f64x4<Self>) -> f64 {
5969 let (a0, a1) = self.split_f64x4(a);
5970 self.reduce_min_precise_f64x2(self.min_precise_f64x2(a0, a1))
5971 }
5972 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
5973 #[inline(always)]
5974 fn reduce_sum_f64x4(self, a: f64x4<Self>) -> f64 {
5975 let (a0, a1) = self.split_f64x4(a);
5976 self.reduce_sum_f64x2(self.add_f64x2(a0, a1))
5977 }
5978 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
5979 #[inline(always)]
5980 fn reduce_product_f64x4(self, a: f64x4<Self>) -> f64 {
5981 let (a0, a1) = self.split_f64x4(a);
5982 self.reduce_product_f64x2(self.mul_f64x2(a0, a1))
5983 }
5984 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5985 #[inline(always)]
5986 fn max_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5987 let (a0, a1) = self.split_f64x4(a);
5988 let (b0, b1) = self.split_f64x4(b);
5989 self.combine_f64x2(self.max_f64x2(a0, b0), self.max_f64x2(a1, b1))
5990 }
5991 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
5992 #[inline(always)]
5993 fn min_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
5994 let (a0, a1) = self.split_f64x4(a);
5995 let (b0, b1) = self.split_f64x4(b);
5996 self.combine_f64x2(self.min_f64x2(a0, b0), self.min_f64x2(a1, b1))
5997 }
5998 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
5999 #[inline(always)]
6000 fn max_precise_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6001 let (a0, a1) = self.split_f64x4(a);
6002 let (b0, b1) = self.split_f64x4(b);
6003 self.combine_f64x2(
6004 self.max_precise_f64x2(a0, b0),
6005 self.max_precise_f64x2(a1, b1),
6006 )
6007 }
6008 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
6009 #[inline(always)]
6010 fn min_precise_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6011 let (a0, a1) = self.split_f64x4(a);
6012 let (b0, b1) = self.split_f64x4(b);
6013 self.combine_f64x2(
6014 self.min_precise_f64x2(a0, b0),
6015 self.min_precise_f64x2(a1, b1),
6016 )
6017 }
6018 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
6019 #[inline(always)]
6020 fn clamp_f64x4(self, a: f64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6021 let (a0, a1) = self.split_f64x4(a);
6022 let (b0, b1) = self.split_f64x4(b);
6023 let (c0, c1) = self.split_f64x4(c);
6024 self.combine_f64x2(self.clamp_f64x2(a0, b0, c0), self.clamp_f64x2(a1, b1, c1))
6025 }
6026 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
6027 #[inline(always)]
6028 fn simd_eq_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6029 let (a0, a1) = self.split_f64x4(a);
6030 let (b0, b1) = self.split_f64x4(b);
6031 self.combine_mask64x2(self.simd_eq_f64x2(a0, b0), self.simd_eq_f64x2(a1, b1))
6032 }
6033 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
6034 #[inline(always)]
6035 fn simd_ne_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6036 self.not_mask64x4(self.simd_eq_f64x4(a, b))
6037 }
6038 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
6039 #[inline(always)]
6040 fn simd_lt_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6041 let (a0, a1) = self.split_f64x4(a);
6042 let (b0, b1) = self.split_f64x4(b);
6043 self.combine_mask64x2(self.simd_lt_f64x2(a0, b0), self.simd_lt_f64x2(a1, b1))
6044 }
6045 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
6046 #[inline(always)]
6047 fn simd_le_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6048 let (a0, a1) = self.split_f64x4(a);
6049 let (b0, b1) = self.split_f64x4(b);
6050 self.combine_mask64x2(self.simd_le_f64x2(a0, b0), self.simd_le_f64x2(a1, b1))
6051 }
6052 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
6053 #[inline(always)]
6054 fn simd_ge_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6055 self.simd_le_f64x4(b, a)
6056 }
6057 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
6058 #[inline(always)]
6059 fn simd_gt_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> mask64x4<Self> {
6060 self.simd_lt_f64x4(b, a)
6061 }
6062 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6063 #[inline(always)]
6064 fn zip_low_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6065 let (a0, _) = self.split_f64x4(a);
6066 let (b0, _) = self.split_f64x4(b);
6067 self.combine_f64x2(self.zip_low_f64x2(a0, b0), self.zip_high_f64x2(a0, b0))
6068 }
6069 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6070 #[inline(always)]
6071 fn zip_high_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6072 let (_, a1) = self.split_f64x4(a);
6073 let (_, b1) = self.split_f64x4(b);
6074 self.combine_f64x2(self.zip_low_f64x2(a1, b1), self.zip_high_f64x2(a1, b1))
6075 }
6076 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6077 #[inline(always)]
6078 fn unzip_low_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6079 let (a0, a1) = self.split_f64x4(a);
6080 let (b0, b1) = self.split_f64x4(b);
6081 self.combine_f64x2(self.unzip_low_f64x2(a0, a1), self.unzip_low_f64x2(b0, b1))
6082 }
6083 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6084 #[inline(always)]
6085 fn unzip_high_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x4<Self> {
6086 let (a0, a1) = self.split_f64x4(a);
6087 let (b0, b1) = self.split_f64x4(b);
6088 self.combine_f64x2(self.unzip_high_f64x2(a0, a1), self.unzip_high_f64x2(b0, b1))
6089 }
6090 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
6091 #[inline(always)]
6092 fn interleave_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> (f64x4<Self>, f64x4<Self>) {
6093 let (a0, a1) = self.split_f64x4(a);
6094 let (b0, b1) = self.split_f64x4(b);
6095 let lo_lo = self.zip_low_f64x2(a0, b0);
6096 let lo_hi = self.zip_high_f64x2(a0, b0);
6097 let hi_lo = self.zip_low_f64x2(a1, b1);
6098 let hi_hi = self.zip_high_f64x2(a1, b1);
6099 (
6100 self.combine_f64x2(lo_lo, lo_hi),
6101 self.combine_f64x2(hi_lo, hi_hi),
6102 )
6103 }
6104 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
6105 #[inline(always)]
6106 fn deinterleave_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> (f64x4<Self>, f64x4<Self>) {
6107 let (a0, a1) = self.split_f64x4(a);
6108 let (b0, b1) = self.split_f64x4(b);
6109 let lo_even = self.unzip_low_f64x2(a0, a1);
6110 let lo_odd = self.unzip_high_f64x2(a0, a1);
6111 let hi_even = self.unzip_low_f64x2(b0, b1);
6112 let hi_odd = self.unzip_high_f64x2(b0, b1);
6113 (
6114 self.combine_f64x2(lo_even, hi_even),
6115 self.combine_f64x2(lo_odd, hi_odd),
6116 )
6117 }
6118 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
6119 #[inline(always)]
6120 fn mul_add_f64x4(self, a: f64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6121 let (a0, a1) = self.split_f64x4(a);
6122 let (b0, b1) = self.split_f64x4(b);
6123 let (c0, c1) = self.split_f64x4(c);
6124 self.combine_f64x2(
6125 self.mul_add_f64x2(a0, b0, c0),
6126 self.mul_add_f64x2(a1, b1, c1),
6127 )
6128 }
6129 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
6130 #[inline(always)]
6131 fn mul_add_precise_f64x4(self, a: f64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6132 let (a0, a1) = self.split_f64x4(a);
6133 let (b0, b1) = self.split_f64x4(b);
6134 let (c0, c1) = self.split_f64x4(c);
6135 self.combine_f64x2(
6136 self.mul_add_precise_f64x2(a0, b0, c0),
6137 self.mul_add_precise_f64x2(a1, b1, c1),
6138 )
6139 }
6140 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
6141 #[inline(always)]
6142 fn mul_sub_f64x4(self, a: f64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6143 let (a0, a1) = self.split_f64x4(a);
6144 let (b0, b1) = self.split_f64x4(b);
6145 let (c0, c1) = self.split_f64x4(c);
6146 self.combine_f64x2(
6147 self.mul_sub_f64x2(a0, b0, c0),
6148 self.mul_sub_f64x2(a1, b1, c1),
6149 )
6150 }
6151 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
6152 #[inline(always)]
6153 fn mul_sub_precise_f64x4(self, a: f64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6154 let (a0, a1) = self.split_f64x4(a);
6155 let (b0, b1) = self.split_f64x4(b);
6156 let (c0, c1) = self.split_f64x4(c);
6157 self.combine_f64x2(
6158 self.mul_sub_precise_f64x2(a0, b0, c0),
6159 self.mul_sub_precise_f64x2(a1, b1, c1),
6160 )
6161 }
6162 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
6163 #[inline(always)]
6164 fn floor_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6165 let (a0, a1) = self.split_f64x4(a);
6166 self.combine_f64x2(self.floor_f64x2(a0), self.floor_f64x2(a1))
6167 }
6168 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
6169 #[inline(always)]
6170 fn ceil_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6171 let (a0, a1) = self.split_f64x4(a);
6172 self.combine_f64x2(self.ceil_f64x2(a0), self.ceil_f64x2(a1))
6173 }
6174 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
6175 #[inline(always)]
6176 fn round_ties_even_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6177 let (a0, a1) = self.split_f64x4(a);
6178 self.combine_f64x2(
6179 self.round_ties_even_f64x2(a0),
6180 self.round_ties_even_f64x2(a1),
6181 )
6182 }
6183 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
6184 #[inline(always)]
6185 fn round_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6186 let (a0, a1) = self.split_f64x4(a);
6187 self.combine_f64x2(self.round_f64x2(a0), self.round_f64x2(a1))
6188 }
6189 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
6190 #[inline(always)]
6191 fn fract_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6192 let (a0, a1) = self.split_f64x4(a);
6193 self.combine_f64x2(self.fract_f64x2(a0), self.fract_f64x2(a1))
6194 }
6195 #[doc = "Return the integer part of each element, rounding towards zero."]
6196 #[inline(always)]
6197 fn trunc_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6198 let (a0, a1) = self.split_f64x4(a);
6199 self.combine_f64x2(self.trunc_f64x2(a0), self.trunc_f64x2(a1))
6200 }
6201 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
6202 #[inline(always)]
6203 fn to_degrees_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6204 let (a0, a1) = self.split_f64x4(a);
6205 self.combine_f64x2(self.to_degrees_f64x2(a0), self.to_degrees_f64x2(a1))
6206 }
6207 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
6208 #[inline(always)]
6209 fn to_radians_f64x4(self, a: f64x4<Self>) -> f64x4<Self> {
6210 let (a0, a1) = self.split_f64x4(a);
6211 self.combine_f64x2(self.to_radians_f64x2(a0), self.to_radians_f64x2(a1))
6212 }
6213 #[doc = "Return a mask indicating which elements are NaN."]
6214 fn is_nan_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6215 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
6216 fn is_infinite_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6217 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
6218 fn is_finite_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6219 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
6220 fn is_subnormal_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6221 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
6222 fn is_normal_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6223 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
6224 fn is_sign_positive_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6225 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
6226 fn is_sign_negative_f64x4(self, a: f64x4<Self>) -> mask64x4<Self>;
6227 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
6228 #[inline(always)]
6229 fn select_f64x4(self, a: mask64x4<Self>, b: f64x4<Self>, c: f64x4<Self>) -> f64x4<Self> {
6230 let (a0, a1) = self.split_mask64x4(a);
6231 let (b0, b1) = self.split_f64x4(b);
6232 let (c0, c1) = self.split_f64x4(c);
6233 self.combine_f64x2(self.select_f64x2(a0, b0, c0), self.select_f64x2(a1, b1, c1))
6234 }
6235 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
6236 fn combine_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f64x8<Self>;
6237 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
6238 fn split_f64x4(self, a: f64x4<Self>) -> (f64x2<Self>, f64x2<Self>);
6239 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nValues are rounded to the nearest representable `f32`, with ties resolved to even; overflow produces signed infinity.This is the same as the `as` operator, and follows the IEEE 754 narrowing behavior in round-to-even mode.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
6240 #[inline(always)]
6241 fn narrow_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f32x8<Self> {
6242 let (a0, a1) = self.split_f64x4(a);
6243 let (b0, b1) = self.split_f64x4(b);
6244 self.combine_f32x4(self.narrow_f64x2(a0, a1), self.narrow_f64x2(b0, b1))
6245 }
6246 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
6247 #[inline(always)]
6248 fn saturating_narrow_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f32x8<Self> {
6249 let (a0, a1) = self.split_f64x4(a);
6250 let (b0, b1) = self.split_f64x4(b);
6251 self.combine_f32x4(
6252 self.saturating_narrow_f64x2(a0, a1),
6253 self.saturating_narrow_f64x2(b0, b1),
6254 )
6255 }
6256 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
6257 #[inline(always)]
6258 fn relaxed_narrow_f64x4(self, a: f64x4<Self>, b: f64x4<Self>) -> f32x8<Self> {
6259 let (a0, a1) = self.split_f64x4(a);
6260 let (b0, b1) = self.split_f64x4(b);
6261 self.combine_f32x4(
6262 self.relaxed_narrow_f64x2(a0, a1),
6263 self.relaxed_narrow_f64x2(b0, b1),
6264 )
6265 }
6266 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
6267 #[inline(always)]
6268 fn cvt_u64_f64x4(self, a: f64x4<Self>) -> u64x4<Self> {
6269 let (a0, a1) = self.split_f64x4(a);
6270 self.combine_u64x2(self.cvt_u64_f64x2(a0), self.cvt_u64_f64x2(a1))
6271 }
6272 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
6273 #[inline(always)]
6274 fn cvt_u64_precise_f64x4(self, a: f64x4<Self>) -> u64x4<Self> {
6275 let (a0, a1) = self.split_f64x4(a);
6276 self.combine_u64x2(
6277 self.cvt_u64_precise_f64x2(a0),
6278 self.cvt_u64_precise_f64x2(a1),
6279 )
6280 }
6281 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
6282 #[inline(always)]
6283 fn cvt_i64_f64x4(self, a: f64x4<Self>) -> i64x4<Self> {
6284 let (a0, a1) = self.split_f64x4(a);
6285 self.combine_i64x2(self.cvt_i64_f64x2(a0), self.cvt_i64_f64x2(a1))
6286 }
6287 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
6288 #[inline(always)]
6289 fn cvt_i64_precise_f64x4(self, a: f64x4<Self>) -> i64x4<Self> {
6290 let (a0, a1) = self.split_f64x4(a);
6291 self.combine_i64x2(
6292 self.cvt_i64_precise_f64x2(a0),
6293 self.cvt_i64_precise_f64x2(a1),
6294 )
6295 }
6296 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
6297 #[inline(always)]
6298 fn abs_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6299 let (a0, a1) = self.split_i64x4(a);
6300 self.combine_i64x2(self.abs_i64x2(a0), self.abs_i64x2(a1))
6301 }
6302 #[doc = "Create a SIMD vector with all elements set to the given value."]
6303 #[inline(always)]
6304 fn splat_i64x4(self, val: i64) -> i64x4<Self> {
6305 let half = self.splat_i64x2(val);
6306 self.combine_i64x2(half, half)
6307 }
6308 #[doc = "Reverse the order of the vector's elements."]
6309 #[inline(always)]
6310 fn reverse_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6311 let (a0, a1) = self.split_i64x4(a);
6312 self.combine_i64x2(self.reverse_i64x2(a1), self.reverse_i64x2(a0))
6313 }
6314 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
6315 fn slide_i64x4<const SHIFT: usize>(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self>;
6316 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
6317 #[inline(always)]
6318 fn slide_within_blocks_i64x4<const SHIFT: usize>(
6319 self,
6320 a: i64x4<Self>,
6321 b: i64x4<Self>,
6322 ) -> i64x4<Self> {
6323 let (a0, a1) = self.split_i64x4(a);
6324 let (b0, b1) = self.split_i64x4(b);
6325 self.combine_i64x2(
6326 self.slide_within_blocks_i64x2::<SHIFT>(a0, b0),
6327 self.slide_within_blocks_i64x2::<SHIFT>(a1, b1),
6328 )
6329 }
6330 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
6331 #[inline(always)]
6332 fn swizzle_dyn_within_blocks_i64x4(self, a: i64x4<Self>, indices: u8x32<Self>) -> i64x4<Self> {
6333 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
6334 }
6335 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
6336 #[inline(always)]
6337 fn swizzle_dyn_i64x4(self, a: i64x4<Self>, indices: u8x32<Self>) -> i64x4<Self> {
6338 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
6339 }
6340 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
6341 #[inline(always)]
6342 fn swizzle_dyn_precise_i64x4(self, a: i64x4<Self>, indices: u8x32<Self>) -> i64x4<Self> {
6343 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
6344 }
6345 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
6346 #[inline(always)]
6347 fn concat_swizzle_dyn_i64x4(
6348 self,
6349 a: i64x4<Self>,
6350 b: i64x4<Self>,
6351 indices: u8x32<Self>,
6352 ) -> i64x4<Self> {
6353 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
6354 Bytes::to_bytes(a),
6355 Bytes::to_bytes(b),
6356 indices,
6357 ))
6358 }
6359 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
6360 #[inline(always)]
6361 fn concat_swizzle_dyn_precise_i64x4(
6362 self,
6363 a: i64x4<Self>,
6364 b: i64x4<Self>,
6365 indices: u8x32<Self>,
6366 ) -> i64x4<Self> {
6367 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
6368 Bytes::to_bytes(a),
6369 Bytes::to_bytes(b),
6370 indices,
6371 ))
6372 }
6373 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
6374 fn compress_i64x4(self, values: i64x4<Self>, mask: mask64x4<Self>) -> i64x4<Self>;
6375 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
6376 fn compress_merge_i64x4(
6377 self,
6378 values: i64x4<Self>,
6379 mask: mask64x4<Self>,
6380 merge: i64x4<Self>,
6381 ) -> i64x4<Self>;
6382 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
6383 fn expand_i64x4(self, values: i64x4<Self>, mask: mask64x4<Self>) -> i64x4<Self>;
6384 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
6385 fn expand_merge_i64x4(
6386 self,
6387 values: i64x4<Self>,
6388 mask: mask64x4<Self>,
6389 merge: i64x4<Self>,
6390 ) -> i64x4<Self>;
6391 #[doc = "Return the number of ones in the binary representation of each element."]
6392 #[inline(always)]
6393 fn count_ones_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6394 let (a0, a1) = self.split_i64x4(a);
6395 self.combine_i64x2(self.count_ones_i64x2(a0), self.count_ones_i64x2(a1))
6396 }
6397 #[doc = "Return the number of zeros in the binary representation of each element."]
6398 #[inline(always)]
6399 fn count_zeros_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6400 let (a0, a1) = self.split_i64x4(a);
6401 self.combine_i64x2(self.count_zeros_i64x2(a0), self.count_zeros_i64x2(a1))
6402 }
6403 #[doc = "Add two vectors element-wise, wrapping on overflow."]
6404 #[inline(always)]
6405 fn add_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6406 let (a0, a1) = self.split_i64x4(a);
6407 let (b0, b1) = self.split_i64x4(b);
6408 self.combine_i64x2(self.add_i64x2(a0, b0), self.add_i64x2(a1, b1))
6409 }
6410 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
6411 #[inline(always)]
6412 fn saturating_add_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6413 let (a0, a1) = self.split_i64x4(a);
6414 let (b0, b1) = self.split_i64x4(b);
6415 self.combine_i64x2(
6416 self.saturating_add_i64x2(a0, b0),
6417 self.saturating_add_i64x2(a1, b1),
6418 )
6419 }
6420 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
6421 #[inline(always)]
6422 fn sub_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6423 let (a0, a1) = self.split_i64x4(a);
6424 let (b0, b1) = self.split_i64x4(b);
6425 self.combine_i64x2(self.sub_i64x2(a0, b0), self.sub_i64x2(a1, b1))
6426 }
6427 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
6428 #[inline(always)]
6429 fn saturating_sub_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6430 let (a0, a1) = self.split_i64x4(a);
6431 let (b0, b1) = self.split_i64x4(b);
6432 self.combine_i64x2(
6433 self.saturating_sub_i64x2(a0, b0),
6434 self.saturating_sub_i64x2(a1, b1),
6435 )
6436 }
6437 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
6438 #[inline(always)]
6439 fn mul_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6440 let (a0, a1) = self.split_i64x4(a);
6441 let (b0, b1) = self.split_i64x4(b);
6442 self.combine_i64x2(self.mul_i64x2(a0, b0), self.mul_i64x2(a1, b1))
6443 }
6444 #[doc = "Compute the bitwise AND of two vectors."]
6445 #[inline(always)]
6446 fn and_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6447 let (a0, a1) = self.split_i64x4(a);
6448 let (b0, b1) = self.split_i64x4(b);
6449 self.combine_i64x2(self.and_i64x2(a0, b0), self.and_i64x2(a1, b1))
6450 }
6451 #[doc = "Compute the bitwise OR of two vectors."]
6452 #[inline(always)]
6453 fn or_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6454 let (a0, a1) = self.split_i64x4(a);
6455 let (b0, b1) = self.split_i64x4(b);
6456 self.combine_i64x2(self.or_i64x2(a0, b0), self.or_i64x2(a1, b1))
6457 }
6458 #[doc = "Compute the bitwise XOR of two vectors."]
6459 #[inline(always)]
6460 fn xor_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6461 let (a0, a1) = self.split_i64x4(a);
6462 let (b0, b1) = self.split_i64x4(b);
6463 self.combine_i64x2(self.xor_i64x2(a0, b0), self.xor_i64x2(a1, b1))
6464 }
6465 #[doc = "Compute the bitwise NOT of the vector."]
6466 #[inline(always)]
6467 fn not_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6468 let (a0, a1) = self.split_i64x4(a);
6469 self.combine_i64x2(self.not_i64x2(a0), self.not_i64x2(a1))
6470 }
6471 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
6472 #[inline(always)]
6473 fn shl_i64x4(self, a: i64x4<Self>, shift: u32) -> i64x4<Self> {
6474 let (a0, a1) = self.split_i64x4(a);
6475 self.combine_i64x2(self.shl_i64x2(a0, shift), self.shl_i64x2(a1, shift))
6476 }
6477 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
6478 #[inline(always)]
6479 fn shlv_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6480 let (a0, a1) = self.split_i64x4(a);
6481 let (b0, b1) = self.split_i64x4(b);
6482 self.combine_i64x2(self.shlv_i64x2(a0, b0), self.shlv_i64x2(a1, b1))
6483 }
6484 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
6485 #[inline(always)]
6486 fn shr_i64x4(self, a: i64x4<Self>, shift: u32) -> i64x4<Self> {
6487 let (a0, a1) = self.split_i64x4(a);
6488 self.combine_i64x2(self.shr_i64x2(a0, shift), self.shr_i64x2(a1, shift))
6489 }
6490 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
6491 #[inline(always)]
6492 fn shrv_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6493 let (a0, a1) = self.split_i64x4(a);
6494 let (b0, b1) = self.split_i64x4(b);
6495 self.combine_i64x2(self.shrv_i64x2(a0, b0), self.shrv_i64x2(a1, b1))
6496 }
6497 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
6498 #[inline(always)]
6499 fn reduce_max_i64x4(self, a: i64x4<Self>) -> i64 {
6500 let (a0, a1) = self.split_i64x4(a);
6501 self.reduce_max_i64x2(self.max_i64x2(a0, a1))
6502 }
6503 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
6504 #[inline(always)]
6505 fn reduce_min_i64x4(self, a: i64x4<Self>) -> i64 {
6506 let (a0, a1) = self.split_i64x4(a);
6507 self.reduce_min_i64x2(self.min_i64x2(a0, a1))
6508 }
6509 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
6510 #[inline(always)]
6511 fn reduce_sum_i64x4(self, a: i64x4<Self>) -> i64 {
6512 let (a0, a1) = self.split_i64x4(a);
6513 self.reduce_sum_i64x2(self.add_i64x2(a0, a1))
6514 }
6515 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
6516 #[inline(always)]
6517 fn reduce_product_i64x4(self, a: i64x4<Self>) -> i64 {
6518 let (a0, a1) = self.split_i64x4(a);
6519 self.reduce_product_i64x2(self.mul_i64x2(a0, a1))
6520 }
6521 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
6522 #[inline(always)]
6523 fn max_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6524 let (a0, a1) = self.split_i64x4(a);
6525 let (b0, b1) = self.split_i64x4(b);
6526 self.combine_i64x2(self.max_i64x2(a0, b0), self.max_i64x2(a1, b1))
6527 }
6528 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
6529 #[inline(always)]
6530 fn min_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6531 let (a0, a1) = self.split_i64x4(a);
6532 let (b0, b1) = self.split_i64x4(b);
6533 self.combine_i64x2(self.min_i64x2(a0, b0), self.min_i64x2(a1, b1))
6534 }
6535 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
6536 #[inline(always)]
6537 fn clamp_i64x4(self, a: i64x4<Self>, b: i64x4<Self>, c: i64x4<Self>) -> i64x4<Self> {
6538 let (a0, a1) = self.split_i64x4(a);
6539 let (b0, b1) = self.split_i64x4(b);
6540 let (c0, c1) = self.split_i64x4(c);
6541 self.combine_i64x2(self.clamp_i64x2(a0, b0, c0), self.clamp_i64x2(a1, b1, c1))
6542 }
6543 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
6544 #[inline(always)]
6545 fn simd_eq_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6546 let (a0, a1) = self.split_i64x4(a);
6547 let (b0, b1) = self.split_i64x4(b);
6548 self.combine_mask64x2(self.simd_eq_i64x2(a0, b0), self.simd_eq_i64x2(a1, b1))
6549 }
6550 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
6551 #[inline(always)]
6552 fn simd_ne_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6553 self.not_mask64x4(self.simd_eq_i64x4(a, b))
6554 }
6555 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
6556 #[inline(always)]
6557 fn simd_lt_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6558 let (a0, a1) = self.split_i64x4(a);
6559 let (b0, b1) = self.split_i64x4(b);
6560 self.combine_mask64x2(self.simd_lt_i64x2(a0, b0), self.simd_lt_i64x2(a1, b1))
6561 }
6562 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
6563 #[inline(always)]
6564 fn simd_le_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6565 let (a0, a1) = self.split_i64x4(a);
6566 let (b0, b1) = self.split_i64x4(b);
6567 self.combine_mask64x2(self.simd_le_i64x2(a0, b0), self.simd_le_i64x2(a1, b1))
6568 }
6569 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
6570 #[inline(always)]
6571 fn simd_ge_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6572 self.simd_le_i64x4(b, a)
6573 }
6574 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
6575 #[inline(always)]
6576 fn simd_gt_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> mask64x4<Self> {
6577 self.simd_lt_i64x4(b, a)
6578 }
6579 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6580 #[inline(always)]
6581 fn zip_low_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6582 let (a0, _) = self.split_i64x4(a);
6583 let (b0, _) = self.split_i64x4(b);
6584 self.combine_i64x2(self.zip_low_i64x2(a0, b0), self.zip_high_i64x2(a0, b0))
6585 }
6586 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6587 #[inline(always)]
6588 fn zip_high_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6589 let (_, a1) = self.split_i64x4(a);
6590 let (_, b1) = self.split_i64x4(b);
6591 self.combine_i64x2(self.zip_low_i64x2(a1, b1), self.zip_high_i64x2(a1, b1))
6592 }
6593 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6594 #[inline(always)]
6595 fn unzip_low_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6596 let (a0, a1) = self.split_i64x4(a);
6597 let (b0, b1) = self.split_i64x4(b);
6598 self.combine_i64x2(self.unzip_low_i64x2(a0, a1), self.unzip_low_i64x2(b0, b1))
6599 }
6600 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6601 #[inline(always)]
6602 fn unzip_high_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x4<Self> {
6603 let (a0, a1) = self.split_i64x4(a);
6604 let (b0, b1) = self.split_i64x4(b);
6605 self.combine_i64x2(self.unzip_high_i64x2(a0, a1), self.unzip_high_i64x2(b0, b1))
6606 }
6607 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
6608 #[inline(always)]
6609 fn interleave_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> (i64x4<Self>, i64x4<Self>) {
6610 let (a0, a1) = self.split_i64x4(a);
6611 let (b0, b1) = self.split_i64x4(b);
6612 let lo_lo = self.zip_low_i64x2(a0, b0);
6613 let lo_hi = self.zip_high_i64x2(a0, b0);
6614 let hi_lo = self.zip_low_i64x2(a1, b1);
6615 let hi_hi = self.zip_high_i64x2(a1, b1);
6616 (
6617 self.combine_i64x2(lo_lo, lo_hi),
6618 self.combine_i64x2(hi_lo, hi_hi),
6619 )
6620 }
6621 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
6622 #[inline(always)]
6623 fn deinterleave_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> (i64x4<Self>, i64x4<Self>) {
6624 let (a0, a1) = self.split_i64x4(a);
6625 let (b0, b1) = self.split_i64x4(b);
6626 let lo_even = self.unzip_low_i64x2(a0, a1);
6627 let lo_odd = self.unzip_high_i64x2(a0, a1);
6628 let hi_even = self.unzip_low_i64x2(b0, b1);
6629 let hi_odd = self.unzip_high_i64x2(b0, b1);
6630 (
6631 self.combine_i64x2(lo_even, hi_even),
6632 self.combine_i64x2(lo_odd, hi_odd),
6633 )
6634 }
6635 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
6636 #[inline(always)]
6637 fn select_i64x4(self, a: mask64x4<Self>, b: i64x4<Self>, c: i64x4<Self>) -> i64x4<Self> {
6638 let (a0, a1) = self.split_mask64x4(a);
6639 let (b0, b1) = self.split_i64x4(b);
6640 let (c0, c1) = self.split_i64x4(c);
6641 self.combine_i64x2(self.select_i64x2(a0, b0, c0), self.select_i64x2(a1, b1, c1))
6642 }
6643 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
6644 fn combine_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i64x8<Self>;
6645 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
6646 fn split_i64x4(self, a: i64x4<Self>) -> (i64x2<Self>, i64x2<Self>);
6647 #[doc = "Negate each element of the vector, wrapping on overflow."]
6648 #[inline(always)]
6649 fn neg_i64x4(self, a: i64x4<Self>) -> i64x4<Self> {
6650 let (a0, a1) = self.split_i64x4(a);
6651 self.combine_i64x2(self.neg_i64x2(a0), self.neg_i64x2(a1))
6652 }
6653 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
6654 #[inline(always)]
6655 fn narrow_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i32x8<Self> {
6656 let (a0, a1) = self.split_i64x4(a);
6657 let (b0, b1) = self.split_i64x4(b);
6658 self.combine_i32x4(self.narrow_i64x2(a0, a1), self.narrow_i64x2(b0, b1))
6659 }
6660 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
6661 #[inline(always)]
6662 fn saturating_narrow_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i32x8<Self> {
6663 let (a0, a1) = self.split_i64x4(a);
6664 let (b0, b1) = self.split_i64x4(b);
6665 self.combine_i32x4(
6666 self.saturating_narrow_i64x2(a0, a1),
6667 self.saturating_narrow_i64x2(b0, b1),
6668 )
6669 }
6670 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
6671 #[inline(always)]
6672 fn relaxed_narrow_i64x4(self, a: i64x4<Self>, b: i64x4<Self>) -> i32x8<Self> {
6673 let (a0, a1) = self.split_i64x4(a);
6674 let (b0, b1) = self.split_i64x4(b);
6675 self.combine_i32x4(
6676 self.relaxed_narrow_i64x2(a0, a1),
6677 self.relaxed_narrow_i64x2(b0, b1),
6678 )
6679 }
6680 #[doc = "Convert each signed 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
6681 #[inline(always)]
6682 fn cvt_f64_i64x4(self, a: i64x4<Self>) -> f64x4<Self> {
6683 let (a0, a1) = self.split_i64x4(a);
6684 self.combine_f64x2(self.cvt_f64_i64x2(a0), self.cvt_f64_i64x2(a1))
6685 }
6686 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
6687 #[inline(always)]
6688 fn abs_u64x4(self, a: u64x4<Self>) -> u64x4<Self> {
6689 a
6690 }
6691 #[doc = "Create a SIMD vector with all elements set to the given value."]
6692 #[inline(always)]
6693 fn splat_u64x4(self, val: u64) -> u64x4<Self> {
6694 let half = self.splat_u64x2(val);
6695 self.combine_u64x2(half, half)
6696 }
6697 #[doc = "Reverse the order of the vector's elements."]
6698 #[inline(always)]
6699 fn reverse_u64x4(self, a: u64x4<Self>) -> u64x4<Self> {
6700 let (a0, a1) = self.split_u64x4(a);
6701 self.combine_u64x2(self.reverse_u64x2(a1), self.reverse_u64x2(a0))
6702 }
6703 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
6704 fn slide_u64x4<const SHIFT: usize>(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self>;
6705 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
6706 #[inline(always)]
6707 fn slide_within_blocks_u64x4<const SHIFT: usize>(
6708 self,
6709 a: u64x4<Self>,
6710 b: u64x4<Self>,
6711 ) -> u64x4<Self> {
6712 let (a0, a1) = self.split_u64x4(a);
6713 let (b0, b1) = self.split_u64x4(b);
6714 self.combine_u64x2(
6715 self.slide_within_blocks_u64x2::<SHIFT>(a0, b0),
6716 self.slide_within_blocks_u64x2::<SHIFT>(a1, b1),
6717 )
6718 }
6719 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
6720 #[inline(always)]
6721 fn swizzle_dyn_within_blocks_u64x4(self, a: u64x4<Self>, indices: u8x32<Self>) -> u64x4<Self> {
6722 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x32(Bytes::to_bytes(a), indices))
6723 }
6724 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
6725 #[inline(always)]
6726 fn swizzle_dyn_u64x4(self, a: u64x4<Self>, indices: u8x32<Self>) -> u64x4<Self> {
6727 Bytes::from_bytes(self.swizzle_dyn_u8x32(Bytes::to_bytes(a), indices))
6728 }
6729 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
6730 #[inline(always)]
6731 fn swizzle_dyn_precise_u64x4(self, a: u64x4<Self>, indices: u8x32<Self>) -> u64x4<Self> {
6732 Bytes::from_bytes(self.swizzle_dyn_precise_u8x32(Bytes::to_bytes(a), indices))
6733 }
6734 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
6735 #[inline(always)]
6736 fn concat_swizzle_dyn_u64x4(
6737 self,
6738 a: u64x4<Self>,
6739 b: u64x4<Self>,
6740 indices: u8x32<Self>,
6741 ) -> u64x4<Self> {
6742 Bytes::from_bytes(self.concat_swizzle_dyn_u8x32(
6743 Bytes::to_bytes(a),
6744 Bytes::to_bytes(b),
6745 indices,
6746 ))
6747 }
6748 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
6749 #[inline(always)]
6750 fn concat_swizzle_dyn_precise_u64x4(
6751 self,
6752 a: u64x4<Self>,
6753 b: u64x4<Self>,
6754 indices: u8x32<Self>,
6755 ) -> u64x4<Self> {
6756 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x32(
6757 Bytes::to_bytes(a),
6758 Bytes::to_bytes(b),
6759 indices,
6760 ))
6761 }
6762 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
6763 fn compress_u64x4(self, values: u64x4<Self>, mask: mask64x4<Self>) -> u64x4<Self>;
6764 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
6765 fn compress_merge_u64x4(
6766 self,
6767 values: u64x4<Self>,
6768 mask: mask64x4<Self>,
6769 merge: u64x4<Self>,
6770 ) -> u64x4<Self>;
6771 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
6772 fn expand_u64x4(self, values: u64x4<Self>, mask: mask64x4<Self>) -> u64x4<Self>;
6773 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
6774 fn expand_merge_u64x4(
6775 self,
6776 values: u64x4<Self>,
6777 mask: mask64x4<Self>,
6778 merge: u64x4<Self>,
6779 ) -> u64x4<Self>;
6780 #[doc = "Return the number of ones in the binary representation of each element."]
6781 #[inline(always)]
6782 fn count_ones_u64x4(self, a: u64x4<Self>) -> u64x4<Self> {
6783 let (a0, a1) = self.split_u64x4(a);
6784 self.combine_u64x2(self.count_ones_u64x2(a0), self.count_ones_u64x2(a1))
6785 }
6786 #[doc = "Return the number of zeros in the binary representation of each element."]
6787 #[inline(always)]
6788 fn count_zeros_u64x4(self, a: u64x4<Self>) -> u64x4<Self> {
6789 let (a0, a1) = self.split_u64x4(a);
6790 self.combine_u64x2(self.count_zeros_u64x2(a0), self.count_zeros_u64x2(a1))
6791 }
6792 #[doc = "Add two vectors element-wise, wrapping on overflow."]
6793 #[inline(always)]
6794 fn add_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6795 let (a0, a1) = self.split_u64x4(a);
6796 let (b0, b1) = self.split_u64x4(b);
6797 self.combine_u64x2(self.add_u64x2(a0, b0), self.add_u64x2(a1, b1))
6798 }
6799 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
6800 #[inline(always)]
6801 fn saturating_add_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6802 let (a0, a1) = self.split_u64x4(a);
6803 let (b0, b1) = self.split_u64x4(b);
6804 self.combine_u64x2(
6805 self.saturating_add_u64x2(a0, b0),
6806 self.saturating_add_u64x2(a1, b1),
6807 )
6808 }
6809 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
6810 #[inline(always)]
6811 fn sub_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6812 let (a0, a1) = self.split_u64x4(a);
6813 let (b0, b1) = self.split_u64x4(b);
6814 self.combine_u64x2(self.sub_u64x2(a0, b0), self.sub_u64x2(a1, b1))
6815 }
6816 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
6817 #[inline(always)]
6818 fn saturating_sub_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6819 let (a0, a1) = self.split_u64x4(a);
6820 let (b0, b1) = self.split_u64x4(b);
6821 self.combine_u64x2(
6822 self.saturating_sub_u64x2(a0, b0),
6823 self.saturating_sub_u64x2(a1, b1),
6824 )
6825 }
6826 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
6827 #[inline(always)]
6828 fn mul_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6829 let (a0, a1) = self.split_u64x4(a);
6830 let (b0, b1) = self.split_u64x4(b);
6831 self.combine_u64x2(self.mul_u64x2(a0, b0), self.mul_u64x2(a1, b1))
6832 }
6833 #[doc = "Compute the bitwise AND of two vectors."]
6834 #[inline(always)]
6835 fn and_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6836 let (a0, a1) = self.split_u64x4(a);
6837 let (b0, b1) = self.split_u64x4(b);
6838 self.combine_u64x2(self.and_u64x2(a0, b0), self.and_u64x2(a1, b1))
6839 }
6840 #[doc = "Compute the bitwise OR of two vectors."]
6841 #[inline(always)]
6842 fn or_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6843 let (a0, a1) = self.split_u64x4(a);
6844 let (b0, b1) = self.split_u64x4(b);
6845 self.combine_u64x2(self.or_u64x2(a0, b0), self.or_u64x2(a1, b1))
6846 }
6847 #[doc = "Compute the bitwise XOR of two vectors."]
6848 #[inline(always)]
6849 fn xor_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6850 let (a0, a1) = self.split_u64x4(a);
6851 let (b0, b1) = self.split_u64x4(b);
6852 self.combine_u64x2(self.xor_u64x2(a0, b0), self.xor_u64x2(a1, b1))
6853 }
6854 #[doc = "Compute the bitwise NOT of the vector."]
6855 #[inline(always)]
6856 fn not_u64x4(self, a: u64x4<Self>) -> u64x4<Self> {
6857 let (a0, a1) = self.split_u64x4(a);
6858 self.combine_u64x2(self.not_u64x2(a0), self.not_u64x2(a1))
6859 }
6860 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
6861 #[inline(always)]
6862 fn shl_u64x4(self, a: u64x4<Self>, shift: u32) -> u64x4<Self> {
6863 let (a0, a1) = self.split_u64x4(a);
6864 self.combine_u64x2(self.shl_u64x2(a0, shift), self.shl_u64x2(a1, shift))
6865 }
6866 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
6867 #[inline(always)]
6868 fn shlv_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6869 let (a0, a1) = self.split_u64x4(a);
6870 let (b0, b1) = self.split_u64x4(b);
6871 self.combine_u64x2(self.shlv_u64x2(a0, b0), self.shlv_u64x2(a1, b1))
6872 }
6873 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
6874 #[inline(always)]
6875 fn shr_u64x4(self, a: u64x4<Self>, shift: u32) -> u64x4<Self> {
6876 let (a0, a1) = self.split_u64x4(a);
6877 self.combine_u64x2(self.shr_u64x2(a0, shift), self.shr_u64x2(a1, shift))
6878 }
6879 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
6880 #[inline(always)]
6881 fn shrv_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6882 let (a0, a1) = self.split_u64x4(a);
6883 let (b0, b1) = self.split_u64x4(b);
6884 self.combine_u64x2(self.shrv_u64x2(a0, b0), self.shrv_u64x2(a1, b1))
6885 }
6886 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
6887 #[inline(always)]
6888 fn reduce_max_u64x4(self, a: u64x4<Self>) -> u64 {
6889 let (a0, a1) = self.split_u64x4(a);
6890 self.reduce_max_u64x2(self.max_u64x2(a0, a1))
6891 }
6892 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
6893 #[inline(always)]
6894 fn reduce_min_u64x4(self, a: u64x4<Self>) -> u64 {
6895 let (a0, a1) = self.split_u64x4(a);
6896 self.reduce_min_u64x2(self.min_u64x2(a0, a1))
6897 }
6898 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
6899 #[inline(always)]
6900 fn reduce_sum_u64x4(self, a: u64x4<Self>) -> u64 {
6901 let (a0, a1) = self.split_u64x4(a);
6902 self.reduce_sum_u64x2(self.add_u64x2(a0, a1))
6903 }
6904 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
6905 #[inline(always)]
6906 fn reduce_product_u64x4(self, a: u64x4<Self>) -> u64 {
6907 let (a0, a1) = self.split_u64x4(a);
6908 self.reduce_product_u64x2(self.mul_u64x2(a0, a1))
6909 }
6910 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
6911 #[inline(always)]
6912 fn max_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6913 let (a0, a1) = self.split_u64x4(a);
6914 let (b0, b1) = self.split_u64x4(b);
6915 self.combine_u64x2(self.max_u64x2(a0, b0), self.max_u64x2(a1, b1))
6916 }
6917 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
6918 #[inline(always)]
6919 fn min_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6920 let (a0, a1) = self.split_u64x4(a);
6921 let (b0, b1) = self.split_u64x4(b);
6922 self.combine_u64x2(self.min_u64x2(a0, b0), self.min_u64x2(a1, b1))
6923 }
6924 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
6925 #[inline(always)]
6926 fn clamp_u64x4(self, a: u64x4<Self>, b: u64x4<Self>, c: u64x4<Self>) -> u64x4<Self> {
6927 let (a0, a1) = self.split_u64x4(a);
6928 let (b0, b1) = self.split_u64x4(b);
6929 let (c0, c1) = self.split_u64x4(c);
6930 self.combine_u64x2(self.clamp_u64x2(a0, b0, c0), self.clamp_u64x2(a1, b1, c1))
6931 }
6932 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
6933 #[inline(always)]
6934 fn simd_eq_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6935 let (a0, a1) = self.split_u64x4(a);
6936 let (b0, b1) = self.split_u64x4(b);
6937 self.combine_mask64x2(self.simd_eq_u64x2(a0, b0), self.simd_eq_u64x2(a1, b1))
6938 }
6939 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
6940 #[inline(always)]
6941 fn simd_ne_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6942 self.not_mask64x4(self.simd_eq_u64x4(a, b))
6943 }
6944 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
6945 #[inline(always)]
6946 fn simd_lt_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6947 let (a0, a1) = self.split_u64x4(a);
6948 let (b0, b1) = self.split_u64x4(b);
6949 self.combine_mask64x2(self.simd_lt_u64x2(a0, b0), self.simd_lt_u64x2(a1, b1))
6950 }
6951 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
6952 #[inline(always)]
6953 fn simd_le_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6954 let (a0, a1) = self.split_u64x4(a);
6955 let (b0, b1) = self.split_u64x4(b);
6956 self.combine_mask64x2(self.simd_le_u64x2(a0, b0), self.simd_le_u64x2(a1, b1))
6957 }
6958 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
6959 #[inline(always)]
6960 fn simd_ge_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6961 self.simd_le_u64x4(b, a)
6962 }
6963 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
6964 #[inline(always)]
6965 fn simd_gt_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> mask64x4<Self> {
6966 self.simd_lt_u64x4(b, a)
6967 }
6968 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6969 #[inline(always)]
6970 fn zip_low_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6971 let (a0, _) = self.split_u64x4(a);
6972 let (b0, _) = self.split_u64x4(b);
6973 self.combine_u64x2(self.zip_low_u64x2(a0, b0), self.zip_high_u64x2(a0, b0))
6974 }
6975 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
6976 #[inline(always)]
6977 fn zip_high_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6978 let (_, a1) = self.split_u64x4(a);
6979 let (_, b1) = self.split_u64x4(b);
6980 self.combine_u64x2(self.zip_low_u64x2(a1, b1), self.zip_high_u64x2(a1, b1))
6981 }
6982 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6983 #[inline(always)]
6984 fn unzip_low_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6985 let (a0, a1) = self.split_u64x4(a);
6986 let (b0, b1) = self.split_u64x4(b);
6987 self.combine_u64x2(self.unzip_low_u64x2(a0, a1), self.unzip_low_u64x2(b0, b1))
6988 }
6989 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
6990 #[inline(always)]
6991 fn unzip_high_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x4<Self> {
6992 let (a0, a1) = self.split_u64x4(a);
6993 let (b0, b1) = self.split_u64x4(b);
6994 self.combine_u64x2(self.unzip_high_u64x2(a0, a1), self.unzip_high_u64x2(b0, b1))
6995 }
6996 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
6997 #[inline(always)]
6998 fn interleave_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> (u64x4<Self>, u64x4<Self>) {
6999 let (a0, a1) = self.split_u64x4(a);
7000 let (b0, b1) = self.split_u64x4(b);
7001 let lo_lo = self.zip_low_u64x2(a0, b0);
7002 let lo_hi = self.zip_high_u64x2(a0, b0);
7003 let hi_lo = self.zip_low_u64x2(a1, b1);
7004 let hi_hi = self.zip_high_u64x2(a1, b1);
7005 (
7006 self.combine_u64x2(lo_lo, lo_hi),
7007 self.combine_u64x2(hi_lo, hi_hi),
7008 )
7009 }
7010 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
7011 #[inline(always)]
7012 fn deinterleave_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> (u64x4<Self>, u64x4<Self>) {
7013 let (a0, a1) = self.split_u64x4(a);
7014 let (b0, b1) = self.split_u64x4(b);
7015 let lo_even = self.unzip_low_u64x2(a0, a1);
7016 let lo_odd = self.unzip_high_u64x2(a0, a1);
7017 let hi_even = self.unzip_low_u64x2(b0, b1);
7018 let hi_odd = self.unzip_high_u64x2(b0, b1);
7019 (
7020 self.combine_u64x2(lo_even, hi_even),
7021 self.combine_u64x2(lo_odd, hi_odd),
7022 )
7023 }
7024 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
7025 #[inline(always)]
7026 fn select_u64x4(self, a: mask64x4<Self>, b: u64x4<Self>, c: u64x4<Self>) -> u64x4<Self> {
7027 let (a0, a1) = self.split_mask64x4(a);
7028 let (b0, b1) = self.split_u64x4(b);
7029 let (c0, c1) = self.split_u64x4(c);
7030 self.combine_u64x2(self.select_u64x2(a0, b0, c0), self.select_u64x2(a1, b1, c1))
7031 }
7032 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
7033 fn combine_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u64x8<Self>;
7034 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
7035 fn split_u64x4(self, a: u64x4<Self>) -> (u64x2<Self>, u64x2<Self>);
7036 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
7037 #[inline(always)]
7038 fn narrow_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u32x8<Self> {
7039 let (a0, a1) = self.split_u64x4(a);
7040 let (b0, b1) = self.split_u64x4(b);
7041 self.combine_u32x4(self.narrow_u64x2(a0, a1), self.narrow_u64x2(b0, b1))
7042 }
7043 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
7044 #[inline(always)]
7045 fn saturating_narrow_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u32x8<Self> {
7046 let (a0, a1) = self.split_u64x4(a);
7047 let (b0, b1) = self.split_u64x4(b);
7048 self.combine_u32x4(
7049 self.saturating_narrow_u64x2(a0, a1),
7050 self.saturating_narrow_u64x2(b0, b1),
7051 )
7052 }
7053 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
7054 #[inline(always)]
7055 fn relaxed_narrow_u64x4(self, a: u64x4<Self>, b: u64x4<Self>) -> u32x8<Self> {
7056 let (a0, a1) = self.split_u64x4(a);
7057 let (b0, b1) = self.split_u64x4(b);
7058 self.combine_u32x4(
7059 self.relaxed_narrow_u64x2(a0, a1),
7060 self.relaxed_narrow_u64x2(b0, b1),
7061 )
7062 }
7063 #[doc = "Convert each unsigned 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
7064 #[inline(always)]
7065 fn cvt_f64_u64x4(self, a: u64x4<Self>) -> f64x4<Self> {
7066 let (a0, a1) = self.split_u64x4(a);
7067 self.combine_f64x2(self.cvt_f64_u64x2(a0), self.cvt_f64_u64x2(a1))
7068 }
7069 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
7070 #[inline(always)]
7071 fn splat_mask64x4(self, val: bool) -> mask64x4<Self> {
7072 let half = self.splat_mask64x2(val);
7073 self.combine_mask64x2(half, half)
7074 }
7075 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
7076 #[inline(always)]
7077 fn from_bitmask_mask64x4(self, bits: u64) -> mask64x4<Self> {
7078 let lo = self.from_bitmask_mask64x2(bits);
7079 let hi = self.from_bitmask_mask64x2(bits >> 2usize);
7080 self.combine_mask64x2(lo, hi)
7081 }
7082 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
7083 #[inline(always)]
7084 fn to_bitmask_mask64x4(self, a: mask64x4<Self>) -> u64 {
7085 let (lo, hi) = self.split_mask64x4(a);
7086 let lo = self.to_bitmask_mask64x2(lo);
7087 let hi = self.to_bitmask_mask64x2(hi);
7088 lo | (hi << 2usize)
7089 }
7090 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
7091 fn from_vector_mask64x4(self, vector: i64x4<Self>) -> mask64x4<Self>;
7092 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
7093 fn to_vector_mask64x4(self, a: mask64x4<Self>) -> i64x4<Self>;
7094 #[doc = "Set one logical lane of a SIMD mask."]
7095 fn set_mask64x4(self, a: &mut mask64x4<Self>, index: usize, value: bool) -> ();
7096 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
7097 fn rotate_elements_left_mask64x4<const OFFSET: usize>(
7098 self,
7099 a: mask64x4<Self>,
7100 ) -> mask64x4<Self>;
7101 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
7102 fn rotate_elements_right_mask64x4<const OFFSET: usize>(
7103 self,
7104 a: mask64x4<Self>,
7105 ) -> mask64x4<Self>;
7106 #[doc = "Compute the logical AND of two masks."]
7107 #[inline(always)]
7108 fn and_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x4<Self> {
7109 let (a0, a1) = self.split_mask64x4(a);
7110 let (b0, b1) = self.split_mask64x4(b);
7111 self.combine_mask64x2(self.and_mask64x2(a0, b0), self.and_mask64x2(a1, b1))
7112 }
7113 #[doc = "Compute the logical OR of two masks."]
7114 #[inline(always)]
7115 fn or_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x4<Self> {
7116 let (a0, a1) = self.split_mask64x4(a);
7117 let (b0, b1) = self.split_mask64x4(b);
7118 self.combine_mask64x2(self.or_mask64x2(a0, b0), self.or_mask64x2(a1, b1))
7119 }
7120 #[doc = "Compute the logical XOR of two masks."]
7121 #[inline(always)]
7122 fn xor_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x4<Self> {
7123 let (a0, a1) = self.split_mask64x4(a);
7124 let (b0, b1) = self.split_mask64x4(b);
7125 self.combine_mask64x2(self.xor_mask64x2(a0, b0), self.xor_mask64x2(a1, b1))
7126 }
7127 #[doc = "Compute the logical NOT of the mask."]
7128 #[inline(always)]
7129 fn not_mask64x4(self, a: mask64x4<Self>) -> mask64x4<Self> {
7130 let (a0, a1) = self.split_mask64x4(a);
7131 self.combine_mask64x2(self.not_mask64x2(a0), self.not_mask64x2(a1))
7132 }
7133 #[doc = "Reverse the order of the mask's logical lanes."]
7134 #[inline(always)]
7135 fn reverse_mask64x4(self, a: mask64x4<Self>) -> mask64x4<Self> {
7136 let (a0, a1) = self.split_mask64x4(a);
7137 self.combine_mask64x2(self.reverse_mask64x2(a1), self.reverse_mask64x2(a0))
7138 }
7139 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
7140 #[inline(always)]
7141 fn select_mask64x4(
7142 self,
7143 a: mask64x4<Self>,
7144 b: mask64x4<Self>,
7145 c: mask64x4<Self>,
7146 ) -> mask64x4<Self> {
7147 let (a0, a1) = self.split_mask64x4(a);
7148 let (b0, b1) = self.split_mask64x4(b);
7149 let (c0, c1) = self.split_mask64x4(c);
7150 self.combine_mask64x2(
7151 self.select_mask64x2(a0, b0, c0),
7152 self.select_mask64x2(a1, b1, c1),
7153 )
7154 }
7155 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
7156 #[inline(always)]
7157 fn simd_eq_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x4<Self> {
7158 let (a0, a1) = self.split_mask64x4(a);
7159 let (b0, b1) = self.split_mask64x4(b);
7160 self.combine_mask64x2(self.simd_eq_mask64x2(a0, b0), self.simd_eq_mask64x2(a1, b1))
7161 }
7162 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
7163 #[inline(always)]
7164 fn simd_ne_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x4<Self> {
7165 self.not_mask64x4(self.simd_eq_mask64x4(a, b))
7166 }
7167 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
7168 #[inline(always)]
7169 fn any_true_mask64x4(self, a: mask64x4<Self>) -> bool {
7170 let (a0, a1) = self.split_mask64x4(a);
7171 self.any_true_mask64x2(self.or_mask64x2(a0, a1))
7172 }
7173 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
7174 #[inline(always)]
7175 fn all_true_mask64x4(self, a: mask64x4<Self>) -> bool {
7176 let (a0, a1) = self.split_mask64x4(a);
7177 self.all_true_mask64x2(self.and_mask64x2(a0, a1))
7178 }
7179 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
7180 #[inline(always)]
7181 fn any_false_mask64x4(self, a: mask64x4<Self>) -> bool {
7182 let (a0, a1) = self.split_mask64x4(a);
7183 self.any_false_mask64x2(self.and_mask64x2(a0, a1))
7184 }
7185 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
7186 #[inline(always)]
7187 fn all_false_mask64x4(self, a: mask64x4<Self>) -> bool {
7188 let (a0, a1) = self.split_mask64x4(a);
7189 self.all_false_mask64x2(self.or_mask64x2(a0, a1))
7190 }
7191 #[doc = "Combine two vectors into a single vector with twice the width.\n\n`a` provides the lower elements and `b` provides the upper elements."]
7192 fn combine_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask64x8<Self>;
7193 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
7194 fn split_mask64x4(self, a: mask64x4<Self>) -> (mask64x2<Self>, mask64x2<Self>);
7195 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
7196 #[inline(always)]
7197 fn narrow_mask64x4(self, a: mask64x4<Self>, b: mask64x4<Self>) -> mask32x8<Self> {
7198 let (a0, a1) = self.split_mask64x4(a);
7199 let (b0, b1) = self.split_mask64x4(b);
7200 self.combine_mask32x4(self.narrow_mask64x2(a0, a1), self.narrow_mask64x2(b0, b1))
7201 }
7202 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
7203 #[inline(always)]
7204 fn abs_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7205 let (a0, a1) = self.split_f32x16(a);
7206 self.combine_f32x8(self.abs_f32x8(a0), self.abs_f32x8(a1))
7207 }
7208 #[doc = "Create a SIMD vector with all elements set to the given value."]
7209 #[inline(always)]
7210 fn splat_f32x16(self, val: f32) -> f32x16<Self> {
7211 let half = self.splat_f32x8(val);
7212 self.combine_f32x8(half, half)
7213 }
7214 #[doc = "Reverse the order of the vector's elements."]
7215 #[inline(always)]
7216 fn reverse_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7217 let (a0, a1) = self.split_f32x16(a);
7218 self.combine_f32x8(self.reverse_f32x8(a1), self.reverse_f32x8(a0))
7219 }
7220 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
7221 fn slide_f32x16<const SHIFT: usize>(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self>;
7222 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
7223 #[inline(always)]
7224 fn slide_within_blocks_f32x16<const SHIFT: usize>(
7225 self,
7226 a: f32x16<Self>,
7227 b: f32x16<Self>,
7228 ) -> f32x16<Self> {
7229 let (a0, a1) = self.split_f32x16(a);
7230 let (b0, b1) = self.split_f32x16(b);
7231 self.combine_f32x8(
7232 self.slide_within_blocks_f32x8::<SHIFT>(a0, b0),
7233 self.slide_within_blocks_f32x8::<SHIFT>(a1, b1),
7234 )
7235 }
7236 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
7237 #[inline(always)]
7238 fn swizzle_dyn_within_blocks_f32x16(
7239 self,
7240 a: f32x16<Self>,
7241 indices: u8x64<Self>,
7242 ) -> f32x16<Self> {
7243 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
7244 }
7245 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
7246 #[inline(always)]
7247 fn swizzle_dyn_f32x16(self, a: f32x16<Self>, indices: u8x64<Self>) -> f32x16<Self> {
7248 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
7249 }
7250 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
7251 #[inline(always)]
7252 fn swizzle_dyn_precise_f32x16(self, a: f32x16<Self>, indices: u8x64<Self>) -> f32x16<Self> {
7253 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
7254 }
7255 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
7256 #[inline(always)]
7257 fn concat_swizzle_dyn_f32x16(
7258 self,
7259 a: f32x16<Self>,
7260 b: f32x16<Self>,
7261 indices: u8x64<Self>,
7262 ) -> f32x16<Self> {
7263 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
7264 Bytes::to_bytes(a),
7265 Bytes::to_bytes(b),
7266 indices,
7267 ))
7268 }
7269 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
7270 #[inline(always)]
7271 fn concat_swizzle_dyn_precise_f32x16(
7272 self,
7273 a: f32x16<Self>,
7274 b: f32x16<Self>,
7275 indices: u8x64<Self>,
7276 ) -> f32x16<Self> {
7277 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
7278 Bytes::to_bytes(a),
7279 Bytes::to_bytes(b),
7280 indices,
7281 ))
7282 }
7283 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
7284 fn compress_f32x16(self, values: f32x16<Self>, mask: mask32x16<Self>) -> f32x16<Self>;
7285 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
7286 fn compress_merge_f32x16(
7287 self,
7288 values: f32x16<Self>,
7289 mask: mask32x16<Self>,
7290 merge: f32x16<Self>,
7291 ) -> f32x16<Self>;
7292 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
7293 fn expand_f32x16(self, values: f32x16<Self>, mask: mask32x16<Self>) -> f32x16<Self>;
7294 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
7295 fn expand_merge_f32x16(
7296 self,
7297 values: f32x16<Self>,
7298 mask: mask32x16<Self>,
7299 merge: f32x16<Self>,
7300 ) -> f32x16<Self>;
7301 #[doc = "Negate each element of the vector."]
7302 #[inline(always)]
7303 fn neg_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7304 let (a0, a1) = self.split_f32x16(a);
7305 self.combine_f32x8(self.neg_f32x8(a0), self.neg_f32x8(a1))
7306 }
7307 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
7308 #[inline(always)]
7309 fn sqrt_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7310 let (a0, a1) = self.split_f32x16(a);
7311 self.combine_f32x8(self.sqrt_f32x8(a0), self.sqrt_f32x8(a1))
7312 }
7313 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
7314 #[inline(always)]
7315 fn approximate_recip_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7316 let (a0, a1) = self.split_f32x16(a);
7317 self.combine_f32x8(
7318 self.approximate_recip_f32x8(a0),
7319 self.approximate_recip_f32x8(a1),
7320 )
7321 }
7322 #[doc = "Add two vectors element-wise."]
7323 #[inline(always)]
7324 fn add_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7325 let (a0, a1) = self.split_f32x16(a);
7326 let (b0, b1) = self.split_f32x16(b);
7327 self.combine_f32x8(self.add_f32x8(a0, b0), self.add_f32x8(a1, b1))
7328 }
7329 #[doc = "Subtract two vectors element-wise."]
7330 #[inline(always)]
7331 fn sub_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7332 let (a0, a1) = self.split_f32x16(a);
7333 let (b0, b1) = self.split_f32x16(b);
7334 self.combine_f32x8(self.sub_f32x8(a0, b0), self.sub_f32x8(a1, b1))
7335 }
7336 #[doc = "Multiply two vectors element-wise."]
7337 #[inline(always)]
7338 fn mul_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7339 let (a0, a1) = self.split_f32x16(a);
7340 let (b0, b1) = self.split_f32x16(b);
7341 self.combine_f32x8(self.mul_f32x8(a0, b0), self.mul_f32x8(a1, b1))
7342 }
7343 #[doc = "Divide two vectors element-wise."]
7344 #[inline(always)]
7345 fn div_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7346 let (a0, a1) = self.split_f32x16(a);
7347 let (b0, b1) = self.split_f32x16(b);
7348 self.combine_f32x8(self.div_f32x8(a0, b0), self.div_f32x8(a1, b1))
7349 }
7350 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
7351 #[inline(always)]
7352 fn copysign_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7353 let (a0, a1) = self.split_f32x16(a);
7354 let (b0, b1) = self.split_f32x16(b);
7355 self.combine_f32x8(self.copysign_f32x8(a0, b0), self.copysign_f32x8(a1, b1))
7356 }
7357 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
7358 #[inline(always)]
7359 fn reduce_max_f32x16(self, a: f32x16<Self>) -> f32 {
7360 let (a0, a1) = self.split_f32x16(a);
7361 self.reduce_max_f32x8(self.max_f32x8(a0, a1))
7362 }
7363 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
7364 #[inline(always)]
7365 fn reduce_min_f32x16(self, a: f32x16<Self>) -> f32 {
7366 let (a0, a1) = self.split_f32x16(a);
7367 self.reduce_min_f32x8(self.min_f32x8(a0, a1))
7368 }
7369 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
7370 #[inline(always)]
7371 fn reduce_max_precise_f32x16(self, a: f32x16<Self>) -> f32 {
7372 let (a0, a1) = self.split_f32x16(a);
7373 self.reduce_max_precise_f32x8(self.max_precise_f32x8(a0, a1))
7374 }
7375 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
7376 #[inline(always)]
7377 fn reduce_min_precise_f32x16(self, a: f32x16<Self>) -> f32 {
7378 let (a0, a1) = self.split_f32x16(a);
7379 self.reduce_min_precise_f32x8(self.min_precise_f32x8(a0, a1))
7380 }
7381 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
7382 #[inline(always)]
7383 fn reduce_sum_f32x16(self, a: f32x16<Self>) -> f32 {
7384 let (a0, a1) = self.split_f32x16(a);
7385 self.reduce_sum_f32x8(self.add_f32x8(a0, a1))
7386 }
7387 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
7388 #[inline(always)]
7389 fn reduce_product_f32x16(self, a: f32x16<Self>) -> f32 {
7390 let (a0, a1) = self.split_f32x16(a);
7391 self.reduce_product_f32x8(self.mul_f32x8(a0, a1))
7392 }
7393 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
7394 #[inline(always)]
7395 fn max_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7396 let (a0, a1) = self.split_f32x16(a);
7397 let (b0, b1) = self.split_f32x16(b);
7398 self.combine_f32x8(self.max_f32x8(a0, b0), self.max_f32x8(a1, b1))
7399 }
7400 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
7401 #[inline(always)]
7402 fn min_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7403 let (a0, a1) = self.split_f32x16(a);
7404 let (b0, b1) = self.split_f32x16(b);
7405 self.combine_f32x8(self.min_f32x8(a0, b0), self.min_f32x8(a1, b1))
7406 }
7407 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
7408 #[inline(always)]
7409 fn max_precise_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7410 let (a0, a1) = self.split_f32x16(a);
7411 let (b0, b1) = self.split_f32x16(b);
7412 self.combine_f32x8(
7413 self.max_precise_f32x8(a0, b0),
7414 self.max_precise_f32x8(a1, b1),
7415 )
7416 }
7417 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
7418 #[inline(always)]
7419 fn min_precise_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7420 let (a0, a1) = self.split_f32x16(a);
7421 let (b0, b1) = self.split_f32x16(b);
7422 self.combine_f32x8(
7423 self.min_precise_f32x8(a0, b0),
7424 self.min_precise_f32x8(a1, b1),
7425 )
7426 }
7427 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
7428 #[inline(always)]
7429 fn clamp_f32x16(self, a: f32x16<Self>, b: f32x16<Self>, c: f32x16<Self>) -> f32x16<Self> {
7430 let (a0, a1) = self.split_f32x16(a);
7431 let (b0, b1) = self.split_f32x16(b);
7432 let (c0, c1) = self.split_f32x16(c);
7433 self.combine_f32x8(self.clamp_f32x8(a0, b0, c0), self.clamp_f32x8(a1, b1, c1))
7434 }
7435 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
7436 #[inline(always)]
7437 fn simd_eq_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7438 let (a0, a1) = self.split_f32x16(a);
7439 let (b0, b1) = self.split_f32x16(b);
7440 self.combine_mask32x8(self.simd_eq_f32x8(a0, b0), self.simd_eq_f32x8(a1, b1))
7441 }
7442 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
7443 #[inline(always)]
7444 fn simd_ne_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7445 self.not_mask32x16(self.simd_eq_f32x16(a, b))
7446 }
7447 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
7448 #[inline(always)]
7449 fn simd_lt_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7450 let (a0, a1) = self.split_f32x16(a);
7451 let (b0, b1) = self.split_f32x16(b);
7452 self.combine_mask32x8(self.simd_lt_f32x8(a0, b0), self.simd_lt_f32x8(a1, b1))
7453 }
7454 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
7455 #[inline(always)]
7456 fn simd_le_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7457 let (a0, a1) = self.split_f32x16(a);
7458 let (b0, b1) = self.split_f32x16(b);
7459 self.combine_mask32x8(self.simd_le_f32x8(a0, b0), self.simd_le_f32x8(a1, b1))
7460 }
7461 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
7462 #[inline(always)]
7463 fn simd_ge_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7464 self.simd_le_f32x16(b, a)
7465 }
7466 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
7467 #[inline(always)]
7468 fn simd_gt_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> mask32x16<Self> {
7469 self.simd_lt_f32x16(b, a)
7470 }
7471 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
7472 #[inline(always)]
7473 fn zip_low_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7474 let (a0, _) = self.split_f32x16(a);
7475 let (b0, _) = self.split_f32x16(b);
7476 self.combine_f32x8(self.zip_low_f32x8(a0, b0), self.zip_high_f32x8(a0, b0))
7477 }
7478 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
7479 #[inline(always)]
7480 fn zip_high_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7481 let (_, a1) = self.split_f32x16(a);
7482 let (_, b1) = self.split_f32x16(b);
7483 self.combine_f32x8(self.zip_low_f32x8(a1, b1), self.zip_high_f32x8(a1, b1))
7484 }
7485 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
7486 #[inline(always)]
7487 fn unzip_low_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7488 let (a0, a1) = self.split_f32x16(a);
7489 let (b0, b1) = self.split_f32x16(b);
7490 self.combine_f32x8(self.unzip_low_f32x8(a0, a1), self.unzip_low_f32x8(b0, b1))
7491 }
7492 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
7493 #[inline(always)]
7494 fn unzip_high_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> f32x16<Self> {
7495 let (a0, a1) = self.split_f32x16(a);
7496 let (b0, b1) = self.split_f32x16(b);
7497 self.combine_f32x8(self.unzip_high_f32x8(a0, a1), self.unzip_high_f32x8(b0, b1))
7498 }
7499 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
7500 #[inline(always)]
7501 fn interleave_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> (f32x16<Self>, f32x16<Self>) {
7502 let (a0, a1) = self.split_f32x16(a);
7503 let (b0, b1) = self.split_f32x16(b);
7504 let lo_lo = self.zip_low_f32x8(a0, b0);
7505 let lo_hi = self.zip_high_f32x8(a0, b0);
7506 let hi_lo = self.zip_low_f32x8(a1, b1);
7507 let hi_hi = self.zip_high_f32x8(a1, b1);
7508 (
7509 self.combine_f32x8(lo_lo, lo_hi),
7510 self.combine_f32x8(hi_lo, hi_hi),
7511 )
7512 }
7513 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
7514 #[inline(always)]
7515 fn deinterleave_f32x16(self, a: f32x16<Self>, b: f32x16<Self>) -> (f32x16<Self>, f32x16<Self>) {
7516 let (a0, a1) = self.split_f32x16(a);
7517 let (b0, b1) = self.split_f32x16(b);
7518 let lo_even = self.unzip_low_f32x8(a0, a1);
7519 let lo_odd = self.unzip_high_f32x8(a0, a1);
7520 let hi_even = self.unzip_low_f32x8(b0, b1);
7521 let hi_odd = self.unzip_high_f32x8(b0, b1);
7522 (
7523 self.combine_f32x8(lo_even, hi_even),
7524 self.combine_f32x8(lo_odd, hi_odd),
7525 )
7526 }
7527 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
7528 #[inline(always)]
7529 fn mul_add_f32x16(self, a: f32x16<Self>, b: f32x16<Self>, c: f32x16<Self>) -> f32x16<Self> {
7530 let (a0, a1) = self.split_f32x16(a);
7531 let (b0, b1) = self.split_f32x16(b);
7532 let (c0, c1) = self.split_f32x16(c);
7533 self.combine_f32x8(
7534 self.mul_add_f32x8(a0, b0, c0),
7535 self.mul_add_f32x8(a1, b1, c1),
7536 )
7537 }
7538 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
7539 #[inline(always)]
7540 fn mul_add_precise_f32x16(
7541 self,
7542 a: f32x16<Self>,
7543 b: f32x16<Self>,
7544 c: f32x16<Self>,
7545 ) -> f32x16<Self> {
7546 let (a0, a1) = self.split_f32x16(a);
7547 let (b0, b1) = self.split_f32x16(b);
7548 let (c0, c1) = self.split_f32x16(c);
7549 self.combine_f32x8(
7550 self.mul_add_precise_f32x8(a0, b0, c0),
7551 self.mul_add_precise_f32x8(a1, b1, c1),
7552 )
7553 }
7554 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
7555 #[inline(always)]
7556 fn mul_sub_f32x16(self, a: f32x16<Self>, b: f32x16<Self>, c: f32x16<Self>) -> f32x16<Self> {
7557 let (a0, a1) = self.split_f32x16(a);
7558 let (b0, b1) = self.split_f32x16(b);
7559 let (c0, c1) = self.split_f32x16(c);
7560 self.combine_f32x8(
7561 self.mul_sub_f32x8(a0, b0, c0),
7562 self.mul_sub_f32x8(a1, b1, c1),
7563 )
7564 }
7565 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
7566 #[inline(always)]
7567 fn mul_sub_precise_f32x16(
7568 self,
7569 a: f32x16<Self>,
7570 b: f32x16<Self>,
7571 c: f32x16<Self>,
7572 ) -> f32x16<Self> {
7573 let (a0, a1) = self.split_f32x16(a);
7574 let (b0, b1) = self.split_f32x16(b);
7575 let (c0, c1) = self.split_f32x16(c);
7576 self.combine_f32x8(
7577 self.mul_sub_precise_f32x8(a0, b0, c0),
7578 self.mul_sub_precise_f32x8(a1, b1, c1),
7579 )
7580 }
7581 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
7582 #[inline(always)]
7583 fn floor_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7584 let (a0, a1) = self.split_f32x16(a);
7585 self.combine_f32x8(self.floor_f32x8(a0), self.floor_f32x8(a1))
7586 }
7587 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
7588 #[inline(always)]
7589 fn ceil_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7590 let (a0, a1) = self.split_f32x16(a);
7591 self.combine_f32x8(self.ceil_f32x8(a0), self.ceil_f32x8(a1))
7592 }
7593 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
7594 #[inline(always)]
7595 fn round_ties_even_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7596 let (a0, a1) = self.split_f32x16(a);
7597 self.combine_f32x8(
7598 self.round_ties_even_f32x8(a0),
7599 self.round_ties_even_f32x8(a1),
7600 )
7601 }
7602 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
7603 #[inline(always)]
7604 fn round_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7605 let (a0, a1) = self.split_f32x16(a);
7606 self.combine_f32x8(self.round_f32x8(a0), self.round_f32x8(a1))
7607 }
7608 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
7609 #[inline(always)]
7610 fn fract_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7611 let (a0, a1) = self.split_f32x16(a);
7612 self.combine_f32x8(self.fract_f32x8(a0), self.fract_f32x8(a1))
7613 }
7614 #[doc = "Return the integer part of each element, rounding towards zero."]
7615 #[inline(always)]
7616 fn trunc_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7617 let (a0, a1) = self.split_f32x16(a);
7618 self.combine_f32x8(self.trunc_f32x8(a0), self.trunc_f32x8(a1))
7619 }
7620 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
7621 #[inline(always)]
7622 fn to_degrees_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7623 let (a0, a1) = self.split_f32x16(a);
7624 self.combine_f32x8(self.to_degrees_f32x8(a0), self.to_degrees_f32x8(a1))
7625 }
7626 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
7627 #[inline(always)]
7628 fn to_radians_f32x16(self, a: f32x16<Self>) -> f32x16<Self> {
7629 let (a0, a1) = self.split_f32x16(a);
7630 self.combine_f32x8(self.to_radians_f32x8(a0), self.to_radians_f32x8(a1))
7631 }
7632 #[doc = "Return a mask indicating which elements are NaN."]
7633 fn is_nan_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7634 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
7635 fn is_infinite_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7636 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
7637 fn is_finite_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7638 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
7639 fn is_subnormal_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7640 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
7641 fn is_normal_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7642 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
7643 fn is_sign_positive_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7644 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
7645 fn is_sign_negative_f32x16(self, a: f32x16<Self>) -> mask32x16<Self>;
7646 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
7647 #[inline(always)]
7648 fn select_f32x16(self, a: mask32x16<Self>, b: f32x16<Self>, c: f32x16<Self>) -> f32x16<Self> {
7649 let (a0, a1) = self.split_mask32x16(a);
7650 let (b0, b1) = self.split_f32x16(b);
7651 let (c0, c1) = self.split_f32x16(c);
7652 self.combine_f32x8(self.select_f32x8(a0, b0, c0), self.select_f32x8(a1, b1, c1))
7653 }
7654 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
7655 fn split_f32x16(self, a: f32x16<Self>) -> (f32x8<Self>, f32x8<Self>);
7656 #[doc = "Widen every `f32` lane exactly into two same-width `f64` vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
7657 #[inline(always)]
7658 fn widen_f32x16(self, a: f32x16<Self>) -> (f64x8<Self>, f64x8<Self>) {
7659 let (a0, a1) = self.split_f32x16(a);
7660 let (a00, a01) = self.widen_f32x8(a0);
7661 let (a10, a11) = self.widen_f32x8(a1);
7662 (self.combine_f64x4(a00, a01), self.combine_f64x4(a10, a11))
7663 }
7664 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results.\n\nOn x86 platforms below AVX-512, this operation will still be slower than converting to `i32`, because there is no native instruction for converting to `u32`.\nIf you know your values fit within range of an `i32`, you should convert to an `i32` and cast to your desired datatype afterwards."]
7665 #[inline(always)]
7666 fn cvt_u32_f32x16(self, a: f32x16<Self>) -> u32x16<Self> {
7667 let (a0, a1) = self.split_f32x16(a);
7668 self.combine_u32x8(self.cvt_u32_f32x8(a0), self.cvt_u32_f32x8(a1))
7669 }
7670 #[doc = "Convert each floating-point element to an unsigned 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
7671 #[inline(always)]
7672 fn cvt_u32_precise_f32x16(self, a: f32x16<Self>) -> u32x16<Self> {
7673 let (a0, a1) = self.split_f32x16(a);
7674 self.combine_u32x8(
7675 self.cvt_u32_precise_f32x8(a0),
7676 self.cvt_u32_precise_f32x8(a1),
7677 )
7678 }
7679 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
7680 #[inline(always)]
7681 fn cvt_i32_f32x16(self, a: f32x16<Self>) -> i32x16<Self> {
7682 let (a0, a1) = self.split_f32x16(a);
7683 self.combine_i32x8(self.cvt_i32_f32x8(a0), self.cvt_i32_f32x8(a1))
7684 }
7685 #[doc = "Convert each floating-point element to a signed 32-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
7686 #[inline(always)]
7687 fn cvt_i32_precise_f32x16(self, a: f32x16<Self>) -> i32x16<Self> {
7688 let (a0, a1) = self.split_f32x16(a);
7689 self.combine_i32x8(
7690 self.cvt_i32_precise_f32x8(a0),
7691 self.cvt_i32_precise_f32x8(a1),
7692 )
7693 }
7694 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
7695 #[inline(always)]
7696 fn abs_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
7697 let (a0, a1) = self.split_i8x64(a);
7698 self.combine_i8x32(self.abs_i8x32(a0), self.abs_i8x32(a1))
7699 }
7700 #[doc = "Create a SIMD vector with all elements set to the given value."]
7701 #[inline(always)]
7702 fn splat_i8x64(self, val: i8) -> i8x64<Self> {
7703 let half = self.splat_i8x32(val);
7704 self.combine_i8x32(half, half)
7705 }
7706 #[doc = "Reverse the order of the vector's elements."]
7707 #[inline(always)]
7708 fn reverse_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
7709 let (a0, a1) = self.split_i8x64(a);
7710 self.combine_i8x32(self.reverse_i8x32(a1), self.reverse_i8x32(a0))
7711 }
7712 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
7713 fn slide_i8x64<const SHIFT: usize>(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self>;
7714 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
7715 #[inline(always)]
7716 fn slide_within_blocks_i8x64<const SHIFT: usize>(
7717 self,
7718 a: i8x64<Self>,
7719 b: i8x64<Self>,
7720 ) -> i8x64<Self> {
7721 let (a0, a1) = self.split_i8x64(a);
7722 let (b0, b1) = self.split_i8x64(b);
7723 self.combine_i8x32(
7724 self.slide_within_blocks_i8x32::<SHIFT>(a0, b0),
7725 self.slide_within_blocks_i8x32::<SHIFT>(a1, b1),
7726 )
7727 }
7728 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
7729 #[inline(always)]
7730 fn swizzle_dyn_within_blocks_i8x64(self, a: i8x64<Self>, indices: u8x64<Self>) -> i8x64<Self> {
7731 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
7732 }
7733 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
7734 #[inline(always)]
7735 fn swizzle_dyn_i8x64(self, a: i8x64<Self>, indices: u8x64<Self>) -> i8x64<Self> {
7736 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
7737 }
7738 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
7739 #[inline(always)]
7740 fn swizzle_dyn_precise_i8x64(self, a: i8x64<Self>, indices: u8x64<Self>) -> i8x64<Self> {
7741 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
7742 }
7743 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
7744 #[inline(always)]
7745 fn concat_swizzle_dyn_i8x64(
7746 self,
7747 a: i8x64<Self>,
7748 b: i8x64<Self>,
7749 indices: u8x64<Self>,
7750 ) -> i8x64<Self> {
7751 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
7752 Bytes::to_bytes(a),
7753 Bytes::to_bytes(b),
7754 indices,
7755 ))
7756 }
7757 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
7758 #[inline(always)]
7759 fn concat_swizzle_dyn_precise_i8x64(
7760 self,
7761 a: i8x64<Self>,
7762 b: i8x64<Self>,
7763 indices: u8x64<Self>,
7764 ) -> i8x64<Self> {
7765 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
7766 Bytes::to_bytes(a),
7767 Bytes::to_bytes(b),
7768 indices,
7769 ))
7770 }
7771 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
7772 fn compress_i8x64(self, values: i8x64<Self>, mask: mask8x64<Self>) -> i8x64<Self>;
7773 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
7774 fn compress_merge_i8x64(
7775 self,
7776 values: i8x64<Self>,
7777 mask: mask8x64<Self>,
7778 merge: i8x64<Self>,
7779 ) -> i8x64<Self>;
7780 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
7781 fn expand_i8x64(self, values: i8x64<Self>, mask: mask8x64<Self>) -> i8x64<Self>;
7782 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
7783 fn expand_merge_i8x64(
7784 self,
7785 values: i8x64<Self>,
7786 mask: mask8x64<Self>,
7787 merge: i8x64<Self>,
7788 ) -> i8x64<Self>;
7789 #[doc = "Return the number of ones in the binary representation of each element."]
7790 #[inline(always)]
7791 fn count_ones_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
7792 let (a0, a1) = self.split_i8x64(a);
7793 self.combine_i8x32(self.count_ones_i8x32(a0), self.count_ones_i8x32(a1))
7794 }
7795 #[doc = "Return the number of zeros in the binary representation of each element."]
7796 #[inline(always)]
7797 fn count_zeros_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
7798 let (a0, a1) = self.split_i8x64(a);
7799 self.combine_i8x32(self.count_zeros_i8x32(a0), self.count_zeros_i8x32(a1))
7800 }
7801 #[doc = "Add two vectors element-wise, wrapping on overflow."]
7802 #[inline(always)]
7803 fn add_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7804 let (a0, a1) = self.split_i8x64(a);
7805 let (b0, b1) = self.split_i8x64(b);
7806 self.combine_i8x32(self.add_i8x32(a0, b0), self.add_i8x32(a1, b1))
7807 }
7808 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
7809 #[inline(always)]
7810 fn saturating_add_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7811 let (a0, a1) = self.split_i8x64(a);
7812 let (b0, b1) = self.split_i8x64(b);
7813 self.combine_i8x32(
7814 self.saturating_add_i8x32(a0, b0),
7815 self.saturating_add_i8x32(a1, b1),
7816 )
7817 }
7818 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
7819 #[inline(always)]
7820 fn sub_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7821 let (a0, a1) = self.split_i8x64(a);
7822 let (b0, b1) = self.split_i8x64(b);
7823 self.combine_i8x32(self.sub_i8x32(a0, b0), self.sub_i8x32(a1, b1))
7824 }
7825 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
7826 #[inline(always)]
7827 fn saturating_sub_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7828 let (a0, a1) = self.split_i8x64(a);
7829 let (b0, b1) = self.split_i8x64(b);
7830 self.combine_i8x32(
7831 self.saturating_sub_i8x32(a0, b0),
7832 self.saturating_sub_i8x32(a1, b1),
7833 )
7834 }
7835 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
7836 #[inline(always)]
7837 fn mul_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7838 let (a0, a1) = self.split_i8x64(a);
7839 let (b0, b1) = self.split_i8x64(b);
7840 self.combine_i8x32(self.mul_i8x32(a0, b0), self.mul_i8x32(a1, b1))
7841 }
7842 #[doc = "Compute the bitwise AND of two vectors."]
7843 #[inline(always)]
7844 fn and_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7845 let (a0, a1) = self.split_i8x64(a);
7846 let (b0, b1) = self.split_i8x64(b);
7847 self.combine_i8x32(self.and_i8x32(a0, b0), self.and_i8x32(a1, b1))
7848 }
7849 #[doc = "Compute the bitwise OR of two vectors."]
7850 #[inline(always)]
7851 fn or_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7852 let (a0, a1) = self.split_i8x64(a);
7853 let (b0, b1) = self.split_i8x64(b);
7854 self.combine_i8x32(self.or_i8x32(a0, b0), self.or_i8x32(a1, b1))
7855 }
7856 #[doc = "Compute the bitwise XOR of two vectors."]
7857 #[inline(always)]
7858 fn xor_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7859 let (a0, a1) = self.split_i8x64(a);
7860 let (b0, b1) = self.split_i8x64(b);
7861 self.combine_i8x32(self.xor_i8x32(a0, b0), self.xor_i8x32(a1, b1))
7862 }
7863 #[doc = "Compute the bitwise NOT of the vector."]
7864 #[inline(always)]
7865 fn not_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
7866 let (a0, a1) = self.split_i8x64(a);
7867 self.combine_i8x32(self.not_i8x32(a0), self.not_i8x32(a1))
7868 }
7869 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
7870 #[inline(always)]
7871 fn shl_i8x64(self, a: i8x64<Self>, shift: u32) -> i8x64<Self> {
7872 let (a0, a1) = self.split_i8x64(a);
7873 self.combine_i8x32(self.shl_i8x32(a0, shift), self.shl_i8x32(a1, shift))
7874 }
7875 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
7876 #[inline(always)]
7877 fn shlv_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7878 let (a0, a1) = self.split_i8x64(a);
7879 let (b0, b1) = self.split_i8x64(b);
7880 self.combine_i8x32(self.shlv_i8x32(a0, b0), self.shlv_i8x32(a1, b1))
7881 }
7882 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
7883 #[inline(always)]
7884 fn shr_i8x64(self, a: i8x64<Self>, shift: u32) -> i8x64<Self> {
7885 let (a0, a1) = self.split_i8x64(a);
7886 self.combine_i8x32(self.shr_i8x32(a0, shift), self.shr_i8x32(a1, shift))
7887 }
7888 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
7889 #[inline(always)]
7890 fn shrv_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7891 let (a0, a1) = self.split_i8x64(a);
7892 let (b0, b1) = self.split_i8x64(b);
7893 self.combine_i8x32(self.shrv_i8x32(a0, b0), self.shrv_i8x32(a1, b1))
7894 }
7895 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
7896 #[inline(always)]
7897 fn reduce_max_i8x64(self, a: i8x64<Self>) -> i8 {
7898 let (a0, a1) = self.split_i8x64(a);
7899 self.reduce_max_i8x32(self.max_i8x32(a0, a1))
7900 }
7901 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
7902 #[inline(always)]
7903 fn reduce_min_i8x64(self, a: i8x64<Self>) -> i8 {
7904 let (a0, a1) = self.split_i8x64(a);
7905 self.reduce_min_i8x32(self.min_i8x32(a0, a1))
7906 }
7907 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
7908 #[inline(always)]
7909 fn reduce_sum_i8x64(self, a: i8x64<Self>) -> i8 {
7910 let (a0, a1) = self.split_i8x64(a);
7911 self.reduce_sum_i8x32(self.add_i8x32(a0, a1))
7912 }
7913 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
7914 #[inline(always)]
7915 fn reduce_product_i8x64(self, a: i8x64<Self>) -> i8 {
7916 let (a0, a1) = self.split_i8x64(a);
7917 self.reduce_product_i8x32(self.mul_i8x32(a0, a1))
7918 }
7919 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
7920 #[inline(always)]
7921 fn max_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7922 let (a0, a1) = self.split_i8x64(a);
7923 let (b0, b1) = self.split_i8x64(b);
7924 self.combine_i8x32(self.max_i8x32(a0, b0), self.max_i8x32(a1, b1))
7925 }
7926 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
7927 #[inline(always)]
7928 fn min_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7929 let (a0, a1) = self.split_i8x64(a);
7930 let (b0, b1) = self.split_i8x64(b);
7931 self.combine_i8x32(self.min_i8x32(a0, b0), self.min_i8x32(a1, b1))
7932 }
7933 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
7934 #[inline(always)]
7935 fn clamp_i8x64(self, a: i8x64<Self>, b: i8x64<Self>, c: i8x64<Self>) -> i8x64<Self> {
7936 let (a0, a1) = self.split_i8x64(a);
7937 let (b0, b1) = self.split_i8x64(b);
7938 let (c0, c1) = self.split_i8x64(c);
7939 self.combine_i8x32(self.clamp_i8x32(a0, b0, c0), self.clamp_i8x32(a1, b1, c1))
7940 }
7941 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
7942 #[inline(always)]
7943 fn simd_eq_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7944 let (a0, a1) = self.split_i8x64(a);
7945 let (b0, b1) = self.split_i8x64(b);
7946 self.combine_mask8x32(self.simd_eq_i8x32(a0, b0), self.simd_eq_i8x32(a1, b1))
7947 }
7948 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
7949 #[inline(always)]
7950 fn simd_ne_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7951 self.not_mask8x64(self.simd_eq_i8x64(a, b))
7952 }
7953 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
7954 #[inline(always)]
7955 fn simd_lt_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7956 let (a0, a1) = self.split_i8x64(a);
7957 let (b0, b1) = self.split_i8x64(b);
7958 self.combine_mask8x32(self.simd_lt_i8x32(a0, b0), self.simd_lt_i8x32(a1, b1))
7959 }
7960 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
7961 #[inline(always)]
7962 fn simd_le_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7963 let (a0, a1) = self.split_i8x64(a);
7964 let (b0, b1) = self.split_i8x64(b);
7965 self.combine_mask8x32(self.simd_le_i8x32(a0, b0), self.simd_le_i8x32(a1, b1))
7966 }
7967 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
7968 #[inline(always)]
7969 fn simd_ge_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7970 self.simd_le_i8x64(b, a)
7971 }
7972 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
7973 #[inline(always)]
7974 fn simd_gt_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> mask8x64<Self> {
7975 self.simd_lt_i8x64(b, a)
7976 }
7977 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
7978 #[inline(always)]
7979 fn zip_low_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7980 let (a0, _) = self.split_i8x64(a);
7981 let (b0, _) = self.split_i8x64(b);
7982 self.combine_i8x32(self.zip_low_i8x32(a0, b0), self.zip_high_i8x32(a0, b0))
7983 }
7984 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
7985 #[inline(always)]
7986 fn zip_high_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7987 let (_, a1) = self.split_i8x64(a);
7988 let (_, b1) = self.split_i8x64(b);
7989 self.combine_i8x32(self.zip_low_i8x32(a1, b1), self.zip_high_i8x32(a1, b1))
7990 }
7991 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
7992 #[inline(always)]
7993 fn unzip_low_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
7994 let (a0, a1) = self.split_i8x64(a);
7995 let (b0, b1) = self.split_i8x64(b);
7996 self.combine_i8x32(self.unzip_low_i8x32(a0, a1), self.unzip_low_i8x32(b0, b1))
7997 }
7998 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
7999 #[inline(always)]
8000 fn unzip_high_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i8x64<Self> {
8001 let (a0, a1) = self.split_i8x64(a);
8002 let (b0, b1) = self.split_i8x64(b);
8003 self.combine_i8x32(self.unzip_high_i8x32(a0, a1), self.unzip_high_i8x32(b0, b1))
8004 }
8005 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
8006 #[inline(always)]
8007 fn interleave_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> (i8x64<Self>, i8x64<Self>) {
8008 let (a0, a1) = self.split_i8x64(a);
8009 let (b0, b1) = self.split_i8x64(b);
8010 let lo_lo = self.zip_low_i8x32(a0, b0);
8011 let lo_hi = self.zip_high_i8x32(a0, b0);
8012 let hi_lo = self.zip_low_i8x32(a1, b1);
8013 let hi_hi = self.zip_high_i8x32(a1, b1);
8014 (
8015 self.combine_i8x32(lo_lo, lo_hi),
8016 self.combine_i8x32(hi_lo, hi_hi),
8017 )
8018 }
8019 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
8020 #[inline(always)]
8021 fn deinterleave_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> (i8x64<Self>, i8x64<Self>) {
8022 let (a0, a1) = self.split_i8x64(a);
8023 let (b0, b1) = self.split_i8x64(b);
8024 let lo_even = self.unzip_low_i8x32(a0, a1);
8025 let lo_odd = self.unzip_high_i8x32(a0, a1);
8026 let hi_even = self.unzip_low_i8x32(b0, b1);
8027 let hi_odd = self.unzip_high_i8x32(b0, b1);
8028 (
8029 self.combine_i8x32(lo_even, hi_even),
8030 self.combine_i8x32(lo_odd, hi_odd),
8031 )
8032 }
8033 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
8034 #[inline(always)]
8035 fn select_i8x64(self, a: mask8x64<Self>, b: i8x64<Self>, c: i8x64<Self>) -> i8x64<Self> {
8036 let (a0, a1) = self.split_mask8x64(a);
8037 let (b0, b1) = self.split_i8x64(b);
8038 let (c0, c1) = self.split_i8x64(c);
8039 self.combine_i8x32(self.select_i8x32(a0, b0, c0), self.select_i8x32(a1, b1, c1))
8040 }
8041 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
8042 fn split_i8x64(self, a: i8x64<Self>) -> (i8x32<Self>, i8x32<Self>);
8043 #[doc = "Negate each element of the vector, wrapping on overflow."]
8044 #[inline(always)]
8045 fn neg_i8x64(self, a: i8x64<Self>) -> i8x64<Self> {
8046 let (a0, a1) = self.split_i8x64(a);
8047 self.combine_i8x32(self.neg_i8x32(a0), self.neg_i8x32(a1))
8048 }
8049 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
8050 #[inline(always)]
8051 fn widen_i8x64(self, a: i8x64<Self>) -> (i16x32<Self>, i16x32<Self>) {
8052 let (a0, a1) = self.split_i8x64(a);
8053 let (a00, a01) = self.widen_i8x32(a0);
8054 let (a10, a11) = self.widen_i8x32(a1);
8055 (self.combine_i16x16(a00, a01), self.combine_i16x16(a10, a11))
8056 }
8057 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
8058 #[inline(always)]
8059 fn widening_mul_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> (i16x32<Self>, i16x32<Self>) {
8060 let (a0, a1) = self.split_i8x64(a);
8061 let (b0, b1) = self.split_i8x64(b);
8062 let (low0, low1) = self.widening_mul_i8x32(a0, b0);
8063 let (high0, high1) = self.widening_mul_i8x32(a1, b1);
8064 (
8065 self.combine_i16x16(low0, low1),
8066 self.combine_i16x16(high0, high1),
8067 )
8068 }
8069 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
8070 #[inline(always)]
8071 fn widening_add_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> (i16x32<Self>, i16x32<Self>) {
8072 let (a0, a1) = self.split_i8x64(a);
8073 let (b0, b1) = self.split_i8x64(b);
8074 let (low0, low1) = self.widening_add_i8x32(a0, b0);
8075 let (high0, high1) = self.widening_add_i8x32(a1, b1);
8076 (
8077 self.combine_i16x16(low0, low1),
8078 self.combine_i16x16(high0, high1),
8079 )
8080 }
8081 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
8082 #[inline(always)]
8083 fn pairwise_widening_add_i8x64(self, a: i8x64<Self>) -> i16x32<Self> {
8084 let (a0, a1) = self.split_i8x64(a);
8085 self.combine_i16x16(
8086 self.pairwise_widening_add_i8x32(a0),
8087 self.pairwise_widening_add_i8x32(a1),
8088 )
8089 }
8090 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
8091 #[inline(always)]
8092 fn pairwise_dot_product_i8x64(self, a: i8x64<Self>, b: i8x64<Self>) -> i16x32<Self> {
8093 let (a0, a1) = self.split_i8x64(a);
8094 let (b0, b1) = self.split_i8x64(b);
8095 self.combine_i16x16(
8096 self.pairwise_dot_product_i8x32(a0, b0),
8097 self.pairwise_dot_product_i8x32(a1, b1),
8098 )
8099 }
8100 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
8101 #[inline(always)]
8102 fn abs_u8x64(self, a: u8x64<Self>) -> u8x64<Self> {
8103 a
8104 }
8105 #[doc = "Create a SIMD vector with all elements set to the given value."]
8106 #[inline(always)]
8107 fn splat_u8x64(self, val: u8) -> u8x64<Self> {
8108 let half = self.splat_u8x32(val);
8109 self.combine_u8x32(half, half)
8110 }
8111 #[doc = "Reverse the order of the vector's elements."]
8112 #[inline(always)]
8113 fn reverse_u8x64(self, a: u8x64<Self>) -> u8x64<Self> {
8114 let (a0, a1) = self.split_u8x64(a);
8115 self.combine_u8x32(self.reverse_u8x32(a1), self.reverse_u8x32(a0))
8116 }
8117 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
8118 fn slide_u8x64<const SHIFT: usize>(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self>;
8119 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
8120 #[inline(always)]
8121 fn slide_within_blocks_u8x64<const SHIFT: usize>(
8122 self,
8123 a: u8x64<Self>,
8124 b: u8x64<Self>,
8125 ) -> u8x64<Self> {
8126 let (a0, a1) = self.split_u8x64(a);
8127 let (b0, b1) = self.split_u8x64(b);
8128 self.combine_u8x32(
8129 self.slide_within_blocks_u8x32::<SHIFT>(a0, b0),
8130 self.slide_within_blocks_u8x32::<SHIFT>(a1, b1),
8131 )
8132 }
8133 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
8134 #[inline(always)]
8135 fn swizzle_dyn_within_blocks_u8x64(self, a: u8x64<Self>, indices: u8x64<Self>) -> u8x64<Self> {
8136 let (a0, a1) = self.split_u8x64(a);
8137 let (indices0, indices1) = self.split_u8x64(indices);
8138 self.combine_u8x32(
8139 self.swizzle_dyn_within_blocks_u8x32(a0, indices0),
8140 self.swizzle_dyn_within_blocks_u8x32(a1, indices1),
8141 )
8142 }
8143 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
8144 fn swizzle_dyn_u8x64(self, a: u8x64<Self>, indices: u8x64<Self>) -> u8x64<Self>;
8145 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
8146 fn swizzle_dyn_precise_u8x64(self, a: u8x64<Self>, indices: u8x64<Self>) -> u8x64<Self>;
8147 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
8148 fn concat_swizzle_dyn_u8x64(
8149 self,
8150 a: u8x64<Self>,
8151 b: u8x64<Self>,
8152 indices: u8x64<Self>,
8153 ) -> u8x64<Self>;
8154 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
8155 fn concat_swizzle_dyn_precise_u8x64(
8156 self,
8157 a: u8x64<Self>,
8158 b: u8x64<Self>,
8159 indices: u8x64<Self>,
8160 ) -> u8x64<Self>;
8161 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
8162 fn compress_u8x64(self, values: u8x64<Self>, mask: mask8x64<Self>) -> u8x64<Self>;
8163 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
8164 fn compress_merge_u8x64(
8165 self,
8166 values: u8x64<Self>,
8167 mask: mask8x64<Self>,
8168 merge: u8x64<Self>,
8169 ) -> u8x64<Self>;
8170 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
8171 fn expand_u8x64(self, values: u8x64<Self>, mask: mask8x64<Self>) -> u8x64<Self>;
8172 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
8173 fn expand_merge_u8x64(
8174 self,
8175 values: u8x64<Self>,
8176 mask: mask8x64<Self>,
8177 merge: u8x64<Self>,
8178 ) -> u8x64<Self>;
8179 #[doc = "Return the number of ones in the binary representation of each element."]
8180 #[inline(always)]
8181 fn count_ones_u8x64(self, a: u8x64<Self>) -> u8x64<Self> {
8182 let (a0, a1) = self.split_u8x64(a);
8183 self.combine_u8x32(self.count_ones_u8x32(a0), self.count_ones_u8x32(a1))
8184 }
8185 #[doc = "Return the number of zeros in the binary representation of each element."]
8186 #[inline(always)]
8187 fn count_zeros_u8x64(self, a: u8x64<Self>) -> u8x64<Self> {
8188 let (a0, a1) = self.split_u8x64(a);
8189 self.combine_u8x32(self.count_zeros_u8x32(a0), self.count_zeros_u8x32(a1))
8190 }
8191 #[doc = "Add two vectors element-wise, wrapping on overflow."]
8192 #[inline(always)]
8193 fn add_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8194 let (a0, a1) = self.split_u8x64(a);
8195 let (b0, b1) = self.split_u8x64(b);
8196 self.combine_u8x32(self.add_u8x32(a0, b0), self.add_u8x32(a1, b1))
8197 }
8198 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
8199 #[inline(always)]
8200 fn saturating_add_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8201 let (a0, a1) = self.split_u8x64(a);
8202 let (b0, b1) = self.split_u8x64(b);
8203 self.combine_u8x32(
8204 self.saturating_add_u8x32(a0, b0),
8205 self.saturating_add_u8x32(a1, b1),
8206 )
8207 }
8208 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
8209 #[inline(always)]
8210 fn sub_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8211 let (a0, a1) = self.split_u8x64(a);
8212 let (b0, b1) = self.split_u8x64(b);
8213 self.combine_u8x32(self.sub_u8x32(a0, b0), self.sub_u8x32(a1, b1))
8214 }
8215 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
8216 #[inline(always)]
8217 fn saturating_sub_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8218 let (a0, a1) = self.split_u8x64(a);
8219 let (b0, b1) = self.split_u8x64(b);
8220 self.combine_u8x32(
8221 self.saturating_sub_u8x32(a0, b0),
8222 self.saturating_sub_u8x32(a1, b1),
8223 )
8224 }
8225 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
8226 #[inline(always)]
8227 fn mul_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8228 let (a0, a1) = self.split_u8x64(a);
8229 let (b0, b1) = self.split_u8x64(b);
8230 self.combine_u8x32(self.mul_u8x32(a0, b0), self.mul_u8x32(a1, b1))
8231 }
8232 #[doc = "Compute the bitwise AND of two vectors."]
8233 #[inline(always)]
8234 fn and_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8235 let (a0, a1) = self.split_u8x64(a);
8236 let (b0, b1) = self.split_u8x64(b);
8237 self.combine_u8x32(self.and_u8x32(a0, b0), self.and_u8x32(a1, b1))
8238 }
8239 #[doc = "Compute the bitwise OR of two vectors."]
8240 #[inline(always)]
8241 fn or_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8242 let (a0, a1) = self.split_u8x64(a);
8243 let (b0, b1) = self.split_u8x64(b);
8244 self.combine_u8x32(self.or_u8x32(a0, b0), self.or_u8x32(a1, b1))
8245 }
8246 #[doc = "Compute the bitwise XOR of two vectors."]
8247 #[inline(always)]
8248 fn xor_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8249 let (a0, a1) = self.split_u8x64(a);
8250 let (b0, b1) = self.split_u8x64(b);
8251 self.combine_u8x32(self.xor_u8x32(a0, b0), self.xor_u8x32(a1, b1))
8252 }
8253 #[doc = "Compute the bitwise NOT of the vector."]
8254 #[inline(always)]
8255 fn not_u8x64(self, a: u8x64<Self>) -> u8x64<Self> {
8256 let (a0, a1) = self.split_u8x64(a);
8257 self.combine_u8x32(self.not_u8x32(a0), self.not_u8x32(a1))
8258 }
8259 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
8260 #[inline(always)]
8261 fn shl_u8x64(self, a: u8x64<Self>, shift: u32) -> u8x64<Self> {
8262 let (a0, a1) = self.split_u8x64(a);
8263 self.combine_u8x32(self.shl_u8x32(a0, shift), self.shl_u8x32(a1, shift))
8264 }
8265 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
8266 #[inline(always)]
8267 fn shlv_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8268 let (a0, a1) = self.split_u8x64(a);
8269 let (b0, b1) = self.split_u8x64(b);
8270 self.combine_u8x32(self.shlv_u8x32(a0, b0), self.shlv_u8x32(a1, b1))
8271 }
8272 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
8273 #[inline(always)]
8274 fn shr_u8x64(self, a: u8x64<Self>, shift: u32) -> u8x64<Self> {
8275 let (a0, a1) = self.split_u8x64(a);
8276 self.combine_u8x32(self.shr_u8x32(a0, shift), self.shr_u8x32(a1, shift))
8277 }
8278 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
8279 #[inline(always)]
8280 fn shrv_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8281 let (a0, a1) = self.split_u8x64(a);
8282 let (b0, b1) = self.split_u8x64(b);
8283 self.combine_u8x32(self.shrv_u8x32(a0, b0), self.shrv_u8x32(a1, b1))
8284 }
8285 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
8286 #[inline(always)]
8287 fn reduce_max_u8x64(self, a: u8x64<Self>) -> u8 {
8288 let (a0, a1) = self.split_u8x64(a);
8289 self.reduce_max_u8x32(self.max_u8x32(a0, a1))
8290 }
8291 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
8292 #[inline(always)]
8293 fn reduce_min_u8x64(self, a: u8x64<Self>) -> u8 {
8294 let (a0, a1) = self.split_u8x64(a);
8295 self.reduce_min_u8x32(self.min_u8x32(a0, a1))
8296 }
8297 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
8298 #[inline(always)]
8299 fn reduce_sum_u8x64(self, a: u8x64<Self>) -> u8 {
8300 let (a0, a1) = self.split_u8x64(a);
8301 self.reduce_sum_u8x32(self.add_u8x32(a0, a1))
8302 }
8303 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
8304 #[inline(always)]
8305 fn reduce_product_u8x64(self, a: u8x64<Self>) -> u8 {
8306 let (a0, a1) = self.split_u8x64(a);
8307 self.reduce_product_u8x32(self.mul_u8x32(a0, a1))
8308 }
8309 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
8310 #[inline(always)]
8311 fn max_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8312 let (a0, a1) = self.split_u8x64(a);
8313 let (b0, b1) = self.split_u8x64(b);
8314 self.combine_u8x32(self.max_u8x32(a0, b0), self.max_u8x32(a1, b1))
8315 }
8316 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
8317 #[inline(always)]
8318 fn min_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8319 let (a0, a1) = self.split_u8x64(a);
8320 let (b0, b1) = self.split_u8x64(b);
8321 self.combine_u8x32(self.min_u8x32(a0, b0), self.min_u8x32(a1, b1))
8322 }
8323 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
8324 #[inline(always)]
8325 fn clamp_u8x64(self, a: u8x64<Self>, b: u8x64<Self>, c: u8x64<Self>) -> u8x64<Self> {
8326 let (a0, a1) = self.split_u8x64(a);
8327 let (b0, b1) = self.split_u8x64(b);
8328 let (c0, c1) = self.split_u8x64(c);
8329 self.combine_u8x32(self.clamp_u8x32(a0, b0, c0), self.clamp_u8x32(a1, b1, c1))
8330 }
8331 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
8332 #[inline(always)]
8333 fn simd_eq_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8334 let (a0, a1) = self.split_u8x64(a);
8335 let (b0, b1) = self.split_u8x64(b);
8336 self.combine_mask8x32(self.simd_eq_u8x32(a0, b0), self.simd_eq_u8x32(a1, b1))
8337 }
8338 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
8339 #[inline(always)]
8340 fn simd_ne_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8341 self.not_mask8x64(self.simd_eq_u8x64(a, b))
8342 }
8343 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
8344 #[inline(always)]
8345 fn simd_lt_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8346 let (a0, a1) = self.split_u8x64(a);
8347 let (b0, b1) = self.split_u8x64(b);
8348 self.combine_mask8x32(self.simd_lt_u8x32(a0, b0), self.simd_lt_u8x32(a1, b1))
8349 }
8350 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
8351 #[inline(always)]
8352 fn simd_le_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8353 let (a0, a1) = self.split_u8x64(a);
8354 let (b0, b1) = self.split_u8x64(b);
8355 self.combine_mask8x32(self.simd_le_u8x32(a0, b0), self.simd_le_u8x32(a1, b1))
8356 }
8357 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
8358 #[inline(always)]
8359 fn simd_ge_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8360 self.simd_le_u8x64(b, a)
8361 }
8362 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
8363 #[inline(always)]
8364 fn simd_gt_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> mask8x64<Self> {
8365 self.simd_lt_u8x64(b, a)
8366 }
8367 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
8368 #[inline(always)]
8369 fn zip_low_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8370 let (a0, _) = self.split_u8x64(a);
8371 let (b0, _) = self.split_u8x64(b);
8372 self.combine_u8x32(self.zip_low_u8x32(a0, b0), self.zip_high_u8x32(a0, b0))
8373 }
8374 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
8375 #[inline(always)]
8376 fn zip_high_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8377 let (_, a1) = self.split_u8x64(a);
8378 let (_, b1) = self.split_u8x64(b);
8379 self.combine_u8x32(self.zip_low_u8x32(a1, b1), self.zip_high_u8x32(a1, b1))
8380 }
8381 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
8382 #[inline(always)]
8383 fn unzip_low_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8384 let (a0, a1) = self.split_u8x64(a);
8385 let (b0, b1) = self.split_u8x64(b);
8386 self.combine_u8x32(self.unzip_low_u8x32(a0, a1), self.unzip_low_u8x32(b0, b1))
8387 }
8388 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
8389 #[inline(always)]
8390 fn unzip_high_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u8x64<Self> {
8391 let (a0, a1) = self.split_u8x64(a);
8392 let (b0, b1) = self.split_u8x64(b);
8393 self.combine_u8x32(self.unzip_high_u8x32(a0, a1), self.unzip_high_u8x32(b0, b1))
8394 }
8395 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
8396 #[inline(always)]
8397 fn interleave_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> (u8x64<Self>, u8x64<Self>) {
8398 let (a0, a1) = self.split_u8x64(a);
8399 let (b0, b1) = self.split_u8x64(b);
8400 let lo_lo = self.zip_low_u8x32(a0, b0);
8401 let lo_hi = self.zip_high_u8x32(a0, b0);
8402 let hi_lo = self.zip_low_u8x32(a1, b1);
8403 let hi_hi = self.zip_high_u8x32(a1, b1);
8404 (
8405 self.combine_u8x32(lo_lo, lo_hi),
8406 self.combine_u8x32(hi_lo, hi_hi),
8407 )
8408 }
8409 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
8410 #[inline(always)]
8411 fn deinterleave_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> (u8x64<Self>, u8x64<Self>) {
8412 let (a0, a1) = self.split_u8x64(a);
8413 let (b0, b1) = self.split_u8x64(b);
8414 let lo_even = self.unzip_low_u8x32(a0, a1);
8415 let lo_odd = self.unzip_high_u8x32(a0, a1);
8416 let hi_even = self.unzip_low_u8x32(b0, b1);
8417 let hi_odd = self.unzip_high_u8x32(b0, b1);
8418 (
8419 self.combine_u8x32(lo_even, hi_even),
8420 self.combine_u8x32(lo_odd, hi_odd),
8421 )
8422 }
8423 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
8424 #[inline(always)]
8425 fn select_u8x64(self, a: mask8x64<Self>, b: u8x64<Self>, c: u8x64<Self>) -> u8x64<Self> {
8426 let (a0, a1) = self.split_mask8x64(a);
8427 let (b0, b1) = self.split_u8x64(b);
8428 let (c0, c1) = self.split_u8x64(c);
8429 self.combine_u8x32(self.select_u8x32(a0, b0, c0), self.select_u8x32(a1, b1, c1))
8430 }
8431 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
8432 fn split_u8x64(self, a: u8x64<Self>) -> (u8x32<Self>, u8x32<Self>);
8433 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
8434 #[inline(always)]
8435 fn widen_u8x64(self, a: u8x64<Self>) -> (u16x32<Self>, u16x32<Self>) {
8436 let (a0, a1) = self.split_u8x64(a);
8437 let (a00, a01) = self.widen_u8x32(a0);
8438 let (a10, a11) = self.widen_u8x32(a1);
8439 (self.combine_u16x16(a00, a01), self.combine_u16x16(a10, a11))
8440 }
8441 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
8442 #[inline(always)]
8443 fn widening_mul_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> (u16x32<Self>, u16x32<Self>) {
8444 let (a0, a1) = self.split_u8x64(a);
8445 let (b0, b1) = self.split_u8x64(b);
8446 let (low0, low1) = self.widening_mul_u8x32(a0, b0);
8447 let (high0, high1) = self.widening_mul_u8x32(a1, b1);
8448 (
8449 self.combine_u16x16(low0, low1),
8450 self.combine_u16x16(high0, high1),
8451 )
8452 }
8453 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
8454 #[inline(always)]
8455 fn widening_add_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> (u16x32<Self>, u16x32<Self>) {
8456 let (a0, a1) = self.split_u8x64(a);
8457 let (b0, b1) = self.split_u8x64(b);
8458 let (low0, low1) = self.widening_add_u8x32(a0, b0);
8459 let (high0, high1) = self.widening_add_u8x32(a1, b1);
8460 (
8461 self.combine_u16x16(low0, low1),
8462 self.combine_u16x16(high0, high1),
8463 )
8464 }
8465 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
8466 #[inline(always)]
8467 fn pairwise_widening_add_u8x64(self, a: u8x64<Self>) -> u16x32<Self> {
8468 let (a0, a1) = self.split_u8x64(a);
8469 self.combine_u16x16(
8470 self.pairwise_widening_add_u8x32(a0),
8471 self.pairwise_widening_add_u8x32(a1),
8472 )
8473 }
8474 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
8475 #[inline(always)]
8476 fn pairwise_dot_product_u8x64(self, a: u8x64<Self>, b: u8x64<Self>) -> u16x32<Self> {
8477 let (a0, a1) = self.split_u8x64(a);
8478 let (b0, b1) = self.split_u8x64(b);
8479 self.combine_u16x16(
8480 self.pairwise_dot_product_u8x32(a0, b0),
8481 self.pairwise_dot_product_u8x32(a1, b1),
8482 )
8483 }
8484 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
8485 #[inline(always)]
8486 fn splat_mask8x64(self, val: bool) -> mask8x64<Self> {
8487 let half = self.splat_mask8x32(val);
8488 self.combine_mask8x32(half, half)
8489 }
8490 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
8491 #[inline(always)]
8492 fn from_bitmask_mask8x64(self, bits: u64) -> mask8x64<Self> {
8493 let lo = self.from_bitmask_mask8x32(bits);
8494 let hi = self.from_bitmask_mask8x32(bits >> 32usize);
8495 self.combine_mask8x32(lo, hi)
8496 }
8497 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
8498 #[inline(always)]
8499 fn to_bitmask_mask8x64(self, a: mask8x64<Self>) -> u64 {
8500 let (lo, hi) = self.split_mask8x64(a);
8501 let lo = self.to_bitmask_mask8x32(lo);
8502 let hi = self.to_bitmask_mask8x32(hi);
8503 lo | (hi << 32usize)
8504 }
8505 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
8506 fn from_vector_mask8x64(self, vector: i8x64<Self>) -> mask8x64<Self>;
8507 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
8508 fn to_vector_mask8x64(self, a: mask8x64<Self>) -> i8x64<Self>;
8509 #[doc = "Set one logical lane of a SIMD mask."]
8510 fn set_mask8x64(self, a: &mut mask8x64<Self>, index: usize, value: bool) -> ();
8511 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
8512 fn rotate_elements_left_mask8x64<const OFFSET: usize>(
8513 self,
8514 a: mask8x64<Self>,
8515 ) -> mask8x64<Self>;
8516 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
8517 fn rotate_elements_right_mask8x64<const OFFSET: usize>(
8518 self,
8519 a: mask8x64<Self>,
8520 ) -> mask8x64<Self>;
8521 #[doc = "Compute the logical AND of two masks."]
8522 #[inline(always)]
8523 fn and_mask8x64(self, a: mask8x64<Self>, b: mask8x64<Self>) -> mask8x64<Self> {
8524 let (a0, a1) = self.split_mask8x64(a);
8525 let (b0, b1) = self.split_mask8x64(b);
8526 self.combine_mask8x32(self.and_mask8x32(a0, b0), self.and_mask8x32(a1, b1))
8527 }
8528 #[doc = "Compute the logical OR of two masks."]
8529 #[inline(always)]
8530 fn or_mask8x64(self, a: mask8x64<Self>, b: mask8x64<Self>) -> mask8x64<Self> {
8531 let (a0, a1) = self.split_mask8x64(a);
8532 let (b0, b1) = self.split_mask8x64(b);
8533 self.combine_mask8x32(self.or_mask8x32(a0, b0), self.or_mask8x32(a1, b1))
8534 }
8535 #[doc = "Compute the logical XOR of two masks."]
8536 #[inline(always)]
8537 fn xor_mask8x64(self, a: mask8x64<Self>, b: mask8x64<Self>) -> mask8x64<Self> {
8538 let (a0, a1) = self.split_mask8x64(a);
8539 let (b0, b1) = self.split_mask8x64(b);
8540 self.combine_mask8x32(self.xor_mask8x32(a0, b0), self.xor_mask8x32(a1, b1))
8541 }
8542 #[doc = "Compute the logical NOT of the mask."]
8543 #[inline(always)]
8544 fn not_mask8x64(self, a: mask8x64<Self>) -> mask8x64<Self> {
8545 let (a0, a1) = self.split_mask8x64(a);
8546 self.combine_mask8x32(self.not_mask8x32(a0), self.not_mask8x32(a1))
8547 }
8548 #[doc = "Reverse the order of the mask's logical lanes."]
8549 #[inline(always)]
8550 fn reverse_mask8x64(self, a: mask8x64<Self>) -> mask8x64<Self> {
8551 let (a0, a1) = self.split_mask8x64(a);
8552 self.combine_mask8x32(self.reverse_mask8x32(a1), self.reverse_mask8x32(a0))
8553 }
8554 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
8555 #[inline(always)]
8556 fn select_mask8x64(
8557 self,
8558 a: mask8x64<Self>,
8559 b: mask8x64<Self>,
8560 c: mask8x64<Self>,
8561 ) -> mask8x64<Self> {
8562 let (a0, a1) = self.split_mask8x64(a);
8563 let (b0, b1) = self.split_mask8x64(b);
8564 let (c0, c1) = self.split_mask8x64(c);
8565 self.combine_mask8x32(
8566 self.select_mask8x32(a0, b0, c0),
8567 self.select_mask8x32(a1, b1, c1),
8568 )
8569 }
8570 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
8571 #[inline(always)]
8572 fn simd_eq_mask8x64(self, a: mask8x64<Self>, b: mask8x64<Self>) -> mask8x64<Self> {
8573 let (a0, a1) = self.split_mask8x64(a);
8574 let (b0, b1) = self.split_mask8x64(b);
8575 self.combine_mask8x32(self.simd_eq_mask8x32(a0, b0), self.simd_eq_mask8x32(a1, b1))
8576 }
8577 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
8578 #[inline(always)]
8579 fn simd_ne_mask8x64(self, a: mask8x64<Self>, b: mask8x64<Self>) -> mask8x64<Self> {
8580 self.not_mask8x64(self.simd_eq_mask8x64(a, b))
8581 }
8582 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
8583 #[inline(always)]
8584 fn any_true_mask8x64(self, a: mask8x64<Self>) -> bool {
8585 let (a0, a1) = self.split_mask8x64(a);
8586 self.any_true_mask8x32(self.or_mask8x32(a0, a1))
8587 }
8588 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
8589 #[inline(always)]
8590 fn all_true_mask8x64(self, a: mask8x64<Self>) -> bool {
8591 let (a0, a1) = self.split_mask8x64(a);
8592 self.all_true_mask8x32(self.and_mask8x32(a0, a1))
8593 }
8594 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
8595 #[inline(always)]
8596 fn any_false_mask8x64(self, a: mask8x64<Self>) -> bool {
8597 let (a0, a1) = self.split_mask8x64(a);
8598 self.any_false_mask8x32(self.and_mask8x32(a0, a1))
8599 }
8600 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
8601 #[inline(always)]
8602 fn all_false_mask8x64(self, a: mask8x64<Self>) -> bool {
8603 let (a0, a1) = self.split_mask8x64(a);
8604 self.all_false_mask8x32(self.or_mask8x32(a0, a1))
8605 }
8606 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
8607 fn split_mask8x64(self, a: mask8x64<Self>) -> (mask8x32<Self>, mask8x32<Self>);
8608 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
8609 #[inline(always)]
8610 fn widen_mask8x64(self, a: mask8x64<Self>) -> (mask16x32<Self>, mask16x32<Self>) {
8611 let (a0, a1) = self.split_mask8x64(a);
8612 let (a00, a01) = self.widen_mask8x32(a0);
8613 let (a10, a11) = self.widen_mask8x32(a1);
8614 (
8615 self.combine_mask16x16(a00, a01),
8616 self.combine_mask16x16(a10, a11),
8617 )
8618 }
8619 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
8620 #[inline(always)]
8621 fn abs_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8622 let (a0, a1) = self.split_i16x32(a);
8623 self.combine_i16x16(self.abs_i16x16(a0), self.abs_i16x16(a1))
8624 }
8625 #[doc = "Create a SIMD vector with all elements set to the given value."]
8626 #[inline(always)]
8627 fn splat_i16x32(self, val: i16) -> i16x32<Self> {
8628 let half = self.splat_i16x16(val);
8629 self.combine_i16x16(half, half)
8630 }
8631 #[doc = "Reverse the order of the vector's elements."]
8632 #[inline(always)]
8633 fn reverse_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8634 let (a0, a1) = self.split_i16x32(a);
8635 self.combine_i16x16(self.reverse_i16x16(a1), self.reverse_i16x16(a0))
8636 }
8637 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
8638 fn slide_i16x32<const SHIFT: usize>(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self>;
8639 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
8640 #[inline(always)]
8641 fn slide_within_blocks_i16x32<const SHIFT: usize>(
8642 self,
8643 a: i16x32<Self>,
8644 b: i16x32<Self>,
8645 ) -> i16x32<Self> {
8646 let (a0, a1) = self.split_i16x32(a);
8647 let (b0, b1) = self.split_i16x32(b);
8648 self.combine_i16x16(
8649 self.slide_within_blocks_i16x16::<SHIFT>(a0, b0),
8650 self.slide_within_blocks_i16x16::<SHIFT>(a1, b1),
8651 )
8652 }
8653 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
8654 #[inline(always)]
8655 fn swizzle_dyn_within_blocks_i16x32(
8656 self,
8657 a: i16x32<Self>,
8658 indices: u8x64<Self>,
8659 ) -> i16x32<Self> {
8660 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
8661 }
8662 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
8663 #[inline(always)]
8664 fn swizzle_dyn_i16x32(self, a: i16x32<Self>, indices: u8x64<Self>) -> i16x32<Self> {
8665 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
8666 }
8667 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
8668 #[inline(always)]
8669 fn swizzle_dyn_precise_i16x32(self, a: i16x32<Self>, indices: u8x64<Self>) -> i16x32<Self> {
8670 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
8671 }
8672 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
8673 #[inline(always)]
8674 fn concat_swizzle_dyn_i16x32(
8675 self,
8676 a: i16x32<Self>,
8677 b: i16x32<Self>,
8678 indices: u8x64<Self>,
8679 ) -> i16x32<Self> {
8680 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
8681 Bytes::to_bytes(a),
8682 Bytes::to_bytes(b),
8683 indices,
8684 ))
8685 }
8686 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
8687 #[inline(always)]
8688 fn concat_swizzle_dyn_precise_i16x32(
8689 self,
8690 a: i16x32<Self>,
8691 b: i16x32<Self>,
8692 indices: u8x64<Self>,
8693 ) -> i16x32<Self> {
8694 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
8695 Bytes::to_bytes(a),
8696 Bytes::to_bytes(b),
8697 indices,
8698 ))
8699 }
8700 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
8701 fn compress_i16x32(self, values: i16x32<Self>, mask: mask16x32<Self>) -> i16x32<Self>;
8702 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
8703 fn compress_merge_i16x32(
8704 self,
8705 values: i16x32<Self>,
8706 mask: mask16x32<Self>,
8707 merge: i16x32<Self>,
8708 ) -> i16x32<Self>;
8709 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
8710 fn expand_i16x32(self, values: i16x32<Self>, mask: mask16x32<Self>) -> i16x32<Self>;
8711 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
8712 fn expand_merge_i16x32(
8713 self,
8714 values: i16x32<Self>,
8715 mask: mask16x32<Self>,
8716 merge: i16x32<Self>,
8717 ) -> i16x32<Self>;
8718 #[doc = "Return the number of ones in the binary representation of each element."]
8719 #[inline(always)]
8720 fn count_ones_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8721 let (a0, a1) = self.split_i16x32(a);
8722 self.combine_i16x16(self.count_ones_i16x16(a0), self.count_ones_i16x16(a1))
8723 }
8724 #[doc = "Return the number of zeros in the binary representation of each element."]
8725 #[inline(always)]
8726 fn count_zeros_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8727 let (a0, a1) = self.split_i16x32(a);
8728 self.combine_i16x16(self.count_zeros_i16x16(a0), self.count_zeros_i16x16(a1))
8729 }
8730 #[doc = "Add two vectors element-wise, wrapping on overflow."]
8731 #[inline(always)]
8732 fn add_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8733 let (a0, a1) = self.split_i16x32(a);
8734 let (b0, b1) = self.split_i16x32(b);
8735 self.combine_i16x16(self.add_i16x16(a0, b0), self.add_i16x16(a1, b1))
8736 }
8737 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
8738 #[inline(always)]
8739 fn saturating_add_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8740 let (a0, a1) = self.split_i16x32(a);
8741 let (b0, b1) = self.split_i16x32(b);
8742 self.combine_i16x16(
8743 self.saturating_add_i16x16(a0, b0),
8744 self.saturating_add_i16x16(a1, b1),
8745 )
8746 }
8747 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
8748 #[inline(always)]
8749 fn sub_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8750 let (a0, a1) = self.split_i16x32(a);
8751 let (b0, b1) = self.split_i16x32(b);
8752 self.combine_i16x16(self.sub_i16x16(a0, b0), self.sub_i16x16(a1, b1))
8753 }
8754 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
8755 #[inline(always)]
8756 fn saturating_sub_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8757 let (a0, a1) = self.split_i16x32(a);
8758 let (b0, b1) = self.split_i16x32(b);
8759 self.combine_i16x16(
8760 self.saturating_sub_i16x16(a0, b0),
8761 self.saturating_sub_i16x16(a1, b1),
8762 )
8763 }
8764 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
8765 #[inline(always)]
8766 fn mul_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8767 let (a0, a1) = self.split_i16x32(a);
8768 let (b0, b1) = self.split_i16x32(b);
8769 self.combine_i16x16(self.mul_i16x16(a0, b0), self.mul_i16x16(a1, b1))
8770 }
8771 #[doc = "Compute the bitwise AND of two vectors."]
8772 #[inline(always)]
8773 fn and_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8774 let (a0, a1) = self.split_i16x32(a);
8775 let (b0, b1) = self.split_i16x32(b);
8776 self.combine_i16x16(self.and_i16x16(a0, b0), self.and_i16x16(a1, b1))
8777 }
8778 #[doc = "Compute the bitwise OR of two vectors."]
8779 #[inline(always)]
8780 fn or_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8781 let (a0, a1) = self.split_i16x32(a);
8782 let (b0, b1) = self.split_i16x32(b);
8783 self.combine_i16x16(self.or_i16x16(a0, b0), self.or_i16x16(a1, b1))
8784 }
8785 #[doc = "Compute the bitwise XOR of two vectors."]
8786 #[inline(always)]
8787 fn xor_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8788 let (a0, a1) = self.split_i16x32(a);
8789 let (b0, b1) = self.split_i16x32(b);
8790 self.combine_i16x16(self.xor_i16x16(a0, b0), self.xor_i16x16(a1, b1))
8791 }
8792 #[doc = "Compute the bitwise NOT of the vector."]
8793 #[inline(always)]
8794 fn not_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8795 let (a0, a1) = self.split_i16x32(a);
8796 self.combine_i16x16(self.not_i16x16(a0), self.not_i16x16(a1))
8797 }
8798 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
8799 #[inline(always)]
8800 fn shl_i16x32(self, a: i16x32<Self>, shift: u32) -> i16x32<Self> {
8801 let (a0, a1) = self.split_i16x32(a);
8802 self.combine_i16x16(self.shl_i16x16(a0, shift), self.shl_i16x16(a1, shift))
8803 }
8804 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
8805 #[inline(always)]
8806 fn shlv_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8807 let (a0, a1) = self.split_i16x32(a);
8808 let (b0, b1) = self.split_i16x32(b);
8809 self.combine_i16x16(self.shlv_i16x16(a0, b0), self.shlv_i16x16(a1, b1))
8810 }
8811 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
8812 #[inline(always)]
8813 fn shr_i16x32(self, a: i16x32<Self>, shift: u32) -> i16x32<Self> {
8814 let (a0, a1) = self.split_i16x32(a);
8815 self.combine_i16x16(self.shr_i16x16(a0, shift), self.shr_i16x16(a1, shift))
8816 }
8817 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
8818 #[inline(always)]
8819 fn shrv_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8820 let (a0, a1) = self.split_i16x32(a);
8821 let (b0, b1) = self.split_i16x32(b);
8822 self.combine_i16x16(self.shrv_i16x16(a0, b0), self.shrv_i16x16(a1, b1))
8823 }
8824 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
8825 #[inline(always)]
8826 fn reduce_max_i16x32(self, a: i16x32<Self>) -> i16 {
8827 let (a0, a1) = self.split_i16x32(a);
8828 self.reduce_max_i16x16(self.max_i16x16(a0, a1))
8829 }
8830 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
8831 #[inline(always)]
8832 fn reduce_min_i16x32(self, a: i16x32<Self>) -> i16 {
8833 let (a0, a1) = self.split_i16x32(a);
8834 self.reduce_min_i16x16(self.min_i16x16(a0, a1))
8835 }
8836 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
8837 #[inline(always)]
8838 fn reduce_sum_i16x32(self, a: i16x32<Self>) -> i16 {
8839 let (a0, a1) = self.split_i16x32(a);
8840 self.reduce_sum_i16x16(self.add_i16x16(a0, a1))
8841 }
8842 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
8843 #[inline(always)]
8844 fn reduce_product_i16x32(self, a: i16x32<Self>) -> i16 {
8845 let (a0, a1) = self.split_i16x32(a);
8846 self.reduce_product_i16x16(self.mul_i16x16(a0, a1))
8847 }
8848 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
8849 #[inline(always)]
8850 fn max_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8851 let (a0, a1) = self.split_i16x32(a);
8852 let (b0, b1) = self.split_i16x32(b);
8853 self.combine_i16x16(self.max_i16x16(a0, b0), self.max_i16x16(a1, b1))
8854 }
8855 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
8856 #[inline(always)]
8857 fn min_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8858 let (a0, a1) = self.split_i16x32(a);
8859 let (b0, b1) = self.split_i16x32(b);
8860 self.combine_i16x16(self.min_i16x16(a0, b0), self.min_i16x16(a1, b1))
8861 }
8862 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
8863 #[inline(always)]
8864 fn clamp_i16x32(self, a: i16x32<Self>, b: i16x32<Self>, c: i16x32<Self>) -> i16x32<Self> {
8865 let (a0, a1) = self.split_i16x32(a);
8866 let (b0, b1) = self.split_i16x32(b);
8867 let (c0, c1) = self.split_i16x32(c);
8868 self.combine_i16x16(self.clamp_i16x16(a0, b0, c0), self.clamp_i16x16(a1, b1, c1))
8869 }
8870 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
8871 #[inline(always)]
8872 fn simd_eq_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8873 let (a0, a1) = self.split_i16x32(a);
8874 let (b0, b1) = self.split_i16x32(b);
8875 self.combine_mask16x16(self.simd_eq_i16x16(a0, b0), self.simd_eq_i16x16(a1, b1))
8876 }
8877 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
8878 #[inline(always)]
8879 fn simd_ne_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8880 self.not_mask16x32(self.simd_eq_i16x32(a, b))
8881 }
8882 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
8883 #[inline(always)]
8884 fn simd_lt_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8885 let (a0, a1) = self.split_i16x32(a);
8886 let (b0, b1) = self.split_i16x32(b);
8887 self.combine_mask16x16(self.simd_lt_i16x16(a0, b0), self.simd_lt_i16x16(a1, b1))
8888 }
8889 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
8890 #[inline(always)]
8891 fn simd_le_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8892 let (a0, a1) = self.split_i16x32(a);
8893 let (b0, b1) = self.split_i16x32(b);
8894 self.combine_mask16x16(self.simd_le_i16x16(a0, b0), self.simd_le_i16x16(a1, b1))
8895 }
8896 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
8897 #[inline(always)]
8898 fn simd_ge_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8899 self.simd_le_i16x32(b, a)
8900 }
8901 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
8902 #[inline(always)]
8903 fn simd_gt_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> mask16x32<Self> {
8904 self.simd_lt_i16x32(b, a)
8905 }
8906 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
8907 #[inline(always)]
8908 fn zip_low_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8909 let (a0, _) = self.split_i16x32(a);
8910 let (b0, _) = self.split_i16x32(b);
8911 self.combine_i16x16(self.zip_low_i16x16(a0, b0), self.zip_high_i16x16(a0, b0))
8912 }
8913 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
8914 #[inline(always)]
8915 fn zip_high_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8916 let (_, a1) = self.split_i16x32(a);
8917 let (_, b1) = self.split_i16x32(b);
8918 self.combine_i16x16(self.zip_low_i16x16(a1, b1), self.zip_high_i16x16(a1, b1))
8919 }
8920 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
8921 #[inline(always)]
8922 fn unzip_low_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8923 let (a0, a1) = self.split_i16x32(a);
8924 let (b0, b1) = self.split_i16x32(b);
8925 self.combine_i16x16(self.unzip_low_i16x16(a0, a1), self.unzip_low_i16x16(b0, b1))
8926 }
8927 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
8928 #[inline(always)]
8929 fn unzip_high_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i16x32<Self> {
8930 let (a0, a1) = self.split_i16x32(a);
8931 let (b0, b1) = self.split_i16x32(b);
8932 self.combine_i16x16(
8933 self.unzip_high_i16x16(a0, a1),
8934 self.unzip_high_i16x16(b0, b1),
8935 )
8936 }
8937 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
8938 #[inline(always)]
8939 fn interleave_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> (i16x32<Self>, i16x32<Self>) {
8940 let (a0, a1) = self.split_i16x32(a);
8941 let (b0, b1) = self.split_i16x32(b);
8942 let lo_lo = self.zip_low_i16x16(a0, b0);
8943 let lo_hi = self.zip_high_i16x16(a0, b0);
8944 let hi_lo = self.zip_low_i16x16(a1, b1);
8945 let hi_hi = self.zip_high_i16x16(a1, b1);
8946 (
8947 self.combine_i16x16(lo_lo, lo_hi),
8948 self.combine_i16x16(hi_lo, hi_hi),
8949 )
8950 }
8951 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
8952 #[inline(always)]
8953 fn deinterleave_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> (i16x32<Self>, i16x32<Self>) {
8954 let (a0, a1) = self.split_i16x32(a);
8955 let (b0, b1) = self.split_i16x32(b);
8956 let lo_even = self.unzip_low_i16x16(a0, a1);
8957 let lo_odd = self.unzip_high_i16x16(a0, a1);
8958 let hi_even = self.unzip_low_i16x16(b0, b1);
8959 let hi_odd = self.unzip_high_i16x16(b0, b1);
8960 (
8961 self.combine_i16x16(lo_even, hi_even),
8962 self.combine_i16x16(lo_odd, hi_odd),
8963 )
8964 }
8965 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
8966 #[inline(always)]
8967 fn select_i16x32(self, a: mask16x32<Self>, b: i16x32<Self>, c: i16x32<Self>) -> i16x32<Self> {
8968 let (a0, a1) = self.split_mask16x32(a);
8969 let (b0, b1) = self.split_i16x32(b);
8970 let (c0, c1) = self.split_i16x32(c);
8971 self.combine_i16x16(
8972 self.select_i16x16(a0, b0, c0),
8973 self.select_i16x16(a1, b1, c1),
8974 )
8975 }
8976 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
8977 fn split_i16x32(self, a: i16x32<Self>) -> (i16x16<Self>, i16x16<Self>);
8978 #[doc = "Negate each element of the vector, wrapping on overflow."]
8979 #[inline(always)]
8980 fn neg_i16x32(self, a: i16x32<Self>) -> i16x32<Self> {
8981 let (a0, a1) = self.split_i16x32(a);
8982 self.combine_i16x16(self.neg_i16x16(a0), self.neg_i16x16(a1))
8983 }
8984 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
8985 #[inline(always)]
8986 fn widen_i16x32(self, a: i16x32<Self>) -> (i32x16<Self>, i32x16<Self>) {
8987 let (a0, a1) = self.split_i16x32(a);
8988 let (a00, a01) = self.widen_i16x16(a0);
8989 let (a10, a11) = self.widen_i16x16(a1);
8990 (self.combine_i32x8(a00, a01), self.combine_i32x8(a10, a11))
8991 }
8992 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
8993 #[inline(always)]
8994 fn widening_mul_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> (i32x16<Self>, i32x16<Self>) {
8995 let (a0, a1) = self.split_i16x32(a);
8996 let (b0, b1) = self.split_i16x32(b);
8997 let (low0, low1) = self.widening_mul_i16x16(a0, b0);
8998 let (high0, high1) = self.widening_mul_i16x16(a1, b1);
8999 (
9000 self.combine_i32x8(low0, low1),
9001 self.combine_i32x8(high0, high1),
9002 )
9003 }
9004 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
9005 #[inline(always)]
9006 fn widening_add_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> (i32x16<Self>, i32x16<Self>) {
9007 let (a0, a1) = self.split_i16x32(a);
9008 let (b0, b1) = self.split_i16x32(b);
9009 let (low0, low1) = self.widening_add_i16x16(a0, b0);
9010 let (high0, high1) = self.widening_add_i16x16(a1, b1);
9011 (
9012 self.combine_i32x8(low0, low1),
9013 self.combine_i32x8(high0, high1),
9014 )
9015 }
9016 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
9017 #[inline(always)]
9018 fn pairwise_widening_add_i16x32(self, a: i16x32<Self>) -> i32x16<Self> {
9019 let (a0, a1) = self.split_i16x32(a);
9020 self.combine_i32x8(
9021 self.pairwise_widening_add_i16x16(a0),
9022 self.pairwise_widening_add_i16x16(a1),
9023 )
9024 }
9025 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
9026 #[inline(always)]
9027 fn pairwise_dot_product_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i32x16<Self> {
9028 let (a0, a1) = self.split_i16x32(a);
9029 let (b0, b1) = self.split_i16x32(b);
9030 self.combine_i32x8(
9031 self.pairwise_dot_product_i16x16(a0, b0),
9032 self.pairwise_dot_product_i16x16(a1, b1),
9033 )
9034 }
9035 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
9036 #[inline(always)]
9037 fn narrow_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i8x64<Self> {
9038 let (a0, a1) = self.split_i16x32(a);
9039 let (b0, b1) = self.split_i16x32(b);
9040 self.combine_i8x32(self.narrow_i16x16(a0, a1), self.narrow_i16x16(b0, b1))
9041 }
9042 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
9043 #[inline(always)]
9044 fn saturating_narrow_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i8x64<Self> {
9045 let (a0, a1) = self.split_i16x32(a);
9046 let (b0, b1) = self.split_i16x32(b);
9047 self.combine_i8x32(
9048 self.saturating_narrow_i16x16(a0, a1),
9049 self.saturating_narrow_i16x16(b0, b1),
9050 )
9051 }
9052 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
9053 #[inline(always)]
9054 fn relaxed_narrow_i16x32(self, a: i16x32<Self>, b: i16x32<Self>) -> i8x64<Self> {
9055 let (a0, a1) = self.split_i16x32(a);
9056 let (b0, b1) = self.split_i16x32(b);
9057 self.combine_i8x32(
9058 self.relaxed_narrow_i16x16(a0, a1),
9059 self.relaxed_narrow_i16x16(b0, b1),
9060 )
9061 }
9062 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
9063 #[inline(always)]
9064 fn abs_u16x32(self, a: u16x32<Self>) -> u16x32<Self> {
9065 a
9066 }
9067 #[doc = "Create a SIMD vector with all elements set to the given value."]
9068 #[inline(always)]
9069 fn splat_u16x32(self, val: u16) -> u16x32<Self> {
9070 let half = self.splat_u16x16(val);
9071 self.combine_u16x16(half, half)
9072 }
9073 #[doc = "Reverse the order of the vector's elements."]
9074 #[inline(always)]
9075 fn reverse_u16x32(self, a: u16x32<Self>) -> u16x32<Self> {
9076 let (a0, a1) = self.split_u16x32(a);
9077 self.combine_u16x16(self.reverse_u16x16(a1), self.reverse_u16x16(a0))
9078 }
9079 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
9080 fn slide_u16x32<const SHIFT: usize>(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self>;
9081 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
9082 #[inline(always)]
9083 fn slide_within_blocks_u16x32<const SHIFT: usize>(
9084 self,
9085 a: u16x32<Self>,
9086 b: u16x32<Self>,
9087 ) -> u16x32<Self> {
9088 let (a0, a1) = self.split_u16x32(a);
9089 let (b0, b1) = self.split_u16x32(b);
9090 self.combine_u16x16(
9091 self.slide_within_blocks_u16x16::<SHIFT>(a0, b0),
9092 self.slide_within_blocks_u16x16::<SHIFT>(a1, b1),
9093 )
9094 }
9095 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
9096 #[inline(always)]
9097 fn swizzle_dyn_within_blocks_u16x32(
9098 self,
9099 a: u16x32<Self>,
9100 indices: u8x64<Self>,
9101 ) -> u16x32<Self> {
9102 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
9103 }
9104 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
9105 #[inline(always)]
9106 fn swizzle_dyn_u16x32(self, a: u16x32<Self>, indices: u8x64<Self>) -> u16x32<Self> {
9107 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
9108 }
9109 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
9110 #[inline(always)]
9111 fn swizzle_dyn_precise_u16x32(self, a: u16x32<Self>, indices: u8x64<Self>) -> u16x32<Self> {
9112 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
9113 }
9114 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
9115 #[inline(always)]
9116 fn concat_swizzle_dyn_u16x32(
9117 self,
9118 a: u16x32<Self>,
9119 b: u16x32<Self>,
9120 indices: u8x64<Self>,
9121 ) -> u16x32<Self> {
9122 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
9123 Bytes::to_bytes(a),
9124 Bytes::to_bytes(b),
9125 indices,
9126 ))
9127 }
9128 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
9129 #[inline(always)]
9130 fn concat_swizzle_dyn_precise_u16x32(
9131 self,
9132 a: u16x32<Self>,
9133 b: u16x32<Self>,
9134 indices: u8x64<Self>,
9135 ) -> u16x32<Self> {
9136 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
9137 Bytes::to_bytes(a),
9138 Bytes::to_bytes(b),
9139 indices,
9140 ))
9141 }
9142 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
9143 fn compress_u16x32(self, values: u16x32<Self>, mask: mask16x32<Self>) -> u16x32<Self>;
9144 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
9145 fn compress_merge_u16x32(
9146 self,
9147 values: u16x32<Self>,
9148 mask: mask16x32<Self>,
9149 merge: u16x32<Self>,
9150 ) -> u16x32<Self>;
9151 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
9152 fn expand_u16x32(self, values: u16x32<Self>, mask: mask16x32<Self>) -> u16x32<Self>;
9153 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
9154 fn expand_merge_u16x32(
9155 self,
9156 values: u16x32<Self>,
9157 mask: mask16x32<Self>,
9158 merge: u16x32<Self>,
9159 ) -> u16x32<Self>;
9160 #[doc = "Return the number of ones in the binary representation of each element."]
9161 #[inline(always)]
9162 fn count_ones_u16x32(self, a: u16x32<Self>) -> u16x32<Self> {
9163 let (a0, a1) = self.split_u16x32(a);
9164 self.combine_u16x16(self.count_ones_u16x16(a0), self.count_ones_u16x16(a1))
9165 }
9166 #[doc = "Return the number of zeros in the binary representation of each element."]
9167 #[inline(always)]
9168 fn count_zeros_u16x32(self, a: u16x32<Self>) -> u16x32<Self> {
9169 let (a0, a1) = self.split_u16x32(a);
9170 self.combine_u16x16(self.count_zeros_u16x16(a0), self.count_zeros_u16x16(a1))
9171 }
9172 #[doc = "Add two vectors element-wise, wrapping on overflow."]
9173 #[inline(always)]
9174 fn add_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9175 let (a0, a1) = self.split_u16x32(a);
9176 let (b0, b1) = self.split_u16x32(b);
9177 self.combine_u16x16(self.add_u16x16(a0, b0), self.add_u16x16(a1, b1))
9178 }
9179 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
9180 #[inline(always)]
9181 fn saturating_add_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9182 let (a0, a1) = self.split_u16x32(a);
9183 let (b0, b1) = self.split_u16x32(b);
9184 self.combine_u16x16(
9185 self.saturating_add_u16x16(a0, b0),
9186 self.saturating_add_u16x16(a1, b1),
9187 )
9188 }
9189 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
9190 #[inline(always)]
9191 fn sub_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9192 let (a0, a1) = self.split_u16x32(a);
9193 let (b0, b1) = self.split_u16x32(b);
9194 self.combine_u16x16(self.sub_u16x16(a0, b0), self.sub_u16x16(a1, b1))
9195 }
9196 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
9197 #[inline(always)]
9198 fn saturating_sub_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9199 let (a0, a1) = self.split_u16x32(a);
9200 let (b0, b1) = self.split_u16x32(b);
9201 self.combine_u16x16(
9202 self.saturating_sub_u16x16(a0, b0),
9203 self.saturating_sub_u16x16(a1, b1),
9204 )
9205 }
9206 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
9207 #[inline(always)]
9208 fn mul_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9209 let (a0, a1) = self.split_u16x32(a);
9210 let (b0, b1) = self.split_u16x32(b);
9211 self.combine_u16x16(self.mul_u16x16(a0, b0), self.mul_u16x16(a1, b1))
9212 }
9213 #[doc = "Compute the bitwise AND of two vectors."]
9214 #[inline(always)]
9215 fn and_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9216 let (a0, a1) = self.split_u16x32(a);
9217 let (b0, b1) = self.split_u16x32(b);
9218 self.combine_u16x16(self.and_u16x16(a0, b0), self.and_u16x16(a1, b1))
9219 }
9220 #[doc = "Compute the bitwise OR of two vectors."]
9221 #[inline(always)]
9222 fn or_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9223 let (a0, a1) = self.split_u16x32(a);
9224 let (b0, b1) = self.split_u16x32(b);
9225 self.combine_u16x16(self.or_u16x16(a0, b0), self.or_u16x16(a1, b1))
9226 }
9227 #[doc = "Compute the bitwise XOR of two vectors."]
9228 #[inline(always)]
9229 fn xor_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9230 let (a0, a1) = self.split_u16x32(a);
9231 let (b0, b1) = self.split_u16x32(b);
9232 self.combine_u16x16(self.xor_u16x16(a0, b0), self.xor_u16x16(a1, b1))
9233 }
9234 #[doc = "Compute the bitwise NOT of the vector."]
9235 #[inline(always)]
9236 fn not_u16x32(self, a: u16x32<Self>) -> u16x32<Self> {
9237 let (a0, a1) = self.split_u16x32(a);
9238 self.combine_u16x16(self.not_u16x16(a0), self.not_u16x16(a1))
9239 }
9240 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
9241 #[inline(always)]
9242 fn shl_u16x32(self, a: u16x32<Self>, shift: u32) -> u16x32<Self> {
9243 let (a0, a1) = self.split_u16x32(a);
9244 self.combine_u16x16(self.shl_u16x16(a0, shift), self.shl_u16x16(a1, shift))
9245 }
9246 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
9247 #[inline(always)]
9248 fn shlv_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9249 let (a0, a1) = self.split_u16x32(a);
9250 let (b0, b1) = self.split_u16x32(b);
9251 self.combine_u16x16(self.shlv_u16x16(a0, b0), self.shlv_u16x16(a1, b1))
9252 }
9253 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
9254 #[inline(always)]
9255 fn shr_u16x32(self, a: u16x32<Self>, shift: u32) -> u16x32<Self> {
9256 let (a0, a1) = self.split_u16x32(a);
9257 self.combine_u16x16(self.shr_u16x16(a0, shift), self.shr_u16x16(a1, shift))
9258 }
9259 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
9260 #[inline(always)]
9261 fn shrv_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9262 let (a0, a1) = self.split_u16x32(a);
9263 let (b0, b1) = self.split_u16x32(b);
9264 self.combine_u16x16(self.shrv_u16x16(a0, b0), self.shrv_u16x16(a1, b1))
9265 }
9266 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
9267 #[inline(always)]
9268 fn reduce_max_u16x32(self, a: u16x32<Self>) -> u16 {
9269 let (a0, a1) = self.split_u16x32(a);
9270 self.reduce_max_u16x16(self.max_u16x16(a0, a1))
9271 }
9272 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
9273 #[inline(always)]
9274 fn reduce_min_u16x32(self, a: u16x32<Self>) -> u16 {
9275 let (a0, a1) = self.split_u16x32(a);
9276 self.reduce_min_u16x16(self.min_u16x16(a0, a1))
9277 }
9278 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
9279 #[inline(always)]
9280 fn reduce_sum_u16x32(self, a: u16x32<Self>) -> u16 {
9281 let (a0, a1) = self.split_u16x32(a);
9282 self.reduce_sum_u16x16(self.add_u16x16(a0, a1))
9283 }
9284 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
9285 #[inline(always)]
9286 fn reduce_product_u16x32(self, a: u16x32<Self>) -> u16 {
9287 let (a0, a1) = self.split_u16x32(a);
9288 self.reduce_product_u16x16(self.mul_u16x16(a0, a1))
9289 }
9290 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
9291 #[inline(always)]
9292 fn max_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9293 let (a0, a1) = self.split_u16x32(a);
9294 let (b0, b1) = self.split_u16x32(b);
9295 self.combine_u16x16(self.max_u16x16(a0, b0), self.max_u16x16(a1, b1))
9296 }
9297 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
9298 #[inline(always)]
9299 fn min_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9300 let (a0, a1) = self.split_u16x32(a);
9301 let (b0, b1) = self.split_u16x32(b);
9302 self.combine_u16x16(self.min_u16x16(a0, b0), self.min_u16x16(a1, b1))
9303 }
9304 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
9305 #[inline(always)]
9306 fn clamp_u16x32(self, a: u16x32<Self>, b: u16x32<Self>, c: u16x32<Self>) -> u16x32<Self> {
9307 let (a0, a1) = self.split_u16x32(a);
9308 let (b0, b1) = self.split_u16x32(b);
9309 let (c0, c1) = self.split_u16x32(c);
9310 self.combine_u16x16(self.clamp_u16x16(a0, b0, c0), self.clamp_u16x16(a1, b1, c1))
9311 }
9312 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
9313 #[inline(always)]
9314 fn simd_eq_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9315 let (a0, a1) = self.split_u16x32(a);
9316 let (b0, b1) = self.split_u16x32(b);
9317 self.combine_mask16x16(self.simd_eq_u16x16(a0, b0), self.simd_eq_u16x16(a1, b1))
9318 }
9319 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
9320 #[inline(always)]
9321 fn simd_ne_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9322 self.not_mask16x32(self.simd_eq_u16x32(a, b))
9323 }
9324 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
9325 #[inline(always)]
9326 fn simd_lt_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9327 let (a0, a1) = self.split_u16x32(a);
9328 let (b0, b1) = self.split_u16x32(b);
9329 self.combine_mask16x16(self.simd_lt_u16x16(a0, b0), self.simd_lt_u16x16(a1, b1))
9330 }
9331 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
9332 #[inline(always)]
9333 fn simd_le_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9334 let (a0, a1) = self.split_u16x32(a);
9335 let (b0, b1) = self.split_u16x32(b);
9336 self.combine_mask16x16(self.simd_le_u16x16(a0, b0), self.simd_le_u16x16(a1, b1))
9337 }
9338 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
9339 #[inline(always)]
9340 fn simd_ge_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9341 self.simd_le_u16x32(b, a)
9342 }
9343 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
9344 #[inline(always)]
9345 fn simd_gt_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> mask16x32<Self> {
9346 self.simd_lt_u16x32(b, a)
9347 }
9348 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
9349 #[inline(always)]
9350 fn zip_low_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9351 let (a0, _) = self.split_u16x32(a);
9352 let (b0, _) = self.split_u16x32(b);
9353 self.combine_u16x16(self.zip_low_u16x16(a0, b0), self.zip_high_u16x16(a0, b0))
9354 }
9355 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
9356 #[inline(always)]
9357 fn zip_high_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9358 let (_, a1) = self.split_u16x32(a);
9359 let (_, b1) = self.split_u16x32(b);
9360 self.combine_u16x16(self.zip_low_u16x16(a1, b1), self.zip_high_u16x16(a1, b1))
9361 }
9362 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
9363 #[inline(always)]
9364 fn unzip_low_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9365 let (a0, a1) = self.split_u16x32(a);
9366 let (b0, b1) = self.split_u16x32(b);
9367 self.combine_u16x16(self.unzip_low_u16x16(a0, a1), self.unzip_low_u16x16(b0, b1))
9368 }
9369 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
9370 #[inline(always)]
9371 fn unzip_high_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u16x32<Self> {
9372 let (a0, a1) = self.split_u16x32(a);
9373 let (b0, b1) = self.split_u16x32(b);
9374 self.combine_u16x16(
9375 self.unzip_high_u16x16(a0, a1),
9376 self.unzip_high_u16x16(b0, b1),
9377 )
9378 }
9379 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
9380 #[inline(always)]
9381 fn interleave_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> (u16x32<Self>, u16x32<Self>) {
9382 let (a0, a1) = self.split_u16x32(a);
9383 let (b0, b1) = self.split_u16x32(b);
9384 let lo_lo = self.zip_low_u16x16(a0, b0);
9385 let lo_hi = self.zip_high_u16x16(a0, b0);
9386 let hi_lo = self.zip_low_u16x16(a1, b1);
9387 let hi_hi = self.zip_high_u16x16(a1, b1);
9388 (
9389 self.combine_u16x16(lo_lo, lo_hi),
9390 self.combine_u16x16(hi_lo, hi_hi),
9391 )
9392 }
9393 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
9394 #[inline(always)]
9395 fn deinterleave_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> (u16x32<Self>, u16x32<Self>) {
9396 let (a0, a1) = self.split_u16x32(a);
9397 let (b0, b1) = self.split_u16x32(b);
9398 let lo_even = self.unzip_low_u16x16(a0, a1);
9399 let lo_odd = self.unzip_high_u16x16(a0, a1);
9400 let hi_even = self.unzip_low_u16x16(b0, b1);
9401 let hi_odd = self.unzip_high_u16x16(b0, b1);
9402 (
9403 self.combine_u16x16(lo_even, hi_even),
9404 self.combine_u16x16(lo_odd, hi_odd),
9405 )
9406 }
9407 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
9408 #[inline(always)]
9409 fn select_u16x32(self, a: mask16x32<Self>, b: u16x32<Self>, c: u16x32<Self>) -> u16x32<Self> {
9410 let (a0, a1) = self.split_mask16x32(a);
9411 let (b0, b1) = self.split_u16x32(b);
9412 let (c0, c1) = self.split_u16x32(c);
9413 self.combine_u16x16(
9414 self.select_u16x16(a0, b0, c0),
9415 self.select_u16x16(a1, b1, c1),
9416 )
9417 }
9418 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
9419 fn split_u16x32(self, a: u16x32<Self>) -> (u16x16<Self>, u16x16<Self>);
9420 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
9421 #[inline(always)]
9422 fn widen_u16x32(self, a: u16x32<Self>) -> (u32x16<Self>, u32x16<Self>) {
9423 let (a0, a1) = self.split_u16x32(a);
9424 let (a00, a01) = self.widen_u16x16(a0);
9425 let (a10, a11) = self.widen_u16x16(a1);
9426 (self.combine_u32x8(a00, a01), self.combine_u32x8(a10, a11))
9427 }
9428 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
9429 #[inline(always)]
9430 fn widening_mul_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> (u32x16<Self>, u32x16<Self>) {
9431 let (a0, a1) = self.split_u16x32(a);
9432 let (b0, b1) = self.split_u16x32(b);
9433 let (low0, low1) = self.widening_mul_u16x16(a0, b0);
9434 let (high0, high1) = self.widening_mul_u16x16(a1, b1);
9435 (
9436 self.combine_u32x8(low0, low1),
9437 self.combine_u32x8(high0, high1),
9438 )
9439 }
9440 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
9441 #[inline(always)]
9442 fn widening_add_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> (u32x16<Self>, u32x16<Self>) {
9443 let (a0, a1) = self.split_u16x32(a);
9444 let (b0, b1) = self.split_u16x32(b);
9445 let (low0, low1) = self.widening_add_u16x16(a0, b0);
9446 let (high0, high1) = self.widening_add_u16x16(a1, b1);
9447 (
9448 self.combine_u32x8(low0, low1),
9449 self.combine_u32x8(high0, high1),
9450 )
9451 }
9452 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
9453 #[inline(always)]
9454 fn pairwise_widening_add_u16x32(self, a: u16x32<Self>) -> u32x16<Self> {
9455 let (a0, a1) = self.split_u16x32(a);
9456 self.combine_u32x8(
9457 self.pairwise_widening_add_u16x16(a0),
9458 self.pairwise_widening_add_u16x16(a1),
9459 )
9460 }
9461 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
9462 #[inline(always)]
9463 fn pairwise_dot_product_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u32x16<Self> {
9464 let (a0, a1) = self.split_u16x32(a);
9465 let (b0, b1) = self.split_u16x32(b);
9466 self.combine_u32x8(
9467 self.pairwise_dot_product_u16x16(a0, b0),
9468 self.pairwise_dot_product_u16x16(a1, b1),
9469 )
9470 }
9471 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
9472 #[inline(always)]
9473 fn narrow_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u8x64<Self> {
9474 let (a0, a1) = self.split_u16x32(a);
9475 let (b0, b1) = self.split_u16x32(b);
9476 self.combine_u8x32(self.narrow_u16x16(a0, a1), self.narrow_u16x16(b0, b1))
9477 }
9478 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
9479 #[inline(always)]
9480 fn saturating_narrow_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u8x64<Self> {
9481 let (a0, a1) = self.split_u16x32(a);
9482 let (b0, b1) = self.split_u16x32(b);
9483 self.combine_u8x32(
9484 self.saturating_narrow_u16x16(a0, a1),
9485 self.saturating_narrow_u16x16(b0, b1),
9486 )
9487 }
9488 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
9489 #[inline(always)]
9490 fn relaxed_narrow_u16x32(self, a: u16x32<Self>, b: u16x32<Self>) -> u8x64<Self> {
9491 let (a0, a1) = self.split_u16x32(a);
9492 let (b0, b1) = self.split_u16x32(b);
9493 self.combine_u8x32(
9494 self.relaxed_narrow_u16x16(a0, a1),
9495 self.relaxed_narrow_u16x16(b0, b1),
9496 )
9497 }
9498 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
9499 #[inline(always)]
9500 fn splat_mask16x32(self, val: bool) -> mask16x32<Self> {
9501 let half = self.splat_mask16x16(val);
9502 self.combine_mask16x16(half, half)
9503 }
9504 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
9505 #[inline(always)]
9506 fn from_bitmask_mask16x32(self, bits: u64) -> mask16x32<Self> {
9507 let lo = self.from_bitmask_mask16x16(bits);
9508 let hi = self.from_bitmask_mask16x16(bits >> 16usize);
9509 self.combine_mask16x16(lo, hi)
9510 }
9511 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
9512 #[inline(always)]
9513 fn to_bitmask_mask16x32(self, a: mask16x32<Self>) -> u64 {
9514 let (lo, hi) = self.split_mask16x32(a);
9515 let lo = self.to_bitmask_mask16x16(lo);
9516 let hi = self.to_bitmask_mask16x16(hi);
9517 lo | (hi << 16usize)
9518 }
9519 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
9520 fn from_vector_mask16x32(self, vector: i16x32<Self>) -> mask16x32<Self>;
9521 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
9522 fn to_vector_mask16x32(self, a: mask16x32<Self>) -> i16x32<Self>;
9523 #[doc = "Set one logical lane of a SIMD mask."]
9524 fn set_mask16x32(self, a: &mut mask16x32<Self>, index: usize, value: bool) -> ();
9525 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
9526 fn rotate_elements_left_mask16x32<const OFFSET: usize>(
9527 self,
9528 a: mask16x32<Self>,
9529 ) -> mask16x32<Self>;
9530 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
9531 fn rotate_elements_right_mask16x32<const OFFSET: usize>(
9532 self,
9533 a: mask16x32<Self>,
9534 ) -> mask16x32<Self>;
9535 #[doc = "Compute the logical AND of two masks."]
9536 #[inline(always)]
9537 fn and_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask16x32<Self> {
9538 let (a0, a1) = self.split_mask16x32(a);
9539 let (b0, b1) = self.split_mask16x32(b);
9540 self.combine_mask16x16(self.and_mask16x16(a0, b0), self.and_mask16x16(a1, b1))
9541 }
9542 #[doc = "Compute the logical OR of two masks."]
9543 #[inline(always)]
9544 fn or_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask16x32<Self> {
9545 let (a0, a1) = self.split_mask16x32(a);
9546 let (b0, b1) = self.split_mask16x32(b);
9547 self.combine_mask16x16(self.or_mask16x16(a0, b0), self.or_mask16x16(a1, b1))
9548 }
9549 #[doc = "Compute the logical XOR of two masks."]
9550 #[inline(always)]
9551 fn xor_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask16x32<Self> {
9552 let (a0, a1) = self.split_mask16x32(a);
9553 let (b0, b1) = self.split_mask16x32(b);
9554 self.combine_mask16x16(self.xor_mask16x16(a0, b0), self.xor_mask16x16(a1, b1))
9555 }
9556 #[doc = "Compute the logical NOT of the mask."]
9557 #[inline(always)]
9558 fn not_mask16x32(self, a: mask16x32<Self>) -> mask16x32<Self> {
9559 let (a0, a1) = self.split_mask16x32(a);
9560 self.combine_mask16x16(self.not_mask16x16(a0), self.not_mask16x16(a1))
9561 }
9562 #[doc = "Reverse the order of the mask's logical lanes."]
9563 #[inline(always)]
9564 fn reverse_mask16x32(self, a: mask16x32<Self>) -> mask16x32<Self> {
9565 let (a0, a1) = self.split_mask16x32(a);
9566 self.combine_mask16x16(self.reverse_mask16x16(a1), self.reverse_mask16x16(a0))
9567 }
9568 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
9569 #[inline(always)]
9570 fn select_mask16x32(
9571 self,
9572 a: mask16x32<Self>,
9573 b: mask16x32<Self>,
9574 c: mask16x32<Self>,
9575 ) -> mask16x32<Self> {
9576 let (a0, a1) = self.split_mask16x32(a);
9577 let (b0, b1) = self.split_mask16x32(b);
9578 let (c0, c1) = self.split_mask16x32(c);
9579 self.combine_mask16x16(
9580 self.select_mask16x16(a0, b0, c0),
9581 self.select_mask16x16(a1, b1, c1),
9582 )
9583 }
9584 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
9585 #[inline(always)]
9586 fn simd_eq_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask16x32<Self> {
9587 let (a0, a1) = self.split_mask16x32(a);
9588 let (b0, b1) = self.split_mask16x32(b);
9589 self.combine_mask16x16(
9590 self.simd_eq_mask16x16(a0, b0),
9591 self.simd_eq_mask16x16(a1, b1),
9592 )
9593 }
9594 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
9595 #[inline(always)]
9596 fn simd_ne_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask16x32<Self> {
9597 self.not_mask16x32(self.simd_eq_mask16x32(a, b))
9598 }
9599 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
9600 #[inline(always)]
9601 fn any_true_mask16x32(self, a: mask16x32<Self>) -> bool {
9602 let (a0, a1) = self.split_mask16x32(a);
9603 self.any_true_mask16x16(self.or_mask16x16(a0, a1))
9604 }
9605 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
9606 #[inline(always)]
9607 fn all_true_mask16x32(self, a: mask16x32<Self>) -> bool {
9608 let (a0, a1) = self.split_mask16x32(a);
9609 self.all_true_mask16x16(self.and_mask16x16(a0, a1))
9610 }
9611 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
9612 #[inline(always)]
9613 fn any_false_mask16x32(self, a: mask16x32<Self>) -> bool {
9614 let (a0, a1) = self.split_mask16x32(a);
9615 self.any_false_mask16x16(self.and_mask16x16(a0, a1))
9616 }
9617 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
9618 #[inline(always)]
9619 fn all_false_mask16x32(self, a: mask16x32<Self>) -> bool {
9620 let (a0, a1) = self.split_mask16x32(a);
9621 self.all_false_mask16x16(self.or_mask16x16(a0, a1))
9622 }
9623 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
9624 fn split_mask16x32(self, a: mask16x32<Self>) -> (mask16x16<Self>, mask16x16<Self>);
9625 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
9626 #[inline(always)]
9627 fn widen_mask16x32(self, a: mask16x32<Self>) -> (mask32x16<Self>, mask32x16<Self>) {
9628 let (a0, a1) = self.split_mask16x32(a);
9629 let (a00, a01) = self.widen_mask16x16(a0);
9630 let (a10, a11) = self.widen_mask16x16(a1);
9631 (
9632 self.combine_mask32x8(a00, a01),
9633 self.combine_mask32x8(a10, a11),
9634 )
9635 }
9636 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
9637 #[inline(always)]
9638 fn narrow_mask16x32(self, a: mask16x32<Self>, b: mask16x32<Self>) -> mask8x64<Self> {
9639 let (a0, a1) = self.split_mask16x32(a);
9640 let (b0, b1) = self.split_mask16x32(b);
9641 self.combine_mask8x32(self.narrow_mask16x16(a0, a1), self.narrow_mask16x16(b0, b1))
9642 }
9643 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
9644 #[inline(always)]
9645 fn abs_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9646 let (a0, a1) = self.split_i32x16(a);
9647 self.combine_i32x8(self.abs_i32x8(a0), self.abs_i32x8(a1))
9648 }
9649 #[doc = "Create a SIMD vector with all elements set to the given value."]
9650 #[inline(always)]
9651 fn splat_i32x16(self, val: i32) -> i32x16<Self> {
9652 let half = self.splat_i32x8(val);
9653 self.combine_i32x8(half, half)
9654 }
9655 #[doc = "Reverse the order of the vector's elements."]
9656 #[inline(always)]
9657 fn reverse_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9658 let (a0, a1) = self.split_i32x16(a);
9659 self.combine_i32x8(self.reverse_i32x8(a1), self.reverse_i32x8(a0))
9660 }
9661 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
9662 fn slide_i32x16<const SHIFT: usize>(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self>;
9663 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
9664 #[inline(always)]
9665 fn slide_within_blocks_i32x16<const SHIFT: usize>(
9666 self,
9667 a: i32x16<Self>,
9668 b: i32x16<Self>,
9669 ) -> i32x16<Self> {
9670 let (a0, a1) = self.split_i32x16(a);
9671 let (b0, b1) = self.split_i32x16(b);
9672 self.combine_i32x8(
9673 self.slide_within_blocks_i32x8::<SHIFT>(a0, b0),
9674 self.slide_within_blocks_i32x8::<SHIFT>(a1, b1),
9675 )
9676 }
9677 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
9678 #[inline(always)]
9679 fn swizzle_dyn_within_blocks_i32x16(
9680 self,
9681 a: i32x16<Self>,
9682 indices: u8x64<Self>,
9683 ) -> i32x16<Self> {
9684 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
9685 }
9686 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
9687 #[inline(always)]
9688 fn swizzle_dyn_i32x16(self, a: i32x16<Self>, indices: u8x64<Self>) -> i32x16<Self> {
9689 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
9690 }
9691 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
9692 #[inline(always)]
9693 fn swizzle_dyn_precise_i32x16(self, a: i32x16<Self>, indices: u8x64<Self>) -> i32x16<Self> {
9694 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
9695 }
9696 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
9697 #[inline(always)]
9698 fn concat_swizzle_dyn_i32x16(
9699 self,
9700 a: i32x16<Self>,
9701 b: i32x16<Self>,
9702 indices: u8x64<Self>,
9703 ) -> i32x16<Self> {
9704 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
9705 Bytes::to_bytes(a),
9706 Bytes::to_bytes(b),
9707 indices,
9708 ))
9709 }
9710 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
9711 #[inline(always)]
9712 fn concat_swizzle_dyn_precise_i32x16(
9713 self,
9714 a: i32x16<Self>,
9715 b: i32x16<Self>,
9716 indices: u8x64<Self>,
9717 ) -> i32x16<Self> {
9718 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
9719 Bytes::to_bytes(a),
9720 Bytes::to_bytes(b),
9721 indices,
9722 ))
9723 }
9724 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
9725 fn compress_i32x16(self, values: i32x16<Self>, mask: mask32x16<Self>) -> i32x16<Self>;
9726 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
9727 fn compress_merge_i32x16(
9728 self,
9729 values: i32x16<Self>,
9730 mask: mask32x16<Self>,
9731 merge: i32x16<Self>,
9732 ) -> i32x16<Self>;
9733 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
9734 fn expand_i32x16(self, values: i32x16<Self>, mask: mask32x16<Self>) -> i32x16<Self>;
9735 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
9736 fn expand_merge_i32x16(
9737 self,
9738 values: i32x16<Self>,
9739 mask: mask32x16<Self>,
9740 merge: i32x16<Self>,
9741 ) -> i32x16<Self>;
9742 #[doc = "Return the number of ones in the binary representation of each element."]
9743 #[inline(always)]
9744 fn count_ones_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9745 let (a0, a1) = self.split_i32x16(a);
9746 self.combine_i32x8(self.count_ones_i32x8(a0), self.count_ones_i32x8(a1))
9747 }
9748 #[doc = "Return the number of zeros in the binary representation of each element."]
9749 #[inline(always)]
9750 fn count_zeros_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9751 let (a0, a1) = self.split_i32x16(a);
9752 self.combine_i32x8(self.count_zeros_i32x8(a0), self.count_zeros_i32x8(a1))
9753 }
9754 #[doc = "Add two vectors element-wise, wrapping on overflow."]
9755 #[inline(always)]
9756 fn add_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9757 let (a0, a1) = self.split_i32x16(a);
9758 let (b0, b1) = self.split_i32x16(b);
9759 self.combine_i32x8(self.add_i32x8(a0, b0), self.add_i32x8(a1, b1))
9760 }
9761 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
9762 #[inline(always)]
9763 fn saturating_add_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9764 let (a0, a1) = self.split_i32x16(a);
9765 let (b0, b1) = self.split_i32x16(b);
9766 self.combine_i32x8(
9767 self.saturating_add_i32x8(a0, b0),
9768 self.saturating_add_i32x8(a1, b1),
9769 )
9770 }
9771 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
9772 #[inline(always)]
9773 fn sub_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9774 let (a0, a1) = self.split_i32x16(a);
9775 let (b0, b1) = self.split_i32x16(b);
9776 self.combine_i32x8(self.sub_i32x8(a0, b0), self.sub_i32x8(a1, b1))
9777 }
9778 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
9779 #[inline(always)]
9780 fn saturating_sub_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9781 let (a0, a1) = self.split_i32x16(a);
9782 let (b0, b1) = self.split_i32x16(b);
9783 self.combine_i32x8(
9784 self.saturating_sub_i32x8(a0, b0),
9785 self.saturating_sub_i32x8(a1, b1),
9786 )
9787 }
9788 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
9789 #[inline(always)]
9790 fn mul_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9791 let (a0, a1) = self.split_i32x16(a);
9792 let (b0, b1) = self.split_i32x16(b);
9793 self.combine_i32x8(self.mul_i32x8(a0, b0), self.mul_i32x8(a1, b1))
9794 }
9795 #[doc = "Compute the bitwise AND of two vectors."]
9796 #[inline(always)]
9797 fn and_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9798 let (a0, a1) = self.split_i32x16(a);
9799 let (b0, b1) = self.split_i32x16(b);
9800 self.combine_i32x8(self.and_i32x8(a0, b0), self.and_i32x8(a1, b1))
9801 }
9802 #[doc = "Compute the bitwise OR of two vectors."]
9803 #[inline(always)]
9804 fn or_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9805 let (a0, a1) = self.split_i32x16(a);
9806 let (b0, b1) = self.split_i32x16(b);
9807 self.combine_i32x8(self.or_i32x8(a0, b0), self.or_i32x8(a1, b1))
9808 }
9809 #[doc = "Compute the bitwise XOR of two vectors."]
9810 #[inline(always)]
9811 fn xor_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9812 let (a0, a1) = self.split_i32x16(a);
9813 let (b0, b1) = self.split_i32x16(b);
9814 self.combine_i32x8(self.xor_i32x8(a0, b0), self.xor_i32x8(a1, b1))
9815 }
9816 #[doc = "Compute the bitwise NOT of the vector."]
9817 #[inline(always)]
9818 fn not_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9819 let (a0, a1) = self.split_i32x16(a);
9820 self.combine_i32x8(self.not_i32x8(a0), self.not_i32x8(a1))
9821 }
9822 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
9823 #[inline(always)]
9824 fn shl_i32x16(self, a: i32x16<Self>, shift: u32) -> i32x16<Self> {
9825 let (a0, a1) = self.split_i32x16(a);
9826 self.combine_i32x8(self.shl_i32x8(a0, shift), self.shl_i32x8(a1, shift))
9827 }
9828 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
9829 #[inline(always)]
9830 fn shlv_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9831 let (a0, a1) = self.split_i32x16(a);
9832 let (b0, b1) = self.split_i32x16(b);
9833 self.combine_i32x8(self.shlv_i32x8(a0, b0), self.shlv_i32x8(a1, b1))
9834 }
9835 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
9836 #[inline(always)]
9837 fn shr_i32x16(self, a: i32x16<Self>, shift: u32) -> i32x16<Self> {
9838 let (a0, a1) = self.split_i32x16(a);
9839 self.combine_i32x8(self.shr_i32x8(a0, shift), self.shr_i32x8(a1, shift))
9840 }
9841 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
9842 #[inline(always)]
9843 fn shrv_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9844 let (a0, a1) = self.split_i32x16(a);
9845 let (b0, b1) = self.split_i32x16(b);
9846 self.combine_i32x8(self.shrv_i32x8(a0, b0), self.shrv_i32x8(a1, b1))
9847 }
9848 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
9849 #[inline(always)]
9850 fn reduce_max_i32x16(self, a: i32x16<Self>) -> i32 {
9851 let (a0, a1) = self.split_i32x16(a);
9852 self.reduce_max_i32x8(self.max_i32x8(a0, a1))
9853 }
9854 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
9855 #[inline(always)]
9856 fn reduce_min_i32x16(self, a: i32x16<Self>) -> i32 {
9857 let (a0, a1) = self.split_i32x16(a);
9858 self.reduce_min_i32x8(self.min_i32x8(a0, a1))
9859 }
9860 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
9861 #[inline(always)]
9862 fn reduce_sum_i32x16(self, a: i32x16<Self>) -> i32 {
9863 let (a0, a1) = self.split_i32x16(a);
9864 self.reduce_sum_i32x8(self.add_i32x8(a0, a1))
9865 }
9866 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
9867 #[inline(always)]
9868 fn reduce_product_i32x16(self, a: i32x16<Self>) -> i32 {
9869 let (a0, a1) = self.split_i32x16(a);
9870 self.reduce_product_i32x8(self.mul_i32x8(a0, a1))
9871 }
9872 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
9873 #[inline(always)]
9874 fn max_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9875 let (a0, a1) = self.split_i32x16(a);
9876 let (b0, b1) = self.split_i32x16(b);
9877 self.combine_i32x8(self.max_i32x8(a0, b0), self.max_i32x8(a1, b1))
9878 }
9879 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
9880 #[inline(always)]
9881 fn min_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9882 let (a0, a1) = self.split_i32x16(a);
9883 let (b0, b1) = self.split_i32x16(b);
9884 self.combine_i32x8(self.min_i32x8(a0, b0), self.min_i32x8(a1, b1))
9885 }
9886 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
9887 #[inline(always)]
9888 fn clamp_i32x16(self, a: i32x16<Self>, b: i32x16<Self>, c: i32x16<Self>) -> i32x16<Self> {
9889 let (a0, a1) = self.split_i32x16(a);
9890 let (b0, b1) = self.split_i32x16(b);
9891 let (c0, c1) = self.split_i32x16(c);
9892 self.combine_i32x8(self.clamp_i32x8(a0, b0, c0), self.clamp_i32x8(a1, b1, c1))
9893 }
9894 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
9895 #[inline(always)]
9896 fn simd_eq_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9897 let (a0, a1) = self.split_i32x16(a);
9898 let (b0, b1) = self.split_i32x16(b);
9899 self.combine_mask32x8(self.simd_eq_i32x8(a0, b0), self.simd_eq_i32x8(a1, b1))
9900 }
9901 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
9902 #[inline(always)]
9903 fn simd_ne_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9904 self.not_mask32x16(self.simd_eq_i32x16(a, b))
9905 }
9906 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
9907 #[inline(always)]
9908 fn simd_lt_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9909 let (a0, a1) = self.split_i32x16(a);
9910 let (b0, b1) = self.split_i32x16(b);
9911 self.combine_mask32x8(self.simd_lt_i32x8(a0, b0), self.simd_lt_i32x8(a1, b1))
9912 }
9913 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
9914 #[inline(always)]
9915 fn simd_le_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9916 let (a0, a1) = self.split_i32x16(a);
9917 let (b0, b1) = self.split_i32x16(b);
9918 self.combine_mask32x8(self.simd_le_i32x8(a0, b0), self.simd_le_i32x8(a1, b1))
9919 }
9920 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
9921 #[inline(always)]
9922 fn simd_ge_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9923 self.simd_le_i32x16(b, a)
9924 }
9925 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
9926 #[inline(always)]
9927 fn simd_gt_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> mask32x16<Self> {
9928 self.simd_lt_i32x16(b, a)
9929 }
9930 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
9931 #[inline(always)]
9932 fn zip_low_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9933 let (a0, _) = self.split_i32x16(a);
9934 let (b0, _) = self.split_i32x16(b);
9935 self.combine_i32x8(self.zip_low_i32x8(a0, b0), self.zip_high_i32x8(a0, b0))
9936 }
9937 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
9938 #[inline(always)]
9939 fn zip_high_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9940 let (_, a1) = self.split_i32x16(a);
9941 let (_, b1) = self.split_i32x16(b);
9942 self.combine_i32x8(self.zip_low_i32x8(a1, b1), self.zip_high_i32x8(a1, b1))
9943 }
9944 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
9945 #[inline(always)]
9946 fn unzip_low_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9947 let (a0, a1) = self.split_i32x16(a);
9948 let (b0, b1) = self.split_i32x16(b);
9949 self.combine_i32x8(self.unzip_low_i32x8(a0, a1), self.unzip_low_i32x8(b0, b1))
9950 }
9951 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
9952 #[inline(always)]
9953 fn unzip_high_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i32x16<Self> {
9954 let (a0, a1) = self.split_i32x16(a);
9955 let (b0, b1) = self.split_i32x16(b);
9956 self.combine_i32x8(self.unzip_high_i32x8(a0, a1), self.unzip_high_i32x8(b0, b1))
9957 }
9958 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
9959 #[inline(always)]
9960 fn interleave_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> (i32x16<Self>, i32x16<Self>) {
9961 let (a0, a1) = self.split_i32x16(a);
9962 let (b0, b1) = self.split_i32x16(b);
9963 let lo_lo = self.zip_low_i32x8(a0, b0);
9964 let lo_hi = self.zip_high_i32x8(a0, b0);
9965 let hi_lo = self.zip_low_i32x8(a1, b1);
9966 let hi_hi = self.zip_high_i32x8(a1, b1);
9967 (
9968 self.combine_i32x8(lo_lo, lo_hi),
9969 self.combine_i32x8(hi_lo, hi_hi),
9970 )
9971 }
9972 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
9973 #[inline(always)]
9974 fn deinterleave_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> (i32x16<Self>, i32x16<Self>) {
9975 let (a0, a1) = self.split_i32x16(a);
9976 let (b0, b1) = self.split_i32x16(b);
9977 let lo_even = self.unzip_low_i32x8(a0, a1);
9978 let lo_odd = self.unzip_high_i32x8(a0, a1);
9979 let hi_even = self.unzip_low_i32x8(b0, b1);
9980 let hi_odd = self.unzip_high_i32x8(b0, b1);
9981 (
9982 self.combine_i32x8(lo_even, hi_even),
9983 self.combine_i32x8(lo_odd, hi_odd),
9984 )
9985 }
9986 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
9987 #[inline(always)]
9988 fn select_i32x16(self, a: mask32x16<Self>, b: i32x16<Self>, c: i32x16<Self>) -> i32x16<Self> {
9989 let (a0, a1) = self.split_mask32x16(a);
9990 let (b0, b1) = self.split_i32x16(b);
9991 let (c0, c1) = self.split_i32x16(c);
9992 self.combine_i32x8(self.select_i32x8(a0, b0, c0), self.select_i32x8(a1, b1, c1))
9993 }
9994 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
9995 fn split_i32x16(self, a: i32x16<Self>) -> (i32x8<Self>, i32x8<Self>);
9996 #[doc = "Negate each element of the vector, wrapping on overflow."]
9997 #[inline(always)]
9998 fn neg_i32x16(self, a: i32x16<Self>) -> i32x16<Self> {
9999 let (a0, a1) = self.split_i32x16(a);
10000 self.combine_i32x8(self.neg_i32x8(a0), self.neg_i32x8(a1))
10001 }
10002 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
10003 #[inline(always)]
10004 fn widen_i32x16(self, a: i32x16<Self>) -> (i64x8<Self>, i64x8<Self>) {
10005 let (a0, a1) = self.split_i32x16(a);
10006 let (a00, a01) = self.widen_i32x8(a0);
10007 let (a10, a11) = self.widen_i32x8(a1);
10008 (self.combine_i64x4(a00, a01), self.combine_i64x4(a10, a11))
10009 }
10010 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
10011 #[inline(always)]
10012 fn widening_mul_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> (i64x8<Self>, i64x8<Self>) {
10013 let (a0, a1) = self.split_i32x16(a);
10014 let (b0, b1) = self.split_i32x16(b);
10015 let (low0, low1) = self.widening_mul_i32x8(a0, b0);
10016 let (high0, high1) = self.widening_mul_i32x8(a1, b1);
10017 (
10018 self.combine_i64x4(low0, low1),
10019 self.combine_i64x4(high0, high1),
10020 )
10021 }
10022 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
10023 #[inline(always)]
10024 fn widening_add_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> (i64x8<Self>, i64x8<Self>) {
10025 let (a0, a1) = self.split_i32x16(a);
10026 let (b0, b1) = self.split_i32x16(b);
10027 let (low0, low1) = self.widening_add_i32x8(a0, b0);
10028 let (high0, high1) = self.widening_add_i32x8(a1, b1);
10029 (
10030 self.combine_i64x4(low0, low1),
10031 self.combine_i64x4(high0, high1),
10032 )
10033 }
10034 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
10035 #[inline(always)]
10036 fn pairwise_widening_add_i32x16(self, a: i32x16<Self>) -> i64x8<Self> {
10037 let (a0, a1) = self.split_i32x16(a);
10038 self.combine_i64x4(
10039 self.pairwise_widening_add_i32x8(a0),
10040 self.pairwise_widening_add_i32x8(a1),
10041 )
10042 }
10043 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
10044 #[inline(always)]
10045 fn pairwise_dot_product_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i64x8<Self> {
10046 let (a0, a1) = self.split_i32x16(a);
10047 let (b0, b1) = self.split_i32x16(b);
10048 self.combine_i64x4(
10049 self.pairwise_dot_product_i32x8(a0, b0),
10050 self.pairwise_dot_product_i32x8(a1, b1),
10051 )
10052 }
10053 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
10054 #[inline(always)]
10055 fn narrow_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i16x32<Self> {
10056 let (a0, a1) = self.split_i32x16(a);
10057 let (b0, b1) = self.split_i32x16(b);
10058 self.combine_i16x16(self.narrow_i32x8(a0, a1), self.narrow_i32x8(b0, b1))
10059 }
10060 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
10061 #[inline(always)]
10062 fn saturating_narrow_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i16x32<Self> {
10063 let (a0, a1) = self.split_i32x16(a);
10064 let (b0, b1) = self.split_i32x16(b);
10065 self.combine_i16x16(
10066 self.saturating_narrow_i32x8(a0, a1),
10067 self.saturating_narrow_i32x8(b0, b1),
10068 )
10069 }
10070 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
10071 #[inline(always)]
10072 fn relaxed_narrow_i32x16(self, a: i32x16<Self>, b: i32x16<Self>) -> i16x32<Self> {
10073 let (a0, a1) = self.split_i32x16(a);
10074 let (b0, b1) = self.split_i32x16(b);
10075 self.combine_i16x16(
10076 self.relaxed_narrow_i32x8(a0, a1),
10077 self.relaxed_narrow_i32x8(b0, b1),
10078 )
10079 }
10080 #[doc = "Convert each signed 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
10081 #[inline(always)]
10082 fn cvt_f32_i32x16(self, a: i32x16<Self>) -> f32x16<Self> {
10083 let (a0, a1) = self.split_i32x16(a);
10084 self.combine_f32x8(self.cvt_f32_i32x8(a0), self.cvt_f32_i32x8(a1))
10085 }
10086 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
10087 #[inline(always)]
10088 fn abs_u32x16(self, a: u32x16<Self>) -> u32x16<Self> {
10089 a
10090 }
10091 #[doc = "Create a SIMD vector with all elements set to the given value."]
10092 #[inline(always)]
10093 fn splat_u32x16(self, val: u32) -> u32x16<Self> {
10094 let half = self.splat_u32x8(val);
10095 self.combine_u32x8(half, half)
10096 }
10097 #[doc = "Reverse the order of the vector's elements."]
10098 #[inline(always)]
10099 fn reverse_u32x16(self, a: u32x16<Self>) -> u32x16<Self> {
10100 let (a0, a1) = self.split_u32x16(a);
10101 self.combine_u32x8(self.reverse_u32x8(a1), self.reverse_u32x8(a0))
10102 }
10103 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
10104 fn slide_u32x16<const SHIFT: usize>(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self>;
10105 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
10106 #[inline(always)]
10107 fn slide_within_blocks_u32x16<const SHIFT: usize>(
10108 self,
10109 a: u32x16<Self>,
10110 b: u32x16<Self>,
10111 ) -> u32x16<Self> {
10112 let (a0, a1) = self.split_u32x16(a);
10113 let (b0, b1) = self.split_u32x16(b);
10114 self.combine_u32x8(
10115 self.slide_within_blocks_u32x8::<SHIFT>(a0, b0),
10116 self.slide_within_blocks_u32x8::<SHIFT>(a1, b1),
10117 )
10118 }
10119 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
10120 #[inline(always)]
10121 fn swizzle_dyn_within_blocks_u32x16(
10122 self,
10123 a: u32x16<Self>,
10124 indices: u8x64<Self>,
10125 ) -> u32x16<Self> {
10126 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
10127 }
10128 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
10129 #[inline(always)]
10130 fn swizzle_dyn_u32x16(self, a: u32x16<Self>, indices: u8x64<Self>) -> u32x16<Self> {
10131 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
10132 }
10133 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
10134 #[inline(always)]
10135 fn swizzle_dyn_precise_u32x16(self, a: u32x16<Self>, indices: u8x64<Self>) -> u32x16<Self> {
10136 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
10137 }
10138 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
10139 #[inline(always)]
10140 fn concat_swizzle_dyn_u32x16(
10141 self,
10142 a: u32x16<Self>,
10143 b: u32x16<Self>,
10144 indices: u8x64<Self>,
10145 ) -> u32x16<Self> {
10146 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
10147 Bytes::to_bytes(a),
10148 Bytes::to_bytes(b),
10149 indices,
10150 ))
10151 }
10152 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
10153 #[inline(always)]
10154 fn concat_swizzle_dyn_precise_u32x16(
10155 self,
10156 a: u32x16<Self>,
10157 b: u32x16<Self>,
10158 indices: u8x64<Self>,
10159 ) -> u32x16<Self> {
10160 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
10161 Bytes::to_bytes(a),
10162 Bytes::to_bytes(b),
10163 indices,
10164 ))
10165 }
10166 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
10167 fn compress_u32x16(self, values: u32x16<Self>, mask: mask32x16<Self>) -> u32x16<Self>;
10168 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
10169 fn compress_merge_u32x16(
10170 self,
10171 values: u32x16<Self>,
10172 mask: mask32x16<Self>,
10173 merge: u32x16<Self>,
10174 ) -> u32x16<Self>;
10175 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
10176 fn expand_u32x16(self, values: u32x16<Self>, mask: mask32x16<Self>) -> u32x16<Self>;
10177 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
10178 fn expand_merge_u32x16(
10179 self,
10180 values: u32x16<Self>,
10181 mask: mask32x16<Self>,
10182 merge: u32x16<Self>,
10183 ) -> u32x16<Self>;
10184 #[doc = "Return the number of ones in the binary representation of each element."]
10185 #[inline(always)]
10186 fn count_ones_u32x16(self, a: u32x16<Self>) -> u32x16<Self> {
10187 let (a0, a1) = self.split_u32x16(a);
10188 self.combine_u32x8(self.count_ones_u32x8(a0), self.count_ones_u32x8(a1))
10189 }
10190 #[doc = "Return the number of zeros in the binary representation of each element."]
10191 #[inline(always)]
10192 fn count_zeros_u32x16(self, a: u32x16<Self>) -> u32x16<Self> {
10193 let (a0, a1) = self.split_u32x16(a);
10194 self.combine_u32x8(self.count_zeros_u32x8(a0), self.count_zeros_u32x8(a1))
10195 }
10196 #[doc = "Add two vectors element-wise, wrapping on overflow."]
10197 #[inline(always)]
10198 fn add_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10199 let (a0, a1) = self.split_u32x16(a);
10200 let (b0, b1) = self.split_u32x16(b);
10201 self.combine_u32x8(self.add_u32x8(a0, b0), self.add_u32x8(a1, b1))
10202 }
10203 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
10204 #[inline(always)]
10205 fn saturating_add_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10206 let (a0, a1) = self.split_u32x16(a);
10207 let (b0, b1) = self.split_u32x16(b);
10208 self.combine_u32x8(
10209 self.saturating_add_u32x8(a0, b0),
10210 self.saturating_add_u32x8(a1, b1),
10211 )
10212 }
10213 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
10214 #[inline(always)]
10215 fn sub_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10216 let (a0, a1) = self.split_u32x16(a);
10217 let (b0, b1) = self.split_u32x16(b);
10218 self.combine_u32x8(self.sub_u32x8(a0, b0), self.sub_u32x8(a1, b1))
10219 }
10220 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
10221 #[inline(always)]
10222 fn saturating_sub_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10223 let (a0, a1) = self.split_u32x16(a);
10224 let (b0, b1) = self.split_u32x16(b);
10225 self.combine_u32x8(
10226 self.saturating_sub_u32x8(a0, b0),
10227 self.saturating_sub_u32x8(a1, b1),
10228 )
10229 }
10230 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
10231 #[inline(always)]
10232 fn mul_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10233 let (a0, a1) = self.split_u32x16(a);
10234 let (b0, b1) = self.split_u32x16(b);
10235 self.combine_u32x8(self.mul_u32x8(a0, b0), self.mul_u32x8(a1, b1))
10236 }
10237 #[doc = "Compute the bitwise AND of two vectors."]
10238 #[inline(always)]
10239 fn and_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10240 let (a0, a1) = self.split_u32x16(a);
10241 let (b0, b1) = self.split_u32x16(b);
10242 self.combine_u32x8(self.and_u32x8(a0, b0), self.and_u32x8(a1, b1))
10243 }
10244 #[doc = "Compute the bitwise OR of two vectors."]
10245 #[inline(always)]
10246 fn or_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10247 let (a0, a1) = self.split_u32x16(a);
10248 let (b0, b1) = self.split_u32x16(b);
10249 self.combine_u32x8(self.or_u32x8(a0, b0), self.or_u32x8(a1, b1))
10250 }
10251 #[doc = "Compute the bitwise XOR of two vectors."]
10252 #[inline(always)]
10253 fn xor_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10254 let (a0, a1) = self.split_u32x16(a);
10255 let (b0, b1) = self.split_u32x16(b);
10256 self.combine_u32x8(self.xor_u32x8(a0, b0), self.xor_u32x8(a1, b1))
10257 }
10258 #[doc = "Compute the bitwise NOT of the vector."]
10259 #[inline(always)]
10260 fn not_u32x16(self, a: u32x16<Self>) -> u32x16<Self> {
10261 let (a0, a1) = self.split_u32x16(a);
10262 self.combine_u32x8(self.not_u32x8(a0), self.not_u32x8(a1))
10263 }
10264 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
10265 #[inline(always)]
10266 fn shl_u32x16(self, a: u32x16<Self>, shift: u32) -> u32x16<Self> {
10267 let (a0, a1) = self.split_u32x16(a);
10268 self.combine_u32x8(self.shl_u32x8(a0, shift), self.shl_u32x8(a1, shift))
10269 }
10270 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
10271 #[inline(always)]
10272 fn shlv_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10273 let (a0, a1) = self.split_u32x16(a);
10274 let (b0, b1) = self.split_u32x16(b);
10275 self.combine_u32x8(self.shlv_u32x8(a0, b0), self.shlv_u32x8(a1, b1))
10276 }
10277 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
10278 #[inline(always)]
10279 fn shr_u32x16(self, a: u32x16<Self>, shift: u32) -> u32x16<Self> {
10280 let (a0, a1) = self.split_u32x16(a);
10281 self.combine_u32x8(self.shr_u32x8(a0, shift), self.shr_u32x8(a1, shift))
10282 }
10283 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
10284 #[inline(always)]
10285 fn shrv_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10286 let (a0, a1) = self.split_u32x16(a);
10287 let (b0, b1) = self.split_u32x16(b);
10288 self.combine_u32x8(self.shrv_u32x8(a0, b0), self.shrv_u32x8(a1, b1))
10289 }
10290 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
10291 #[inline(always)]
10292 fn reduce_max_u32x16(self, a: u32x16<Self>) -> u32 {
10293 let (a0, a1) = self.split_u32x16(a);
10294 self.reduce_max_u32x8(self.max_u32x8(a0, a1))
10295 }
10296 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
10297 #[inline(always)]
10298 fn reduce_min_u32x16(self, a: u32x16<Self>) -> u32 {
10299 let (a0, a1) = self.split_u32x16(a);
10300 self.reduce_min_u32x8(self.min_u32x8(a0, a1))
10301 }
10302 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
10303 #[inline(always)]
10304 fn reduce_sum_u32x16(self, a: u32x16<Self>) -> u32 {
10305 let (a0, a1) = self.split_u32x16(a);
10306 self.reduce_sum_u32x8(self.add_u32x8(a0, a1))
10307 }
10308 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
10309 #[inline(always)]
10310 fn reduce_product_u32x16(self, a: u32x16<Self>) -> u32 {
10311 let (a0, a1) = self.split_u32x16(a);
10312 self.reduce_product_u32x8(self.mul_u32x8(a0, a1))
10313 }
10314 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
10315 #[inline(always)]
10316 fn max_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10317 let (a0, a1) = self.split_u32x16(a);
10318 let (b0, b1) = self.split_u32x16(b);
10319 self.combine_u32x8(self.max_u32x8(a0, b0), self.max_u32x8(a1, b1))
10320 }
10321 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
10322 #[inline(always)]
10323 fn min_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10324 let (a0, a1) = self.split_u32x16(a);
10325 let (b0, b1) = self.split_u32x16(b);
10326 self.combine_u32x8(self.min_u32x8(a0, b0), self.min_u32x8(a1, b1))
10327 }
10328 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
10329 #[inline(always)]
10330 fn clamp_u32x16(self, a: u32x16<Self>, b: u32x16<Self>, c: u32x16<Self>) -> u32x16<Self> {
10331 let (a0, a1) = self.split_u32x16(a);
10332 let (b0, b1) = self.split_u32x16(b);
10333 let (c0, c1) = self.split_u32x16(c);
10334 self.combine_u32x8(self.clamp_u32x8(a0, b0, c0), self.clamp_u32x8(a1, b1, c1))
10335 }
10336 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
10337 #[inline(always)]
10338 fn simd_eq_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10339 let (a0, a1) = self.split_u32x16(a);
10340 let (b0, b1) = self.split_u32x16(b);
10341 self.combine_mask32x8(self.simd_eq_u32x8(a0, b0), self.simd_eq_u32x8(a1, b1))
10342 }
10343 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
10344 #[inline(always)]
10345 fn simd_ne_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10346 self.not_mask32x16(self.simd_eq_u32x16(a, b))
10347 }
10348 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
10349 #[inline(always)]
10350 fn simd_lt_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10351 let (a0, a1) = self.split_u32x16(a);
10352 let (b0, b1) = self.split_u32x16(b);
10353 self.combine_mask32x8(self.simd_lt_u32x8(a0, b0), self.simd_lt_u32x8(a1, b1))
10354 }
10355 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
10356 #[inline(always)]
10357 fn simd_le_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10358 let (a0, a1) = self.split_u32x16(a);
10359 let (b0, b1) = self.split_u32x16(b);
10360 self.combine_mask32x8(self.simd_le_u32x8(a0, b0), self.simd_le_u32x8(a1, b1))
10361 }
10362 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
10363 #[inline(always)]
10364 fn simd_ge_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10365 self.simd_le_u32x16(b, a)
10366 }
10367 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
10368 #[inline(always)]
10369 fn simd_gt_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> mask32x16<Self> {
10370 self.simd_lt_u32x16(b, a)
10371 }
10372 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
10373 #[inline(always)]
10374 fn zip_low_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10375 let (a0, _) = self.split_u32x16(a);
10376 let (b0, _) = self.split_u32x16(b);
10377 self.combine_u32x8(self.zip_low_u32x8(a0, b0), self.zip_high_u32x8(a0, b0))
10378 }
10379 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
10380 #[inline(always)]
10381 fn zip_high_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10382 let (_, a1) = self.split_u32x16(a);
10383 let (_, b1) = self.split_u32x16(b);
10384 self.combine_u32x8(self.zip_low_u32x8(a1, b1), self.zip_high_u32x8(a1, b1))
10385 }
10386 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
10387 #[inline(always)]
10388 fn unzip_low_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10389 let (a0, a1) = self.split_u32x16(a);
10390 let (b0, b1) = self.split_u32x16(b);
10391 self.combine_u32x8(self.unzip_low_u32x8(a0, a1), self.unzip_low_u32x8(b0, b1))
10392 }
10393 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
10394 #[inline(always)]
10395 fn unzip_high_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u32x16<Self> {
10396 let (a0, a1) = self.split_u32x16(a);
10397 let (b0, b1) = self.split_u32x16(b);
10398 self.combine_u32x8(self.unzip_high_u32x8(a0, a1), self.unzip_high_u32x8(b0, b1))
10399 }
10400 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
10401 #[inline(always)]
10402 fn interleave_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> (u32x16<Self>, u32x16<Self>) {
10403 let (a0, a1) = self.split_u32x16(a);
10404 let (b0, b1) = self.split_u32x16(b);
10405 let lo_lo = self.zip_low_u32x8(a0, b0);
10406 let lo_hi = self.zip_high_u32x8(a0, b0);
10407 let hi_lo = self.zip_low_u32x8(a1, b1);
10408 let hi_hi = self.zip_high_u32x8(a1, b1);
10409 (
10410 self.combine_u32x8(lo_lo, lo_hi),
10411 self.combine_u32x8(hi_lo, hi_hi),
10412 )
10413 }
10414 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
10415 #[inline(always)]
10416 fn deinterleave_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> (u32x16<Self>, u32x16<Self>) {
10417 let (a0, a1) = self.split_u32x16(a);
10418 let (b0, b1) = self.split_u32x16(b);
10419 let lo_even = self.unzip_low_u32x8(a0, a1);
10420 let lo_odd = self.unzip_high_u32x8(a0, a1);
10421 let hi_even = self.unzip_low_u32x8(b0, b1);
10422 let hi_odd = self.unzip_high_u32x8(b0, b1);
10423 (
10424 self.combine_u32x8(lo_even, hi_even),
10425 self.combine_u32x8(lo_odd, hi_odd),
10426 )
10427 }
10428 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
10429 #[inline(always)]
10430 fn select_u32x16(self, a: mask32x16<Self>, b: u32x16<Self>, c: u32x16<Self>) -> u32x16<Self> {
10431 let (a0, a1) = self.split_mask32x16(a);
10432 let (b0, b1) = self.split_u32x16(b);
10433 let (c0, c1) = self.split_u32x16(c);
10434 self.combine_u32x8(self.select_u32x8(a0, b0, c0), self.select_u32x8(a1, b1, c1))
10435 }
10436 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
10437 fn split_u32x16(self, a: u32x16<Self>) -> (u32x8<Self>, u32x8<Self>);
10438 #[doc = "Widen every lane into two same-width vectors.\n\nThe first result contains the widened lower lanes and the second contains the widened upper lanes."]
10439 #[inline(always)]
10440 fn widen_u32x16(self, a: u32x16<Self>) -> (u64x8<Self>, u64x8<Self>) {
10441 let (a0, a1) = self.split_u32x16(a);
10442 let (a00, a01) = self.widen_u32x8(a0);
10443 let (a10, a11) = self.widen_u32x8(a1);
10444 (self.combine_u64x4(a00, a01), self.combine_u64x4(a10, a11))
10445 }
10446 #[doc = "Multiply corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
10447 #[inline(always)]
10448 fn widening_mul_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> (u64x8<Self>, u64x8<Self>) {
10449 let (a0, a1) = self.split_u32x16(a);
10450 let (b0, b1) = self.split_u32x16(b);
10451 let (low0, low1) = self.widening_mul_u32x8(a0, b0);
10452 let (high0, high1) = self.widening_mul_u32x8(a1, b1);
10453 (
10454 self.combine_u64x4(low0, low1),
10455 self.combine_u64x4(high0, high1),
10456 )
10457 }
10458 #[doc = "Add corresponding integer lanes exactly into twice-wide lanes. The first result contains the lower lanes and the second contains the upper lanes."]
10459 #[inline(always)]
10460 fn widening_add_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> (u64x8<Self>, u64x8<Self>) {
10461 let (a0, a1) = self.split_u32x16(a);
10462 let (b0, b1) = self.split_u32x16(b);
10463 let (low0, low1) = self.widening_add_u32x8(a0, b0);
10464 let (high0, high1) = self.widening_add_u32x8(a1, b1);
10465 (
10466 self.combine_u64x4(low0, low1),
10467 self.combine_u64x4(high0, high1),
10468 )
10469 }
10470 #[doc = "Add adjacent integer lanes exactly into twice-wide lanes.\n\nOutput lane `i` is `widen(a[2*i]) + widen(a[2*i+1])`. The result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. The sum cannot overflow the widened type.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` produces `[3, 7, 11, 15]`. See [`SimdIntWiden::pairwise_widening_add`] for supported types and examples."]
10471 #[inline(always)]
10472 fn pairwise_widening_add_u32x16(self, a: u32x16<Self>) -> u64x8<Self> {
10473 let (a0, a1) = self.split_u32x16(a);
10474 self.combine_u64x4(
10475 self.pairwise_widening_add_u32x8(a0),
10476 self.pairwise_widening_add_u32x8(a1),
10477 )
10478 }
10479 #[doc = "Multiply corresponding integer lanes exactly in the widened type, then sum adjacent pairs of products.\n\nThe result has half as many lanes, twice the lane width, and unchanged signedness and total bit width. Lane `i` is `widen(a[2*i]) * widen(b[2*i]) + widen(a[2*i+1]) * widen(b[2*i+1])`; addition wraps in the destination type, including in debug builds.\n\nFor example, `[1, 2, 3, 4, 5, 6, 7, 8]` and `[10, 20, 30, 40, 50, 60, 70, 80]` produce `[50, 250, 610, 1130]`. See [`SimdIntWiden::pairwise_dot_product`] for examples."]
10480 #[inline(always)]
10481 fn pairwise_dot_product_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u64x8<Self> {
10482 let (a0, a1) = self.split_u32x16(a);
10483 let (b0, b1) = self.split_u32x16(b);
10484 self.combine_u64x4(
10485 self.pairwise_dot_product_u32x8(a0, b0),
10486 self.pairwise_dot_product_u32x8(a1, b1),
10487 )
10488 }
10489 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
10490 #[inline(always)]
10491 fn narrow_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u16x32<Self> {
10492 let (a0, a1) = self.split_u32x16(a);
10493 let (b0, b1) = self.split_u32x16(b);
10494 self.combine_u16x16(self.narrow_u32x8(a0, a1), self.narrow_u32x8(b0, b1))
10495 }
10496 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
10497 #[inline(always)]
10498 fn saturating_narrow_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u16x32<Self> {
10499 let (a0, a1) = self.split_u32x16(a);
10500 let (b0, b1) = self.split_u32x16(b);
10501 self.combine_u16x16(
10502 self.saturating_narrow_u32x8(a0, a1),
10503 self.saturating_narrow_u32x8(b0, b1),
10504 )
10505 }
10506 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
10507 #[inline(always)]
10508 fn relaxed_narrow_u32x16(self, a: u32x16<Self>, b: u32x16<Self>) -> u16x32<Self> {
10509 let (a0, a1) = self.split_u32x16(a);
10510 let (b0, b1) = self.split_u32x16(b);
10511 self.combine_u16x16(
10512 self.relaxed_narrow_u32x8(a0, a1),
10513 self.relaxed_narrow_u32x8(b0, b1),
10514 )
10515 }
10516 #[doc = "Convert each unsigned 32-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
10517 #[inline(always)]
10518 fn cvt_f32_u32x16(self, a: u32x16<Self>) -> f32x16<Self> {
10519 let (a0, a1) = self.split_u32x16(a);
10520 self.combine_f32x8(self.cvt_f32_u32x8(a0), self.cvt_f32_u32x8(a1))
10521 }
10522 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
10523 #[inline(always)]
10524 fn splat_mask32x16(self, val: bool) -> mask32x16<Self> {
10525 let half = self.splat_mask32x8(val);
10526 self.combine_mask32x8(half, half)
10527 }
10528 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
10529 #[inline(always)]
10530 fn from_bitmask_mask32x16(self, bits: u64) -> mask32x16<Self> {
10531 let lo = self.from_bitmask_mask32x8(bits);
10532 let hi = self.from_bitmask_mask32x8(bits >> 8usize);
10533 self.combine_mask32x8(lo, hi)
10534 }
10535 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
10536 #[inline(always)]
10537 fn to_bitmask_mask32x16(self, a: mask32x16<Self>) -> u64 {
10538 let (lo, hi) = self.split_mask32x16(a);
10539 let lo = self.to_bitmask_mask32x8(lo);
10540 let hi = self.to_bitmask_mask32x8(hi);
10541 lo | (hi << 8usize)
10542 }
10543 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
10544 fn from_vector_mask32x16(self, vector: i32x16<Self>) -> mask32x16<Self>;
10545 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
10546 fn to_vector_mask32x16(self, a: mask32x16<Self>) -> i32x16<Self>;
10547 #[doc = "Set one logical lane of a SIMD mask."]
10548 fn set_mask32x16(self, a: &mut mask32x16<Self>, index: usize, value: bool) -> ();
10549 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
10550 fn rotate_elements_left_mask32x16<const OFFSET: usize>(
10551 self,
10552 a: mask32x16<Self>,
10553 ) -> mask32x16<Self>;
10554 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
10555 fn rotate_elements_right_mask32x16<const OFFSET: usize>(
10556 self,
10557 a: mask32x16<Self>,
10558 ) -> mask32x16<Self>;
10559 #[doc = "Compute the logical AND of two masks."]
10560 #[inline(always)]
10561 fn and_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask32x16<Self> {
10562 let (a0, a1) = self.split_mask32x16(a);
10563 let (b0, b1) = self.split_mask32x16(b);
10564 self.combine_mask32x8(self.and_mask32x8(a0, b0), self.and_mask32x8(a1, b1))
10565 }
10566 #[doc = "Compute the logical OR of two masks."]
10567 #[inline(always)]
10568 fn or_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask32x16<Self> {
10569 let (a0, a1) = self.split_mask32x16(a);
10570 let (b0, b1) = self.split_mask32x16(b);
10571 self.combine_mask32x8(self.or_mask32x8(a0, b0), self.or_mask32x8(a1, b1))
10572 }
10573 #[doc = "Compute the logical XOR of two masks."]
10574 #[inline(always)]
10575 fn xor_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask32x16<Self> {
10576 let (a0, a1) = self.split_mask32x16(a);
10577 let (b0, b1) = self.split_mask32x16(b);
10578 self.combine_mask32x8(self.xor_mask32x8(a0, b0), self.xor_mask32x8(a1, b1))
10579 }
10580 #[doc = "Compute the logical NOT of the mask."]
10581 #[inline(always)]
10582 fn not_mask32x16(self, a: mask32x16<Self>) -> mask32x16<Self> {
10583 let (a0, a1) = self.split_mask32x16(a);
10584 self.combine_mask32x8(self.not_mask32x8(a0), self.not_mask32x8(a1))
10585 }
10586 #[doc = "Reverse the order of the mask's logical lanes."]
10587 #[inline(always)]
10588 fn reverse_mask32x16(self, a: mask32x16<Self>) -> mask32x16<Self> {
10589 let (a0, a1) = self.split_mask32x16(a);
10590 self.combine_mask32x8(self.reverse_mask32x8(a1), self.reverse_mask32x8(a0))
10591 }
10592 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
10593 #[inline(always)]
10594 fn select_mask32x16(
10595 self,
10596 a: mask32x16<Self>,
10597 b: mask32x16<Self>,
10598 c: mask32x16<Self>,
10599 ) -> mask32x16<Self> {
10600 let (a0, a1) = self.split_mask32x16(a);
10601 let (b0, b1) = self.split_mask32x16(b);
10602 let (c0, c1) = self.split_mask32x16(c);
10603 self.combine_mask32x8(
10604 self.select_mask32x8(a0, b0, c0),
10605 self.select_mask32x8(a1, b1, c1),
10606 )
10607 }
10608 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
10609 #[inline(always)]
10610 fn simd_eq_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask32x16<Self> {
10611 let (a0, a1) = self.split_mask32x16(a);
10612 let (b0, b1) = self.split_mask32x16(b);
10613 self.combine_mask32x8(self.simd_eq_mask32x8(a0, b0), self.simd_eq_mask32x8(a1, b1))
10614 }
10615 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
10616 #[inline(always)]
10617 fn simd_ne_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask32x16<Self> {
10618 self.not_mask32x16(self.simd_eq_mask32x16(a, b))
10619 }
10620 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
10621 #[inline(always)]
10622 fn any_true_mask32x16(self, a: mask32x16<Self>) -> bool {
10623 let (a0, a1) = self.split_mask32x16(a);
10624 self.any_true_mask32x8(self.or_mask32x8(a0, a1))
10625 }
10626 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
10627 #[inline(always)]
10628 fn all_true_mask32x16(self, a: mask32x16<Self>) -> bool {
10629 let (a0, a1) = self.split_mask32x16(a);
10630 self.all_true_mask32x8(self.and_mask32x8(a0, a1))
10631 }
10632 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
10633 #[inline(always)]
10634 fn any_false_mask32x16(self, a: mask32x16<Self>) -> bool {
10635 let (a0, a1) = self.split_mask32x16(a);
10636 self.any_false_mask32x8(self.and_mask32x8(a0, a1))
10637 }
10638 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
10639 #[inline(always)]
10640 fn all_false_mask32x16(self, a: mask32x16<Self>) -> bool {
10641 let (a0, a1) = self.split_mask32x16(a);
10642 self.all_false_mask32x8(self.or_mask32x8(a0, a1))
10643 }
10644 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
10645 fn split_mask32x16(self, a: mask32x16<Self>) -> (mask32x8<Self>, mask32x8<Self>);
10646 #[doc = "Widen each boolean lane into two masks of the same logical width, preserving its value.\n\nThe first result contains the lower lanes and the second contains the upper lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
10647 #[inline(always)]
10648 fn widen_mask32x16(self, a: mask32x16<Self>) -> (mask64x8<Self>, mask64x8<Self>) {
10649 let (a0, a1) = self.split_mask32x16(a);
10650 let (a00, a01) = self.widen_mask32x8(a0);
10651 let (a10, a11) = self.widen_mask32x8(a1);
10652 (
10653 self.combine_mask64x4(a00, a01),
10654 self.combine_mask64x4(a10, a11),
10655 )
10656 }
10657 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
10658 #[inline(always)]
10659 fn narrow_mask32x16(self, a: mask32x16<Self>, b: mask32x16<Self>) -> mask16x32<Self> {
10660 let (a0, a1) = self.split_mask32x16(a);
10661 let (b0, b1) = self.split_mask32x16(b);
10662 self.combine_mask16x16(self.narrow_mask32x8(a0, a1), self.narrow_mask32x8(b0, b1))
10663 }
10664 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
10665 #[inline(always)]
10666 fn abs_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
10667 let (a0, a1) = self.split_f64x8(a);
10668 self.combine_f64x4(self.abs_f64x4(a0), self.abs_f64x4(a1))
10669 }
10670 #[doc = "Create a SIMD vector with all elements set to the given value."]
10671 #[inline(always)]
10672 fn splat_f64x8(self, val: f64) -> f64x8<Self> {
10673 let half = self.splat_f64x4(val);
10674 self.combine_f64x4(half, half)
10675 }
10676 #[doc = "Reverse the order of the vector's elements."]
10677 #[inline(always)]
10678 fn reverse_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
10679 let (a0, a1) = self.split_f64x8(a);
10680 self.combine_f64x4(self.reverse_f64x4(a1), self.reverse_f64x4(a0))
10681 }
10682 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
10683 fn slide_f64x8<const SHIFT: usize>(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self>;
10684 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
10685 #[inline(always)]
10686 fn slide_within_blocks_f64x8<const SHIFT: usize>(
10687 self,
10688 a: f64x8<Self>,
10689 b: f64x8<Self>,
10690 ) -> f64x8<Self> {
10691 let (a0, a1) = self.split_f64x8(a);
10692 let (b0, b1) = self.split_f64x8(b);
10693 self.combine_f64x4(
10694 self.slide_within_blocks_f64x4::<SHIFT>(a0, b0),
10695 self.slide_within_blocks_f64x4::<SHIFT>(a1, b1),
10696 )
10697 }
10698 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
10699 #[inline(always)]
10700 fn swizzle_dyn_within_blocks_f64x8(self, a: f64x8<Self>, indices: u8x64<Self>) -> f64x8<Self> {
10701 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
10702 }
10703 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
10704 #[inline(always)]
10705 fn swizzle_dyn_f64x8(self, a: f64x8<Self>, indices: u8x64<Self>) -> f64x8<Self> {
10706 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
10707 }
10708 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
10709 #[inline(always)]
10710 fn swizzle_dyn_precise_f64x8(self, a: f64x8<Self>, indices: u8x64<Self>) -> f64x8<Self> {
10711 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
10712 }
10713 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
10714 #[inline(always)]
10715 fn concat_swizzle_dyn_f64x8(
10716 self,
10717 a: f64x8<Self>,
10718 b: f64x8<Self>,
10719 indices: u8x64<Self>,
10720 ) -> f64x8<Self> {
10721 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
10722 Bytes::to_bytes(a),
10723 Bytes::to_bytes(b),
10724 indices,
10725 ))
10726 }
10727 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
10728 #[inline(always)]
10729 fn concat_swizzle_dyn_precise_f64x8(
10730 self,
10731 a: f64x8<Self>,
10732 b: f64x8<Self>,
10733 indices: u8x64<Self>,
10734 ) -> f64x8<Self> {
10735 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
10736 Bytes::to_bytes(a),
10737 Bytes::to_bytes(b),
10738 indices,
10739 ))
10740 }
10741 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
10742 fn compress_f64x8(self, values: f64x8<Self>, mask: mask64x8<Self>) -> f64x8<Self>;
10743 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
10744 fn compress_merge_f64x8(
10745 self,
10746 values: f64x8<Self>,
10747 mask: mask64x8<Self>,
10748 merge: f64x8<Self>,
10749 ) -> f64x8<Self>;
10750 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
10751 fn expand_f64x8(self, values: f64x8<Self>, mask: mask64x8<Self>) -> f64x8<Self>;
10752 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
10753 fn expand_merge_f64x8(
10754 self,
10755 values: f64x8<Self>,
10756 mask: mask64x8<Self>,
10757 merge: f64x8<Self>,
10758 ) -> f64x8<Self>;
10759 #[doc = "Negate each element of the vector."]
10760 #[inline(always)]
10761 fn neg_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
10762 let (a0, a1) = self.split_f64x8(a);
10763 self.combine_f64x4(self.neg_f64x4(a0), self.neg_f64x4(a1))
10764 }
10765 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
10766 #[inline(always)]
10767 fn sqrt_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
10768 let (a0, a1) = self.split_f64x8(a);
10769 self.combine_f64x4(self.sqrt_f64x4(a0), self.sqrt_f64x4(a1))
10770 }
10771 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
10772 #[inline(always)]
10773 fn approximate_recip_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
10774 let (a0, a1) = self.split_f64x8(a);
10775 self.combine_f64x4(
10776 self.approximate_recip_f64x4(a0),
10777 self.approximate_recip_f64x4(a1),
10778 )
10779 }
10780 #[doc = "Add two vectors element-wise."]
10781 #[inline(always)]
10782 fn add_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10783 let (a0, a1) = self.split_f64x8(a);
10784 let (b0, b1) = self.split_f64x8(b);
10785 self.combine_f64x4(self.add_f64x4(a0, b0), self.add_f64x4(a1, b1))
10786 }
10787 #[doc = "Subtract two vectors element-wise."]
10788 #[inline(always)]
10789 fn sub_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10790 let (a0, a1) = self.split_f64x8(a);
10791 let (b0, b1) = self.split_f64x8(b);
10792 self.combine_f64x4(self.sub_f64x4(a0, b0), self.sub_f64x4(a1, b1))
10793 }
10794 #[doc = "Multiply two vectors element-wise."]
10795 #[inline(always)]
10796 fn mul_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10797 let (a0, a1) = self.split_f64x8(a);
10798 let (b0, b1) = self.split_f64x8(b);
10799 self.combine_f64x4(self.mul_f64x4(a0, b0), self.mul_f64x4(a1, b1))
10800 }
10801 #[doc = "Divide two vectors element-wise."]
10802 #[inline(always)]
10803 fn div_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10804 let (a0, a1) = self.split_f64x8(a);
10805 let (b0, b1) = self.split_f64x8(b);
10806 self.combine_f64x4(self.div_f64x4(a0, b0), self.div_f64x4(a1, b1))
10807 }
10808 #[doc = "Return a vector with the magnitude of `a` and the sign of `b` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
10809 #[inline(always)]
10810 fn copysign_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10811 let (a0, a1) = self.split_f64x8(a);
10812 let (b0, b1) = self.split_f64x8(b);
10813 self.combine_f64x4(self.copysign_f64x4(a0, b0), self.copysign_f64x4(a1, b1))
10814 }
10815 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
10816 #[inline(always)]
10817 fn reduce_max_f64x8(self, a: f64x8<Self>) -> f64 {
10818 let (a0, a1) = self.split_f64x8(a);
10819 self.reduce_max_f64x4(self.max_f64x4(a0, a1))
10820 }
10821 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
10822 #[inline(always)]
10823 fn reduce_min_f64x8(self, a: f64x8<Self>) -> f64 {
10824 let (a0, a1) = self.split_f64x8(a);
10825 self.reduce_min_f64x4(self.min_f64x4(a0, a1))
10826 }
10827 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
10828 #[inline(always)]
10829 fn reduce_max_precise_f64x8(self, a: f64x8<Self>) -> f64 {
10830 let (a0, a1) = self.split_f64x8(a);
10831 self.reduce_max_precise_f64x4(self.max_precise_f64x4(a0, a1))
10832 }
10833 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
10834 #[inline(always)]
10835 fn reduce_min_precise_f64x8(self, a: f64x8<Self>) -> f64 {
10836 let (a0, a1) = self.split_f64x8(a);
10837 self.reduce_min_precise_f64x4(self.min_precise_f64x4(a0, a1))
10838 }
10839 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
10840 #[inline(always)]
10841 fn reduce_sum_f64x8(self, a: f64x8<Self>) -> f64 {
10842 let (a0, a1) = self.split_f64x8(a);
10843 self.reduce_sum_f64x4(self.add_f64x4(a0, a1))
10844 }
10845 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
10846 #[inline(always)]
10847 fn reduce_product_f64x8(self, a: f64x8<Self>) -> f64 {
10848 let (a0, a1) = self.split_f64x8(a);
10849 self.reduce_product_f64x4(self.mul_f64x4(a0, a1))
10850 }
10851 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
10852 #[inline(always)]
10853 fn max_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10854 let (a0, a1) = self.split_f64x8(a);
10855 let (b0, b1) = self.split_f64x8(b);
10856 self.combine_f64x4(self.max_f64x4(a0, b0), self.max_f64x4(a1, b1))
10857 }
10858 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
10859 #[inline(always)]
10860 fn min_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10861 let (a0, a1) = self.split_f64x8(a);
10862 let (b0, b1) = self.split_f64x8(b);
10863 self.combine_f64x4(self.min_f64x4(a0, b0), self.min_f64x4(a1, b1))
10864 }
10865 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
10866 #[inline(always)]
10867 fn max_precise_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10868 let (a0, a1) = self.split_f64x8(a);
10869 let (b0, b1) = self.split_f64x8(b);
10870 self.combine_f64x4(
10871 self.max_precise_f64x4(a0, b0),
10872 self.max_precise_f64x4(a1, b1),
10873 )
10874 }
10875 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
10876 #[inline(always)]
10877 fn min_precise_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10878 let (a0, a1) = self.split_f64x8(a);
10879 let (b0, b1) = self.split_f64x8(b);
10880 self.combine_f64x4(
10881 self.min_precise_f64x4(a0, b0),
10882 self.min_precise_f64x4(a1, b1),
10883 )
10884 }
10885 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
10886 #[inline(always)]
10887 fn clamp_f64x8(self, a: f64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
10888 let (a0, a1) = self.split_f64x8(a);
10889 let (b0, b1) = self.split_f64x8(b);
10890 let (c0, c1) = self.split_f64x8(c);
10891 self.combine_f64x4(self.clamp_f64x4(a0, b0, c0), self.clamp_f64x4(a1, b1, c1))
10892 }
10893 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
10894 #[inline(always)]
10895 fn simd_eq_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10896 let (a0, a1) = self.split_f64x8(a);
10897 let (b0, b1) = self.split_f64x8(b);
10898 self.combine_mask64x4(self.simd_eq_f64x4(a0, b0), self.simd_eq_f64x4(a1, b1))
10899 }
10900 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
10901 #[inline(always)]
10902 fn simd_ne_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10903 self.not_mask64x8(self.simd_eq_f64x8(a, b))
10904 }
10905 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
10906 #[inline(always)]
10907 fn simd_lt_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10908 let (a0, a1) = self.split_f64x8(a);
10909 let (b0, b1) = self.split_f64x8(b);
10910 self.combine_mask64x4(self.simd_lt_f64x4(a0, b0), self.simd_lt_f64x4(a1, b1))
10911 }
10912 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
10913 #[inline(always)]
10914 fn simd_le_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10915 let (a0, a1) = self.split_f64x8(a);
10916 let (b0, b1) = self.split_f64x8(b);
10917 self.combine_mask64x4(self.simd_le_f64x4(a0, b0), self.simd_le_f64x4(a1, b1))
10918 }
10919 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
10920 #[inline(always)]
10921 fn simd_ge_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10922 self.simd_le_f64x8(b, a)
10923 }
10924 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
10925 #[inline(always)]
10926 fn simd_gt_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> mask64x8<Self> {
10927 self.simd_lt_f64x8(b, a)
10928 }
10929 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
10930 #[inline(always)]
10931 fn zip_low_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10932 let (a0, _) = self.split_f64x8(a);
10933 let (b0, _) = self.split_f64x8(b);
10934 self.combine_f64x4(self.zip_low_f64x4(a0, b0), self.zip_high_f64x4(a0, b0))
10935 }
10936 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
10937 #[inline(always)]
10938 fn zip_high_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10939 let (_, a1) = self.split_f64x8(a);
10940 let (_, b1) = self.split_f64x8(b);
10941 self.combine_f64x4(self.zip_low_f64x4(a1, b1), self.zip_high_f64x4(a1, b1))
10942 }
10943 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
10944 #[inline(always)]
10945 fn unzip_low_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10946 let (a0, a1) = self.split_f64x8(a);
10947 let (b0, b1) = self.split_f64x8(b);
10948 self.combine_f64x4(self.unzip_low_f64x4(a0, a1), self.unzip_low_f64x4(b0, b1))
10949 }
10950 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
10951 #[inline(always)]
10952 fn unzip_high_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f64x8<Self> {
10953 let (a0, a1) = self.split_f64x8(a);
10954 let (b0, b1) = self.split_f64x8(b);
10955 self.combine_f64x4(self.unzip_high_f64x4(a0, a1), self.unzip_high_f64x4(b0, b1))
10956 }
10957 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
10958 #[inline(always)]
10959 fn interleave_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> (f64x8<Self>, f64x8<Self>) {
10960 let (a0, a1) = self.split_f64x8(a);
10961 let (b0, b1) = self.split_f64x8(b);
10962 let lo_lo = self.zip_low_f64x4(a0, b0);
10963 let lo_hi = self.zip_high_f64x4(a0, b0);
10964 let hi_lo = self.zip_low_f64x4(a1, b1);
10965 let hi_hi = self.zip_high_f64x4(a1, b1);
10966 (
10967 self.combine_f64x4(lo_lo, lo_hi),
10968 self.combine_f64x4(hi_lo, hi_hi),
10969 )
10970 }
10971 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
10972 #[inline(always)]
10973 fn deinterleave_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> (f64x8<Self>, f64x8<Self>) {
10974 let (a0, a1) = self.split_f64x8(a);
10975 let (b0, b1) = self.split_f64x8(b);
10976 let lo_even = self.unzip_low_f64x4(a0, a1);
10977 let lo_odd = self.unzip_high_f64x4(a0, a1);
10978 let hi_even = self.unzip_low_f64x4(b0, b1);
10979 let hi_odd = self.unzip_high_f64x4(b0, b1);
10980 (
10981 self.combine_f64x4(lo_even, hi_even),
10982 self.combine_f64x4(lo_odd, hi_odd),
10983 )
10984 }
10985 #[doc = "Compute `(a * b) + c` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
10986 #[inline(always)]
10987 fn mul_add_f64x8(self, a: f64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
10988 let (a0, a1) = self.split_f64x8(a);
10989 let (b0, b1) = self.split_f64x8(b);
10990 let (c0, c1) = self.split_f64x8(c);
10991 self.combine_f64x4(
10992 self.mul_add_f64x4(a0, b0, c0),
10993 self.mul_add_f64x4(a1, b1, c1),
10994 )
10995 }
10996 #[doc = "Compute `(a * b) + c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
10997 #[inline(always)]
10998 fn mul_add_precise_f64x8(self, a: f64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
10999 let (a0, a1) = self.split_f64x8(a);
11000 let (b0, b1) = self.split_f64x8(b);
11001 let (c0, c1) = self.split_f64x8(c);
11002 self.combine_f64x4(
11003 self.mul_add_precise_f64x4(a0, b0, c0),
11004 self.mul_add_precise_f64x4(a1, b1, c1),
11005 )
11006 }
11007 #[doc = "Compute `(a * b) - c` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
11008 #[inline(always)]
11009 fn mul_sub_f64x8(self, a: f64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
11010 let (a0, a1) = self.split_f64x8(a);
11011 let (b0, b1) = self.split_f64x8(b);
11012 let (c0, c1) = self.split_f64x8(c);
11013 self.combine_f64x4(
11014 self.mul_sub_f64x4(a0, b0, c0),
11015 self.mul_sub_f64x4(a1, b1, c1),
11016 )
11017 }
11018 #[doc = "Compute `(a * b) - c` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
11019 #[inline(always)]
11020 fn mul_sub_precise_f64x8(self, a: f64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
11021 let (a0, a1) = self.split_f64x8(a);
11022 let (b0, b1) = self.split_f64x8(b);
11023 let (c0, c1) = self.split_f64x8(c);
11024 self.combine_f64x4(
11025 self.mul_sub_precise_f64x4(a0, b0, c0),
11026 self.mul_sub_precise_f64x4(a1, b1, c1),
11027 )
11028 }
11029 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
11030 #[inline(always)]
11031 fn floor_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11032 let (a0, a1) = self.split_f64x8(a);
11033 self.combine_f64x4(self.floor_f64x4(a0), self.floor_f64x4(a1))
11034 }
11035 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
11036 #[inline(always)]
11037 fn ceil_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11038 let (a0, a1) = self.split_f64x8(a);
11039 self.combine_f64x4(self.ceil_f64x4(a0), self.ceil_f64x4(a1))
11040 }
11041 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
11042 #[inline(always)]
11043 fn round_ties_even_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11044 let (a0, a1) = self.split_f64x8(a);
11045 self.combine_f64x4(
11046 self.round_ties_even_f64x4(a0),
11047 self.round_ties_even_f64x4(a1),
11048 )
11049 }
11050 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
11051 #[inline(always)]
11052 fn round_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11053 let (a0, a1) = self.split_f64x8(a);
11054 self.combine_f64x4(self.round_f64x4(a0), self.round_f64x4(a1))
11055 }
11056 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `a - a.trunc()`."]
11057 #[inline(always)]
11058 fn fract_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11059 let (a0, a1) = self.split_f64x8(a);
11060 self.combine_f64x4(self.fract_f64x4(a0), self.fract_f64x4(a1))
11061 }
11062 #[doc = "Return the integer part of each element, rounding towards zero."]
11063 #[inline(always)]
11064 fn trunc_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11065 let (a0, a1) = self.split_f64x8(a);
11066 self.combine_f64x4(self.trunc_f64x4(a0), self.trunc_f64x4(a1))
11067 }
11068 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
11069 #[inline(always)]
11070 fn to_degrees_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11071 let (a0, a1) = self.split_f64x8(a);
11072 self.combine_f64x4(self.to_degrees_f64x4(a0), self.to_degrees_f64x4(a1))
11073 }
11074 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
11075 #[inline(always)]
11076 fn to_radians_f64x8(self, a: f64x8<Self>) -> f64x8<Self> {
11077 let (a0, a1) = self.split_f64x8(a);
11078 self.combine_f64x4(self.to_radians_f64x4(a0), self.to_radians_f64x4(a1))
11079 }
11080 #[doc = "Return a mask indicating which elements are NaN."]
11081 fn is_nan_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11082 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
11083 fn is_infinite_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11084 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
11085 fn is_finite_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11086 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
11087 fn is_subnormal_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11088 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
11089 fn is_normal_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11090 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
11091 fn is_sign_positive_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11092 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
11093 fn is_sign_negative_f64x8(self, a: f64x8<Self>) -> mask64x8<Self>;
11094 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
11095 #[inline(always)]
11096 fn select_f64x8(self, a: mask64x8<Self>, b: f64x8<Self>, c: f64x8<Self>) -> f64x8<Self> {
11097 let (a0, a1) = self.split_mask64x8(a);
11098 let (b0, b1) = self.split_f64x8(b);
11099 let (c0, c1) = self.split_f64x8(c);
11100 self.combine_f64x4(self.select_f64x4(a0, b0, c0), self.select_f64x4(a1, b1, c1))
11101 }
11102 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
11103 fn split_f64x8(self, a: f64x8<Self>) -> (f64x4<Self>, f64x4<Self>);
11104 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nValues are rounded to the nearest representable `f32`, with ties resolved to even; overflow produces signed infinity.This is the same as the `as` operator, and follows the IEEE 754 narrowing behavior in round-to-even mode.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
11105 #[inline(always)]
11106 fn narrow_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f32x16<Self> {
11107 let (a0, a1) = self.split_f64x8(a);
11108 let (b0, b1) = self.split_f64x8(b);
11109 self.combine_f32x8(self.narrow_f64x4(a0, a1), self.narrow_f64x4(b0, b1))
11110 }
11111 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
11112 #[inline(always)]
11113 fn saturating_narrow_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f32x16<Self> {
11114 let (a0, a1) = self.split_f64x8(a);
11115 let (b0, b1) = self.split_f64x8(b);
11116 self.combine_f32x8(
11117 self.saturating_narrow_f64x4(a0, a1),
11118 self.saturating_narrow_f64x4(b0, b1),
11119 )
11120 }
11121 #[doc = "Convert the lanes of two `f64` vectors to `f32` and concatenate them into one same-width vector.\n\nFor floating-point vectors this is identical to `narrow`, including its rounding and overflow behavior.\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
11122 #[inline(always)]
11123 fn relaxed_narrow_f64x8(self, a: f64x8<Self>, b: f64x8<Self>) -> f32x16<Self> {
11124 let (a0, a1) = self.split_f64x8(a);
11125 let (b0, b1) = self.split_f64x8(b);
11126 self.combine_f32x8(
11127 self.relaxed_narrow_f64x4(a0, a1),
11128 self.relaxed_narrow_f64x4(b0, b1),
11129 )
11130 }
11131 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
11132 #[inline(always)]
11133 fn cvt_u64_f64x8(self, a: f64x8<Self>) -> u64x8<Self> {
11134 let (a0, a1) = self.split_f64x8(a);
11135 self.combine_u64x4(self.cvt_u64_f64x4(a0), self.cvt_u64_f64x4(a1))
11136 }
11137 #[doc = "Convert each floating-point element to an unsigned 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
11138 #[inline(always)]
11139 fn cvt_u64_precise_f64x8(self, a: f64x8<Self>) -> u64x8<Self> {
11140 let (a0, a1) = self.split_f64x8(a);
11141 self.combine_u64x4(
11142 self.cvt_u64_precise_f64x4(a0),
11143 self.cvt_u64_precise_f64x4(a1),
11144 )
11145 }
11146 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values or NaN will produce implementation-defined results."]
11147 #[inline(always)]
11148 fn cvt_i64_f64x8(self, a: f64x8<Self>) -> i64x8<Self> {
11149 let (a0, a1) = self.split_f64x8(a);
11150 self.combine_i64x4(self.cvt_i64_f64x4(a0), self.cvt_i64_f64x4(a1))
11151 }
11152 #[doc = "Convert each floating-point element to a signed 64-bit integer, truncating towards zero.\n\nOut-of-range values are saturated to the closest in-range value. NaN becomes 0."]
11153 #[inline(always)]
11154 fn cvt_i64_precise_f64x8(self, a: f64x8<Self>) -> i64x8<Self> {
11155 let (a0, a1) = self.split_f64x8(a);
11156 self.combine_i64x4(
11157 self.cvt_i64_precise_f64x4(a0),
11158 self.cvt_i64_precise_f64x4(a1),
11159 )
11160 }
11161 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
11162 #[inline(always)]
11163 fn abs_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11164 let (a0, a1) = self.split_i64x8(a);
11165 self.combine_i64x4(self.abs_i64x4(a0), self.abs_i64x4(a1))
11166 }
11167 #[doc = "Create a SIMD vector with all elements set to the given value."]
11168 #[inline(always)]
11169 fn splat_i64x8(self, val: i64) -> i64x8<Self> {
11170 let half = self.splat_i64x4(val);
11171 self.combine_i64x4(half, half)
11172 }
11173 #[doc = "Reverse the order of the vector's elements."]
11174 #[inline(always)]
11175 fn reverse_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11176 let (a0, a1) = self.split_i64x8(a);
11177 self.combine_i64x4(self.reverse_i64x4(a1), self.reverse_i64x4(a0))
11178 }
11179 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
11180 fn slide_i64x8<const SHIFT: usize>(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self>;
11181 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
11182 #[inline(always)]
11183 fn slide_within_blocks_i64x8<const SHIFT: usize>(
11184 self,
11185 a: i64x8<Self>,
11186 b: i64x8<Self>,
11187 ) -> i64x8<Self> {
11188 let (a0, a1) = self.split_i64x8(a);
11189 let (b0, b1) = self.split_i64x8(b);
11190 self.combine_i64x4(
11191 self.slide_within_blocks_i64x4::<SHIFT>(a0, b0),
11192 self.slide_within_blocks_i64x4::<SHIFT>(a1, b1),
11193 )
11194 }
11195 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
11196 #[inline(always)]
11197 fn swizzle_dyn_within_blocks_i64x8(self, a: i64x8<Self>, indices: u8x64<Self>) -> i64x8<Self> {
11198 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
11199 }
11200 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
11201 #[inline(always)]
11202 fn swizzle_dyn_i64x8(self, a: i64x8<Self>, indices: u8x64<Self>) -> i64x8<Self> {
11203 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
11204 }
11205 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
11206 #[inline(always)]
11207 fn swizzle_dyn_precise_i64x8(self, a: i64x8<Self>, indices: u8x64<Self>) -> i64x8<Self> {
11208 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
11209 }
11210 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
11211 #[inline(always)]
11212 fn concat_swizzle_dyn_i64x8(
11213 self,
11214 a: i64x8<Self>,
11215 b: i64x8<Self>,
11216 indices: u8x64<Self>,
11217 ) -> i64x8<Self> {
11218 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
11219 Bytes::to_bytes(a),
11220 Bytes::to_bytes(b),
11221 indices,
11222 ))
11223 }
11224 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
11225 #[inline(always)]
11226 fn concat_swizzle_dyn_precise_i64x8(
11227 self,
11228 a: i64x8<Self>,
11229 b: i64x8<Self>,
11230 indices: u8x64<Self>,
11231 ) -> i64x8<Self> {
11232 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
11233 Bytes::to_bytes(a),
11234 Bytes::to_bytes(b),
11235 indices,
11236 ))
11237 }
11238 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
11239 fn compress_i64x8(self, values: i64x8<Self>, mask: mask64x8<Self>) -> i64x8<Self>;
11240 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
11241 fn compress_merge_i64x8(
11242 self,
11243 values: i64x8<Self>,
11244 mask: mask64x8<Self>,
11245 merge: i64x8<Self>,
11246 ) -> i64x8<Self>;
11247 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
11248 fn expand_i64x8(self, values: i64x8<Self>, mask: mask64x8<Self>) -> i64x8<Self>;
11249 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
11250 fn expand_merge_i64x8(
11251 self,
11252 values: i64x8<Self>,
11253 mask: mask64x8<Self>,
11254 merge: i64x8<Self>,
11255 ) -> i64x8<Self>;
11256 #[doc = "Return the number of ones in the binary representation of each element."]
11257 #[inline(always)]
11258 fn count_ones_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11259 let (a0, a1) = self.split_i64x8(a);
11260 self.combine_i64x4(self.count_ones_i64x4(a0), self.count_ones_i64x4(a1))
11261 }
11262 #[doc = "Return the number of zeros in the binary representation of each element."]
11263 #[inline(always)]
11264 fn count_zeros_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11265 let (a0, a1) = self.split_i64x8(a);
11266 self.combine_i64x4(self.count_zeros_i64x4(a0), self.count_zeros_i64x4(a1))
11267 }
11268 #[doc = "Add two vectors element-wise, wrapping on overflow."]
11269 #[inline(always)]
11270 fn add_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11271 let (a0, a1) = self.split_i64x8(a);
11272 let (b0, b1) = self.split_i64x8(b);
11273 self.combine_i64x4(self.add_i64x4(a0, b0), self.add_i64x4(a1, b1))
11274 }
11275 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
11276 #[inline(always)]
11277 fn saturating_add_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11278 let (a0, a1) = self.split_i64x8(a);
11279 let (b0, b1) = self.split_i64x8(b);
11280 self.combine_i64x4(
11281 self.saturating_add_i64x4(a0, b0),
11282 self.saturating_add_i64x4(a1, b1),
11283 )
11284 }
11285 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
11286 #[inline(always)]
11287 fn sub_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11288 let (a0, a1) = self.split_i64x8(a);
11289 let (b0, b1) = self.split_i64x8(b);
11290 self.combine_i64x4(self.sub_i64x4(a0, b0), self.sub_i64x4(a1, b1))
11291 }
11292 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
11293 #[inline(always)]
11294 fn saturating_sub_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11295 let (a0, a1) = self.split_i64x8(a);
11296 let (b0, b1) = self.split_i64x8(b);
11297 self.combine_i64x4(
11298 self.saturating_sub_i64x4(a0, b0),
11299 self.saturating_sub_i64x4(a1, b1),
11300 )
11301 }
11302 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
11303 #[inline(always)]
11304 fn mul_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11305 let (a0, a1) = self.split_i64x8(a);
11306 let (b0, b1) = self.split_i64x8(b);
11307 self.combine_i64x4(self.mul_i64x4(a0, b0), self.mul_i64x4(a1, b1))
11308 }
11309 #[doc = "Compute the bitwise AND of two vectors."]
11310 #[inline(always)]
11311 fn and_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11312 let (a0, a1) = self.split_i64x8(a);
11313 let (b0, b1) = self.split_i64x8(b);
11314 self.combine_i64x4(self.and_i64x4(a0, b0), self.and_i64x4(a1, b1))
11315 }
11316 #[doc = "Compute the bitwise OR of two vectors."]
11317 #[inline(always)]
11318 fn or_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11319 let (a0, a1) = self.split_i64x8(a);
11320 let (b0, b1) = self.split_i64x8(b);
11321 self.combine_i64x4(self.or_i64x4(a0, b0), self.or_i64x4(a1, b1))
11322 }
11323 #[doc = "Compute the bitwise XOR of two vectors."]
11324 #[inline(always)]
11325 fn xor_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11326 let (a0, a1) = self.split_i64x8(a);
11327 let (b0, b1) = self.split_i64x8(b);
11328 self.combine_i64x4(self.xor_i64x4(a0, b0), self.xor_i64x4(a1, b1))
11329 }
11330 #[doc = "Compute the bitwise NOT of the vector."]
11331 #[inline(always)]
11332 fn not_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11333 let (a0, a1) = self.split_i64x8(a);
11334 self.combine_i64x4(self.not_i64x4(a0), self.not_i64x4(a1))
11335 }
11336 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
11337 #[inline(always)]
11338 fn shl_i64x8(self, a: i64x8<Self>, shift: u32) -> i64x8<Self> {
11339 let (a0, a1) = self.split_i64x8(a);
11340 self.combine_i64x4(self.shl_i64x4(a0, shift), self.shl_i64x4(a1, shift))
11341 }
11342 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
11343 #[inline(always)]
11344 fn shlv_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11345 let (a0, a1) = self.split_i64x8(a);
11346 let (b0, b1) = self.split_i64x8(b);
11347 self.combine_i64x4(self.shlv_i64x4(a0, b0), self.shlv_i64x4(a1, b1))
11348 }
11349 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
11350 #[inline(always)]
11351 fn shr_i64x8(self, a: i64x8<Self>, shift: u32) -> i64x8<Self> {
11352 let (a0, a1) = self.split_i64x8(a);
11353 self.combine_i64x4(self.shr_i64x4(a0, shift), self.shr_i64x4(a1, shift))
11354 }
11355 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
11356 #[inline(always)]
11357 fn shrv_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11358 let (a0, a1) = self.split_i64x8(a);
11359 let (b0, b1) = self.split_i64x8(b);
11360 self.combine_i64x4(self.shrv_i64x4(a0, b0), self.shrv_i64x4(a1, b1))
11361 }
11362 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
11363 #[inline(always)]
11364 fn reduce_max_i64x8(self, a: i64x8<Self>) -> i64 {
11365 let (a0, a1) = self.split_i64x8(a);
11366 self.reduce_max_i64x4(self.max_i64x4(a0, a1))
11367 }
11368 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
11369 #[inline(always)]
11370 fn reduce_min_i64x8(self, a: i64x8<Self>) -> i64 {
11371 let (a0, a1) = self.split_i64x8(a);
11372 self.reduce_min_i64x4(self.min_i64x4(a0, a1))
11373 }
11374 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
11375 #[inline(always)]
11376 fn reduce_sum_i64x8(self, a: i64x8<Self>) -> i64 {
11377 let (a0, a1) = self.split_i64x8(a);
11378 self.reduce_sum_i64x4(self.add_i64x4(a0, a1))
11379 }
11380 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
11381 #[inline(always)]
11382 fn reduce_product_i64x8(self, a: i64x8<Self>) -> i64 {
11383 let (a0, a1) = self.split_i64x8(a);
11384 self.reduce_product_i64x4(self.mul_i64x4(a0, a1))
11385 }
11386 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
11387 #[inline(always)]
11388 fn max_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11389 let (a0, a1) = self.split_i64x8(a);
11390 let (b0, b1) = self.split_i64x8(b);
11391 self.combine_i64x4(self.max_i64x4(a0, b0), self.max_i64x4(a1, b1))
11392 }
11393 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
11394 #[inline(always)]
11395 fn min_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11396 let (a0, a1) = self.split_i64x8(a);
11397 let (b0, b1) = self.split_i64x8(b);
11398 self.combine_i64x4(self.min_i64x4(a0, b0), self.min_i64x4(a1, b1))
11399 }
11400 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
11401 #[inline(always)]
11402 fn clamp_i64x8(self, a: i64x8<Self>, b: i64x8<Self>, c: i64x8<Self>) -> i64x8<Self> {
11403 let (a0, a1) = self.split_i64x8(a);
11404 let (b0, b1) = self.split_i64x8(b);
11405 let (c0, c1) = self.split_i64x8(c);
11406 self.combine_i64x4(self.clamp_i64x4(a0, b0, c0), self.clamp_i64x4(a1, b1, c1))
11407 }
11408 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
11409 #[inline(always)]
11410 fn simd_eq_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11411 let (a0, a1) = self.split_i64x8(a);
11412 let (b0, b1) = self.split_i64x8(b);
11413 self.combine_mask64x4(self.simd_eq_i64x4(a0, b0), self.simd_eq_i64x4(a1, b1))
11414 }
11415 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
11416 #[inline(always)]
11417 fn simd_ne_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11418 self.not_mask64x8(self.simd_eq_i64x8(a, b))
11419 }
11420 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
11421 #[inline(always)]
11422 fn simd_lt_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11423 let (a0, a1) = self.split_i64x8(a);
11424 let (b0, b1) = self.split_i64x8(b);
11425 self.combine_mask64x4(self.simd_lt_i64x4(a0, b0), self.simd_lt_i64x4(a1, b1))
11426 }
11427 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
11428 #[inline(always)]
11429 fn simd_le_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11430 let (a0, a1) = self.split_i64x8(a);
11431 let (b0, b1) = self.split_i64x8(b);
11432 self.combine_mask64x4(self.simd_le_i64x4(a0, b0), self.simd_le_i64x4(a1, b1))
11433 }
11434 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
11435 #[inline(always)]
11436 fn simd_ge_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11437 self.simd_le_i64x8(b, a)
11438 }
11439 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
11440 #[inline(always)]
11441 fn simd_gt_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> mask64x8<Self> {
11442 self.simd_lt_i64x8(b, a)
11443 }
11444 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
11445 #[inline(always)]
11446 fn zip_low_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11447 let (a0, _) = self.split_i64x8(a);
11448 let (b0, _) = self.split_i64x8(b);
11449 self.combine_i64x4(self.zip_low_i64x4(a0, b0), self.zip_high_i64x4(a0, b0))
11450 }
11451 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
11452 #[inline(always)]
11453 fn zip_high_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11454 let (_, a1) = self.split_i64x8(a);
11455 let (_, b1) = self.split_i64x8(b);
11456 self.combine_i64x4(self.zip_low_i64x4(a1, b1), self.zip_high_i64x4(a1, b1))
11457 }
11458 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
11459 #[inline(always)]
11460 fn unzip_low_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11461 let (a0, a1) = self.split_i64x8(a);
11462 let (b0, b1) = self.split_i64x8(b);
11463 self.combine_i64x4(self.unzip_low_i64x4(a0, a1), self.unzip_low_i64x4(b0, b1))
11464 }
11465 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
11466 #[inline(always)]
11467 fn unzip_high_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i64x8<Self> {
11468 let (a0, a1) = self.split_i64x8(a);
11469 let (b0, b1) = self.split_i64x8(b);
11470 self.combine_i64x4(self.unzip_high_i64x4(a0, a1), self.unzip_high_i64x4(b0, b1))
11471 }
11472 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
11473 #[inline(always)]
11474 fn interleave_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> (i64x8<Self>, i64x8<Self>) {
11475 let (a0, a1) = self.split_i64x8(a);
11476 let (b0, b1) = self.split_i64x8(b);
11477 let lo_lo = self.zip_low_i64x4(a0, b0);
11478 let lo_hi = self.zip_high_i64x4(a0, b0);
11479 let hi_lo = self.zip_low_i64x4(a1, b1);
11480 let hi_hi = self.zip_high_i64x4(a1, b1);
11481 (
11482 self.combine_i64x4(lo_lo, lo_hi),
11483 self.combine_i64x4(hi_lo, hi_hi),
11484 )
11485 }
11486 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
11487 #[inline(always)]
11488 fn deinterleave_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> (i64x8<Self>, i64x8<Self>) {
11489 let (a0, a1) = self.split_i64x8(a);
11490 let (b0, b1) = self.split_i64x8(b);
11491 let lo_even = self.unzip_low_i64x4(a0, a1);
11492 let lo_odd = self.unzip_high_i64x4(a0, a1);
11493 let hi_even = self.unzip_low_i64x4(b0, b1);
11494 let hi_odd = self.unzip_high_i64x4(b0, b1);
11495 (
11496 self.combine_i64x4(lo_even, hi_even),
11497 self.combine_i64x4(lo_odd, hi_odd),
11498 )
11499 }
11500 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
11501 #[inline(always)]
11502 fn select_i64x8(self, a: mask64x8<Self>, b: i64x8<Self>, c: i64x8<Self>) -> i64x8<Self> {
11503 let (a0, a1) = self.split_mask64x8(a);
11504 let (b0, b1) = self.split_i64x8(b);
11505 let (c0, c1) = self.split_i64x8(c);
11506 self.combine_i64x4(self.select_i64x4(a0, b0, c0), self.select_i64x4(a1, b1, c1))
11507 }
11508 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
11509 fn split_i64x8(self, a: i64x8<Self>) -> (i64x4<Self>, i64x4<Self>);
11510 #[doc = "Negate each element of the vector, wrapping on overflow."]
11511 #[inline(always)]
11512 fn neg_i64x8(self, a: i64x8<Self>) -> i64x8<Self> {
11513 let (a0, a1) = self.split_i64x8(a);
11514 self.combine_i64x4(self.neg_i64x4(a0), self.neg_i64x4(a1))
11515 }
11516 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
11517 #[inline(always)]
11518 fn narrow_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i32x16<Self> {
11519 let (a0, a1) = self.split_i64x8(a);
11520 let (b0, b1) = self.split_i64x8(b);
11521 self.combine_i32x8(self.narrow_i64x4(a0, a1), self.narrow_i64x4(b0, b1))
11522 }
11523 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
11524 #[inline(always)]
11525 fn saturating_narrow_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i32x16<Self> {
11526 let (a0, a1) = self.split_i64x8(a);
11527 let (b0, b1) = self.split_i64x8(b);
11528 self.combine_i32x8(
11529 self.saturating_narrow_i64x4(a0, a1),
11530 self.saturating_narrow_i64x4(b0, b1),
11531 )
11532 }
11533 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
11534 #[inline(always)]
11535 fn relaxed_narrow_i64x8(self, a: i64x8<Self>, b: i64x8<Self>) -> i32x16<Self> {
11536 let (a0, a1) = self.split_i64x8(a);
11537 let (b0, b1) = self.split_i64x8(b);
11538 self.combine_i32x8(
11539 self.relaxed_narrow_i64x4(a0, a1),
11540 self.relaxed_narrow_i64x4(b0, b1),
11541 )
11542 }
11543 #[doc = "Convert each signed 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
11544 #[inline(always)]
11545 fn cvt_f64_i64x8(self, a: i64x8<Self>) -> f64x8<Self> {
11546 let (a0, a1) = self.split_i64x8(a);
11547 self.combine_f64x4(self.cvt_f64_i64x4(a0), self.cvt_f64_i64x4(a1))
11548 }
11549 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
11550 #[inline(always)]
11551 fn abs_u64x8(self, a: u64x8<Self>) -> u64x8<Self> {
11552 a
11553 }
11554 #[doc = "Create a SIMD vector with all elements set to the given value."]
11555 #[inline(always)]
11556 fn splat_u64x8(self, val: u64) -> u64x8<Self> {
11557 let half = self.splat_u64x4(val);
11558 self.combine_u64x4(half, half)
11559 }
11560 #[doc = "Reverse the order of the vector's elements."]
11561 #[inline(always)]
11562 fn reverse_u64x8(self, a: u64x8<Self>) -> u64x8<Self> {
11563 let (a0, a1) = self.split_u64x8(a);
11564 self.combine_u64x4(self.reverse_u64x4(a1), self.reverse_u64x4(a0))
11565 }
11566 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
11567 fn slide_u64x8<const SHIFT: usize>(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self>;
11568 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
11569 #[inline(always)]
11570 fn slide_within_blocks_u64x8<const SHIFT: usize>(
11571 self,
11572 a: u64x8<Self>,
11573 b: u64x8<Self>,
11574 ) -> u64x8<Self> {
11575 let (a0, a1) = self.split_u64x8(a);
11576 let (b0, b1) = self.split_u64x8(b);
11577 self.combine_u64x4(
11578 self.slide_within_blocks_u64x4::<SHIFT>(a0, b0),
11579 self.slide_within_blocks_u64x4::<SHIFT>(a1, b1),
11580 )
11581 }
11582 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
11583 #[inline(always)]
11584 fn swizzle_dyn_within_blocks_u64x8(self, a: u64x8<Self>, indices: u8x64<Self>) -> u64x8<Self> {
11585 Bytes::from_bytes(self.swizzle_dyn_within_blocks_u8x64(Bytes::to_bytes(a), indices))
11586 }
11587 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
11588 #[inline(always)]
11589 fn swizzle_dyn_u64x8(self, a: u64x8<Self>, indices: u8x64<Self>) -> u64x8<Self> {
11590 Bytes::from_bytes(self.swizzle_dyn_u8x64(Bytes::to_bytes(a), indices))
11591 }
11592 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
11593 #[inline(always)]
11594 fn swizzle_dyn_precise_u64x8(self, a: u64x8<Self>, indices: u8x64<Self>) -> u64x8<Self> {
11595 Bytes::from_bytes(self.swizzle_dyn_precise_u8x64(Bytes::to_bytes(a), indices))
11596 }
11597 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
11598 #[inline(always)]
11599 fn concat_swizzle_dyn_u64x8(
11600 self,
11601 a: u64x8<Self>,
11602 b: u64x8<Self>,
11603 indices: u8x64<Self>,
11604 ) -> u64x8<Self> {
11605 Bytes::from_bytes(self.concat_swizzle_dyn_u8x64(
11606 Bytes::to_bytes(a),
11607 Bytes::to_bytes(b),
11608 indices,
11609 ))
11610 }
11611 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
11612 #[inline(always)]
11613 fn concat_swizzle_dyn_precise_u64x8(
11614 self,
11615 a: u64x8<Self>,
11616 b: u64x8<Self>,
11617 indices: u8x64<Self>,
11618 ) -> u64x8<Self> {
11619 Bytes::from_bytes(self.concat_swizzle_dyn_precise_u8x64(
11620 Bytes::to_bytes(a),
11621 Bytes::to_bytes(b),
11622 indices,
11623 ))
11624 }
11625 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
11626 fn compress_u64x8(self, values: u64x8<Self>, mask: mask64x8<Self>) -> u64x8<Self>;
11627 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = values[i];\n k += 1;\n }\n}\nreturn result;\n```"]
11628 fn compress_merge_u64x8(
11629 self,
11630 values: u64x8<Self>,
11631 mask: mask64x8<Self>,
11632 merge: u64x8<Self>,
11633 ) -> u64x8<Self>;
11634 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
11635 fn expand_u64x8(self, values: u64x8<Self>, mask: mask64x8<Self>) -> u64x8<Self>;
11636 #[doc = "Expand consecutive low elements from `values` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = values[k];\n k += 1;\n }\n}\nreturn result;\n```"]
11637 fn expand_merge_u64x8(
11638 self,
11639 values: u64x8<Self>,
11640 mask: mask64x8<Self>,
11641 merge: u64x8<Self>,
11642 ) -> u64x8<Self>;
11643 #[doc = "Return the number of ones in the binary representation of each element."]
11644 #[inline(always)]
11645 fn count_ones_u64x8(self, a: u64x8<Self>) -> u64x8<Self> {
11646 let (a0, a1) = self.split_u64x8(a);
11647 self.combine_u64x4(self.count_ones_u64x4(a0), self.count_ones_u64x4(a1))
11648 }
11649 #[doc = "Return the number of zeros in the binary representation of each element."]
11650 #[inline(always)]
11651 fn count_zeros_u64x8(self, a: u64x8<Self>) -> u64x8<Self> {
11652 let (a0, a1) = self.split_u64x8(a);
11653 self.combine_u64x4(self.count_zeros_u64x4(a0), self.count_zeros_u64x4(a1))
11654 }
11655 #[doc = "Add two vectors element-wise, wrapping on overflow."]
11656 #[inline(always)]
11657 fn add_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11658 let (a0, a1) = self.split_u64x8(a);
11659 let (b0, b1) = self.split_u64x8(b);
11660 self.combine_u64x4(self.add_u64x4(a0, b0), self.add_u64x4(a1, b1))
11661 }
11662 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
11663 #[inline(always)]
11664 fn saturating_add_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11665 let (a0, a1) = self.split_u64x8(a);
11666 let (b0, b1) = self.split_u64x8(b);
11667 self.combine_u64x4(
11668 self.saturating_add_u64x4(a0, b0),
11669 self.saturating_add_u64x4(a1, b1),
11670 )
11671 }
11672 #[doc = "Subtract two vectors element-wise, wrapping on overflow."]
11673 #[inline(always)]
11674 fn sub_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11675 let (a0, a1) = self.split_u64x8(a);
11676 let (b0, b1) = self.split_u64x8(b);
11677 self.combine_u64x4(self.sub_u64x4(a0, b0), self.sub_u64x4(a1, b1))
11678 }
11679 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
11680 #[inline(always)]
11681 fn saturating_sub_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11682 let (a0, a1) = self.split_u64x8(a);
11683 let (b0, b1) = self.split_u64x8(b);
11684 self.combine_u64x4(
11685 self.saturating_sub_u64x4(a0, b0),
11686 self.saturating_sub_u64x4(a1, b1),
11687 )
11688 }
11689 #[doc = "Multiply two vectors element-wise, wrapping on overflow."]
11690 #[inline(always)]
11691 fn mul_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11692 let (a0, a1) = self.split_u64x8(a);
11693 let (b0, b1) = self.split_u64x8(b);
11694 self.combine_u64x4(self.mul_u64x4(a0, b0), self.mul_u64x4(a1, b1))
11695 }
11696 #[doc = "Compute the bitwise AND of two vectors."]
11697 #[inline(always)]
11698 fn and_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11699 let (a0, a1) = self.split_u64x8(a);
11700 let (b0, b1) = self.split_u64x8(b);
11701 self.combine_u64x4(self.and_u64x4(a0, b0), self.and_u64x4(a1, b1))
11702 }
11703 #[doc = "Compute the bitwise OR of two vectors."]
11704 #[inline(always)]
11705 fn or_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11706 let (a0, a1) = self.split_u64x8(a);
11707 let (b0, b1) = self.split_u64x8(b);
11708 self.combine_u64x4(self.or_u64x4(a0, b0), self.or_u64x4(a1, b1))
11709 }
11710 #[doc = "Compute the bitwise XOR of two vectors."]
11711 #[inline(always)]
11712 fn xor_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11713 let (a0, a1) = self.split_u64x8(a);
11714 let (b0, b1) = self.split_u64x8(b);
11715 self.combine_u64x4(self.xor_u64x4(a0, b0), self.xor_u64x4(a1, b1))
11716 }
11717 #[doc = "Compute the bitwise NOT of the vector."]
11718 #[inline(always)]
11719 fn not_u64x8(self, a: u64x8<Self>) -> u64x8<Self> {
11720 let (a0, a1) = self.split_u64x8(a);
11721 self.combine_u64x4(self.not_u64x4(a0), self.not_u64x4(a1))
11722 }
11723 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
11724 #[inline(always)]
11725 fn shl_u64x8(self, a: u64x8<Self>, shift: u32) -> u64x8<Self> {
11726 let (a0, a1) = self.split_u64x8(a);
11727 self.combine_u64x4(self.shl_u64x4(a0, shift), self.shl_u64x4(a1, shift))
11728 }
11729 #[doc = "Shift each element left by the given number of bits.\n\nBits shifted out of the left side are discarded, and zeros are shifted in on the right.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
11730 #[inline(always)]
11731 fn shlv_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11732 let (a0, a1) = self.split_u64x8(a);
11733 let (b0, b1) = self.split_u64x8(b);
11734 self.combine_u64x4(self.shlv_u64x4(a0, b0), self.shlv_u64x4(a1, b1))
11735 }
11736 #[doc = "Shift each element right by the given number of bits.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform."]
11737 #[inline(always)]
11738 fn shr_u64x8(self, a: u64x8<Self>, shift: u32) -> u64x8<Self> {
11739 let (a0, a1) = self.split_u64x8(a);
11740 self.combine_u64x4(self.shr_u64x4(a0, shift), self.shr_u64x4(a1, shift))
11741 }
11742 #[doc = "Shift each element right by the corresponding element in another vector.\n\nFor unsigned integers, zeros are shifted in on the left. For signed integers, the sign bit is replicated.\n\nWhen shifting out of bounds (e.g. shifting a 32-bit value by 32 or more), the result is implementation-defined and may vary by platform.\n\n# Performance\nThis per-lane shift is slower than shifting the entire vector by a scalar. It is not vectorized at all on WebAssembly, SSE4.2, and for `u8` and `i8` elements on AVX2. Prefer shifting by a single scalar value instead of by a vector whenever possible."]
11743 #[inline(always)]
11744 fn shrv_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11745 let (a0, a1) = self.split_u64x8(a);
11746 let (b0, b1) = self.split_u64x8(b);
11747 self.combine_u64x4(self.shrv_u64x4(a0, b0), self.shrv_u64x4(a1, b1))
11748 }
11749 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
11750 #[inline(always)]
11751 fn reduce_max_u64x8(self, a: u64x8<Self>) -> u64 {
11752 let (a0, a1) = self.split_u64x8(a);
11753 self.reduce_max_u64x4(self.max_u64x4(a0, a1))
11754 }
11755 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
11756 #[inline(always)]
11757 fn reduce_min_u64x8(self, a: u64x8<Self>) -> u64 {
11758 let (a0, a1) = self.split_u64x8(a);
11759 self.reduce_min_u64x4(self.min_u64x4(a0, a1))
11760 }
11761 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
11762 #[inline(always)]
11763 fn reduce_sum_u64x8(self, a: u64x8<Self>) -> u64 {
11764 let (a0, a1) = self.split_u64x8(a);
11765 self.reduce_sum_u64x4(self.add_u64x4(a0, a1))
11766 }
11767 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
11768 #[inline(always)]
11769 fn reduce_product_u64x8(self, a: u64x8<Self>) -> u64 {
11770 let (a0, a1) = self.split_u64x8(a);
11771 self.reduce_product_u64x4(self.mul_u64x4(a0, a1))
11772 }
11773 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
11774 #[inline(always)]
11775 fn max_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11776 let (a0, a1) = self.split_u64x8(a);
11777 let (b0, b1) = self.split_u64x8(b);
11778 self.combine_u64x4(self.max_u64x4(a0, b0), self.max_u64x4(a1, b1))
11779 }
11780 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
11781 #[inline(always)]
11782 fn min_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11783 let (a0, a1) = self.split_u64x8(a);
11784 let (b0, b1) = self.split_u64x8(b);
11785 self.combine_u64x4(self.min_u64x4(a0, b0), self.min_u64x4(a1, b1))
11786 }
11787 #[doc = "Clamp each element to the interval `[b, c]`.\n\nIf `b > c`, or `b` or `c` are NaN, the result is implementation-defined for that lane.\n\nIf `a` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `b > c` for any element or any element of `b` or `c` is NaN."]
11788 #[inline(always)]
11789 fn clamp_u64x8(self, a: u64x8<Self>, b: u64x8<Self>, c: u64x8<Self>) -> u64x8<Self> {
11790 let (a0, a1) = self.split_u64x8(a);
11791 let (b0, b1) = self.split_u64x8(b);
11792 let (c0, c1) = self.split_u64x8(c);
11793 self.combine_u64x4(self.clamp_u64x4(a0, b0, c0), self.clamp_u64x4(a1, b1, c1))
11794 }
11795 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
11796 #[inline(always)]
11797 fn simd_eq_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11798 let (a0, a1) = self.split_u64x8(a);
11799 let (b0, b1) = self.split_u64x8(b);
11800 self.combine_mask64x4(self.simd_eq_u64x4(a0, b0), self.simd_eq_u64x4(a1, b1))
11801 }
11802 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
11803 #[inline(always)]
11804 fn simd_ne_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11805 self.not_mask64x8(self.simd_eq_u64x8(a, b))
11806 }
11807 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `a` is less than `b`, and false if not."]
11808 #[inline(always)]
11809 fn simd_lt_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11810 let (a0, a1) = self.split_u64x8(a);
11811 let (b0, b1) = self.split_u64x8(b);
11812 self.combine_mask64x4(self.simd_lt_u64x4(a0, b0), self.simd_lt_u64x4(a1, b1))
11813 }
11814 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `a` is less than or equal to `b`, and false if not."]
11815 #[inline(always)]
11816 fn simd_le_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11817 let (a0, a1) = self.split_u64x8(a);
11818 let (b0, b1) = self.split_u64x8(b);
11819 self.combine_mask64x4(self.simd_le_u64x4(a0, b0), self.simd_le_u64x4(a1, b1))
11820 }
11821 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `a` is greater than or equal to `b`, and false if not."]
11822 #[inline(always)]
11823 fn simd_ge_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11824 self.simd_le_u64x8(b, a)
11825 }
11826 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `a` is greater than `b`, and false if not."]
11827 #[inline(always)]
11828 fn simd_gt_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> mask64x8<Self> {
11829 self.simd_lt_u64x8(b, a)
11830 }
11831 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
11832 #[inline(always)]
11833 fn zip_low_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11834 let (a0, _) = self.split_u64x8(a);
11835 let (b0, _) = self.split_u64x8(b);
11836 self.combine_u64x4(self.zip_low_u64x4(a0, b0), self.zip_high_u64x4(a0, b0))
11837 }
11838 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
11839 #[inline(always)]
11840 fn zip_high_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11841 let (_, a1) = self.split_u64x8(a);
11842 let (_, b1) = self.split_u64x8(b);
11843 self.combine_u64x4(self.zip_low_u64x4(a1, b1), self.zip_high_u64x4(a1, b1))
11844 }
11845 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
11846 #[inline(always)]
11847 fn unzip_low_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11848 let (a0, a1) = self.split_u64x8(a);
11849 let (b0, b1) = self.split_u64x8(b);
11850 self.combine_u64x4(self.unzip_low_u64x4(a0, a1), self.unzip_low_u64x4(b0, b1))
11851 }
11852 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
11853 #[inline(always)]
11854 fn unzip_high_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u64x8<Self> {
11855 let (a0, a1) = self.split_u64x8(a);
11856 let (b0, b1) = self.split_u64x8(b);
11857 self.combine_u64x4(self.unzip_high_u64x4(a0, a1), self.unzip_high_u64x4(b0, b1))
11858 }
11859 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `a` and `b`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
11860 #[inline(always)]
11861 fn interleave_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> (u64x8<Self>, u64x8<Self>) {
11862 let (a0, a1) = self.split_u64x8(a);
11863 let (b0, b1) = self.split_u64x8(b);
11864 let lo_lo = self.zip_low_u64x4(a0, b0);
11865 let lo_hi = self.zip_high_u64x4(a0, b0);
11866 let hi_lo = self.zip_low_u64x4(a1, b1);
11867 let hi_hi = self.zip_high_u64x4(a1, b1);
11868 (
11869 self.combine_u64x4(lo_lo, lo_hi),
11870 self.combine_u64x4(hi_lo, hi_hi),
11871 )
11872 }
11873 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `a` followed by all even-indexed elements from `b`. The second result contains all odd-indexed elements from `a` followed by all odd-indexed elements from `b`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
11874 #[inline(always)]
11875 fn deinterleave_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> (u64x8<Self>, u64x8<Self>) {
11876 let (a0, a1) = self.split_u64x8(a);
11877 let (b0, b1) = self.split_u64x8(b);
11878 let lo_even = self.unzip_low_u64x4(a0, a1);
11879 let lo_odd = self.unzip_high_u64x4(a0, a1);
11880 let hi_even = self.unzip_low_u64x4(b0, b1);
11881 let hi_odd = self.unzip_high_u64x4(b0, b1);
11882 (
11883 self.combine_u64x4(lo_even, hi_even),
11884 self.combine_u64x4(lo_odd, hi_odd),
11885 )
11886 }
11887 #[doc = "Select elements from b and c based on the mask operand a.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
11888 #[inline(always)]
11889 fn select_u64x8(self, a: mask64x8<Self>, b: u64x8<Self>, c: u64x8<Self>) -> u64x8<Self> {
11890 let (a0, a1) = self.split_mask64x8(a);
11891 let (b0, b1) = self.split_u64x8(b);
11892 let (c0, c1) = self.split_u64x8(c);
11893 self.combine_u64x4(self.select_u64x4(a0, b0, c0), self.select_u64x4(a1, b1, c1))
11894 }
11895 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
11896 fn split_u64x8(self, a: u64x8<Self>) -> (u64x4<Self>, u64x4<Self>);
11897 #[doc = "Truncate the lanes of two vectors and concatenate them into one same-width vector.\n\nEach lane retains its low destination-width bits. `a` provides the lower result lanes and `b` provides the upper result lanes."]
11898 #[inline(always)]
11899 fn narrow_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u32x16<Self> {
11900 let (a0, a1) = self.split_u64x8(a);
11901 let (b0, b1) = self.split_u64x8(b);
11902 self.combine_u32x8(self.narrow_u64x4(a0, a1), self.narrow_u64x4(b0, b1))
11903 }
11904 #[doc = "Narrow the lanes of two vectors with saturation and concatenate them into one same-width vector.\n\nEach lane is clamped to the destination type's range. `a` provides the lower result lanes and `b` provides the upper result lanes."]
11905 #[inline(always)]
11906 fn saturating_narrow_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u32x16<Self> {
11907 let (a0, a1) = self.split_u64x8(a);
11908 let (b0, b1) = self.split_u64x8(b);
11909 self.combine_u32x8(
11910 self.saturating_narrow_u64x4(a0, a1),
11911 self.saturating_narrow_u64x4(b0, b1),
11912 )
11913 }
11914 #[doc = "Narrow the lanes of two vectors using the cheapest operation for the active SIMD backend and concatenate them into one same-width vector.\n\nInputs must fit in the destination type; in debug mode this function will panic if any of the inputs do not fit. Out-of-range results in release builds produce arbitrary values (but remain memory-safe).\n\n`a` provides the lower result lanes and `b` provides the upper result lanes."]
11915 #[inline(always)]
11916 fn relaxed_narrow_u64x8(self, a: u64x8<Self>, b: u64x8<Self>) -> u32x16<Self> {
11917 let (a0, a1) = self.split_u64x8(a);
11918 let (b0, b1) = self.split_u64x8(b);
11919 self.combine_u32x8(
11920 self.relaxed_narrow_u64x4(a0, a1),
11921 self.relaxed_narrow_u64x4(b0, b1),
11922 )
11923 }
11924 #[doc = "Convert each unsigned 64-bit integer element to a floating-point value.\n\nValues that cannot be exactly represented are rounded to the nearest representable value."]
11925 #[inline(always)]
11926 fn cvt_f64_u64x8(self, a: u64x8<Self>) -> f64x8<Self> {
11927 let (a0, a1) = self.split_u64x8(a);
11928 self.combine_f64x4(self.cvt_f64_u64x4(a0), self.cvt_f64_u64x4(a1))
11929 }
11930 #[doc = "Create a SIMD mask with all lanes set from the given boolean value."]
11931 #[inline(always)]
11932 fn splat_mask64x8(self, val: bool) -> mask64x8<Self> {
11933 let half = self.splat_mask64x4(val);
11934 self.combine_mask64x4(half, half)
11935 }
11936 #[doc = "Create a SIMD mask from a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are ignored."]
11937 #[inline(always)]
11938 fn from_bitmask_mask64x8(self, bits: u64) -> mask64x8<Self> {
11939 let lo = self.from_bitmask_mask64x4(bits);
11940 let hi = self.from_bitmask_mask64x4(bits >> 4usize);
11941 self.combine_mask64x4(lo, hi)
11942 }
11943 #[doc = "Convert a SIMD mask to a compact bitmask.\n\nBit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above the number of lanes in this mask are cleared."]
11944 #[inline(always)]
11945 fn to_bitmask_mask64x8(self, a: mask64x8<Self>) -> u64 {
11946 let (lo, hi) = self.split_mask64x8(a);
11947 let lo = self.to_bitmask_mask64x4(lo);
11948 let hi = self.to_bitmask_mask64x4(hi);
11949 lo | (hi << 4usize)
11950 }
11951 #[doc = "Create a SIMD mask from an integer vector of the same width.\n\nA lane value of -1 means \"true\", a lane value of 0 means \"false\", and all other lane values result in unspecified behavior."]
11952 fn from_vector_mask64x8(self, vector: i64x8<Self>) -> mask64x8<Self>;
11953 #[doc = "Convert a SIMD mask to an integer vector of the same width.\n\n\"True\" maps to -1 and \"false\" maps to 0."]
11954 fn to_vector_mask64x8(self, a: mask64x8<Self>) -> i64x8<Self>;
11955 #[doc = "Set one logical lane of a SIMD mask."]
11956 fn set_mask64x8(self, a: &mut mask64x8<Self>, index: usize, value: bool) -> ();
11957 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
11958 fn rotate_elements_left_mask64x8<const OFFSET: usize>(
11959 self,
11960 a: mask64x8<Self>,
11961 ) -> mask64x8<Self>;
11962 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
11963 fn rotate_elements_right_mask64x8<const OFFSET: usize>(
11964 self,
11965 a: mask64x8<Self>,
11966 ) -> mask64x8<Self>;
11967 #[doc = "Compute the logical AND of two masks."]
11968 #[inline(always)]
11969 fn and_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask64x8<Self> {
11970 let (a0, a1) = self.split_mask64x8(a);
11971 let (b0, b1) = self.split_mask64x8(b);
11972 self.combine_mask64x4(self.and_mask64x4(a0, b0), self.and_mask64x4(a1, b1))
11973 }
11974 #[doc = "Compute the logical OR of two masks."]
11975 #[inline(always)]
11976 fn or_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask64x8<Self> {
11977 let (a0, a1) = self.split_mask64x8(a);
11978 let (b0, b1) = self.split_mask64x8(b);
11979 self.combine_mask64x4(self.or_mask64x4(a0, b0), self.or_mask64x4(a1, b1))
11980 }
11981 #[doc = "Compute the logical XOR of two masks."]
11982 #[inline(always)]
11983 fn xor_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask64x8<Self> {
11984 let (a0, a1) = self.split_mask64x8(a);
11985 let (b0, b1) = self.split_mask64x8(b);
11986 self.combine_mask64x4(self.xor_mask64x4(a0, b0), self.xor_mask64x4(a1, b1))
11987 }
11988 #[doc = "Compute the logical NOT of the mask."]
11989 #[inline(always)]
11990 fn not_mask64x8(self, a: mask64x8<Self>) -> mask64x8<Self> {
11991 let (a0, a1) = self.split_mask64x8(a);
11992 self.combine_mask64x4(self.not_mask64x4(a0), self.not_mask64x4(a1))
11993 }
11994 #[doc = "Reverse the order of the mask's logical lanes."]
11995 #[inline(always)]
11996 fn reverse_mask64x8(self, a: mask64x8<Self>) -> mask64x8<Self> {
11997 let (a0, a1) = self.split_mask64x8(a);
11998 self.combine_mask64x4(self.reverse_mask64x4(a1), self.reverse_mask64x4(a0))
11999 }
12000 #[doc = "Select elements from `b` and `c` based on the mask operand `a`.\n\nThis operation's behavior is unspecified if a was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information."]
12001 #[inline(always)]
12002 fn select_mask64x8(
12003 self,
12004 a: mask64x8<Self>,
12005 b: mask64x8<Self>,
12006 c: mask64x8<Self>,
12007 ) -> mask64x8<Self> {
12008 let (a0, a1) = self.split_mask64x8(a);
12009 let (b0, b1) = self.split_mask64x8(b);
12010 let (c0, c1) = self.split_mask64x8(c);
12011 self.combine_mask64x4(
12012 self.select_mask64x4(a0, b0, c0),
12013 self.select_mask64x4(a1, b1, c1),
12014 )
12015 }
12016 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
12017 #[inline(always)]
12018 fn simd_eq_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask64x8<Self> {
12019 let (a0, a1) = self.split_mask64x8(a);
12020 let (b0, b1) = self.split_mask64x8(b);
12021 self.combine_mask64x4(self.simd_eq_mask64x4(a0, b0), self.simd_eq_mask64x4(a1, b1))
12022 }
12023 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
12024 #[inline(always)]
12025 fn simd_ne_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask64x8<Self> {
12026 self.not_mask64x8(self.simd_eq_mask64x8(a, b))
12027 }
12028 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12029 #[inline(always)]
12030 fn any_true_mask64x8(self, a: mask64x8<Self>) -> bool {
12031 let (a0, a1) = self.split_mask64x8(a);
12032 self.any_true_mask64x4(self.or_mask64x4(a0, a1))
12033 }
12034 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12035 #[inline(always)]
12036 fn all_true_mask64x8(self, a: mask64x8<Self>) -> bool {
12037 let (a0, a1) = self.split_mask64x8(a);
12038 self.all_true_mask64x4(self.and_mask64x4(a0, a1))
12039 }
12040 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12041 #[inline(always)]
12042 fn any_false_mask64x8(self, a: mask64x8<Self>) -> bool {
12043 let (a0, a1) = self.split_mask64x8(a);
12044 self.any_false_mask64x4(self.and_mask64x4(a0, a1))
12045 }
12046 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12047 #[inline(always)]
12048 fn all_false_mask64x8(self, a: mask64x8<Self>) -> bool {
12049 let (a0, a1) = self.split_mask64x8(a);
12050 self.all_false_mask64x4(self.or_mask64x4(a0, a1))
12051 }
12052 #[doc = "Split a vector into two vectors of half the width.\n\nReturns a tuple of (lower half, upper half)."]
12053 fn split_mask64x8(self, a: mask64x8<Self>) -> (mask64x4<Self>, mask64x4<Self>);
12054 #[doc = "Narrow each boolean lane of two masks and concatenate them into one mask of the same logical width, preserving each value.\n\n`a` supplies the lower result lanes and `b` supplies the upper result lanes. Masks constructed from integer lanes other than 0 or -1 have unspecified behavior."]
12055 #[inline(always)]
12056 fn narrow_mask64x8(self, a: mask64x8<Self>, b: mask64x8<Self>) -> mask32x16<Self> {
12057 let (a0, a1) = self.split_mask64x8(a);
12058 let (b0, b1) = self.split_mask64x8(b);
12059 self.combine_mask32x8(self.narrow_mask64x4(a0, a1), self.narrow_mask64x4(b0, b1))
12060 }
12061}
12062pub(crate) mod arch_types {
12063 use crate::transmute::SimdPod;
12064 #[expect(
12065 unnameable_types,
12066 reason = "The native vector types that back a `Simd` implementation are an internal implementation detail, and intentionally kept private"
12067 )]
12068 pub trait ArchTypes: Sized {
12069 type f32x4: Copy + Send + Sync + SimdPod;
12070 type i8x16: Copy + Send + Sync + SimdPod;
12071 type u8x16: Copy + Send + Sync + SimdPod;
12072 type mask8x16: Copy + Send + Sync + SimdPod;
12073 type i16x8: Copy + Send + Sync + SimdPod;
12074 type u16x8: Copy + Send + Sync + SimdPod;
12075 type mask16x8: Copy + Send + Sync + SimdPod;
12076 type i32x4: Copy + Send + Sync + SimdPod;
12077 type u32x4: Copy + Send + Sync + SimdPod;
12078 type mask32x4: Copy + Send + Sync + SimdPod;
12079 type f64x2: Copy + Send + Sync + SimdPod;
12080 type i64x2: Copy + Send + Sync + SimdPod;
12081 type u64x2: Copy + Send + Sync + SimdPod;
12082 type mask64x2: Copy + Send + Sync + SimdPod;
12083 type f32x8: Copy + Send + Sync + SimdPod;
12084 type i8x32: Copy + Send + Sync + SimdPod;
12085 type u8x32: Copy + Send + Sync + SimdPod;
12086 type mask8x32: Copy + Send + Sync + SimdPod;
12087 type i16x16: Copy + Send + Sync + SimdPod;
12088 type u16x16: Copy + Send + Sync + SimdPod;
12089 type mask16x16: Copy + Send + Sync + SimdPod;
12090 type i32x8: Copy + Send + Sync + SimdPod;
12091 type u32x8: Copy + Send + Sync + SimdPod;
12092 type mask32x8: Copy + Send + Sync + SimdPod;
12093 type f64x4: Copy + Send + Sync + SimdPod;
12094 type i64x4: Copy + Send + Sync + SimdPod;
12095 type u64x4: Copy + Send + Sync + SimdPod;
12096 type mask64x4: Copy + Send + Sync + SimdPod;
12097 type f32x16: Copy + Send + Sync + SimdPod;
12098 type i8x64: Copy + Send + Sync + SimdPod;
12099 type u8x64: Copy + Send + Sync + SimdPod;
12100 type mask8x64: Copy + Send + Sync + SimdPod;
12101 type i16x32: Copy + Send + Sync + SimdPod;
12102 type u16x32: Copy + Send + Sync + SimdPod;
12103 type mask16x32: Copy + Send + Sync + SimdPod;
12104 type i32x16: Copy + Send + Sync + SimdPod;
12105 type u32x16: Copy + Send + Sync + SimdPod;
12106 type mask32x16: Copy + Send + Sync + SimdPod;
12107 type f64x8: Copy + Send + Sync + SimdPod;
12108 type i64x8: Copy + Send + Sync + SimdPod;
12109 type u64x8: Copy + Send + Sync + SimdPod;
12110 type mask64x8: Copy + Send + Sync + SimdPod;
12111 #[inline(always)]
12112 fn mask8x16_from_array(self, val: [i8; 16usize]) -> Self::mask8x16 {
12113 crate::transmute::checked_transmute_copy(&val)
12114 }
12115 #[inline(always)]
12116 fn mask8x16_to_array(self, val: Self::mask8x16) -> [i8; 16usize] {
12117 crate::transmute::checked_transmute_copy(&val)
12118 }
12119 #[inline(always)]
12120 fn mask16x8_from_array(self, val: [i16; 8usize]) -> Self::mask16x8 {
12121 crate::transmute::checked_transmute_copy(&val)
12122 }
12123 #[inline(always)]
12124 fn mask16x8_to_array(self, val: Self::mask16x8) -> [i16; 8usize] {
12125 crate::transmute::checked_transmute_copy(&val)
12126 }
12127 #[inline(always)]
12128 fn mask32x4_from_array(self, val: [i32; 4usize]) -> Self::mask32x4 {
12129 crate::transmute::checked_transmute_copy(&val)
12130 }
12131 #[inline(always)]
12132 fn mask32x4_to_array(self, val: Self::mask32x4) -> [i32; 4usize] {
12133 crate::transmute::checked_transmute_copy(&val)
12134 }
12135 #[inline(always)]
12136 fn mask64x2_from_array(self, val: [i64; 2usize]) -> Self::mask64x2 {
12137 crate::transmute::checked_transmute_copy(&val)
12138 }
12139 #[inline(always)]
12140 fn mask64x2_to_array(self, val: Self::mask64x2) -> [i64; 2usize] {
12141 crate::transmute::checked_transmute_copy(&val)
12142 }
12143 #[inline(always)]
12144 fn mask8x32_from_array(self, val: [i8; 32usize]) -> Self::mask8x32 {
12145 crate::transmute::checked_transmute_copy(&val)
12146 }
12147 #[inline(always)]
12148 fn mask8x32_to_array(self, val: Self::mask8x32) -> [i8; 32usize] {
12149 crate::transmute::checked_transmute_copy(&val)
12150 }
12151 #[inline(always)]
12152 fn mask16x16_from_array(self, val: [i16; 16usize]) -> Self::mask16x16 {
12153 crate::transmute::checked_transmute_copy(&val)
12154 }
12155 #[inline(always)]
12156 fn mask16x16_to_array(self, val: Self::mask16x16) -> [i16; 16usize] {
12157 crate::transmute::checked_transmute_copy(&val)
12158 }
12159 #[inline(always)]
12160 fn mask32x8_from_array(self, val: [i32; 8usize]) -> Self::mask32x8 {
12161 crate::transmute::checked_transmute_copy(&val)
12162 }
12163 #[inline(always)]
12164 fn mask32x8_to_array(self, val: Self::mask32x8) -> [i32; 8usize] {
12165 crate::transmute::checked_transmute_copy(&val)
12166 }
12167 #[inline(always)]
12168 fn mask64x4_from_array(self, val: [i64; 4usize]) -> Self::mask64x4 {
12169 crate::transmute::checked_transmute_copy(&val)
12170 }
12171 #[inline(always)]
12172 fn mask64x4_to_array(self, val: Self::mask64x4) -> [i64; 4usize] {
12173 crate::transmute::checked_transmute_copy(&val)
12174 }
12175 #[inline(always)]
12176 fn mask8x64_from_array(self, val: [i8; 64usize]) -> Self::mask8x64 {
12177 crate::transmute::checked_transmute_copy(&val)
12178 }
12179 #[inline(always)]
12180 fn mask8x64_to_array(self, val: Self::mask8x64) -> [i8; 64usize] {
12181 crate::transmute::checked_transmute_copy(&val)
12182 }
12183 #[inline(always)]
12184 fn mask16x32_from_array(self, val: [i16; 32usize]) -> Self::mask16x32 {
12185 crate::transmute::checked_transmute_copy(&val)
12186 }
12187 #[inline(always)]
12188 fn mask16x32_to_array(self, val: Self::mask16x32) -> [i16; 32usize] {
12189 crate::transmute::checked_transmute_copy(&val)
12190 }
12191 #[inline(always)]
12192 fn mask32x16_from_array(self, val: [i32; 16usize]) -> Self::mask32x16 {
12193 crate::transmute::checked_transmute_copy(&val)
12194 }
12195 #[inline(always)]
12196 fn mask32x16_to_array(self, val: Self::mask32x16) -> [i32; 16usize] {
12197 crate::transmute::checked_transmute_copy(&val)
12198 }
12199 #[inline(always)]
12200 fn mask64x8_from_array(self, val: [i64; 8usize]) -> Self::mask64x8 {
12201 crate::transmute::checked_transmute_copy(&val)
12202 }
12203 #[inline(always)]
12204 fn mask64x8_to_array(self, val: Self::mask64x8) -> [i64; 8usize] {
12205 crate::transmute::checked_transmute_copy(&val)
12206 }
12207 }
12208}
12209#[doc = r" Base functionality implemented by all SIMD vectors."]
12210pub trait SimdBase<S: Simd>:
12211 ExtractToken<S = S>
12212 + Copy
12213 + Sync
12214 + Send
12215 + Debug
12216 + 'static
12217 + Seal
12218 + Bytes<Bytes = Self::ByteVector>
12219 + SimdFrom<Self::Element, S>
12220 + SimdFrom<Self::Array, S>
12221 + core::ops::Index<usize, Output = Self::Element>
12222 + core::ops::IndexMut<usize, Output = Self::Element>
12223 + core::ops::Deref<Target = Self::Array>
12224 + core::ops::DerefMut<Target = Self::Array>
12225 + core::ops::Add<Output = Self>
12226 + core::ops::AddAssign
12227 + core::ops::Add<Self::Element, Output = Self>
12228 + core::ops::AddAssign<Self::Element>
12229 + core::ops::Sub<Output = Self>
12230 + core::ops::SubAssign
12231 + core::ops::Sub<Self::Element, Output = Self>
12232 + core::ops::SubAssign<Self::Element>
12233 + core::ops::Mul<Output = Self>
12234 + core::ops::MulAssign
12235 + core::ops::Mul<Self::Element, Output = Self>
12236 + core::ops::MulAssign<Self::Element>
12237{
12238 #[doc = r" The type of this vector's elements."]
12239 type Element: SimdElement;
12240 #[doc = r" The same-width SIMD vector of `u8` lanes used as the byte representation."]
12241 #[doc = r""]
12242 #[doc = r" This is the same type as [`Bytes::Bytes`]."]
12243 #[doc = r""]
12244 #[doc = r" This associated type exists because expressing the `SimdBase` bound directly on"]
12245 #[doc = r" [`Bytes::Bytes`] creates a trait-solver cycle. The `Bytes<Bytes ="]
12246 #[doc = r" Self::ByteVector>` supertrait bound ensures that the two types are identical."]
12247 #[doc = r" Generic callers should normally use [`Bytes::Bytes`], not this associated type."]
12248 type ByteVector: SimdBase<S, Element = u8, ByteVector = Self::ByteVector>;
12249 #[doc = r" This vector type's lane count. This is useful when you're"]
12250 #[doc = r" working with a native-width vector (e.g. [`Simd::f32s`]) and"]
12251 #[doc = r" want to process data in native-width chunks."]
12252 const LEN: usize;
12253 #[doc = r" A SIMD vector mask with the same number of logical lanes."]
12254 #[doc = r""]
12255 #[doc = r" Masks intentionally do not implement [`SimdBase`]. SSE, NEON, WASM, and the"]
12256 #[doc = r" fallback backend currently store masks as all-zero/all-one integer vectors, but"]
12257 #[doc = r" AVX-512/RVV/SVE-style targets use compact predicate registers instead."]
12258 type Mask: SimdMask<S, Element = <Self::Element as SimdElement>::Mask> + Select<Self>;
12259 #[doc = r" A 128-bit SIMD vector of the same scalar type."]
12260 type Block: SimdBase<S, Element = Self::Element, Block = Self::Block>;
12261 #[doc = r" The array type that this vector type corresponds to, which will"]
12262 #[doc = r" always be `[Self::Element; Self::LEN]`. It has the same layout as"]
12263 #[doc = r" this vector type, but likely has a lower alignment."]
12264 type Array: Copy
12265 + Debug
12266 + IntoIterator<Item = Self::Element>
12267 + AsRef<[Self::Element]>
12268 + AsMut<[Self::Element]>
12269 + From<Self>;
12270 fn as_slice(&self) -> &[Self::Element];
12271 fn as_mut_slice(&mut self) -> &mut [Self::Element];
12272 #[doc = r" Create a SIMD vector from a slice."]
12273 #[doc = r""]
12274 #[doc = r" The slice must be exactly the size of the SIMD vector."]
12275 fn from_slice(simd: S, slice: &[Self::Element]) -> Self;
12276 #[doc = r" Store a SIMD vector into a slice."]
12277 #[doc = r""]
12278 #[doc = r" The slice must be exactly the size of the SIMD vector."]
12279 fn store_slice(&self, slice: &mut [Self::Element]);
12280 #[doc = r" Create a SIMD vector from its corresponding lane array."]
12281 #[inline(always)]
12282 fn load_array(simd: S, val: Self::Array) -> Self {
12283 Self::simd_from(simd, val)
12284 }
12285 #[doc = r" Create a SIMD vector from a reference to its corresponding lane array."]
12286 #[inline(always)]
12287 fn load_array_ref(simd: S, val: &Self::Array) -> Self {
12288 Self::load_array(simd, *val)
12289 }
12290 #[doc = r" Convert this SIMD vector to its corresponding lane array."]
12291 #[inline(always)]
12292 fn to_array(self) -> Self::Array {
12293 *self
12294 }
12295 #[doc = r" Project this SIMD vector reference to its corresponding lane array reference."]
12296 #[inline(always)]
12297 fn as_array(&self) -> &Self::Array {
12298 self
12299 }
12300 #[doc = r" Project this mutable SIMD vector reference to its corresponding mutable lane array reference."]
12301 #[inline(always)]
12302 fn as_mut_array(&mut self) -> &mut Self::Array {
12303 self
12304 }
12305 #[doc = r" Store this SIMD vector into its corresponding lane array."]
12306 #[inline(always)]
12307 fn store_array(self, dest: &mut Self::Array) {
12308 *dest = self.to_array();
12309 }
12310 #[doc = r" Create a SIMD vector from a 128-bit vector of the same scalar"]
12311 #[doc = r" type, repeated."]
12312 fn block_splat(block: Self::Block) -> Self;
12313 #[doc = r" Create a SIMD vector where each element is produced by"]
12314 #[doc = r" calling `f` with that element's lane index (from 0 to"]
12315 #[doc = r" [`SimdBase::LEN`] - 1)."]
12316 fn from_fn(simd: S, f: impl FnMut(usize) -> Self::Element) -> Self;
12317 #[doc = r" Rotate the vector elements to the left by `OFFSET`."]
12318 #[doc = r""]
12319 #[doc = r" If `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
12320 #[inline(always)]
12321 fn rotate_elements_left<const OFFSET: usize>(self) -> Self {
12322 match OFFSET % Self::LEN {
12323 0 => self.slide::<0>(self),
12324 1 => self.slide::<1>(self),
12325 2 => self.slide::<2>(self),
12326 3 => self.slide::<3>(self),
12327 4 => self.slide::<4>(self),
12328 5 => self.slide::<5>(self),
12329 6 => self.slide::<6>(self),
12330 7 => self.slide::<7>(self),
12331 8 => self.slide::<8>(self),
12332 9 => self.slide::<9>(self),
12333 10 => self.slide::<10>(self),
12334 11 => self.slide::<11>(self),
12335 12 => self.slide::<12>(self),
12336 13 => self.slide::<13>(self),
12337 14 => self.slide::<14>(self),
12338 15 => self.slide::<15>(self),
12339 16 => self.slide::<16>(self),
12340 17 => self.slide::<17>(self),
12341 18 => self.slide::<18>(self),
12342 19 => self.slide::<19>(self),
12343 20 => self.slide::<20>(self),
12344 21 => self.slide::<21>(self),
12345 22 => self.slide::<22>(self),
12346 23 => self.slide::<23>(self),
12347 24 => self.slide::<24>(self),
12348 25 => self.slide::<25>(self),
12349 26 => self.slide::<26>(self),
12350 27 => self.slide::<27>(self),
12351 28 => self.slide::<28>(self),
12352 29 => self.slide::<29>(self),
12353 30 => self.slide::<30>(self),
12354 31 => self.slide::<31>(self),
12355 32 => self.slide::<32>(self),
12356 33 => self.slide::<33>(self),
12357 34 => self.slide::<34>(self),
12358 35 => self.slide::<35>(self),
12359 36 => self.slide::<36>(self),
12360 37 => self.slide::<37>(self),
12361 38 => self.slide::<38>(self),
12362 39 => self.slide::<39>(self),
12363 40 => self.slide::<40>(self),
12364 41 => self.slide::<41>(self),
12365 42 => self.slide::<42>(self),
12366 43 => self.slide::<43>(self),
12367 44 => self.slide::<44>(self),
12368 45 => self.slide::<45>(self),
12369 46 => self.slide::<46>(self),
12370 47 => self.slide::<47>(self),
12371 48 => self.slide::<48>(self),
12372 49 => self.slide::<49>(self),
12373 50 => self.slide::<50>(self),
12374 51 => self.slide::<51>(self),
12375 52 => self.slide::<52>(self),
12376 53 => self.slide::<53>(self),
12377 54 => self.slide::<54>(self),
12378 55 => self.slide::<55>(self),
12379 56 => self.slide::<56>(self),
12380 57 => self.slide::<57>(self),
12381 58 => self.slide::<58>(self),
12382 59 => self.slide::<59>(self),
12383 60 => self.slide::<60>(self),
12384 61 => self.slide::<61>(self),
12385 62 => self.slide::<62>(self),
12386 63 => self.slide::<63>(self),
12387 _ => unreachable!(),
12388 }
12389 }
12390 #[doc = r" Rotate the vector elements to the right by `OFFSET`."]
12391 #[doc = r""]
12392 #[doc = r" If `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
12393 #[inline(always)]
12394 fn rotate_elements_right<const OFFSET: usize>(self) -> Self {
12395 match Self::LEN - OFFSET % Self::LEN {
12396 1 => self.slide::<1>(self),
12397 2 => self.slide::<2>(self),
12398 3 => self.slide::<3>(self),
12399 4 => self.slide::<4>(self),
12400 5 => self.slide::<5>(self),
12401 6 => self.slide::<6>(self),
12402 7 => self.slide::<7>(self),
12403 8 => self.slide::<8>(self),
12404 9 => self.slide::<9>(self),
12405 10 => self.slide::<10>(self),
12406 11 => self.slide::<11>(self),
12407 12 => self.slide::<12>(self),
12408 13 => self.slide::<13>(self),
12409 14 => self.slide::<14>(self),
12410 15 => self.slide::<15>(self),
12411 16 => self.slide::<16>(self),
12412 17 => self.slide::<17>(self),
12413 18 => self.slide::<18>(self),
12414 19 => self.slide::<19>(self),
12415 20 => self.slide::<20>(self),
12416 21 => self.slide::<21>(self),
12417 22 => self.slide::<22>(self),
12418 23 => self.slide::<23>(self),
12419 24 => self.slide::<24>(self),
12420 25 => self.slide::<25>(self),
12421 26 => self.slide::<26>(self),
12422 27 => self.slide::<27>(self),
12423 28 => self.slide::<28>(self),
12424 29 => self.slide::<29>(self),
12425 30 => self.slide::<30>(self),
12426 31 => self.slide::<31>(self),
12427 32 => self.slide::<32>(self),
12428 33 => self.slide::<33>(self),
12429 34 => self.slide::<34>(self),
12430 35 => self.slide::<35>(self),
12431 36 => self.slide::<36>(self),
12432 37 => self.slide::<37>(self),
12433 38 => self.slide::<38>(self),
12434 39 => self.slide::<39>(self),
12435 40 => self.slide::<40>(self),
12436 41 => self.slide::<41>(self),
12437 42 => self.slide::<42>(self),
12438 43 => self.slide::<43>(self),
12439 44 => self.slide::<44>(self),
12440 45 => self.slide::<45>(self),
12441 46 => self.slide::<46>(self),
12442 47 => self.slide::<47>(self),
12443 48 => self.slide::<48>(self),
12444 49 => self.slide::<49>(self),
12445 50 => self.slide::<50>(self),
12446 51 => self.slide::<51>(self),
12447 52 => self.slide::<52>(self),
12448 53 => self.slide::<53>(self),
12449 54 => self.slide::<54>(self),
12450 55 => self.slide::<55>(self),
12451 56 => self.slide::<56>(self),
12452 57 => self.slide::<57>(self),
12453 58 => self.slide::<58>(self),
12454 59 => self.slide::<59>(self),
12455 60 => self.slide::<60>(self),
12456 61 => self.slide::<61>(self),
12457 62 => self.slide::<62>(self),
12458 63 => self.slide::<63>(self),
12459 64 => self.slide::<64>(self),
12460 _ => unreachable!(),
12461 }
12462 }
12463 #[doc = r" Shift the vector elements to the left by `OFFSET`, filling in with `padding` from the right."]
12464 #[doc = r""]
12465 #[doc = r" If `OFFSET` is greater than or equal to `Self::LEN`, all lanes are filled with `padding`."]
12466 #[inline(always)]
12467 fn shift_elements_left<const OFFSET: usize>(self, padding: Self::Element) -> Self {
12468 match OFFSET.min(Self::LEN) {
12469 0 => self.slide::<0>(padding),
12470 1 => self.slide::<1>(padding),
12471 2 => self.slide::<2>(padding),
12472 3 => self.slide::<3>(padding),
12473 4 => self.slide::<4>(padding),
12474 5 => self.slide::<5>(padding),
12475 6 => self.slide::<6>(padding),
12476 7 => self.slide::<7>(padding),
12477 8 => self.slide::<8>(padding),
12478 9 => self.slide::<9>(padding),
12479 10 => self.slide::<10>(padding),
12480 11 => self.slide::<11>(padding),
12481 12 => self.slide::<12>(padding),
12482 13 => self.slide::<13>(padding),
12483 14 => self.slide::<14>(padding),
12484 15 => self.slide::<15>(padding),
12485 16 => self.slide::<16>(padding),
12486 17 => self.slide::<17>(padding),
12487 18 => self.slide::<18>(padding),
12488 19 => self.slide::<19>(padding),
12489 20 => self.slide::<20>(padding),
12490 21 => self.slide::<21>(padding),
12491 22 => self.slide::<22>(padding),
12492 23 => self.slide::<23>(padding),
12493 24 => self.slide::<24>(padding),
12494 25 => self.slide::<25>(padding),
12495 26 => self.slide::<26>(padding),
12496 27 => self.slide::<27>(padding),
12497 28 => self.slide::<28>(padding),
12498 29 => self.slide::<29>(padding),
12499 30 => self.slide::<30>(padding),
12500 31 => self.slide::<31>(padding),
12501 32 => self.slide::<32>(padding),
12502 33 => self.slide::<33>(padding),
12503 34 => self.slide::<34>(padding),
12504 35 => self.slide::<35>(padding),
12505 36 => self.slide::<36>(padding),
12506 37 => self.slide::<37>(padding),
12507 38 => self.slide::<38>(padding),
12508 39 => self.slide::<39>(padding),
12509 40 => self.slide::<40>(padding),
12510 41 => self.slide::<41>(padding),
12511 42 => self.slide::<42>(padding),
12512 43 => self.slide::<43>(padding),
12513 44 => self.slide::<44>(padding),
12514 45 => self.slide::<45>(padding),
12515 46 => self.slide::<46>(padding),
12516 47 => self.slide::<47>(padding),
12517 48 => self.slide::<48>(padding),
12518 49 => self.slide::<49>(padding),
12519 50 => self.slide::<50>(padding),
12520 51 => self.slide::<51>(padding),
12521 52 => self.slide::<52>(padding),
12522 53 => self.slide::<53>(padding),
12523 54 => self.slide::<54>(padding),
12524 55 => self.slide::<55>(padding),
12525 56 => self.slide::<56>(padding),
12526 57 => self.slide::<57>(padding),
12527 58 => self.slide::<58>(padding),
12528 59 => self.slide::<59>(padding),
12529 60 => self.slide::<60>(padding),
12530 61 => self.slide::<61>(padding),
12531 62 => self.slide::<62>(padding),
12532 63 => self.slide::<63>(padding),
12533 64 => self.slide::<64>(padding),
12534 _ => unreachable!(),
12535 }
12536 }
12537 #[doc = r" Shift the vector elements to the right by `OFFSET`, filling in with `padding` from the left."]
12538 #[doc = r""]
12539 #[doc = r" If `OFFSET` is greater than or equal to `Self::LEN`, all lanes are filled with `padding`."]
12540 #[inline(always)]
12541 fn shift_elements_right<const OFFSET: usize>(self, padding: Self::Element) -> Self {
12542 let padding = Self::splat(self.token(), padding);
12543 match Self::LEN.saturating_sub(OFFSET) {
12544 0 => padding.slide::<0>(self),
12545 1 => padding.slide::<1>(self),
12546 2 => padding.slide::<2>(self),
12547 3 => padding.slide::<3>(self),
12548 4 => padding.slide::<4>(self),
12549 5 => padding.slide::<5>(self),
12550 6 => padding.slide::<6>(self),
12551 7 => padding.slide::<7>(self),
12552 8 => padding.slide::<8>(self),
12553 9 => padding.slide::<9>(self),
12554 10 => padding.slide::<10>(self),
12555 11 => padding.slide::<11>(self),
12556 12 => padding.slide::<12>(self),
12557 13 => padding.slide::<13>(self),
12558 14 => padding.slide::<14>(self),
12559 15 => padding.slide::<15>(self),
12560 16 => padding.slide::<16>(self),
12561 17 => padding.slide::<17>(self),
12562 18 => padding.slide::<18>(self),
12563 19 => padding.slide::<19>(self),
12564 20 => padding.slide::<20>(self),
12565 21 => padding.slide::<21>(self),
12566 22 => padding.slide::<22>(self),
12567 23 => padding.slide::<23>(self),
12568 24 => padding.slide::<24>(self),
12569 25 => padding.slide::<25>(self),
12570 26 => padding.slide::<26>(self),
12571 27 => padding.slide::<27>(self),
12572 28 => padding.slide::<28>(self),
12573 29 => padding.slide::<29>(self),
12574 30 => padding.slide::<30>(self),
12575 31 => padding.slide::<31>(self),
12576 32 => padding.slide::<32>(self),
12577 33 => padding.slide::<33>(self),
12578 34 => padding.slide::<34>(self),
12579 35 => padding.slide::<35>(self),
12580 36 => padding.slide::<36>(self),
12581 37 => padding.slide::<37>(self),
12582 38 => padding.slide::<38>(self),
12583 39 => padding.slide::<39>(self),
12584 40 => padding.slide::<40>(self),
12585 41 => padding.slide::<41>(self),
12586 42 => padding.slide::<42>(self),
12587 43 => padding.slide::<43>(self),
12588 44 => padding.slide::<44>(self),
12589 45 => padding.slide::<45>(self),
12590 46 => padding.slide::<46>(self),
12591 47 => padding.slide::<47>(self),
12592 48 => padding.slide::<48>(self),
12593 49 => padding.slide::<49>(self),
12594 50 => padding.slide::<50>(self),
12595 51 => padding.slide::<51>(self),
12596 52 => padding.slide::<52>(self),
12597 53 => padding.slide::<53>(self),
12598 54 => padding.slide::<54>(self),
12599 55 => padding.slide::<55>(self),
12600 56 => padding.slide::<56>(self),
12601 57 => padding.slide::<57>(self),
12602 58 => padding.slide::<58>(self),
12603 59 => padding.slide::<59>(self),
12604 60 => padding.slide::<60>(self),
12605 61 => padding.slide::<61>(self),
12606 62 => padding.slide::<62>(self),
12607 63 => padding.slide::<63>(self),
12608 64 => padding.slide::<64>(self),
12609 _ => unreachable!(),
12610 }
12611 }
12612 #[doc = "Compute the absolute value of each element.\n\nUnsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches `i32::abs()`.\n\nFor floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero."]
12613 fn abs(self) -> Self;
12614 #[doc = "Create a SIMD vector with all elements set to the given value."]
12615 fn splat(simd: S, val: Self::Element) -> Self;
12616 #[doc = "Reverse the order of the vector's elements."]
12617 fn reverse(self) -> Self;
12618 #[doc = "Concatenate `[self, rhs]` and extract `Self::LEN` elements starting at index `SHIFT`.\n\n`SHIFT` must be within [0, `Self::LEN`].\n\nThis can be used to implement a \"shift items\" operation by providing all zeroes as one operand. For a left shift, the right-hand side should be all zeroes. For a right shift by `M` items, the left-hand side should be all zeroes, and the shift amount will be `Self::LEN - M`.\n\nThis can also be used to rotate items within a vector by providing the same vector as both operands.\n\n```text\n\nslide::<1>([a b c d], [e f g h]) == [b c d e]\n\n```"]
12619 fn slide<const SHIFT: usize>(self, rhs: impl SimdInto<Self, S>) -> Self;
12620 #[doc = "Like `slide`, but operates independently on each 128-bit block."]
12621 fn slide_within_blocks<const SHIFT: usize>(self, rhs: impl SimdInto<Self, S>) -> Self;
12622 #[doc = "Dynamically swizzle this vector's bytes independently within each 128-bit block.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values `0..=15` select the corresponding byte from the same 128-bit input block.\n\nOut-of-range index behavior varies by platform."]
12623 fn swizzle_dyn_within_blocks(self, indices: impl SimdInto<Self::Bytes, S>) -> Self;
12624 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::swizzle_dyn_precise`] if out-of-range indices must produce zero."]
12625 fn swizzle_dyn(self, indices: impl SimdInto<Self::Bytes, S>) -> Self;
12626 #[doc = "Dynamically swizzle this vector's bytes across the whole vector.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the vector's byte length select the corresponding byte from the input vector. Out-of-range indices produce zero."]
12627 fn swizzle_dyn_precise(self, indices: impl SimdInto<Self::Bytes, S>) -> Self;
12628 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices safely produce implementation-defined byte values.\n\nUse [`SimdBase::concat_swizzle_dyn_precise`] if out-of-range indices must produce zero."]
12629 fn concat_swizzle_dyn(
12630 self,
12631 rhs: impl SimdInto<Self, S>,
12632 indices: impl SimdInto<Self::Bytes, S>,
12633 ) -> Self;
12634 #[doc = "Dynamically select bytes from the concatenation of this vector and `rhs`.\n\nThe `indices` operand is a same-width byte vector. For each output byte, index values within the concatenated vectors' byte length select the corresponding byte: the first vector comes first, followed by `rhs`. Out-of-range indices produce zero."]
12635 fn concat_swizzle_dyn_precise(
12636 self,
12637 rhs: impl SimdInto<Self, S>,
12638 indices: impl SimdInto<Self::Bytes, S>,
12639 ) -> Self;
12640 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\nThis is equivalent to [`SimdBase::compress_merge`] with a zeroed merge vector."]
12641 fn compress(self, mask: Self::Mask) -> Self;
12642 #[doc = "Compact the elements selected by `mask` into consecutive low lanes, preserving their order.\n\nLanes above the number of selected elements retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[k] = self[i];\n k += 1;\n }\n}\nreturn result;\n```"]
12643 fn compress_merge(self, mask: Self::Mask, merge: impl SimdInto<Self, S>) -> Self;
12644 #[doc = "Expand consecutive low elements from `self` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes are zero (positive zero for floats).\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros..\n\nThis is equivalent to [`SimdBase::expand_merge`] with a zeroed merge vector."]
12645 fn expand(self, mask: Self::Mask) -> Self;
12646 #[doc = "Expand consecutive low elements from `self` into the lanes selected by `mask`, preserving their order.\n\nUnselected lanes retain the corresponding values from `merge`.\n\nElements are moved without changing their bits, including floating-point NaN payloads and signed zeros.\n\n## Pseudo code\n\n```ignore\nlet mut result = merge;\nlet mut k = 0;\nfor i in 0..LEN {\n if mask[i] {\n result[i] = self[k];\n k += 1;\n }\n}\nreturn result;\n```"]
12647 fn expand_merge(self, mask: Self::Mask, merge: impl SimdInto<Self, S>) -> Self;
12648 #[doc = "Return the maximum element in the vector. Integer vectors always return the exact maximum.\n\nFor floating-point vectors with no NaNs, this returns the true maximum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true maximum. See `reduce_max_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
12649 fn reduce_max(self) -> Self::Element;
12650 #[doc = "Return the minimum element in the vector. Integer vectors always return the exact minimum.\n\nFor floating-point vectors with no NaNs, this returns the true minimum. If any lane is NaN, the entire result is implementation-defined: it may be NaN or a numeric lane that is not the true minimum. See `reduce_min_precise` for a version that ignores quiet NaNs.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned."]
12651 fn reduce_min(self) -> Self::Element;
12652 #[doc = "Return the maximum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_max`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true maximum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true maximum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
12653 fn reduce_max_precise(self) -> Self::Element;
12654 #[doc = "Return the minimum element in the vector, ignoring quiet NaNs.\n\nFor integer vectors, this operation is the same as `reduce_min`.\n\nFor floating-point vectors, quiet NaNs are ignored. If there is at least one numeric lane, this returns the true minimum of the numeric lanes. If all lanes are quiet NaNs, this returns NaN, with an unspecified payload and sign.\n\nIf the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.\n\nIf any lane is a *signaling* NaN, the result is fully non-deterministic: it may be NaN or a numeric lane and is not guaranteed to be the true minimum.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
12655 fn reduce_min_precise(self) -> Self::Element;
12656 #[doc = "Return the sum of all elements in the vector. Integer addition wraps.\n\n# Floating-point accuracy\n\nFor an input vector with N lanes, any lane's contribution may be rounded at most `log2(N)` times.\n\nFor a fixed vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nBecause floating-point addition is not associative, separately reducing smaller vectors and then adding their results can differ from reducing their combined wider vector. See [Taming Floating-Point Sums](https://orlp.net/blog/taming-float-sums/) for more information and for other summation algorithms, including exact summation without accumulated rounding error. In that article's terms, our method has the precision properties of pairwise summation, although the exact pairing of values is different."]
12657 fn reduce_sum(self) -> Self::Element;
12658 #[doc = "Return the product of all elements in the vector. Integer multiplication wraps.\n\n# Floating-point behavior\n\nFor a vector with N elements, this operation performs N-1 roundings.\n\nFor a given vector type and lane count, this operation produces the same result on all platforms and backends down to the bit pattern, except that when the result is NaN, its exact bit pattern is unspecified. This fixed-width guarantee does not make code using native-width associated types such as `S::f32s` independent of the selected SIMD level, because their lane counts can differ.\n\nThe result of this operation is **not** bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.\n\nIntermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.\n\nBecause floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector."]
12659 fn reduce_product(self) -> Self::Element;
12660 #[doc = "Return the element-wise maximum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
12661 fn max(self, rhs: impl SimdInto<Self, S>) -> Self;
12662 #[doc = "Return the element-wise minimum of two vectors.\n\nFor floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one."]
12663 fn min(self, rhs: impl SimdInto<Self, S>) -> Self;
12664 #[doc = "Return the element-wise maximum of two vectors.\n\nFor integer vectors, this operation is the same as `max`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
12665 fn max_precise(self, rhs: impl SimdInto<Self, S>) -> Self;
12666 #[doc = "Return the element-wise minimum of two vectors.\n\nFor integer vectors, this operation is the same as `min`.\n\nFor floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\nIf a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\nSignaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them."]
12667 fn min_precise(self, rhs: impl SimdInto<Self, S>) -> Self;
12668 #[doc = "Clamp each element to the interval `[min, max]`.\n\nIf `min > max`, or `min` or `max` are NaN, the result is implementation-defined for that lane.\n\nIf `self` is NaN, the result is an implementation-defined non-deterministic NaN value. I.e. the result of the lane will be a NaN value but its exact bit pattern is not specified.\n\nIf one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n# Panics\nPanics with debug assertions if `min > max` for any element or any element of `min` or `max` is NaN."]
12669 fn clamp(self, min: impl SimdInto<Self, S>, max: impl SimdInto<Self, S>) -> Self;
12670 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
12671 fn simd_eq(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12672 #[doc = "Compare two vectors element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nFor floating-point vectors, this follows Rust's `!=` semantics: a lane is true if either operand is NaN, including when both are NaN. Positive and negative zero compare equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
12673 fn simd_ne(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12674 #[doc = "Compare two vectors element-wise for less than.\n\nReturns a mask where each logical lane is true if `self` is less than `rhs`, and false if not."]
12675 fn simd_lt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12676 #[doc = "Compare two vectors element-wise for less than or equal.\n\nReturns a mask where each logical lane is true if `self` is less than or equal to `rhs`, and false if not."]
12677 fn simd_le(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12678 #[doc = "Compare two vectors element-wise for greater than or equal.\n\nReturns a mask where each logical lane is true if `self` is greater than or equal to `rhs`, and false if not."]
12679 fn simd_ge(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12680 #[doc = "Compare two vectors element-wise for greater than.\n\nReturns a mask where each logical lane is true if `self` is greater than `rhs`, and false if not."]
12681 fn simd_gt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
12682 #[doc = "Interleave the lower half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, b0, a1, b1]`.\n\n**Note:** This operation is only useful if you need to discard elements `a2, a3, b2, b3`.\n For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
12683 fn zip_low(self, rhs: impl SimdInto<Self, S>) -> Self;
12684 #[doc = "Interleave the upper half elements of two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a2, b2, a3, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a1, b0, b1`.For fully interleaving two vectors prefer `interleave`,\n which is faster than `zip_low` followed by `zip_high` on some platforms."]
12685 fn zip_high(self, rhs: impl SimdInto<Self, S>) -> Self;
12686 #[doc = "Extract even-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a0, a2, b0, b2]`.\n\n**Note:** This operation is only useful if you need to discard elements `a1, a3, b1, b3`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
12687 fn unzip_low(self, rhs: impl SimdInto<Self, S>) -> Self;
12688 #[doc = "Extract odd-indexed elements from two vectors.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `[a1, a3, b1, b3]`.\n\n**Note:** This operation is only useful if you need to discard elements `a0, a2, b0, b2`.For fully deinterleaving two vectors prefer `deinterleave`,\n which is faster than `unzip_low` followed by `unzip_high` on some platforms."]
12689 fn unzip_high(self, rhs: impl SimdInto<Self, S>) -> Self;
12690 #[doc = "Interleave two vectors.\n\nThe resulting vectors contain elements taken alternately from `self` and `rhs`, first filling the first result, and then the second.\n\nThe reverse of this operation is `deinterleave`.\n\nFor vectors `[a0, a1, a2, a3]` and `[b0, b1, b2, b3]`, returns `([a0, b0, a1, b1], [a2, b2, a3, b3])`."]
12691 fn interleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self);
12692 #[doc = "Deinterleave two vectors.\n\nThe first result contains all even-indexed elements from `self` followed by all even-indexed elements from `rhs`. The second result contains all odd-indexed elements from `self` followed by all odd-indexed elements from `rhs`.\n\nThe reverse of this operation is `interleave`.\n\nFor vectors `[a0, b0, a1, b1]` and `[a2, b2, a3, b3]`, returns `([a0, a1, a2, a3], [b0, b1, b2, b3])`."]
12693 fn deinterleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self);
12694}
12695#[doc = r" Functionality implemented by floating-point SIMD vectors."]
12696pub trait SimdFloat<S: Simd>:
12697 SimdBase<S, Element: SimdFloatElement>
12698 + Seal
12699 + core::ops::Neg<Output = Self>
12700 + core::ops::Div<Output = Self>
12701 + core::ops::DivAssign
12702 + core::ops::Div<Self::Element, Output = Self>
12703 + core::ops::DivAssign<Self::Element>
12704{
12705 #[doc = r" Bit representation of this SIMD float vector type."]
12706 type Bits: SimdInt<
12707 S,
12708 Element = <Self::Element as SimdFloatElement>::Bits,
12709 ByteVector = Self::ByteVector,
12710 >;
12711 #[doc = r" Raw transmutation to an unsigned integer vector type with the same size and number of elements."]
12712 #[doc = r""]
12713 #[doc = r" This is analogous to [`f32::to_bits`] and [`f64::to_bits`]."]
12714 fn to_bits(self) -> Self::Bits {
12715 self.bitcast()
12716 }
12717 #[doc = r" Raw transmutation from an unsigned integer vector type with the same size and number of elements."]
12718 #[doc = r""]
12719 #[doc = r" This is analogous to [`f32::from_bits`] and [`f64::from_bits`]."]
12720 fn from_bits(bits: Self::Bits) -> Self {
12721 bits.bitcast()
12722 }
12723 #[doc = r" Convert this floating-point type to an integer. This is a convenience method that"]
12724 #[doc = r" delegates to [`SimdCvtTruncate::truncate_from`], and can only be called if there"]
12725 #[doc = r" actually exists a target type of the same bit width (`u32`/`i32` for `f32`, or"]
12726 #[doc = r" `u64`/`i64` for `f64`)."]
12727 #[doc = r""]
12728 #[doc = r" For more information about the semantics of this specific conversion, see the"]
12729 #[doc = r" concrete `SimdCvtTruncate` implementations for integer types."]
12730 #[inline(always)]
12731 fn to_int<T: SimdCvtTruncate<Self>>(self) -> T {
12732 T::truncate_from(self)
12733 }
12734 #[doc = r" Convert this floating-point type to an integer, saturating on overflow and returning"]
12735 #[doc = r" 0 for NaN. This is a convenience method that delegates to"]
12736 #[doc = r" [`SimdCvtTruncate::truncate_from_precise`], and can only be called if there actually"]
12737 #[doc = r" exists a target type of the same bit width (`u32`/`i32` for `f32`, or `u64`/`i64`"]
12738 #[doc = r" for `f64`)."]
12739 #[doc = r""]
12740 #[doc = r" For more information about the semantics of this specific conversion, see the"]
12741 #[doc = r" concrete `SimdCvtTruncate` implementations for integer types."]
12742 #[inline(always)]
12743 fn to_int_precise<T: SimdCvtTruncate<Self>>(self) -> T {
12744 T::truncate_from_precise(self)
12745 }
12746 #[doc = "Compute the square root of each element.\n\nNegative elements other than `-0.0` will become NaN."]
12747 fn sqrt(self) -> Self;
12748 #[doc = "Compute an approximate reciprocal (`1. / x`) for each element.\n\nThis uses a fast hardware estimate where available, and falls back to exact division otherwise.\n\nOn x86 for `f32`, this has a relative error less than `1.5 × 2^-12`. On `AArch64` (`f32` and `f64`), this has a relative error less than `2^-8`. The precision of this operation may change as new platform support is added."]
12749 fn approximate_recip(self) -> Self;
12750 #[doc = "Return a vector with the magnitude of `self` and the sign of `rhs` for each element.\n\nThis operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit."]
12751 fn copysign(self, rhs: impl SimdInto<Self, S>) -> Self;
12752 #[doc = "Compute `(self * op1) + op2` (fused multiply-add) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by an add, which will result in two rounding errors."]
12753 fn mul_add(self, op1: impl SimdInto<Self, S>, op2: impl SimdInto<Self, S>) -> Self;
12754 #[doc = "Compute `(self * op1) + op2` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-plus-add rounded once to the element type. This may be substantially slower than `mul_add` on platforms without fused multiply-add instructions, including WebAssembly.\n\n# Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
12755 fn mul_add_precise(self, op1: impl SimdInto<Self, S>, op2: impl SimdInto<Self, S>) -> Self;
12756 #[doc = "Compute `(self * op1) - op2` (fused multiply-subtract) for each element.\n\nDepending on platform support, the result may be computed with only one rounding error, or may be implemented as a regular multiply followed by a subtract, which will result in two rounding errors."]
12757 fn mul_sub(self, op1: impl SimdInto<Self, S>, op2: impl SimdInto<Self, S>) -> Self;
12758 #[doc = "Compute `(self * op1) - op2` for each element, with a single rounding at the end.\n\nThe result is the infinite-precision product-minus-subtrahend rounded once to the element type. This may be substantially slower than `mul_sub` on platforms without fused multiply-add instructions, including WebAssembly.\n # Precision guarantees\n\nThis function is **not** susceptible to [the bug](https://github.com/rust-lang/compiler-builtins/issues/1262) in Rust standard library and in musl libc that causes incorrect rounding for near-zero values on CPUs without hardware support for this operation.\n\nOn the tier-2 i586-* targets, this function is correct if and only if SSE2 is available on the CPU.\n\nThe exact `NaN` payloads as well as signaling `NaN`s are not preserved."]
12759 fn mul_sub_precise(self, op1: impl SimdInto<Self, S>, op2: impl SimdInto<Self, S>) -> Self;
12760 #[doc = "Return the largest integer less than or equal to each element, that is, round towards negative infinity."]
12761 fn floor(self) -> Self;
12762 #[doc = "Return the smallest integer greater than or equal to each element, that is, round towards positive infinity."]
12763 fn ceil(self) -> Self;
12764 #[doc = "Round each element to the nearest integer, with ties rounding to the nearest even integer."]
12765 fn round_ties_even(self) -> Self;
12766 #[doc = "Round each element to the nearest integer, with ties rounding away from zero.\n\n## Performance considerations\n\nOnly `AArch64` has native instructions for this operation. `round` has to be emulated on all other platforms which is around 2-4x slower than `round_ties_even`. Prefer using [`round_ties_even`](SimdFloat::round_ties_even) if possible."]
12767 fn round(self) -> Self;
12768 #[doc = "Return the fractional part of each element.\n\nThis is equivalent to `self - self.trunc()`."]
12769 fn fract(self) -> Self;
12770 #[doc = "Return the integer part of each element, rounding towards zero."]
12771 fn trunc(self) -> Self;
12772 #[doc = "Converts radians to degrees.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
12773 fn to_degrees(self) -> Self;
12774 #[doc = "Converts degrees to radians.\n\nThe precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next."]
12775 fn to_radians(self) -> Self;
12776 #[doc = "Return a mask indicating which elements are NaN."]
12777 fn is_nan(self) -> Self::Mask;
12778 #[doc = "Return a mask indicating which elements are positive or negative infinite."]
12779 fn is_infinite(self) -> Self::Mask;
12780 #[doc = "Return a mask indicating which elements are neither infinite nor NaN."]
12781 fn is_finite(self) -> Self::Mask;
12782 #[doc = "Return a mask indicating which elements are subnormal.\n\nThis classifies the stored bit pattern, even when floating-point operations treat subnormals as zero."]
12783 fn is_subnormal(self) -> Self::Mask;
12784 #[doc = "Return a mask indicating which elements are neither zero, infinite, subnormal, or NaN."]
12785 fn is_normal(self) -> Self::Mask;
12786 #[doc = "Return a mask indicating which elements have a positive sign, including `+0.0`, NaNs with positive sign bit and positive infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_positive`] for details."]
12787 fn is_sign_positive(self) -> Self::Mask;
12788 #[doc = "Return a mask indicating which elements have a negative sign, including `-0.0`, NaNs with negative sign bit and negative infinity.\n\nNaN inputs may produce an unexpected or non-portable result, see [`f32::is_sign_negative`] for details."]
12789 fn is_sign_negative(self) -> Self::Mask;
12790}
12791#[doc = r" Functionality implemented by (signed and unsigned) integer SIMD vectors."]
12792pub trait SimdInt<S: Simd>:
12793 SimdBase<S, Element: SimdIntElement>
12794 + Seal
12795 + core::ops::BitAnd<Output = Self>
12796 + core::ops::BitAndAssign
12797 + core::ops::BitAnd<Self::Element, Output = Self>
12798 + core::ops::BitAndAssign<Self::Element>
12799 + core::ops::BitOr<Output = Self>
12800 + core::ops::BitOrAssign
12801 + core::ops::BitOr<Self::Element, Output = Self>
12802 + core::ops::BitOrAssign<Self::Element>
12803 + core::ops::BitXor<Output = Self>
12804 + core::ops::BitXorAssign
12805 + core::ops::BitXor<Self::Element, Output = Self>
12806 + core::ops::BitXorAssign<Self::Element>
12807 + core::ops::Not<Output = Self>
12808 + core::ops::Shl<u32, Output = Self>
12809 + core::ops::ShlAssign<u32>
12810 + core::ops::Shl<Output = Self>
12811 + core::ops::ShlAssign
12812 + core::ops::Shr<u32, Output = Self>
12813 + core::ops::ShrAssign<u32>
12814 + core::ops::Shr<Output = Self>
12815 + core::ops::ShrAssign
12816{
12817 #[doc = r" Convert this integer type to a floating-point type. This is a convenience method"]
12818 #[doc = r" that delegates to [`SimdCvtFloat::float_from`], and can only be called if there"]
12819 #[doc = r" actually exists a target type of the same bit width (`f32` or `f64`)."]
12820 #[inline(always)]
12821 fn to_float<T: SimdCvtFloat<Self>>(self) -> T {
12822 T::float_from(self)
12823 }
12824 #[doc = "Return the number of ones in the binary representation of each element."]
12825 fn count_ones(self) -> Self;
12826 #[doc = "Return the number of zeros in the binary representation of each element."]
12827 fn count_zeros(self) -> Self;
12828 #[doc = "Add two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping addition on x86."]
12829 fn saturating_add(self, rhs: impl SimdInto<Self, S>) -> Self;
12830 #[doc = "Subtract two vectors element-wise, saturating on overflow.\n\n\"Saturating\" means that if the result is not representable, the closest representable value (either `Element::MAX` or `Element::MIN`) is returned.\n\nOn x86 it is implemented in hardware only for 8-bit and 16-bit elements. For 32-bit and 64-bit vectors this operation is slower than wrapping subtraction on x86."]
12831 fn saturating_sub(self, rhs: impl SimdInto<Self, S>) -> Self;
12832}
12833#[doc = r" Functionality implemented by SIMD masks."]
12834#[doc = r""]
12835#[doc = r" A mask has one logical boolean lane per SIMD lane. Its storage is intentionally opaque:"]
12836#[doc = r" current backends may use all-zero/all-one integer vectors internally, while future"]
12837#[doc = r" predicate-register backends may use a compact representation."]
12838pub trait SimdMask<S: Simd>:
12839 ExtractToken<S = S>
12840 + Copy
12841 + Sync
12842 + Send
12843 + 'static
12844 + Seal
12845 + Select<Self>
12846 + core::ops::BitAnd<Output = Self>
12847 + core::ops::BitAndAssign
12848 + core::ops::BitOr<Output = Self>
12849 + core::ops::BitOrAssign
12850 + core::ops::BitXor<Output = Self>
12851 + core::ops::BitXorAssign
12852 + core::ops::Not<Output = Self>
12853{
12854 #[doc = r" The signed integer type used when converting this mask to and from lane values."]
12855 #[doc = r""]
12856 #[doc = r" False lanes are encoded as all zeroes (integer value 0), and true lanes are encoded as all ones"]
12857 #[doc = r" (integer value -1)."]
12858 type Element: SimdIntElement<Mask = Self::Element> + core::ops::Neg<Output = Self::Element>;
12859 #[doc = r" This mask's corresponding integer vector type."]
12860 type Ints: SimdInt<S, Element = Self::Element, Mask = Self>
12861 + core::ops::Neg<Output = Self::Ints>;
12862 #[doc = r" This mask type's lane count."]
12863 const LEN: usize;
12864 #[doc = r" Create a SIMD mask with all lanes set to the given boolean value."]
12865 fn splat(simd: S, val: bool) -> Self;
12866 #[doc = r" Create a mask from a compact bitmask."]
12867 #[doc = r""]
12868 #[doc = r" Bit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above"]
12869 #[doc = r" [`Self::LEN`] are ignored."]
12870 fn from_bitmask(simd: S, bits: u64) -> Self;
12871 #[doc = r" Convert this mask to a compact bitmask."]
12872 #[doc = r""]
12873 #[doc = r" Bit `i` maps to lane `i`, with lane 0 in the least significant bit. Bits above"]
12874 #[doc = r" [`Self::LEN`] are cleared."]
12875 fn to_bitmask(self) -> u64;
12876 #[doc = r" Create a SIMD mask from signed integer mask lanes."]
12877 fn from_vector(v: Self::Ints) -> Self;
12878 #[doc = r" Convert this SIMD mask to signed integer mask lanes."]
12879 fn to_vector(self) -> Self::Ints;
12880 #[doc = r" Test whether one logical lane is set."]
12881 #[doc = r""]
12882 #[doc = r" Panics if `index` is greater than or equal to the number of lanes in the mask."]
12883 #[inline(always)]
12884 fn test(&self, index: usize) -> bool {
12885 assert!(
12886 index < Self::LEN,
12887 "mask lane index {index} is out of bounds for {} lanes",
12888 Self::LEN
12889 );
12890 (((*self).to_bitmask() >> index) & 1) != 0
12891 }
12892 #[doc = r" Sets the value of one logical lane."]
12893 #[doc = r""]
12894 #[doc = r" Panics if `index` is greater than or equal to the number of lanes in the mask."]
12895 fn set(&mut self, index: usize, value: bool);
12896 #[doc = r" Create a SIMD mask from signed integer mask lanes."]
12897 #[doc = r""]
12898 #[doc = r" The slice must be exactly the size of the SIMD mask."]
12899 fn from_slice(simd: S, slice: &[Self::Element]) -> Self;
12900 #[doc = r" Store this SIMD mask as signed integer mask lanes."]
12901 #[doc = r""]
12902 #[doc = r" The slice must be exactly the size of the SIMD mask."]
12903 fn store_slice(&self, slice: &mut [Self::Element]);
12904 #[doc = "Rotate the mask elements to the left by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
12905 fn rotate_elements_left<const OFFSET: usize>(self) -> Self;
12906 #[doc = "Rotate the mask elements to the right by `OFFSET`.\n\nIf `OFFSET` is greater than or equal to `Self::LEN`, it wraps modulo `Self::LEN`."]
12907 fn rotate_elements_right<const OFFSET: usize>(self) -> Self;
12908 #[doc = "Reverse the order of the mask's logical lanes."]
12909 fn reverse(self) -> Self;
12910 #[doc = "Compare two vectors element-wise for equality.\n\nReturns a mask where each logical lane is true if the corresponding elements are equal, and false if not."]
12911 fn simd_eq(self, rhs: impl SimdInto<Self, S>) -> Self;
12912 #[doc = "Compare two masks element-wise for inequality.\n\nReturns a mask where each logical lane is true if the corresponding elements are unequal, and false if equal.\n\nThis is equivalent to negating the mask returned by `simd_eq`."]
12913 fn simd_ne(self, rhs: impl SimdInto<Self, S>) -> Self;
12914 #[doc = "Returns true if any logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12915 fn any_true(self) -> bool;
12916 #[doc = "Returns true if all logical lanes in this mask are true.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12917 fn all_true(self) -> bool;
12918 #[doc = "Returns true if any logical lanes in this mask are false.\n\nThis is logically equivalent to `!all_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12919 fn any_false(self) -> bool;
12920 #[doc = "Returns true if all logical lanes in this mask are false.\n\nThis is logically equivalent to `!any_true`, but may be faster.\n\nMasks may be converted to and from signed integer lane arrays for compatibility with older APIs. For those conversions, false is encoded as all zeroes (integer value 0) and true is encoded as all ones (integer value -1).\n\nBehavior on masks constructed from any other integer bit pattern is unspecified. It may vary depending on architecture, feature level, the mask elements' width, the mask vector's width, or library version.\n\nThe behavior is also not guaranteed to be logically consistent for such non-canonical masks. `any_true` may not return the same result as `!all_false`, and `all_true` may not return the same result as `!any_false`.\n\nThe [`select`](crate::Select::select) operation also has unspecified behavior for non-canonical masks. That behavior may not match the behavior of this operation."]
12921 fn all_false(self) -> bool;
12922}