Skip to main content

Crate algea

Crate algea 

Source
Expand description

§algea

Crates.io Documentation CI License: MIT License: Apache-2.0

Portable, SIMD-accelerated vectors and matrices.

algea provides small fixed-size algebra types whose storage and operations are selected for the target. It supports f32, f64, i32, i64, u32, and u64 elements, with vector dimensions and matrix row and column counts from one through four. Both row_major and column_major matrix storage are supported.

Implementations pursue target-specific performance, so floating-point results are not guaranteed to be bit-for-bit identical; see Floating-point reproducibility.

§Stability

Documented public APIs follow Semantic Versioning.

The __internal module is public solely to support implementation details that must remain reachable across crate boundaries, including bounds on public APIs. It is not a supported public API and may be changed, moved, or removed in any release. Downstream crates must not refer to it directly.

§Examples

Vectors provide lane-wise arithmetic and common geometric operations:

use algea::vector;

let a = vector![1.0_f32, 2.0, 3.0];
let b = vector![4.0_f32, 5.0, 6.0];

assert_eq!(a + b, vector![5.0, 7.0, 9.0]);
assert_eq!(a.dot(b), 32.0);

Row-major matrices are constructed from rows:

use algea::row_major::Matrix;

let a = Matrix::<f32, 2, 2>::from_rows([[1.0, 2.0], [3.0, 4.0]]);
let b = Matrix::<f32, 2, 2>::from_rows([[5.0, 6.0], [7.0, 8.0]]);

assert_eq!((a * b).to_rows(), [[19.0, 22.0], [43.0, 50.0]]);

Column-major matrices represent the same operations but are constructed from columns:

use algea::column_major::Matrix;

let a = Matrix::<f32, 2, 2>::from_columns([[1.0, 3.0], [2.0, 4.0]]);
let b = Matrix::<f32, 2, 2>::from_columns([[5.0, 7.0], [6.0, 8.0]]);

assert_eq!((a * b).to_columns(), [[19.0, 43.0], [22.0, 50.0]]);

Elements convert between types with cast:

use algea::vector;

let v = vector![1.5_f64, -2.5, 3.5];

assert_eq!(v.cast::<i32>(), vector![1_i32, -2, 3]);

§Generic code

The Element family of traits expresses which element types and dimensions are available. Generic code can state that requirement in either of the following equivalent forms:

use algea::{Element, Vector};

fn by_parameter<T: Element<D>, const D: usize>(value: Vector<T, D>) {
    let _ = value;
}

fn by_where_clause<const D: usize>(value: Vector<f32, D>)
where
    f32: Element<D>,
{
    let _ = value;
}

§Arithmetic semantics

Operations follow std::simd::Simd, not the scalar operators, wherever the two differ. Integer addition, subtraction, multiplication, and negation therefore wrap in both debug and release builds; integer division by zero panics; and dividing the most negative value by -1 wraps back to that value. SIMD padding lanes do not participate in public operations or panic checks.

Casting an element follows Rust’s as conversion, as std::simd::Simd::cast does, for every pair of supported types. That includes saturation at the destination’s limits and NaN becoming zero when a floating-point value becomes an integer, and the sign of zero when a floating-point value changes width. The bit pattern of a NaN result is not specified.

§Floating-point reproducibility

A floating-point result is not guaranteed to be the same everywhere. What varies, and why:

  • Between targets. Each backend picks the order of additions and whether to use fused multiply-add from what the target offers, so the same expression can round differently on x86-64, aarch64 and WebAssembly.
  • Between target-feature sets of one target. Enabling FMA on x86-64, or relaxed-simd on WebAssembly, changes how many roundings an expression takes.
  • Between runtimes, on WebAssembly with relaxed-simd. Those instructions leave fusing to the runtime, so one binary can round differently under two engines. wasmtime -W relaxed-simd-deterministic=y pins it to the unfused behaviour.
  • Between versions of this crate. A release may change the shape of a kernel, and with it the order of additions.

Integer results, comparisons, and casts are exact, so none of this applies to them.

§Layout

Note: The layouts documented below describe the current implementation only. This crate does not guarantee that memory layout, size, alignment, padding, or element placement remains unchanged across crate versions, platforms, or selected backends. These details may change; do not rely on them for serialization, persistent data, FFI, or reinterpreting memory.

When the SIMD backend is selected, vectors have the following layouts. Sizes and alignments are in bytes. In both tables, a 32-bit T is f32, i32, or u32, and a 64-bit T is f64, i64, or u64.

TypeSize (32-bit)Alignment (32-bit)Size (64-bit)Alignment (64-bit)
Vector<T, 1>4488
Vector<T, 2>881616
Vector<T, 3>16163232
Vector<T, 4>16163232

SIMD-backed matrices have the following layouts. Each column-major matrix and the transposed row-major shape shown beside it use the same storage layout.

TypeSize (32-bit)Alignment (32-bit)Size (64-bit)Alignment (64-bit)
column_major::Matrix<T, 1, 1> / row_major::Matrix<T, 1, 1>4488
column_major::Matrix<T, 2, 1> / row_major::Matrix<T, 1, 2>881616
column_major::Matrix<T, 3, 1> / row_major::Matrix<T, 1, 3>16163232
column_major::Matrix<T, 4, 1> / row_major::Matrix<T, 1, 4>16163232
column_major::Matrix<T, 1, 2> / row_major::Matrix<T, 2, 1>881616
column_major::Matrix<T, 2, 2> / row_major::Matrix<T, 2, 2>16163232
column_major::Matrix<T, 3, 2> / row_major::Matrix<T, 2, 3>32166432
column_major::Matrix<T, 4, 2> / row_major::Matrix<T, 2, 4>32166432
column_major::Matrix<T, 1, 3> / row_major::Matrix<T, 3, 1>16163232
column_major::Matrix<T, 2, 3> / row_major::Matrix<T, 3, 2>321648 or 6416 or 32
column_major::Matrix<T, 3, 3> / row_major::Matrix<T, 3, 3>48169632
column_major::Matrix<T, 4, 3> / row_major::Matrix<T, 3, 4>48169632
column_major::Matrix<T, 1, 4> / row_major::Matrix<T, 4, 1>16163232
column_major::Matrix<T, 2, 4> / row_major::Matrix<T, 4, 2>32166432
column_major::Matrix<T, 3, 4> / row_major::Matrix<T, 4, 3>641612832
column_major::Matrix<T, 4, 4> / row_major::Matrix<T, 4, 4>641612832

The 2x3 shape is the one whose 64-bit storage depends on the target: three two-lane units, 48 bytes with alignment 16, unless a four-lane 64-bit value occupies one register, where it is two four-lane units, 64 bytes with alignment 32.

When the non-SIMD backend is selected, storage uses scalar arrays instead. A Vector<T, D> then has the size of D elements and the alignment of one, and a matrix has the size of R * C elements with the same alignment. The SIMD tables above therefore do not describe non-SIMD layouts.

§Comparison and alternatives

algea focuses on portable, target-selected SIMD implementations of small fixed-size vectors and matrices, with explicit row-major and column-major storage. Depending on the application, another crate may be a better fit.

✅ supported, ⚠️ conditional or partial, see the footnote, ❌ not supported.

Cratex86 SIMDARM NEONWasm SIMDno_stdGeneric elementGeneric sizeInteger vectorsLane-wise vector *Non-square matricesColumn-majorRow-majorSame results across targetsThree-lane vector4x4 matrix
algea✅✅✅❌✅⚠️ 1✅✅✅✅✅❌ 2Vector<f32, 3>Matrix<f32, 4, 4>
glam 0.33✅ 3✅ 3✅ 3✅ 4❌ 5❌✅✅❌✅❌✅ 6Vec3, Vec3A 3Mat4
nalgebra 0.35⚠️ 7⚠️ 7⚠️ 7✅ 4✅✅ 8✅❌ 9✅✅❌✅ 10Matrix<f32, U3, U1, ArrayStorage<f32, 3, 1>> 11Matrix<f32, U4, U4, ArrayStorage<f32, 4, 4>> 11
cgmath 0.18❌❌❌❌✅❌✅❌ 12❌✅❌✅ 10Vector3<f32>Matrix4<f32>
euclid 0.22❌❌❌✅✅ 13❌✅❌ 14❌✅❌✅ 10Vector3D<f32, U>Transform3D<f32, S, D>
ultraviolet 0.9⚠️ 15⚠️ 15⚠️ 15❌❌ 5❌⚠️ 16✅❌✅❌⚠️ 15Vec3Mat4
vek 0.17⚠️ 17⚠️ 17⚠️ 17✅✅❌✅✅❌✅✅ 18✅ 10Vec3<f32>Mat4<f32> 18
pathfinder_geometry 0.5✅⚠️ 19❌❌❌ 5❌⚠️ 20✅❌✅❌❌Vector3FTransform4F

§License

Licensed under either of Apache License, Version 2.0 or the MIT license, at your option.


  1. Vector dimensions and matrix row and column counts are generic parameters, but only one through four are implemented. ↩

  2. See Floating-point reproducibility for what varies and why. Whether the other crates hold their arithmetic fixed from one version to the next is not stated here either way. ↩

  3. On by default and used for Vec3A, Mat4 and the other 16-byte-aligned types; the scalar-math feature turns it off and core-simd swaps it for std::simd. ↩ 1 2 3 4

  4. With default-features = false, and a libm feature for the floating-point functions. ↩ 1 2

  5. Separate concrete types per element type rather than one generic type. ↩ 1 2 3

  6. Documented as the default, with the fast-math feature as the opt-out that allows platform-specific optimizations. ↩

  7. SIMD comes from simba’s SIMD element types, which put several matrices in the lanes of one value rather than the lanes of one matrix. The crate itself has no target-specific code paths. ↩ 1 2 3

  8. Also SMatrix<f32, R, C> for any static size, dimensions beyond four, dynamically sized matrices, and decompositions. ↩

  9. * is the matrix product, and a vector is a one-column matrix, so v * w does not compile. The element-wise product is the component_mul method. ↩

  10. Follows from having no target-specific code paths, rather than from a documented guarantee. ↩ 1 2 3 4

  11. Usually written through the aliases Vector3<f32> and Matrix4<f32>. ↩ 1 2

  12. * multiplies by a scalar. The element-wise product is ElementWise::mul_element_wise. ↩

  13. Also generic over a unit marker, so lengths in different spaces do not mix. ↩

  14. * multiplies by a scalar or applies a transform. The element-wise product is the component_mul method. ↩

  15. In the wide types, Vec3x4 and Mat4x4 for example. Each of those holds four or eight separate vectors or matrices, one per lane, and follows wide’s per-target paths; a lone Vec3 or Mat4 is plain scalar code. ↩ 1 2 3 4

  16. Needs the int feature, which is not enabled by default. ↩

  17. The repr_simd feature unlocks SIMD variants of the types, and needs a nightly compiler. ↩ 1 2 3

  18. Mat4<f32> is the column-major type; the row-major one is vek::mat::repr_c::row_major::Mat4<f32>. ↩ 1 2

  19. Only on a nightly compiler. ↩

  20. Vector2I only. ↩

Re-exports§

pub use support::Element;
pub use support::FloatElement;
pub use support::IntElement;
pub use support::MaskElement;
pub use support::SintElement;
pub use support::UintElement;

Modules§

column_major
Column-major matrices and their multiplication traits.
marker
Marker traits describing scalar lane capabilities.
row_major
Row-major matrices and their multiplication traits.
support
Dimension-dependent traits used to express supported vector and matrix types.

Macros§

vector
Constructs a vector by concatenating scalar and vector expressions.

Structs§

Mask
A lane mask represented by signed integer lanes.
Vector
A fixed-size, orientation-independent vector.

Traits§

EachOrd
Provides lane-wise ordering operations.
Select
Selects lanes from two values according to a mask.