pub trait SimdNarrow<S: Simd>: SimdBase<S> + Seal {
type Narrowed: SimdWiden<S, Widened = Self>;
// Required methods
fn narrow(self, high: Self) -> Self::Narrowed;
fn saturating_narrow(self, high: Self) -> Self::Narrowed;
fn relaxed_narrow(self, high: Self) -> Self::Narrowed;
}Expand description
Narrowing conversion of two numeric SIMD vectors.
Both inputs have the same bit width as the result. The first input supplies the lower result
lanes and the second input supplies the upper result lanes. Integer narrowing either retains
the low destination-width bits or saturates, depending on the method. Floating-point narrowing
converts f64 to f32 using Rust’s as semantics; for floats,
saturating_narrow and
relaxed_narrow are identical to narrow.
use fearless_simd::{f32x4, f64x2, prelude::*, i16x8, i8x16};
fn fixed<S: Simd>(low: i16x8<S>, high: i16x8<S>) -> i8x16<S> {
low.narrow(high)
}
fn native<S: Simd>(low: S::i16s, high: S::i16s) -> S::i8s {
low.saturating_narrow(high)
}
fn fixed_float<S: Simd>(low: f64x2<S>, high: f64x2<S>) -> f32x4<S> {
low.narrow(high)
}
fn native_float<S: Simd>(low: S::f64s, high: S::f64s) -> S::f32s {
low.saturating_narrow(high)
}Required Associated Types§
Required Methods§
Sourcefn narrow(self, high: Self) -> Self::Narrowed
fn narrow(self, high: Self) -> Self::Narrowed
Narrow every lane.
This conversion behaves identically to the as operator:
- Integers are truncated.
- Floating-point values follow IEEE 754 narrowing behavior in round-to-even mode:
they are rounded to the nearest representable
f32, with ties resolved to even; overflow produces signed infinity.
§Example
use fearless_simd::{dispatch, Level, i64x2, i32x4, prelude::*};
let level = Level::new();
dispatch!(level, simd => {
let low = i64x2::simd_from(simd, [1, -1]);
let high = i64x2::simd_from(simd, [i64::MAX - 5, i64::MIN + 5]);
let narrowed: i32x4<_> = low.narrow(high);
assert_eq!(*narrowed, [1, -1, -6, 5]);
});Sourcefn saturating_narrow(self, high: Self) -> Self::Narrowed
fn saturating_narrow(self, high: Self) -> Self::Narrowed
Narrow with saturation for integers. Floats behave identically to narrow.
Integer values that overflow the narrowed type become the closest representable value for the narrowed type.
For example, 1234u16 becomes u8::MAX after narrowing, and -1234i16 becomes i8::MIN.
§Example
use fearless_simd::{dispatch, Level, i64x2, i32x4, prelude::*};
let level = Level::new();
dispatch!(level, simd => {
let low = i64x2::simd_from(simd, [1, -1]);
let high = i64x2::simd_from(simd, [i64::MAX - 5, i64::MIN + 5]);
let narrowed: i32x4<_> = low.saturating_narrow(high);
assert_eq!(*narrowed, [1, -1, i32::MAX, i32::MIN]);
});Sourcefn relaxed_narrow(self, high: Self) -> Self::Narrowed
fn relaxed_narrow(self, high: Self) -> Self::Narrowed
Narrow using the cheapest operation for the active SIMD backend, assuming no overflow.
This is useful when you’re sure the result fits into the destination type,
so the distinction between narrow and saturating_narrow
doesn’t matter.
This method will panic in debug mode if any of the inputs do not fit into the narrower type. This operation remains memory-safe and never causes undefined behavior, but will produce arbitrary values on overflow in release mode.
Floats behave identically to narrow, with no additional precondition.
§Example
use fearless_simd::{dispatch, Level, i64x2, i32x4, prelude::*};
let level = Level::new();
dispatch!(level, simd => {
let low = i64x2::simd_from(simd, [1, -1]);
let high = i64x2::simd_from(simd, [5, -5]);
let narrowed: i32x4<_> = low.relaxed_narrow(high);
assert_eq!(*narrowed, [1, -1, 5, -5]);
});Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".