Struct slipstream::vector::Vector[][src]

#[repr(C)]pub struct Vector<A, B, const S: usize> where
    A: Align,
    B: Repr, 
{ /* fields omitted */ }

A vector type.

Vector types are mostly well aligned fixed sized arrays. Unlike the arrays, they have the usual numeric operators and several helpful methods implemented on them. They perform the operations „per lane“ independently and allow the CPU to parallelize the computations.

The types have convenient aliases ‒ for example u32x4 is an alias for Vector<Align16, u32, 4> and corresponds to [u32; 4] (but aligned to 16 bytes).

While these can be operated as arrays (indexing, copying between slices, etc), it is better to perform operations on whole vectors at once.

The usual comparing operators don’t exist (<=), but there are „per lane“ comparison operators that return mask vectors ‒ vectors of boolean-like values. These can either be examined manually, or fed into other operations on vectors, like blend or gather_load_masked.

Examples

let a = i32x4::new([1, -2, 3, -4]);
let b = -a;                           // [-1, 2, -3, 4]
let positive = a.ge(i32x4::splat(1)); // Lane-wise a >= 1
// Will take from b where positive is true, from a otherwise
let abs = b.blend(a, positive);
assert_eq!(abs, i32x4::new([1, 2, 3, 4]));

Implementations

impl<A, B, const S: usize> Vector<A, B, S> where
    A: Align,
    B: Repr, 
[src]

pub const LANES: usize[src]

Number of lanes of the vector.

pub unsafe fn new_unchecked(input: *const B) -> Self[src]

Loads the vector without doing bounds checks.

Safety

The pointed to memory must be valid in Self::LANES consecutive cells ‒ eg. it must contain a full array of the base types.

pub fn new<I>(input: I) -> Self where
    I: AsRef<[B]>, 
[src]

Loads the vector from correctly sized slice.

This loads the vector from correctly sized slice or anything that can be converted to it ‒ specifically, fixed sized arrays and other vectors work.

Example

let vec = (0..10).collect::<Vec<_>>();
let v1 = u32x4::new(&vec[0..4]);
let v2 = u32x4::new(v1);
let v3 = u32x4::new([2, 3, 4, 5]);
assert_eq!(v1 + v2 + v3, u32x4::new([2, 5, 8, 11]));

Panics

If the provided slice is of incompatible size.

pub fn splat(value: B) -> Self[src]

Produces a vector of all lanes set to the same value.

let v = f32x4::splat(1.2);
assert_eq!(v, f32x4::new([1.2, 1.2, 1.2, 1.2]));

pub fn gather_load<I, Idx>(input: I, idx: Idx) -> Self where
    I: AsRef<[B]>,
    Idx: AsRef<[usize]>, 
[src]

Loads the vector from a slice by indexing it.

Unlike new, this can load the vector from discontinuous parts of the slice, out of order or multiple lanes from the same location. This flexibility comes at the cost of lower performance (in particular, I’ve never seen this to get auto-vectorized even though a gather instruction exists), therefore prefer new where possible.

Examples

let input = (2..100).collect::<Vec<_>>();
let vec = u32x4::gather_load(&input, [3, 3, 1, 32]);
assert_eq!(vec, u32x4::new([5, 5, 3, 34]));

It is possible to use another vector as the indices:

let indices = usizex4::new([1, 2, 3, 4]) * usizex4::splat(2);
let input = (0..10).collect::<Vec<_>>();
let vec = u32x4::gather_load(&input, indices);
assert_eq!(vec, u32x4::new([2, 4, 6, 8]));

It is possible to use another vector as an input, allowing to narrow it down or shuffle.

let a = u32x4::new([1, 2, 3, 4]);
let b = u32x4::gather_load(a, [2, 0, 1, 3]);
assert_eq!(b, u32x4::new([3, 1, 2, 4]));
let c = u32x2::gather_load(a, [2, 2]);
assert_eq!(c, u32x2::new([3, 3]));

Panics

  • If the idx slice doesn’t have the same length as the vector.
  • If any of the indices is out of bounds of the input.

pub fn gather_load_masked<I, Idx, M, MB>(
    self,
    input: I,
    idx: Idx,
    mask: M
) -> Self where
    I: AsRef<[B]>,
    Idx: AsRef<[usize]>,
    M: AsRef<[MB]>,
    MB: Mask
[src]

Loads enabled lanes from a slice by indexing it.

This is similar to gather_load. However, the loading of lanes is enabled by a mask. If the corresponding lane mask is not set, the value is taken from self. In other words, if the mask is all-true, it is semantically equivalent to gather_load, expect with possible worse performance.

Examples

let input = (0..100).collect::<Vec<_>>();
let v = u32x4::default().gather_load_masked(
    &input,
    [1, 4, 2, 2],
    [m32::TRUE, m32::FALSE, m32::FALSE, m32::TRUE]
);
assert_eq!(v, u32x4::new([1, 0, 0, 2]));
let left = u32x2::new([1, 2]);
let right = u32x2::new([3, 4]);
let idx = usizex4::new([0, 1, 0, 1]);
let mask = m32x4::new([m32::TRUE, m32::TRUE, m32::FALSE, m32::FALSE]);
let v = u32x4::default()
    .gather_load_masked(left, idx, mask)
    .gather_load_masked(right, idx, !mask);
assert_eq!(v, u32x4::new([1, 2, 3, 4]));

Panics

  • If the mask or the idx parameter is of different length than the vector.
  • If any of the active indices are out of bounds of input.

pub fn store<O: AsMut<[B]>>(self, output: O)[src]

Stores the content into a continuous slice of the correct length.

This is less general than scatter_store, that one allows storing to different parts of the slice.

The counterpart of this is new.

Panics

If the length doesn’t match.

pub fn scatter_store<O, Idx>(self, output: O, idx: Idx) where
    O: AsMut<[B]>,
    Idx: AsRef<[usize]>, 
[src]

Store the vector into a slice by indexing it.

This is the inverse of gather_load. It takes the lanes of the vector and stores them into the slice into given indices.

If you want to store it into a continuous slice, it is potentially faster to do it using the copy_from_slice method or by store:

let mut data = vec![0; 6];
let v = u32x4::new([1, 2, 3, 4]);
data[0..4].copy_from_slice(&v[..]);
assert_eq!(&data[..], &[1, 2, 3, 4, 0, 0]);
v.store(&mut data[..4]);
assert_eq!(&data[..], &[1, 2, 3, 4, 0, 0]);

Examples

let mut data = vec![0; 6];
let v = u32x4::new([1, 2, 3, 4]);
v.scatter_store(&mut data, [2, 5, 0, 1]);
assert_eq!(&data[..], &[3, 4, 1, 0, 0, 2]);

Warning

If multiple lanes are to be stored into the same slice element, it is not specified which of them will end up being stored. It is not UB to do so and it’ll always be one of them, however it may change between versions or even between compilation targets which.

This is to allow for potential different behaviour of different platforms.

Panics

  • If the idx has a different length than the vector.
  • If any of the indices are out of bounds of output.

pub fn scatter_store_masked<O, Idx, M, MB>(self, output: O, idx: Idx, mask: M) where
    O: AsMut<[B]>,
    Idx: AsRef<[usize]>,
    M: AsRef<[MB]>,
    MB: Mask
[src]

A masked version of scatter_store.

This acts in the same way as scatter_store, except lanes disabled by the mask are not stored anywhere.

Panics

  • If the idx or mask has a different length than the vector.
  • If any of the active indices are out of bounds of output.

pub fn blend<M, MB>(self, other: Self, mask: M) -> Self where
    M: AsRef<[MB]>,
    MB: Mask
[src]

Blend self and other using mask.

Imports enabled lanes from other, keeps disabled lanes from self.

Examples

let odd = u32x4::new([1, 3, 5, 7]);
let even = u32x4::new([2, 4, 6, 8]);
let mask = m32x4::new([m32::TRUE, m32::FALSE, m32::TRUE, m32::FALSE]);
assert_eq!(odd.blend(even, mask), u32x4::new([2, 3, 6, 7]));

pub fn maximum(self, other: Self) -> Self where
    B: PartialOrd
[src]

A lane-wise maximum.

Examples

let a = u32x4::new([1, 4, 2, 5]);
let b = u32x4::new([2, 3, 2, 6]);
assert_eq!(a.maximum(b), u32x4::new([2, 4, 2, 6]));

pub fn minimum(self, other: Self) -> Self where
    B: PartialOrd
[src]

A lane-wise maximum.

Examples

let a = u32x4::new([1, 4, 2, 5]);
let b = u32x4::new([2, 3, 2, 6]);
assert_eq!(a.minimum(b), u32x4::new([1, 3, 2, 5]));

pub fn horizontal_sum(self) -> B where
    B: Add<Output = B>, 
[src]

Sums the lanes together.

The additions are done in a tree manner: (a[0] + a[1]) + (a[2] + a[3]).

Note that this is potentially a slow operation. Prefer to do as many operations on whole vectors and only at the very end perform the horizontal operation.

pub fn horizontal_product(self) -> B where
    B: Mul<Output = B>, 
[src]

Multiplies all the lanes of the vector.

The multiplications are done in a tree manner: (a[0] * a[1]) * (a[2] * a[3]).

Note that this is potentially a slow operation. Prefer to do as many operations on whole vectors and only at the very end perform the horizontal operation.

pub fn eq(self, other: Self) -> Self::Mask where
    B: PartialEq
[src]

Lane-wise ==.

pub fn lt(self, other: Self) -> Self::Mask where
    B: PartialOrd
[src]

Lane-wise <.

pub fn gt(self, other: Self) -> Self::Mask where
    B: PartialOrd
[src]

Lane-wise >.

pub fn le(self, other: Self) -> Self::Mask where
    B: PartialOrd
[src]

Lane-wise <=.

pub fn ge(self, other: Self) -> Self::Mask where
    B: PartialOrd
[src]

Lane-wise >=.

Trait Implementations

impl<A: Align, B: Add<Output = B> + Repr, const S: usize> Add<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the + operator.

impl<A: Align, B: Add<Output = B> + Repr, const S: usize> Add<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the + operator.

impl<A: Align, B: AddAssign + Repr, const S: usize> AddAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: AddAssign + Repr, const S: usize> AddAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Repr, const S: usize> AsMut<[B; S]> for Vector<A, B, S>[src]

impl<A: Align, B: Repr, const S: usize> AsMut<[B]> for Vector<A, B, S>[src]

impl<A: Align, B: Repr, const S: usize> AsRef<[B; S]> for Vector<A, B, S>[src]

impl<A: Align, B: Repr, const S: usize> AsRef<[B]> for Vector<A, B, S>[src]

impl<A: Align, B: BitAnd<Output = B> + Repr, const S: usize> BitAnd<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the & operator.

impl<A: Align, B: BitAnd<Output = B> + Repr, const S: usize> BitAnd<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the & operator.

impl<A: Align, B: BitAndAssign + Repr, const S: usize> BitAndAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: BitAndAssign + Repr, const S: usize> BitAndAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: BitOr<Output = B> + Repr, const S: usize> BitOr<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the | operator.

impl<A: Align, B: BitOr<Output = B> + Repr, const S: usize> BitOr<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the | operator.

impl<A: Align, B: BitOrAssign + Repr, const S: usize> BitOrAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: BitOrAssign + Repr, const S: usize> BitOrAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: BitXor<Output = B> + Repr, const S: usize> BitXor<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the ^ operator.

impl<A: Align, B: BitXor<Output = B> + Repr, const S: usize> BitXor<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the ^ operator.

impl<A: Align, B: BitXorAssign + Repr, const S: usize> BitXorAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: BitXorAssign + Repr, const S: usize> BitXorAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Clone, B: Clone, const S: usize> Clone for Vector<A, B, S> where
    A: Align,
    B: Repr, 
[src]

impl<A: Copy, B: Copy, const S: usize> Copy for Vector<A, B, S> where
    A: Align,
    B: Repr, 
[src]

impl<A: Align, B: Debug + Repr, const S: usize> Debug for Vector<A, B, S>[src]

impl<A: Align, B: Default + Repr, const S: usize> Default for Vector<A, B, S>[src]

impl<A: Align, B: Repr, const S: usize> Deref for Vector<A, B, S>[src]

type Target = [B; S]

The resulting type after dereferencing.

impl<A: Align, B: Repr, const S: usize> DerefMut for Vector<A, B, S>[src]

impl<A: Align, B: Div<Output = B> + Repr, const S: usize> Div<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the / operator.

impl<A: Align, B: Div<Output = B> + Repr, const S: usize> Div<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the / operator.

impl<A: Align, B: DivAssign + Repr, const S: usize> DivAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: DivAssign + Repr, const S: usize> DivAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Eq + Repr, const S: usize> Eq for Vector<A, B, S>[src]

impl<I, A, B, const S: usize> Index<I> for Vector<A, B, S> where
    A: Align,
    B: Repr,
    [B; S]: Index<I>, 
[src]

type Output = <[B; S] as Index<I>>::Output

The returned type after indexing.

impl<I, A, B, const S: usize> IndexMut<I> for Vector<A, B, S> where
    A: Align,
    B: Repr,
    [B; S]: IndexMut<I>, 
[src]

impl<A: Align, B: Repr, const S: usize> Masked for Vector<A, B, S>[src]

type Mask = Vector<A, B::Mask, S>

The mask type for this vector. Read more

impl<A: Align, B: Mul<Output = B> + Repr, const S: usize> Mul<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the * operator.

impl<A: Align, B: Mul<Output = B> + Repr, const S: usize> Mul<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the * operator.

impl<A: Align, B: MulAssign + Repr, const S: usize> MulAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: MulAssign + Repr, const S: usize> MulAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Neg<Output = B> + Repr, const S: usize> Neg for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the - operator.

impl<A: Align, B: Not<Output = B> + Repr, const S: usize> Not for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the ! operator.

impl<A: Align, B: PartialEq + Repr, const S: usize> PartialEq<[B; S]> for Vector<A, B, S>[src]

impl<A: Align, B: PartialEq + Repr, const S: usize> PartialEq<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: PartialEq + Repr, const S: usize> PartialEq<Vector<A, B, S>> for [B; S][src]

impl<A: Align, B: MulAssign + Repr, const S: usize> Product<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Rem<Output = B> + Repr, const S: usize> Rem<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the % operator.

impl<A: Align, B: Rem<Output = B> + Repr, const S: usize> Rem<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the % operator.

impl<A: Align, B: RemAssign + Repr, const S: usize> RemAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: RemAssign + Repr, const S: usize> RemAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Shl<Output = B> + Repr, const S: usize> Shl<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the << operator.

impl<A: Align, B: Shl<Output = B> + Repr, const S: usize> Shl<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the << operator.

impl<A: Align, B: ShlAssign + Repr, const S: usize> ShlAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: ShlAssign + Repr, const S: usize> ShlAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Shr<Output = B> + Repr, const S: usize> Shr<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the >> operator.

impl<A: Align, B: Shr<Output = B> + Repr, const S: usize> Shr<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the >> operator.

impl<A: Align, B: ShrAssign + Repr, const S: usize> ShrAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: ShrAssign + Repr, const S: usize> ShrAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: Sub<Output = B> + Repr, const S: usize> Sub<B> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the - operator.

impl<A: Align, B: Sub<Output = B> + Repr, const S: usize> Sub<Vector<A, B, S>> for Vector<A, B, S>[src]

type Output = Self

The resulting type after applying the - operator.

impl<A: Align, B: SubAssign + Repr, const S: usize> SubAssign<B> for Vector<A, B, S>[src]

impl<A: Align, B: SubAssign + Repr, const S: usize> SubAssign<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<A: Align, B: AddAssign + Default + Repr, const S: usize> Sum<Vector<A, B, S>> for Vector<A, B, S>[src]

impl<'a, A: Align, B: Repr, const S: usize> Vectorizable<&'a mut Vector<A, B, S>> for &'a mut [Vector<A, B, S>][src]

type Padding = ()

The input type provided by user to fill in the padding/uneven end. Read more

type Vectorizer = &'a mut [Vector<A, B, S>]

An internal type managing the splitting into vectors. Read more

impl<'a, A: Align, B: Repr, const S: usize> Vectorizable<Vector<A, B, S>> for &'a [B][src]

type Vectorizer = ReadVectorizer<'a, A, B, S>

An internal type managing the splitting into vectors. Read more

type Padding = Vector<A, B, S>

The input type provided by user to fill in the padding/uneven end. Read more

impl<'a, A: Align, B: Repr, const S: usize> Vectorizable<Vector<A, B, S>> for &'a [Vector<A, B, S>][src]

type Padding = ()

The input type provided by user to fill in the padding/uneven end. Read more

type Vectorizer = &'a [Vector<A, B, S>]

An internal type managing the splitting into vectors. Read more

Auto Trait Implementations

impl<A, B, const S: usize> Send for Vector<A, B, S> where
    A: Send

impl<A, B, const S: usize> Sync for Vector<A, B, S> where
    A: Sync

impl<A, B, const S: usize> Unpin for Vector<A, B, S> where
    A: Unpin,
    B: Unpin

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.