Expand description
Lightweight generic fixed-array vector types.
This crate provides Simd, a fixed-lane vector type Simd<T, N> over
[T; N], with lane-wise arithmetic (vector/vector and vector/scalar),
multiply-add (fused where the target has hardware FMA; see below), float
functions, comparisons producing masks, mask selection, horizontal
reductions, and slice load/store — all implemented without intrinsics and
without runtime instruction dispatch.
Performance relies on the compiler auto-vectorizing this portable code;
build with -C target-cpu=native (or a similar target-cpu setting) to
obtain SIMD-level efficiency. Correctness does not depend on it.
Element categories are expressed by trait bounds rather than by distinct
types: arithmetic requires num_traits::Num, the float functions require
num_traits::Float, multiply-add requires num_traits::MulAdd where
the target has hardware FMA and core::ops::Mul with core::ops::Add
otherwise, and bitwise operations require the element’s own
core::ops implementations. bool is a valid element, and
Simd<bool, N> doubles as the mask type. The lane count N is an
arbitrary const generic.
A full one-file map of the API surface — written for users and AI coding
agents — lives in the guide module (kept as src/guide.md in the
repository).
Concrete aliases such as f64x8 are enforced-alignment types
(Aligned64<f64, 8>): array-backed siblings of Simd that
share one implementation — every operation is defined once for Simd and
the five aligned types together. The alignment is the vector’s byte size
rounded up to a power of two, capped at 64 bytes; conversions between plain
and aligned vectors are From/.0/to_simd. Masks (Simd<bool, N> and
the maskN aliases) carry no enforced alignment; per-lane selection is
mask_select on the value (available on every vector
type), or Simd::select on the mask for plain vectors.
§Multiply-add semantics
mul_add and fma_from follow the
compilation target (see docs/adr/0005 in the repository for the
measured trade-off):
- targets with hardware FMA — x86 built with
-C target-cpuofx86-64-v3or higher (includingnative), and all aarch64: the element’s fusednum_traits::MulAdd, a single rounding per lane, one FMA instruction per register, no extra flags. - targets without — generic x86-64,
x86-64-v2, and architectures the predicate does not know: a separated multiply and add (two roundings per lane) that never degrades into the slow software-fused libmfmacalls (~4.6x slower than separated there). Under-C llvm-args=-fp-contract=fastthis form still fuses into a hardware FMA instruction on capable targets. - the non-default cargo feature
use_libm_fmapins the fused form on every target, accepting the libm softwarefmawhere hardware is absent — use it when results must be bit-identical across build targets.
§Example
Same example as the README; kept as a doctest so it is verified by CI.
use lightweight_simd::{f64x8, Simd};
// typed aliases (enforced alignment) or the generic Simd<T, N>
let a = f64x8::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
let b = f64x8::splat(2.0);
let c = a.mul_add(b, f64x8::one()); // a*b + 1, fused on FMA targets
assert_eq!(c.reduce_sum(), 80.0);
let mask = a.simd_gt(f64x8::splat(4.0)); // comparisons -> masks
assert_eq!(a.mask_select(mask, b).to_array(), [2.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 8.0]);
let mut buf = [0.0; 8];
a.store_slice(&mut buf); // slice load/store
// any element type and lane count
let u = Simd::from([10u32, 20, 30]);
assert_eq!((u * 3).to_array(), [30, 60, 90]);Re-exports§
pub use aligned::Aligned4;pub use aligned::Aligned8;pub use aligned::Aligned16;pub use aligned::Aligned32;pub use aligned::Aligned64;
Modules§
- aligned
- Enforced-alignment vector types.
- guide
- Dummy doc-only module: renders
src/guide.md(the one-file API overview, also linked from the README) into the rustdoc output.
Structs§
- Simd
- A fixed-length vector of
Nlanes of element typeT.
Type Aliases§
- f32x2
- Alias of
Simd<f32, 2>with enforced alignment (Aligned8). - f32x4
- Alias of
Simd<f32, 4>with enforced alignment (Aligned16). - f32x8
- Alias of
Simd<f32, 8>with enforced alignment (Aligned32). - f32x16
- Alias of
Simd<f32, 16>with enforced alignment (Aligned64). - f64x2
- Alias of
Simd<f64, 2>with enforced alignment (Aligned16). - f64x4
- Alias of
Simd<f64, 4>with enforced alignment (Aligned32). - f64x8
- Alias of
Simd<f64, 8>with enforced alignment (Aligned64). - f64x16
- Alias of
Simd<f64, 16>with enforced alignment (Aligned64). - i8x8
- Alias of
Simd<i8, 8>with enforced alignment (Aligned8). - i8x16
- Alias of
Simd<i8, 16>with enforced alignment (Aligned16). - i8x32
- Alias of
Simd<i8, 32>with enforced alignment (Aligned32). - i8x64
- Alias of
Simd<i8, 64>with enforced alignment (Aligned64). - i16x4
- Alias of
Simd<i16, 4>with enforced alignment (Aligned8). - i16x8
- Alias of
Simd<i16, 8>with enforced alignment (Aligned16). - i16x16
- Alias of
Simd<i16, 16>with enforced alignment (Aligned32). - i16x32
- Alias of
Simd<i16, 32>with enforced alignment (Aligned64). - i32x4
- Alias of
Simd<i32, 4>with enforced alignment (Aligned16). - i32x8
- Alias of
Simd<i32, 8>with enforced alignment (Aligned32). - i32x16
- Alias of
Simd<i32, 16>with enforced alignment (Aligned64). - i64x2
- Alias of
Simd<i64, 2>with enforced alignment (Aligned16). - i64x4
- Alias of
Simd<i64, 4>with enforced alignment (Aligned32). - i64x8
- Alias of
Simd<i64, 8>with enforced alignment (Aligned64). - i64x16
- Alias of
Simd<i64, 16>with enforced alignment (Aligned64). - mask4
- Plain (unaligned) mask alias of
Simd<bool, 4>. - mask8
- Plain (unaligned) mask alias of
Simd<bool, 8>. - mask16
- Plain (unaligned) mask alias of
Simd<bool, 16>. - mask32
- Plain (unaligned) mask alias of
Simd<bool, 32>.