pub trait SimdBase<S: Simd>:
ExtractToken<S = S>
+ Copy
+ Sync
+ Send
+ Debug
+ 'static
+ Seal
+ Bytes<Bytes = Self::ByteVector>
+ SimdFrom<Self::Element, S>
+ SimdFrom<Self::Array, S>
+ Index<usize, Output = Self::Element>
+ IndexMut<usize, Output = Self::Element>
+ Deref<Target = Self::Array>
+ DerefMut<Target = Self::Array>
+ Add<Output = Self>
+ AddAssign
+ Add<Self::Element, Output = Self>
+ AddAssign<Self::Element>
+ Sub<Output = Self>
+ SubAssign
+ Sub<Self::Element, Output = Self>
+ SubAssign<Self::Element>
+ Mul<Output = Self>
+ MulAssign
+ Mul<Self::Element, Output = Self>
+ MulAssign<Self::Element> {
type Element: SimdElement;
type ByteVector: SimdBase<S, Element = u8, ByteVector = Self::ByteVector>;
type Mask: SimdMask<S, Element = <Self::Element as SimdElement>::Mask> + Select<Self>;
type Block: SimdBase<S, Element = Self::Element, Block = Self::Block>;
type Array: Copy + Debug + IntoIterator<Item = Self::Element> + AsRef<[Self::Element]> + AsMut<[Self::Element]> + From<Self>;
const LEN: usize;
Show 45 methods
// Required methods
fn as_slice(&self) -> &[Self::Element];
fn as_mut_slice(&mut self) -> &mut [Self::Element];
fn from_slice(simd: S, slice: &[Self::Element]) -> Self;
fn store_slice(&self, slice: &mut [Self::Element]);
fn block_splat(block: Self::Block) -> Self;
fn from_fn(simd: S, f: impl FnMut(usize) -> Self::Element) -> Self;
fn abs(self) -> Self;
fn splat(simd: S, val: Self::Element) -> Self;
fn reverse(self) -> Self;
fn slide<const SHIFT: usize>(self, rhs: impl SimdInto<Self, S>) -> Self;
fn slide_within_blocks<const SHIFT: usize>(
self,
rhs: impl SimdInto<Self, S>,
) -> Self;
fn swizzle_dyn_within_blocks(
self,
indices: impl SimdInto<Self::Bytes, S>,
) -> Self;
fn swizzle_dyn(self, indices: impl SimdInto<Self::Bytes, S>) -> Self;
fn swizzle_dyn_precise(self, indices: impl SimdInto<Self::Bytes, S>) -> Self;
fn reduce_max(self) -> Self::Element;
fn reduce_min(self) -> Self::Element;
fn reduce_max_precise(self) -> Self::Element;
fn reduce_min_precise(self) -> Self::Element;
fn reduce_sum(self) -> Self::Element;
fn reduce_product(self) -> Self::Element;
fn max(self, rhs: impl SimdInto<Self, S>) -> Self;
fn min(self, rhs: impl SimdInto<Self, S>) -> Self;
fn max_precise(self, rhs: impl SimdInto<Self, S>) -> Self;
fn min_precise(self, rhs: impl SimdInto<Self, S>) -> Self;
fn simd_eq(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
fn simd_lt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
fn simd_le(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
fn simd_ge(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
fn simd_gt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask;
fn zip_low(self, rhs: impl SimdInto<Self, S>) -> Self;
fn zip_high(self, rhs: impl SimdInto<Self, S>) -> Self;
fn unzip_low(self, rhs: impl SimdInto<Self, S>) -> Self;
fn unzip_high(self, rhs: impl SimdInto<Self, S>) -> Self;
fn interleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self);
fn deinterleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self);
// Provided methods
fn load_array(simd: S, val: Self::Array) -> Self { ... }
fn load_array_ref(simd: S, val: &Self::Array) -> Self { ... }
fn to_array(self) -> Self::Array { ... }
fn as_array(&self) -> &Self::Array { ... }
fn as_mut_array(&mut self) -> &mut Self::Array { ... }
fn store_array(self, dest: &mut Self::Array) { ... }
fn rotate_elements_left<const OFFSET: usize>(self) -> Self { ... }
fn rotate_elements_right<const OFFSET: usize>(self) -> Self { ... }
fn shift_elements_left<const OFFSET: usize>(
self,
padding: Self::Element,
) -> Self { ... }
fn shift_elements_right<const OFFSET: usize>(
self,
padding: Self::Element,
) -> Self { ... }
}Expand description
Base functionality implemented by all SIMD vectors.
Required Associated Constants§
Sourceconst LEN: usize
const LEN: usize
This vector type’s lane count. This is useful when you’re
working with a native-width vector (e.g. Simd::f32s) and
want to process data in native-width chunks.
Required Associated Types§
Sourcetype Element: SimdElement
type Element: SimdElement
The type of this vector’s elements.
Sourcetype ByteVector: SimdBase<S, Element = u8, ByteVector = Self::ByteVector>
type ByteVector: SimdBase<S, Element = u8, ByteVector = Self::ByteVector>
The same-width SIMD vector of u8 lanes used as the byte representation.
This is the same type as Bytes::Bytes.
This associated type exists because expressing the SimdBase bound directly on
Bytes::Bytes creates a trait-solver cycle. The Bytes<Bytes = Self::ByteVector> supertrait bound ensures that the two types are identical.
Generic callers should normally use Bytes::Bytes, not this associated type.
Sourcetype Mask: SimdMask<S, Element = <Self::Element as SimdElement>::Mask> + Select<Self>
type Mask: SimdMask<S, Element = <Self::Element as SimdElement>::Mask> + Select<Self>
A SIMD vector mask with the same number of logical lanes.
Masks intentionally do not implement SimdBase. SSE, NEON, WASM, and the
fallback backend currently store masks as all-zero/all-one integer vectors, but
AVX-512/RVV/SVE-style targets use compact predicate registers instead.
Sourcetype Block: SimdBase<S, Element = Self::Element, Block = Self::Block>
type Block: SimdBase<S, Element = Self::Element, Block = Self::Block>
A 128-bit SIMD vector of the same scalar type.
Sourcetype Array: Copy + Debug + IntoIterator<Item = Self::Element> + AsRef<[Self::Element]> + AsMut<[Self::Element]> + From<Self>
type Array: Copy + Debug + IntoIterator<Item = Self::Element> + AsRef<[Self::Element]> + AsMut<[Self::Element]> + From<Self>
The array type that this vector type corresponds to, which will
always be [Self::Element; Self::LEN]. It has the same layout as
this vector type, but likely has a lower alignment.
Required Methods§
fn as_slice(&self) -> &[Self::Element]
fn as_mut_slice(&mut self) -> &mut [Self::Element]
Sourcefn from_slice(simd: S, slice: &[Self::Element]) -> Self
fn from_slice(simd: S, slice: &[Self::Element]) -> Self
Create a SIMD vector from a slice.
The slice must be exactly the size of the SIMD vector.
Sourcefn store_slice(&self, slice: &mut [Self::Element])
fn store_slice(&self, slice: &mut [Self::Element])
Store a SIMD vector into a slice.
The slice must be exactly the size of the SIMD vector.
Sourcefn block_splat(block: Self::Block) -> Self
fn block_splat(block: Self::Block) -> Self
Create a SIMD vector from a 128-bit vector of the same scalar type, repeated.
Sourcefn from_fn(simd: S, f: impl FnMut(usize) -> Self::Element) -> Self
fn from_fn(simd: S, f: impl FnMut(usize) -> Self::Element) -> Self
Create a SIMD vector where each element is produced by
calling f with that element’s lane index (from 0 to
SimdBase::LEN - 1).
Sourcefn abs(self) -> Self
fn abs(self) -> Self
Compute the absolute value of each element.
Unsigned integers are unchanged. Signed integers use wrapping absolute value: the minimum representable value remains unchanged. This matches i32::abs().
For floating-point elements, clear the sign bit, preserving all other bits. For example, negative zero becomes positive zero.
Sourcefn splat(simd: S, val: Self::Element) -> Self
fn splat(simd: S, val: Self::Element) -> Self
Create a SIMD vector with all elements set to the given value.
Sourcefn slide<const SHIFT: usize>(self, rhs: impl SimdInto<Self, S>) -> Self
fn slide<const SHIFT: usize>(self, rhs: impl SimdInto<Self, S>) -> Self
Concatenate [self, rhs] and extract Self::LEN elements starting at index SHIFT.
SHIFT must be within [0, Self::LEN].
This 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.
This can also be used to rotate items within a vector by providing the same vector as both operands.
slide::<1>([a b c d], [e f g h]) == [b c d e]
Sourcefn slide_within_blocks<const SHIFT: usize>(
self,
rhs: impl SimdInto<Self, S>,
) -> Self
fn slide_within_blocks<const SHIFT: usize>( self, rhs: impl SimdInto<Self, S>, ) -> Self
Like slide, but operates independently on each 128-bit block.
Sourcefn swizzle_dyn_within_blocks(
self,
indices: impl SimdInto<Self::Bytes, S>,
) -> Self
fn swizzle_dyn_within_blocks( self, indices: impl SimdInto<Self::Bytes, S>, ) -> Self
Dynamically swizzle this vector’s bytes independently within each 128-bit block.
The 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.
Out-of-range index behavior varies by platform.
Sourcefn swizzle_dyn(self, indices: impl SimdInto<Self::Bytes, S>) -> Self
fn swizzle_dyn(self, indices: impl SimdInto<Self::Bytes, S>) -> Self
Dynamically swizzle this vector’s bytes across the whole vector.
The 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.
Use SimdBase::swizzle_dyn_precise if out-of-range indices must produce zero.
Sourcefn swizzle_dyn_precise(self, indices: impl SimdInto<Self::Bytes, S>) -> Self
fn swizzle_dyn_precise(self, indices: impl SimdInto<Self::Bytes, S>) -> Self
Dynamically swizzle this vector’s bytes across the whole vector.
The 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.
Sourcefn reduce_max(self) -> Self::Element
fn reduce_max(self) -> Self::Element
Return the maximum element in the vector. Integer vectors always return the exact maximum.
For 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.
If the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.
Sourcefn reduce_min(self) -> Self::Element
fn reduce_min(self) -> Self::Element
Return the minimum element in the vector. Integer vectors always return the exact minimum.
For 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.
If the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.
Sourcefn reduce_max_precise(self) -> Self::Element
fn reduce_max_precise(self) -> Self::Element
Return the maximum element in the vector, ignoring quiet NaNs.
For integer vectors, this operation is the same as reduce_max.
For 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.
If the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.
If 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. Signaling 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.
Sourcefn reduce_min_precise(self) -> Self::Element
fn reduce_min_precise(self) -> Self::Element
Return the minimum element in the vector, ignoring quiet NaNs.
For integer vectors, this operation is the same as reduce_min.
For 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.
If the floating-point vector contains both positive zero and negative zero, either sign of zero may be returned.
If 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. Signaling 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.
Sourcefn reduce_sum(self) -> Self::Element
fn reduce_sum(self) -> Self::Element
Return the sum of all elements in the vector. Integer addition wraps.
§Floating-point accuracy
For an input vector with N lanes, any lane’s contribution may be rounded at most log2(N) times.
For 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.
Because 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 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.
Sourcefn reduce_product(self) -> Self::Element
fn reduce_product(self) -> Self::Element
Return the product of all elements in the vector. Integer multiplication wraps.
§Floating-point behavior
For a vector with N elements, this operation performs N-1 roundings.
For 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.
The result of this operation is not bit-exact to scalar product of the elements because it multiplies elements in a different (but fixed) order.
Intermediate operations can overflow, underflow, or multiply infinity by zero to produce NaN even when the exact real-number product is representable.
Because floating-point multiplication is not associative, separately reducing smaller vectors and then multiplying their results can differ from reducing their combined wider vector.
Sourcefn max(self, rhs: impl SimdInto<Self, S>) -> Self
fn max(self, rhs: impl SimdInto<Self, S>) -> Self
Return the element-wise maximum of two vectors.
For 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.
If 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.
Sourcefn min(self, rhs: impl SimdInto<Self, S>) -> Self
fn min(self, rhs: impl SimdInto<Self, S>) -> Self
Return the element-wise minimum of two vectors.
For 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.
If 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.
Sourcefn max_precise(self, rhs: impl SimdInto<Self, S>) -> Self
fn max_precise(self, rhs: impl SimdInto<Self, S>) -> Self
Return the element-wise maximum of two vectors.
For integer vectors, this operation is the same as max.
For floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.
If one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.
If 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. Signaling 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.
Sourcefn min_precise(self, rhs: impl SimdInto<Self, S>) -> Self
fn min_precise(self, rhs: impl SimdInto<Self, S>) -> Self
Return the element-wise minimum of two vectors.
For integer vectors, this operation is the same as min.
For floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.
If one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.
If 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. Signaling 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.
Sourcefn simd_eq(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
fn simd_eq(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
Compare two vectors element-wise for equality.
Returns a mask where each logical lane is true if the corresponding elements are equal, and false if not.
Sourcefn simd_lt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
fn simd_lt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
Compare two vectors element-wise for less than.
Returns a mask where each logical lane is true if self is less than rhs, and false if not.
Sourcefn simd_le(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
fn simd_le(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
Compare two vectors element-wise for less than or equal.
Returns a mask where each logical lane is true if self is less than or equal to rhs, and false if not.
Sourcefn simd_ge(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
fn simd_ge(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
Compare two vectors element-wise for greater than or equal.
Returns a mask where each logical lane is true if self is greater than or equal to rhs, and false if not.
Sourcefn simd_gt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
fn simd_gt(self, rhs: impl SimdInto<Self, S>) -> Self::Mask
Compare two vectors element-wise for greater than.
Returns a mask where each logical lane is true if self is greater than rhs, and false if not.
Sourcefn zip_low(self, rhs: impl SimdInto<Self, S>) -> Self
fn zip_low(self, rhs: impl SimdInto<Self, S>) -> Self
Interleave the lower half elements of two vectors.
For vectors [a0, a1, a2, a3] and [b0, b1, b2, b3], returns [a0, b0, a1, b1].
Note: This operation is only useful if you need to discard elements a2, a3, b2, b3.
For fully interleaving two vectors prefer interleave,
which is faster than zip_low followed by zip_high on some platforms.
Sourcefn zip_high(self, rhs: impl SimdInto<Self, S>) -> Self
fn zip_high(self, rhs: impl SimdInto<Self, S>) -> Self
Interleave the upper half elements of two vectors.
For vectors [a0, a1, a2, a3] and [b0, b1, b2, b3], returns [a2, b2, a3, b3].
Note: This operation is only useful if you need to discard elements a0, a1, b0, b1.For fully interleaving two vectors prefer interleave,
which is faster than zip_low followed by zip_high on some platforms.
Sourcefn unzip_low(self, rhs: impl SimdInto<Self, S>) -> Self
fn unzip_low(self, rhs: impl SimdInto<Self, S>) -> Self
Extract even-indexed elements from two vectors.
For vectors [a0, a1, a2, a3] and [b0, b1, b2, b3], returns [a0, a2, b0, b2].
Note: This operation is only useful if you need to discard elements a1, a3, b1, b3.For fully deinterleaving two vectors prefer deinterleave,
which is faster than unzip_low followed by unzip_high on some platforms.
Sourcefn unzip_high(self, rhs: impl SimdInto<Self, S>) -> Self
fn unzip_high(self, rhs: impl SimdInto<Self, S>) -> Self
Extract odd-indexed elements from two vectors.
For vectors [a0, a1, a2, a3] and [b0, b1, b2, b3], returns [a1, a3, b1, b3].
Note: This operation is only useful if you need to discard elements a0, a2, b0, b2.For fully deinterleaving two vectors prefer deinterleave,
which is faster than unzip_low followed by unzip_high on some platforms.
Sourcefn interleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self)
fn interleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self)
Interleave two vectors.
The resulting vectors contain elements taken alternately from self and rhs, first filling the first result, and then the second.
The reverse of this operation is deinterleave.
For vectors [a0, a1, a2, a3] and [b0, b1, b2, b3], returns ([a0, b0, a1, b1], [a2, b2, a3, b3]).
Sourcefn deinterleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self)
fn deinterleave(self, rhs: impl SimdInto<Self, S>) -> (Self, Self)
Deinterleave two vectors.
The 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.
The reverse of this operation is interleave.
For vectors [a0, b0, a1, b1] and [a2, b2, a3, b3], returns ([a0, a1, a2, a3], [b0, b1, b2, b3]).
Provided Methods§
Sourcefn load_array(simd: S, val: Self::Array) -> Self
fn load_array(simd: S, val: Self::Array) -> Self
Create a SIMD vector from its corresponding lane array.
Sourcefn load_array_ref(simd: S, val: &Self::Array) -> Self
fn load_array_ref(simd: S, val: &Self::Array) -> Self
Create a SIMD vector from a reference to its corresponding lane array.
Sourcefn as_array(&self) -> &Self::Array
fn as_array(&self) -> &Self::Array
Project this SIMD vector reference to its corresponding lane array reference.
Sourcefn as_mut_array(&mut self) -> &mut Self::Array
fn as_mut_array(&mut self) -> &mut Self::Array
Project this mutable SIMD vector reference to its corresponding mutable lane array reference.
Sourcefn store_array(self, dest: &mut Self::Array)
fn store_array(self, dest: &mut Self::Array)
Store this SIMD vector into its corresponding lane array.
Sourcefn rotate_elements_left<const OFFSET: usize>(self) -> Self
fn rotate_elements_left<const OFFSET: usize>(self) -> Self
Rotate the vector elements to the left by OFFSET.
If OFFSET is greater than or equal to Self::LEN, it wraps modulo Self::LEN.
Sourcefn rotate_elements_right<const OFFSET: usize>(self) -> Self
fn rotate_elements_right<const OFFSET: usize>(self) -> Self
Rotate the vector elements to the right by OFFSET.
If OFFSET is greater than or equal to Self::LEN, it wraps modulo Self::LEN.
Sourcefn shift_elements_left<const OFFSET: usize>(
self,
padding: Self::Element,
) -> Self
fn shift_elements_left<const OFFSET: usize>( self, padding: Self::Element, ) -> Self
Shift the vector elements to the left by OFFSET, filling in with padding from the right.
If OFFSET is greater than or equal to Self::LEN, all lanes are filled with padding.
Sourcefn shift_elements_right<const OFFSET: usize>(
self,
padding: Self::Element,
) -> Self
fn shift_elements_right<const OFFSET: usize>( self, padding: Self::Element, ) -> Self
Shift the vector elements to the right by OFFSET, filling in with padding from the left.
If OFFSET is greater than or equal to Self::LEN, all lanes are filled with padding.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".