Skip to main content

SimdIntWiden

Trait SimdIntWiden 

Source
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§

Source

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]);
Source

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]);
Source

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()
}
Source

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".

Implementors§

Source§

impl<S: Simd> SimdIntWiden<S> for i8x16<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i8x32<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i8x64<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i16x8<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i16x16<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i16x32<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i32x4<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i32x8<S>

Source§

impl<S: Simd> SimdIntWiden<S> for i32x16<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u8x16<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u8x32<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u8x64<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u16x8<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u16x16<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u16x32<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u32x4<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u32x8<S>

Source§

impl<S: Simd> SimdIntWiden<S> for u32x16<S>