pub trait SimdIntWiden<S: Simd>: SimdInt<S> + SimdWiden<S, Widened: SimdInt<S>> {
// Required methods
fn widening_mul(
self,
rhs: impl SimdInto<Self, S>,
) -> (Self::Widened, Self::Widened);
fn widening_add(
self,
rhs: impl SimdInto<Self, S>,
) -> (Self::Widened, Self::Widened);
fn pairwise_widening_add(self) -> Self::Widened;
fn pairwise_dot_product(self, rhs: impl SimdInto<Self, S>) -> Self::Widened;
}Expand description
Widening arithmetic on integer SIMD vectors.
Each output vector has twice-wide lanes and the same total bit width as the inputs.
Self::widening_mul and Self::widening_add return the lower and upper halves
as two vectors, just like SimdWiden::widen. The pairwise operations combine
adjacent lanes into a single vector with half as many lanes.
Required Methods§
Sourcefn widening_mul(
self,
rhs: impl SimdInto<Self, S>,
) -> (Self::Widened, Self::Widened)
fn widening_mul( self, rhs: impl SimdInto<Self, S>, ) -> (Self::Widened, Self::Widened)
Multiply corresponding lanes exactly, returning the lower and upper halves.
§Examples
let a = i16x8::from_slice(simd, &[100, 200, 300, 400, 500, 600, 700, 800]);
let (lower, upper) = a.widening_mul(10_000);
assert_eq!(*lower, [1_000_000, 2_000_000, 3_000_000, 4_000_000]);
assert_eq!(*upper, [5_000_000, 6_000_000, 7_000_000, 8_000_000]);Sourcefn widening_add(
self,
rhs: impl SimdInto<Self, S>,
) -> (Self::Widened, Self::Widened)
fn widening_add( self, rhs: impl SimdInto<Self, S>, ) -> (Self::Widened, Self::Widened)
Add corresponding lanes exactly, returning the lower and upper halves.
§Examples
let a = u16x8::from_slice(simd, &[1_000, 2_000, 3_000, 4_000, 5_000, 6_000, 7_000, 8_000]);
let (lower, upper) = a.widening_add(60_000);
assert_eq!(*lower, [61_000, 62_000, 63_000, 64_000]);
assert_eq!(*upper, [65_000, 66_000, 67_000, 68_000]);Sourcefn pairwise_widening_add(self) -> Self::Widened
fn pairwise_widening_add(self) -> Self::Widened
Add adjacent integer lanes, widening the result to avoid overflow.
Output lane i is widen(self[2*i]) + widen(self[2*i+1]). The result has
half as many lanes, twice the lane width, and the same signedness and total
vector bit width as the input.
§Examples
let a = i16x8::from_slice(simd, &[1, 2, 3, 4, 5, 6, 7, 8]);
// \ / \ / \ / \ /
// 3 7 11 15
let pairs: i32x4<_> = a.pairwise_widening_add();
assert_eq!(*pairs, [3, 7, 11, 15]);Works on native-width vectors too:
fn native<S: Simd>(a: S::u8s) -> S::u16s {
a.pairwise_widening_add()
}Sourcefn pairwise_dot_product(self, rhs: impl SimdInto<Self, S>) -> Self::Widened
fn pairwise_dot_product(self, rhs: impl SimdInto<Self, S>) -> Self::Widened
Multiply corresponding lanes, then add adjacent pairs of products.
Each adjacent pair of lanes is an independent two-element dot product. The result
has half as many lanes, each twice as wide, with the same signedness and total bit
width as the inputs. For inputs a and b, output lane i is:
result[i] = widen(a[2*i]) * widen(b[2*i])
+ widen(a[2*i+1]) * widen(b[2*i+1])For example:
a = [ 1, 2, 3, 4, 5, 6, 7, 8]
| | | | | | | |
|---| |---| |---| |---|
| | | | | | | |
b = [10, 20, 30, 40, 50, 60, 70, 80]
result = [ 50, 250, 610, 1130]Here, 1*10 + 2*20 = 50, 3*30 + 4*40 = 250, and so on.
Multiplication is exact in the widened type. Addition wraps in the widened type.
§Examples
let a = i16x8::from_slice(simd, &[ 1, 2, 3, 4, 5, 6, 7, 8]);
let b = i16x8::from_slice(simd, &[10, 20, 30, 40, 50, 60, 70, 80]);
let result: i32x4<_> = a.pairwise_dot_product(b);
assert_eq!(*result, [50, 250, 610, 1130]);
let min = i8x16::splat(simd, i8::MIN /* = -128 */);
assert_eq!(*min.pairwise_dot_product(min), [i16::MIN /* = -32768 */; 8]);Works on native-width vectors too:
fn native<S: Simd>(a: S::i16s, b: S::i16s) -> S::i32s {
a.pairwise_dot_product(b)
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".