Masks
Rust also provides a “truthy” vector type: Mask<T, N>
.
While operating like bool
, the element type of a mask is always a signed integer.
The size of the integer corresponds to the vector elements that the mask can interact with.
Masks operate like [bool; N]
, but their layout is unspecified and target-specific.
Elementwise operations with masks
Masks are typically produced by comparisons. Like vectors, they also support elementwise operations:
#![feature(portable_simd)] fn main() {} // mask32x4 is an alias for Mask<i32, 4> // // SimdPartialOrd is the elementwise counterpart to PartialOrd, // and provides `simd_lt`, `simd_gt`, etc. use std::simd::{f32x4, mask32x4, SimdPartialOrd}; fn is_between(x: f32x4, lower_bound: f32x4, upper_bound: f32x4) -> mask32x4 { let above_lower_bound: mask32x4 = x.simd_gt(lower_bound); let below_upper_bound: mask32x4 = x.simd_lt(upper_bound); above_lower_bound & below_upper_bound }
Reduction operations
Masks also support reduction operations:
#![feature(portable_simd)] fn main() {} use std::simd::{f32x4, mask32x4, SimdFloat}; // SimdFloat provides is_infinite fn any_infinite(vectors: &[f32x4]) -> bool { let mut infinite = mask32x4::splat(false); for v in vectors { infinite |= v.is_infinite(); } // check if any element is `true` infinite.any() }
Conditionally selecting elements
Masks can be used to conditionally select elements from two vectors:
#![feature(portable_simd)] fn main() {} use std::simd::{f32x4, mask32x4, SimdFloat}; // SimdFloat provides is_nan /// replace nan values with 0 fn replace_nan(x: f32x4) -> f32x4 { let nans: mask32x4 = x.is_nan(); nans.select(f32x4::splat(0.0), x) }