Expand description
User-facing vector types and the trait hierarchy that defines them.
This module is the top of Thermite’s public API. It provides the
Vector<R> newtype - the value you actually compute with - and the tower
of traits (GenericVector and its descendants) that describe what a
vector can do.
§Generic over behavior, not over a backend
The central idea of Thermite is that you write code against
GenericVector (or a more specific trait like NumericVector,
FloatVector, or IntegerVector) and let the caller pick the concrete
type. That concrete type decides the ISA, the lane count, and the element
type - your code does not name any of them:
use thermite::prelude::*;
use thermite::math::TranscendentalMath;
// Works on any backend, any width, any float element type.
fn gaussian<V: FloatVector + TranscendentalMath>(v: V) -> V {
(-v * v).exp()
}Crucially, “generic” here is stronger than “generic over the hardware
backend”. A GenericVector is not required to be a dense array of scalars
sitting in a hardware register at all. The trait describes an algebra of
lanes, and anything that satisfies that algebra is a first-class vector.
§Composable abstractions all the way up
Because the trait bounds are the only contract, wrapper types that are not SIMD registers in any conventional sense can still implement the hierarchy and flow through the very same generic functions:
- Complex numbers - a
Complex<V>pairing two real vectors implements theGenericVector/FloatVectortraits, so a function written for realFloatVectors operates transparently on complex data. - Compensated arithmetic - a double-double
Compensated<V>that tracks rounding error implements the same traits; existing generic code gains extended precision just by being instantiated with it. - Dual / hyperdual numbers - automatic differentiation via the same trait composition, so a generic numeric routine differentiates itself when handed a dual type.
And these compose: Complex<Compensated<f32x8>> is a perfectly valid vector
type where every complex operation is carried out in compensated real
arithmetic, all still SIMD-accelerated underneath. The function you wrote
once against FloatVector does not change.
§The trait hierarchy
Each trait adds capability on top of the previous one; bound on the least specific trait that supplies the operations you need.
GenericVector construction, lane access, memory I/O, gather/scatter,
| reinterpretation, map/fold/reduce, interleave
|- BitwiseVector &, |, ^, !, andnot, ternlog
| \- BitshiftVector shifts, rotations, byte-shifts
\- PartialOrdVector cmp_lt/le/gt/ge/eq/ne -> Mask
\- NumericVector +, -, *, /, %, min/max/clamp, reductions, FMA
|- SignedVector abs, signum, copysign, neg
| \- FloatVector sqrt, rcp/rsqrt, rounding, mix, consts
| \- FloatVectorWithBits ldexp/frexp, bit-level ops
\- IntegerVector saturating/wrapping, popcount, dividers
| (also requires BitshiftVector)
|- SignedIntegerVector arithmetic shift, avg
| (also requires SignedVector)
\- UnsignedIntegerVector is_power_of_two, parity, avgFloatVector and SignedIntegerVector both sit under SignedVector;
SignedIntegerVector additionally requires IntegerVector, so it is the
meeting point of the signed and integer branches. IntegerVector itself
does not require SignedVector - unsigned integer vectors are
integers without being signed.
Alongside these, LinAlg3Vector/LinAlg4Vector add 3D/4D linear-algebra
operations, and the Swizzle/Swizzle3/Swizzle4 traits add lane
permutation. Masked (_c/_m/_z) variants of most operations live in the
ops submodule.
Three layers cooperate to make all of this work: an Element (the scalar),
a Register (the functional hardware layer),
and Vector<R> (this module’s ergonomic wrapper). Most users only ever
touch the Vector layer and its traits.
Re-exports§
pub use crate::register::StreamGroup;
Modules§
- ops
- Operator traits behind the vector arithmetic, plus the masked
_c/_m/_zforms of each. - streaming
- Non-temporal (streaming) vector loads and stores.
- unaligned
- Unaligned vector loads and stores, directly and via iterators.
Structs§
- NumVector
- Wraps a generic vector to provide implementations of
num_traitstraits. - Value
Groups - Lanes of a vector partitioned into groups of equal value, produced by
group_by_value. - Vector
- SIMD Vector type.
Traits§
- AsFloat
Vector With Bits Kernel - Some algorithms may benefit from being able to access the bitwise representation of floating point vectors. However, not all vectors support this functionality, and those that do may be passed as generic FloatVector. Therefore, this is a way of upcasting a FloatVector to a FloatVectorWithBits, if possible. If not possible, returns None.
- BitCast
Vector - Zero-cost bit-level reinterpretation between vector types of the same size and lane count.
- Bitshift
Vector - Shifts and rotates over the lanes of an integer vector, by an immediate, by a runtime scalar, or by a per-lane count.
- Bitwise
Vector - Bitwise operations over the lanes of a vector:
&,|,^,!,bitandnot, and the arbitrary three-inputternlog. - Cast
Vector - Per-lane numeric conversion between vector types.
- Concat
- Joining two
HALF-width values into one double-widthSelf, and splitting back apart. - Concat
Vector Concatspecialized to vector types:Selfis aGenericVectorthat is the concatenation of twoHALFvectors of the same element type, and whose mask is likewise the concatenation of twoHALFmasks.- Extend
- Zero-extend a narrower
FROMvalue into a widerSelf, and narrow back. - Extend
Vector - Zero-extend vectors
- Float
Vector - Floating-point vectors: the bound most user code should be written against.
- Float
Vector With Bits - A
FloatVectorthat additionally exposes its raw bit representation as companion integer vectors, enabling bit-level float algorithms. - Float
Vector With Register - Float vector types which have an associated hardware register type.
- Fully
Interoperable PartiallyInteroperableplus zero-cost bit-level reinterpretation (BitCastVector) amongSelf,A, andB.- Generic
Vector - Core trait for generic vector types.
- Generic
Vector2 - Convenience accessors
x()/y()automatically available on any 2-laneGenericVector. - Generic
Vector3 - Convenience accessors
x()/y()/z()automatically available on any 3-laneGenericVector. - Generic
Vector4 - Convenience accessors
x()/y()/z()/w()automatically available on any 4-laneGenericVector. - Indexable
Vector - A vector type that supports gather/scatter using index vectors of type
I. - Integer
Vector - Vectors of integer elements.
- Interleave
- Pairwise lane interleaving and its exact inverse, the building block for moving between array-of-structs and struct-of-arrays layouts.
- LinAlg3
Vector - Vector suitable for 3D linear algebra operations.
- LinAlg4
Vector - Vector suitable for 4D linear algebra operations.
- Mask
Interoperable - Three vector types (
Self,A,B) whose masks can all be freely cast to one another. - NewConst
- Carrier for a compile-time constant array of
Nper-lane values of element typeE. - NewVector
- A vector type that can build a constant of itself from a compile-time
NewConstarray carrier. - Numeric
Vector - Vectors that support arithmetic and comparison operations on their elements.
- Packed
Float Vector - A
u16/u8integer vector reinterpreted as a vector of packed floats (formatS: fp16, bfloat16, the fp8 variants, …), transcodable to and from the widerf32vectorFof the same lane count. - Partial
OrdVector - Per-lane comparison producing a
Mask. - Partially
Interoperable MaskInteroperableplus bidirectional numeric (CastVector) conversion amongSelf,A, andB.- Sad16
Vector - A
u8vector whose absolute differences can be summed in groups of 2 byte-lanes into theu16vectorW(same total width,LANES / 2output lanes). - Sad32
Vector - A
u8vector whose absolute differences can be summed in groups of 4 byte-lanes into theu32vectorW(same total width,LANES / 4output lanes). - Sad64
Vector - A
u8vector whose absolute differences can be summed in groups of 8 byte-lanes into theu64vectorW(same total width,LANES / 8output lanes) - x86PSADBWsemantics. - Signed
Integer Vector - The operations that need both a sign and integer lanes: arithmetic (sign-filling) right shifts, the overflow-free averages, and the rounded high-half multiply.
- Signed
Integer Vector With Register - SignedBits integer vector types which have an associated hardware register type.
- Signed
Vector - Vectors whose elements can represent negative values.
- Splat
Const - Simple associated constant splat trait.
- Splat
Vector - A vector type that can splat a compile-time
SplatConstcarrier into a constant of itself. - Swizzle3
- Only available for “3-lane” (ignoring 4th lane)
LinAlg3Registervectors, this allows human-readable swizzle/permutations of the vector. Permutations will ignore the 4th lane of the register, leaving it unchanged. - Swizzle4
- Only available for 4-lane vectors, this allows human-readable swizzle/permutations of the vector.
- Swizzle
Vector - A
GenericVectorwhose lanes can be permuted by theSwizzlemachinery for its lane count. - Unsigned
Integer Vector - The operations that read better on unsigned lanes: the power-of-two and inclusive-range predicates, and the unsigned averages.
- Unsigned
Integer Vector With Register - Unsigned integer vector types which have an associated hardware register type.
- Vector
Indices - An unsigned integer vector that can be used as the index operand for
gather/scatter operations producing/consuming a vector of type
V. - Vector
Value - Associates a constant carrier
Cwith the concrete vector constantVit produces. - Vector
With Register - Escape hatch tying a
Vectorto its specific underlyingRegistertype.
Functions§
- const_
new - Build a vector
Vfrom the compile-time constant per-lane array carried byC. - const_
splat - Build a vector
Vwith every lane set to the compile-time constant carried byE.