pub trait Backend<T: Scalar>: Copy {
type Vector: Copy;
type Mask: Copy;
type IVector: Copy;
const UNROLL: usize = 4;
Show 55 methods
// Required methods
fn lanes(self) -> usize;
fn splat(self, v: T) -> Self::Vector;
fn load(self, s: &[T]) -> Self::Vector;
fn store(self, v: Self::Vector, s: &mut [T]);
fn add(self, a: Self::Vector, b: Self::Vector) -> Self::Vector;
fn sub(self, a: Self::Vector, b: Self::Vector) -> Self::Vector;
fn mul(self, a: Self::Vector, b: Self::Vector) -> Self::Vector;
fn neg(self, a: Self::Vector) -> Self::Vector;
fn min(self, a: Self::Vector, b: Self::Vector) -> Self::Vector;
fn max(self, a: Self::Vector, b: Self::Vector) -> Self::Vector;
fn le(self, a: Self::Vector, b: Self::Vector) -> Self::Mask;
fn lt(self, a: Self::Vector, b: Self::Vector) -> Self::Mask;
fn ge(self, a: Self::Vector, b: Self::Vector) -> Self::Mask;
fn gt(self, a: Self::Vector, b: Self::Vector) -> Self::Mask;
fn mask_and(self, a: Self::Mask, b: Self::Mask) -> Self::Mask;
fn mask_or(self, a: Self::Mask, b: Self::Mask) -> Self::Mask;
fn mask_not(self, a: Self::Mask) -> Self::Mask;
fn select(
self,
m: Self::Mask,
a: Self::Vector,
b: Self::Vector,
) -> Self::Vector;
fn any(self, m: Self::Mask) -> bool;
fn all(self, m: Self::Mask) -> bool;
fn reduce_sum(self, v: Self::Vector) -> T;
fn reduce_min(self, v: Self::Vector) -> T;
fn reduce_max(self, v: Self::Vector) -> T;
fn iload(self, s: &[u32]) -> Self::IVector;
fn istore(self, v: Self::IVector, out: &mut [u32]);
// Provided methods
fn div(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vector
where T: FloatScalar { ... }
fn fma(
self,
_a: Self::Vector,
_b: Self::Vector,
_c: Self::Vector,
) -> Self::Vector
where T: FloatScalar { ... }
fn sqrt(self, _a: Self::Vector) -> Self::Vector
where T: FloatScalar { ... }
fn madd(
self,
a: Self::Vector,
b: Self::Vector,
acc: Self::Vector,
) -> Self::Vector { ... }
fn shl(self, _a: Self::Vector, _k: u32) -> Self::Vector
where T: IntScalar { ... }
fn shr(self, _a: Self::Vector, _k: u32) -> Self::Vector
where T: IntScalar { ... }
fn bit_and(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vector
where T: IntScalar { ... }
fn bit_or(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vector
where T: IntScalar { ... }
fn bit_xor(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vector
where T: IntScalar { ... }
fn bit_not(self, _a: Self::Vector) -> Self::Vector
where T: IntScalar { ... }
fn abs(self, a: Self::Vector) -> Self::Vector { ... }
fn mask_bitmask(self, m: Self::Mask) -> u32 { ... }
fn isplat(self, v: u32) -> Self::IVector { ... }
fn iramp(self) -> Self::IVector { ... }
fn iadd(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn isub(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn imul(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn iand(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn ior(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn ixor(self, a: Self::IVector, b: Self::IVector) -> Self::IVector { ... }
fn inot(self, a: Self::IVector) -> Self::IVector { ... }
fn ishl(self, a: Self::IVector, k: u32) -> Self::IVector { ... }
fn ishr(self, a: Self::IVector, k: u32) -> Self::IVector { ... }
fn ishr_arith(self, a: Self::IVector, k: u32) -> Self::IVector { ... }
fn ieq(self, a: Self::IVector, b: Self::IVector) -> Self::Mask { ... }
fn ilt_u(self, a: Self::IVector, b: Self::IVector) -> Self::Mask { ... }
fn ilt_s(self, a: Self::IVector, b: Self::IVector) -> Self::Mask { ... }
fn iselect(
self,
m: Self::Mask,
a: Self::IVector,
b: Self::IVector,
) -> Self::IVector { ... }
fn to_bits(self, v: Self::Vector) -> Self::IVector { ... }
fn from_bits(self, v: Self::IVector) -> Self::Vector { ... }
}Expand description
An instruction-set execution context for scalar T. Implemented by ScalarBackend
(every T) and, per (ISA, scalar), by the hand-rolled core::arch backends.
Provided Associated Constants§
Sourceconst UNROLL: usize = 4
const UNROLL: usize = 4
Independent accumulator chains the multi-accumulator reductions (Gang::reduce,
Gang::zip_reduce, Gang::count_n) run: the ILP unroll factor, a compile-time constant
baked in at dispatch. Must not exceed MAX_UNROLL. The default suits
x86’s 2–3 vector pipes; wide cores (Apple NEON, SVE) raise it, the scalar floor drops it to 1.
Required Associated Types§
Sourcetype Vector: Copy
type Vector: Copy
The varying register holding Backend::lanes elements of T.
Sourcetype Mask: Copy
type Mask: Copy
The boolean mask companion to Backend::Vector.
Sourcetype IVector: Copy
type IVector: Copy
The 32-bit integer companion register: lanes() lanes of u32 (reinterpretable as
i32) riding alongside the float lanes, for lane indices, counters, and bit manipulation.
Every default below is a correct-but-slow store/compute/reload round-trip; backends with
native integer lanes override the ones that matter.
Required Methods§
fn splat(self, v: T) -> Self::Vector
Sourcefn load(self, s: &[T]) -> Self::Vector
fn load(self, s: &[T]) -> Self::Vector
Load exactly one register. s.len() must equal Backend::lanes.
Sourcefn store(self, v: Self::Vector, s: &mut [T])
fn store(self, v: Self::Vector, s: &mut [T])
Store exactly one register. s.len() must equal Backend::lanes.
fn add(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
fn sub(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
fn mul(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
Sourcefn neg(self, a: Self::Vector) -> Self::Vector
fn neg(self, a: Self::Vector) -> Self::Vector
Negation: IEEE sign flip for the float elements, wrapping for the integer elements.
Sourcefn min(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
fn min(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
Lane-wise IEEE 754-2019 minimumNumber: if exactly one operand of a lane is NaN, that lane
takes the other operand; NaN comes out only when both are NaN. Which zero wins a
-0.0/+0.0 tie is backend-specific. Every backend implements this contract, natively
where the ISA has it (aarch64 FMINNM, RVV vfmin), with a NaN-patching fixup where it
doesn’t (x86 min + unord-blend, wasm pmin + bitselect).
Sourcefn max(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
fn max(self, a: Self::Vector, b: Self::Vector) -> Self::Vector
Lane-wise IEEE 754-2019 maximumNumber; see min for the NaN contract.
fn le(self, a: Self::Vector, b: Self::Vector) -> Self::Mask
fn lt(self, a: Self::Vector, b: Self::Vector) -> Self::Mask
fn ge(self, a: Self::Vector, b: Self::Vector) -> Self::Mask
fn gt(self, a: Self::Vector, b: Self::Vector) -> Self::Mask
fn mask_and(self, a: Self::Mask, b: Self::Mask) -> Self::Mask
fn mask_or(self, a: Self::Mask, b: Self::Mask) -> Self::Mask
fn mask_not(self, a: Self::Mask) -> Self::Mask
fn select(self, m: Self::Mask, a: Self::Vector, b: Self::Vector) -> Self::Vector
fn reduce_sum(self, v: Self::Vector) -> T
Sourcefn reduce_min(self, v: Self::Vector) -> T
fn reduce_min(self, v: Self::Vector) -> T
Horizontal minimum with min’s minimumNumber semantics folded pairwise:
NaN lanes are ignored, and the result is NaN only if every lane is NaN.
Sourcefn reduce_max(self, v: Self::Vector) -> T
fn reduce_max(self, v: Self::Vector) -> T
Horizontal maximum; see reduce_min.
Provided Methods§
Sourcefn div(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: FloatScalar,
fn div(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: FloatScalar,
Float-family only. where T: FloatScalar makes integer-element calls a compile error, so
the defaults below are statically unreachable; float backends override them.
fn fma(
self,
_a: Self::Vector,
_b: Self::Vector,
_c: Self::Vector,
) -> Self::Vectorwhere
T: FloatScalar,
fn sqrt(self, _a: Self::Vector) -> Self::Vectorwhere
T: FloatScalar,
Sourcefn madd(
self,
a: Self::Vector,
b: Self::Vector,
acc: Self::Vector,
) -> Self::Vector
fn madd( self, a: Self::Vector, b: Self::Vector, acc: Self::Vector, ) -> Self::Vector
a*b + acc with the element family’s natural fusion: float backends override this with
their fused fma; integer elements and the portable default use the two-op multiply-add
(wrapping for ints). Family-neutral so shared machinery (the runtime unroll sweep, generic
reduction steps) can use it without a FloatScalar bound.
Sourcefn shl(self, _a: Self::Vector, _k: u32) -> Self::Vectorwhere
T: IntScalar,
fn shl(self, _a: Self::Vector, _k: u32) -> Self::Vectorwhere
T: IntScalar,
Integer-family only: lane-wise shift by a uniform count (k < 32). shr is logical
(zero-filling) for u32, arithmetic (sign-filling) for i32. Statically unreachable
defaults, same scheme as div.
fn shr(self, _a: Self::Vector, _k: u32) -> Self::Vectorwhere
T: IntScalar,
Sourcefn bit_and(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: IntScalar,
fn bit_and(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: IntScalar,
Integer-family lane-wise bitwise ops.
fn bit_or(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: IntScalar,
fn bit_xor(self, _a: Self::Vector, _b: Self::Vector) -> Self::Vectorwhere
T: IntScalar,
fn bit_not(self, _a: Self::Vector) -> Self::Vectorwhere
T: IntScalar,
Sourcefn abs(self, a: Self::Vector) -> Self::Vector
fn abs(self, a: Self::Vector) -> Self::Vector
Absolute value. The default is max(a, -a); backends override with a dedicated
instruction or a sign-bit clear.
Sourcefn mask_bitmask(self, m: Self::Mask) -> u32
fn mask_bitmask(self, m: Self::Mask) -> u32
Pack the mask into the low lanes bits of a u32: bit i set iff lane
i is set; bits at and above lanes() are zero. Lets a caller popcount the set lanes or
walk them by trailing_zeros. The default materializes the mask through select+store
and packs scalar; fixed-width backends override it with a native movemask. lanes() never
exceeds MAX_LANES (32), so a u32 always has room.
fn isplat(self, v: u32) -> Self::IVector
Sourcefn iadd(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
fn iadd(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
Wrapping lane-wise arithmetic, matching SIMD integer instruction semantics.
fn isub(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
Sourcefn imul(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
fn imul(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
Low 32 bits of the lane-wise product (vmul/pmulld semantics, identical for u32
and i32).
fn iand(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
fn ior(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
fn ixor(self, a: Self::IVector, b: Self::IVector) -> Self::IVector
fn inot(self, a: Self::IVector) -> Self::IVector
Sourcefn ishl(self, a: Self::IVector, k: u32) -> Self::IVector
fn ishl(self, a: Self::IVector, k: u32) -> Self::IVector
Lane-wise shifts by a uniform count; k must be < 32.
Sourcefn ishr(self, a: Self::IVector, k: u32) -> Self::IVector
fn ishr(self, a: Self::IVector, k: u32) -> Self::IVector
Logical (zero-filling) right shift; k must be < 32.
Sourcefn ishr_arith(self, a: Self::IVector, k: u32) -> Self::IVector
fn ishr_arith(self, a: Self::IVector, k: u32) -> Self::IVector
Arithmetic (sign-filling) right shift, for the i32 view; k must be < 32.
fn ieq(self, a: Self::IVector, b: Self::IVector) -> Self::Mask
Sourcefn ilt_s(self, a: Self::IVector, b: Self::IVector) -> Self::Mask
fn ilt_s(self, a: Self::IVector, b: Self::IVector) -> Self::Mask
Signed lane-wise < (the i32 view).
Sourcefn iselect(
self,
m: Self::Mask,
a: Self::IVector,
b: Self::IVector,
) -> Self::IVector
fn iselect( self, m: Self::Mask, a: Self::IVector, b: Self::IVector, ) -> Self::IVector
m ? a : b on integer lanes, with the same Mask the float compares
produce.
Sourcefn to_bits(self, v: Self::Vector) -> Self::IVector
fn to_bits(self, v: Self::Vector) -> Self::IVector
Reinterpret each float lane’s bit pattern as a u32 lane: exact for 32-bit T; 16-bit
T zero-extends; f64 truncates to the low half (see Scalar::to_bits32).
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".