ggmath/lib.rs
1//! A fast linear algebra library for games and graphics.
2//!
3//! - Vectors: [`Vec2<T>`], [`Vec3<T>`], [`Vec4<T>`]
4//! - Square Matrices: [`Mat2<T>`], [`Mat3<T>`], [`Mat4<T>`]
5//! - Quaternions: [`Quat<T>`]
6//! - Affine Transforms: [`Affine2<T>`], [`Affine3<T>`]
7//! - Masks: [`Mask2<T>`], [`Mask3<T>`], [`Mask4<T>`]
8//!
9//! SIMD variants:
10//!
11//! - Vectors: [`Vec2A<T>`], [`Vec3A<T>`], [`Vec4A<T>`]
12//! - Square Matrices: [`Mat2A<T>`], [`Mat3A<T>`], [`Mat4A<T>`]
13//! - Quaternions: [`QuatA<T>`]
14//! - Affine Transforms: [`Affine2A<T>`], [`Affine3A<T>`]
15//! - Masks: [`Mask2A<T>`], [`Mask3A<T>`], [`Mask4A<T>`]
16//!
17//! Underlying generic types:
18//!
19//! - [`Vector<N, T, A>`]
20//! - [`Matrix<N, T, A>`]
21//! - [`Quaternion<T, A>`]
22//! - [`Affine<N, T, A>`]
23//! - [`Mask<N, T, A>`]
24//!
25//! # SIMD
26//!
27//! SIMD variants use specialization to have appropriate alignment and to use
28//! explicit SIMD in function implementations.
29//!
30//! SIMD results in faster computations, but can actually hurt performance if
31//! the bottleneck is memory bandwidth rather than computation throughput. For
32//! maximum performance, there are both SIMD, non-SIMD and SoA types
33//! ([see below](#soa)).
34//!
35//! | Type | [`Vec3<f32>`] | [`Vec3A<f32>`] | [`Mat3<f32>`] | [`Mat3A<f32>`] |
36//! | ----------------- | ------------- | -------------- | ------------- | -------------- |
37//! | Size (bytes) | 12 | 16 | 36 | 48 |
38//! | Alignment (bytes) | 4 | 16 | 4 | 16 |
39//! | Padding (bytes) | 0 | 4 | 0 | 12 |
40//!
41//! | Type | [`Vec4<f32>`] | [`Vec4A<f32>`] | [`Mat4<f32>`] | [`Mat4A<f32>`] |
42//! | ----------------- | ------------- | -------------- | ------------- | -------------- |
43//! | Size (bytes) | 16 | 16 | 64 | 64 |
44//! | Alignment (bytes) | 4 | 16 | 4 | 16 |
45//! | Padding (bytes) | 0 | 0 | 0 | 0 |
46//!
47//! > This table is true only for target architectures that have SIMD and are
48//! > supported. Types incompatible with SIMD use fallback implementations.
49//! > Currently support is limited to [`f32`] types on x86 and aarch64.
50//!
51//! # Generics
52//!
53//! The underlying types are generic over:
54//!
55//! - `T`: The element type
56//! - `N`: The dimension
57//! - `A`: The alignment mode (SIMD or non-SIMD)
58//!
59//! The traits [`PrimitiveFloat`], [`PrimitiveInteger`], [`PrimitiveSigned`] and
60//! [`PrimitiveUnsigned`] give generic contexts access to most primitive
61//! functionality. These traits do not expose functions directly, they only
62//! enable functionality for vectors, matrices, etc. For complete primitive
63//! generics, add the [`num-primitive`] crate as an optional dependency.
64//!
65//! # Affine transforms
66//!
67//! An affine transform contains a linear transformation and a translation
68//! vector. It can represent scale, rotation, shear and translation, but cannot
69//! represent projections. [`Affine2<T>`] is equivalent to [`Mat3<T>`], and
70//! [`Affine3<T>`] is equivalent to [`Mat4<T>`].
71//!
72//! Affine transforms take less memory than matrices and perform better for
73//! select operations (see [benchmark results]).
74//!
75//! | Type | [`Affine2<f32>`] | [`Mat3<f32>`] | [`Affine2A<f32>`] | [`Mat3A<f32>`] |
76//! | ----------------- | ---------------- | ------------- | ----------------- | -------------- |
77//! | Size (bytes) | 24 | 36 | 32 | 48 |
78//! | Alignment (bytes) | 4 | 4 | 16 | 16 |
79//!
80//! | Type | [`Affine3<f32>`] | [`Mat4<f32>`] | [`Affine3A<f32>`] | [`Mat4A<f32>`] |
81//! | ----------------- | ---------------- | ------------- | ----------------- | -------------- |
82//! | Size (bytes) | 48 | 64 | 64 | 64 |
83//! | Alignment (bytes) | 4 | 4 | 16 | 16 |
84//!
85//! > This table is true only for target architectures that have SIMD and are
86//! > supported.
87//!
88//! # Masks
89//!
90//! Masks are boolean vectors optimized for specific vector types. For example,
91//! [`Mask3A<f32>`] performs better than [`Vec3A<bool>`] for operations
92//! involving [`Vec3A<f32>`].
93//!
94//! # SoA
95//!
96//! SoA, or Structure of Arrays, refers to math types where each element `T`
97//! contains multiple values. For example, [`Vec3<f32x4>`] represents four 3D
98//! vectors, stored in memory as:
99//!
100//! `x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4`
101//!
102//! SoA is faster than standard SIMD. For example, computing the dot product for
103//! [`Vec3<f32>`] is quite slow because SIMD is not built for horizontal
104//! operations, while for [`Vec3<f32x4>`] it is much faster because each element
105//! is a SIMD register and there are no horizontal operations.
106//!
107//! However, SoA requires that algorithms are designed to process multiple
108//! values at the same time, which can be quite challenging. Because of this, it
109//! is best to only use SoA for performance-critical algorithms.
110//!
111//! SoA is supported through an optional dependency for the [`wide`] crate.
112//! Almost all functionality that exists for standard types also exists for SoA
113//! types.
114//!
115//! > [The `docs.rs` page] currently doesn't show [`wide`] support. See
116//! > [this issue](https://github.com/Noam2Stein/ggmath/issues/45).
117//!
118//! # Fixed-point numbers
119//!
120//! Currently, there is only basic support for fixed-point numbers, through the
121//! [`fixed`] feature flag which implements [`Scalar`] for [`fixed`] types. See
122//! [this issue](https://github.com/Noam2Stein/ggmath/issues/46) for better
123//! fixed-point number support.
124//!
125//! # Linear algebra conventions
126//!
127//! [`ggmath`] is coordinate-system agnostic, and should work for both
128//! right-handed and left-handed coordinate systems.
129//!
130//! [`ggmath`] uses left-multiplication, meaning to transform a vector by a
131//! matrix (or quaternion) you write `vector * matrix` and not
132//! `matrix * vector`. This means matrices are stored in row-major order.
133//!
134//! # Why another math crate?
135//!
136//! [`ggmath`] exists because existing similar libraries are missing certain
137//! features:
138//!
139//! - SIMD alignment (e.g., `Vec3` is `__m128`, important for performance)
140//! - Generics (over primitives or arbitrary types, avoids macros)
141//! - SoA (niche, but important for game engines)
142//! - Fixed-point numbers (niche too, but important for game engines that aim to
143//! be flexible)
144//!
145//! Existing similar libraries:
146//!
147//! - [`glam`]: Supports SIMD alignment, but does not use generics, and as a
148//! result SoA and fixed-point numbers are out of scope.
149//!
150//! - [`ultraviolet`]: Supports SoA, but does not support SIMD alignment because
151//! its types are simple scalar structs. Does not use generics, and as a
152//! result fixed-point numbers are probably out of scope.
153//!
154//! - [`cgmath`]: Supports generics (could also support SoA and fixed-point
155//! numbers) but does not support SIMD alignment, because its types are simple
156//! scalar structs.
157//!
158//! - [`nalgebra`]: Less graphics oriented and thus has a larger, more
159//! complicated API more suitable for general linear algebra.
160//!
161//! [`ggmath`] has a design where types are generic over `N` and `T`, but also
162//! whether SIMD alignment is enabled or disabled, enabling it to support both
163//! SIMD alignment and generics. Changing existing libraries to use this design
164//! would be out of scope.
165//!
166//! # Usage
167//!
168//! Rust must be updated to version `1.95.0` or later.
169//!
170//! Add this to your Cargo.toml:
171//!
172//! ```toml
173//! [dependencies]
174//! ggmath = "0.17.1"
175//! ```
176//!
177//! For [`no_std`] support, enable the [`libm`] feature:
178//!
179//! ```toml
180//! [dependencies]
181//! ggmath = { version = "0.17.1", features = ["libm"] }
182//! ```
183//!
184//! # Feature flags
185//!
186//! - [`bytemuck`]: Implements [`bytemuck`] traits for [`ggmath`] types.
187//!
188//! - [`fixed`]: Implements [`Scalar`] for fixed-point numbers.
189//!
190//! - [`libm`]: Uses [`libm`] instead of [`std`] as the backend for
191//! floating-point functions. This makes the crate [`no_std`].
192//!
193//! - [`mint`]: Implements conversions between [`ggmath`] and [`mint`] types.
194//!
195//! - [`rand`]: Implements [`rand`] traits for [`ggmath`] types.
196//!
197//! - [`serde`]: Implements [`Serialize`] and [`Deserialize`] for [`ggmath`]
198//! types.
199//!
200//! - [`wide`]: Implements functionality for SoA types.
201//!
202//! [`ggmath`]: crate
203//! [`num-primitive`]: https://crates.io/crates/num-primitive
204//!
205//! [benchmark results]: https://github.com/Noam2Stein/ggmath/blob/main/BENCH_RESULTS.md
206//!
207//! [`wide`]: https://crates.io/crates/wide
208//! [The `docs.rs` page]: https://docs.rs/ggmath
209//!
210//! [`fixed`]: https://crates.io/crates/fixed
211//!
212//! [`glam`]: https://crates.io/crates/glam
213//! [`ultraviolet`]: https://crates.io/crates/ultraviolet
214//! [`cgmath`]: https://crates.io/crates/cgmath
215//! [`nalgebra`]: https://crates.io/crates/nalgebra
216//!
217//! [`no_std`]: https://docs.rust-embedded.org/book/intro/no-std.html
218//! [`libm`]: https://crates.io/crates/libm
219//!
220//! [`bytemuck`]: https://crates.io/crates/bytemuck
221//! [`std`]: https://doc.rust-lang.org/std
222//! [`mint`]: https://crates.io/crates/mint
223//! [`rand`]: https://crates.io/crates/rand
224//! [`serde`]: https://crates.io/crates/serde
225//! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html
226//! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html
227
228#![forbid(missing_docs)]
229#![cfg_attr(feature = "libm", no_std)]
230
231pub use crate::{
232 affine::{Affine, Affine2, Affine2A, Affine3, Affine3A},
233 alignment::{Aligned, Alignment, Unaligned},
234 constants::{NegOne, One, Zero},
235 euler_rot::EulerRot,
236 float_ext::FloatExt,
237 length::{Length, SupportedLength},
238 mask::{Mask, Mask2, Mask2A, Mask3, Mask3A, Mask4, Mask4A},
239 matrix::{Mat2, Mat2A, Mat3, Mat3A, Mat4, Mat4A, Matrix},
240 primitive_traits::{PrimitiveFloat, PrimitiveInteger, PrimitiveSigned, PrimitiveUnsigned},
241 quaternion::{Quat, QuatA, Quaternion},
242 scalar::{CustomScalar, Scalar},
243 vector::{Vec2, Vec2A, Vec3, Vec3A, Vec4, Vec4A, Vector},
244};
245
246mod affine;
247mod alignment;
248mod backend;
249mod constants;
250mod euler_rot;
251mod float_ext;
252mod length;
253mod mask;
254mod matrix;
255mod primitive_traits;
256mod quaternion;
257mod scalar;
258mod third_party;
259mod utils;
260mod vector;
261
262#[cfg(test)]
263mod test_utils;