glam/
lib.rs

1/*!
2# glam
3
4`glam` is a simple and fast linear algebra library for games and graphics.
5
6## Features
7
8* [`f32`](mod@f32) types
9  * vectors: [`Vec2`], [`Vec3`], [`Vec3A`] and [`Vec4`]
10  * square matrices: [`Mat2`], [`Mat3`], [`Mat3A`] and [`Mat4`]
11  * a quaternion type: [`Quat`]
12  * affine transformation types: [`Affine2`], [`Affine3`] and [`Affine3A`]
13* [`f64`](mod@f64) types
14  * vectors: [`DVec2`], [`DVec3`] and [`DVec4`]
15  * square matrices: [`DMat2`], [`DMat3`] and [`DMat4`]
16  * a quaternion type: [`DQuat`]
17  * affine transformation types: [`DAffine2`] and [`DAffine3`]
18* [`i8`](mod@i8) types
19  * vectors: [`I8Vec2`], [`I8Vec3`] and [`I8Vec4`]
20* [`u8`](mod@u8) types
21  * vectors: [`U8Vec2`], [`U8Vec3`] and [`U8Vec4`]
22* [`i16`](mod@i16) types
23  * vectors: [`I16Vec2`], [`I16Vec3`] and [`I16Vec4`]
24* [`u16`](mod@u16) types
25  * vectors: [`U16Vec2`], [`U16Vec3`] and [`U16Vec4`]
26* [`i32`](mod@i32) types
27  * vectors: [`IVec2`], [`IVec3`] and [`IVec4`]
28* [`u32`](mod@u32) types
29  * vectors: [`UVec2`], [`UVec3`] and [`UVec4`]
30* [`i64`](mod@i64) types
31  * vectors: [`I64Vec2`], [`I64Vec3`] and [`I64Vec4`]
32* [`u64`](mod@u64) types
33  * vectors: [`U64Vec2`], [`U64Vec3`] and [`U64Vec4`]
34* [`isize`](mod@isize) types
35  * vectors: [`ISizeVec2`], [`ISizeVec3`] and [`ISizeVec4`]
36* [`usize`](mod@usize) types
37  * vectors: [`USizeVec2`], [`USizeVec3`] and [`USizeVec4`]
38* [`bool`](mod@bool) types
39  * vectors: [`BVec2`], [`BVec3`] and [`BVec4`]
40
41## SIMD
42
43`glam` is built with SIMD in mind. Many `f32` types use 128-bit SIMD vector types for storage
44and/or implementation. The use of SIMD generally enables better performance than using primitive
45numeric types such as `f32`.
46
47Some `glam` types use SIMD for storage meaning they are 16 byte aligned, these types include
48`Mat2`, `Mat3A`, `Mat4`, `Quat`, `Vec3A`, `Vec4`, `Affine2` an `Affine3A`. Types
49with an `A` suffix are a SIMD alternative to a scalar type, e.g. `Vec3` uses `f32` storage and
50`Vec3A` uses SIMD storage.
51
52When SIMD is not available on the target the types will maintain 16 byte alignment and internal
53padding so that object sizes and layouts will not change between architectures. There are scalar
54math fallback implementations exist when SIMD is not available. It is intended to add support for
55other SIMD architectures once they appear in stable Rust.
56
57Currently only SSE2 on x86/x86_64, NEON on Aarch64, and simd128 on WASM are supported.
58
59## Vec3A and Mat3A
60
61`Vec3A` is a SIMD optimized version of the `Vec3` type, which due to 16 byte alignment results
62in `Vec3A` containing 4 bytes of padding making it 16 bytes in size in total. `Mat3A` is composed
63of three `Vec3A` columns.
64
65| Type       | `f32` bytes | Align bytes | Size bytes | Padding |
66|:-----------|------------:|------------:|-----------:|--------:|
67|[`Vec3`]    |           12|            4|          12|        0|
68|[`Vec3A`]   |           12|           16|          16|        4|
69|[`Mat3`]    |           36|            4|          36|        0|
70|[`Mat3A`]   |           36|           16|          48|       12|
71
72Despite this wasted space the SIMD implementations tend to outperform `f32` implementations in
73[**mathbench**](https://github.com/bitshifter/mathbench-rs) benchmarks.
74
75`glam` treats [`Vec3`] as the default 3D vector type and [`Vec3A`] a special case for optimization.
76When methods need to return a 3D vector they will generally return [`Vec3`].
77
78There are [`From`] trait implementations for converting from [`Vec4`] to a [`Vec3A`] and between
79[`Vec3`] and [`Vec3A`] (and vice versa).
80
81```
82use glam::{Vec3, Vec3A, Vec4};
83
84let v4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
85
86// Convert from `Vec4` to `Vec3A`, this is a no-op if SIMD is supported.
87// We use an explicit method here instead of a From impl as data is lost in the conversion.
88let v3a = Vec3A::from_vec4(v4);
89assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
90
91// Convert from `Vec3A` to `Vec3`.
92let v3 = Vec3::from(v3a);
93assert_eq!(Vec3::new(1.0, 2.0, 3.0), v3);
94
95// Convert from `Vec3` to `Vec3A`.
96let v3a = Vec3A::from(v3);
97assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
98```
99
100## Affine2, Affine3 and Affine3A
101
102`Affine2`, `Affine3` and `Affine3A` are composed of a linear transform matrix and a vector
103translation. The represent 2D and 3D affine transformations which are commonly used in games.
104
105`Affine3` is composed from `Vec3` and `Mat3` whereas `Affine3A` is composed from `Mat3A` and
106`Vec3A`. `Affine3A` will generally be faster but is 16 byte aligned and 64 btyes verses `Affine3`
107which is 48 bytes.
108
109The table below shows the performance advantage of `Affine2` over `Mat3A` and `Mat3A` over `Mat3`.
110
111| operation          | `Mat3`      | `Mat3A`    | `Affine2`  |
112|--------------------|-------------|------------|------------|
113| inverse            | 11.4±0.09ns | 7.1±0.09ns | 5.4±0.06ns |
114| mul self           | 10.5±0.04ns | 5.2±0.05ns | 4.0±0.05ns |
115| transform point2   |  2.7±0.02ns | 2.7±0.03ns | 2.8±0.04ns |
116| transform vector2  |  2.6±0.01ns | 2.6±0.03ns | 2.3±0.02ns |
117
118Performance is much closer between `Mat4` and `Affine3A` with the affine type being faster to
119invert.
120
121| operation          | `Mat4`      | `Affine3A`  |
122|--------------------|-------------|-------------|
123| inverse            | 15.9±0.11ns | 10.8±0.06ns |
124| mul self           |  7.3±0.05ns |  7.0±0.06ns |
125| transform point3   |  3.6±0.02ns |  4.3±0.04ns |
126| transform point3a  |  3.0±0.02ns |  3.0±0.04ns |
127| transform vector3  |  4.1±0.02ns |  3.9±0.04ns |
128| transform vector3a |  2.8±0.02ns |  2.8±0.02ns |
129
130Benchmarks were taken on an Intel Core i7-4710HQ.
131
132## Linear algebra conventions
133
134`glam` interprets vectors as column matrices (also known as column vectors) meaning when
135transforming a vector with a matrix the matrix goes on the left.
136
137```
138use glam::{Mat3, Vec3};
139let m = Mat3::IDENTITY;
140let x = Vec3::X;
141let v = m * x;
142assert_eq!(v, x);
143```
144
145Matrices are stored in memory in column-major order.
146
147All angles are in radians. Rust provides the `f32::to_radians()` and `f64::to_radians()` methods to
148convert from degrees.
149
150## Direct element access
151
152Because some types may internally be implemented using SIMD types, direct access to vector elements
153is supported by implementing the [`Deref`] and [`DerefMut`] traits.
154
155```
156use glam::Vec3A;
157let mut v = Vec3A::new(1.0, 2.0, 3.0);
158assert_eq!(3.0, v.z);
159v.z += 1.0;
160assert_eq!(4.0, v.z);
161```
162
163[`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html
164[`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
165
166## glam assertions
167
168`glam` does not enforce validity checks on method parameters at runtime. For example methods that
169require normalized vectors as input such as `Quat::from_axis_angle(axis, angle)` will not check
170that axis is a valid normalized vector. To help catch unintended misuse of `glam` the
171`debug-glam-assert` or `glam-assert` features can be enabled to add checks ensure that inputs to
172are valid.
173
174## Vector swizzles
175
176`glam` vector types have functions allowing elements of vectors to be reordered, this includes
177creating a vector of a different size from the vectors elements.
178
179The swizzle functions are implemented using traits to add them to each vector type. This is
180primarily because there are a lot of swizzle functions which can obfuscate the other vector
181functions in documentation and so on. The traits are [`Vec2Swizzles`], [`Vec3Swizzles`] and
182[`Vec4Swizzles`].
183
184Note that the [`Vec3Swizzles`] implementation for [`Vec3A`] will return a [`Vec3A`] for 3 element
185swizzles, all other implementations will return [`Vec3`].
186
187```
188use glam::{swizzles::*, Vec2, Vec3, Vec3A, Vec4};
189
190let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
191
192// Reverse elements of `v`, if SIMD is supported this will use a vector shuffle.
193let wzyx = v.wzyx();
194assert_eq!(Vec4::new(4.0, 3.0, 2.0, 1.0), wzyx);
195
196// Swizzle the yzw elements of `v` into a `Vec3`
197let yzw = v.yzw();
198assert_eq!(Vec3::new(2.0, 3.0, 4.0), yzw);
199
200// To swizzle a `Vec4` into a `Vec3A` swizzle the `Vec4` first then convert to
201// `Vec3A`. If SIMD is supported this will use a vector shuffle. The last
202// element of the shuffled `Vec4` is ignored by the `Vec3A`.
203let yzw = Vec3A::from_vec4(v.yzwx());
204assert_eq!(Vec3A::new(2.0, 3.0, 4.0), yzw);
205
206// You can swizzle from a `Vec4` to a `Vec2`
207let xy = v.xy();
208assert_eq!(Vec2::new(1.0, 2.0), xy);
209
210// And back again
211let yyxx = xy.yyxx();
212assert_eq!(Vec4::new(2.0, 2.0, 1.0, 1.0), yyxx);
213```
214
215## SIMD and scalar consistency
216
217`glam` types implement `serde` `Serialize` and `Deserialize` traits to ensure
218that they will serialize and deserialize exactly the same whether or not
219SIMD support is being used.
220
221The SIMD versions implement the `core::fmt::Debug` and `core::fmt::Display`
222traits so they print the same as the scalar version.
223
224```
225use glam::Vec4;
226let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
227assert_eq!(format!("{}", a), "[1, 2, 3, 4]");
228```
229
230## Optional features
231
232All `glam` dependencies are optional, however some are required for tests
233and benchmarks.
234
235* `approx` - traits and macros for approximate float comparisons
236* `arbitrary` - implementations of `Arbitrary` trait for all `glam` types.
237* `bytemuck` - for casting into slices of bytes
238* `encase` - `encase` trait implementations for `glam` types.
239* `libm` - uses `libm` math functions instead of `std`
240* `mint` - for interoperating with other 3D math libraries
241* `rand` - implementations of `Distribution` trait for all `glam` types.
242* `rkyv` - implementations of `Archive`, `Serialize` and `Deserialize` for all
243  `glam` types. Note that serialization is not interoperable with and without the
244  `scalar-math` feature. It should work between all other builds of `glam`.
245  Endian conversion is currently not supported
246* `bytecheck` - to perform archive validation when using the `rkyv` feature
247* `serde` - implementations of `Serialize` and `Deserialize` for all `glam`
248  types. Note that serialization should work between builds of `glam` with and without SIMD enabled
249* `speedy` - implementations of `speedy`'s `Readable` and `Writable` for all `glam` types.
250* `zerocopy` - implementations of zerocopy traits for safe transmutes.
251
252## Feature gates
253
254* `std` - the default feature, has no dependencies.
255* `nostd-libm` - uses `libm` math functions if `std` is not available
256* `scalar-math` - disables SIMD support and uses native alignment for all types.
257* `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters
258  passed to `glam` to help catch runtime errors.
259* `glam-assert` - adds assertions to all builds which check the validity of parameters passed to
260  `glam` to help catch runtime errors.
261* `cuda` - forces `glam` types to match expected cuda alignment
262* `fast-math` - By default, glam attempts to provide bit-for-bit identical results on all platforms.
263  Using this feature will enable platform specific optimizations that may not be identical to other
264  platforms. **Intermediate libraries should not use this feature and defer the decision to the
265  final binary build**.
266* `core-simd` - enables SIMD support via the portable simd module. This is an unstable feature which
267  requires a nightly Rust toolchain and `std` support.
268
269## Minimum Supported Rust Version (MSRV)
270
271The minimum supported Rust version is `1.68.2`.
272
273*/
274#![doc(html_root_url = "https://docs.rs/glam/0.31.1")]
275#![cfg_attr(not(feature = "std"), no_std)]
276#![cfg_attr(target_arch = "spirv", feature(repr_simd))]
277#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
278#![deny(
279    rust_2018_compatibility,
280    rust_2018_idioms,
281    future_incompatible,
282    nonstandard_style
283)]
284// clippy doesn't like `to_array(&self)`
285#![allow(clippy::wrong_self_convention)]
286#![cfg_attr(
287    all(feature = "core-simd", not(feature = "scalar-math")),
288    feature(portable_simd)
289)]
290
291#[cfg(all(
292    not(feature = "std"),
293    not(feature = "libm"),
294    not(feature = "nostd-libm")
295))]
296compile_error!(
297    "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`."
298);
299
300#[macro_use]
301mod macros;
302
303mod align16;
304mod deref;
305mod euler;
306mod features;
307
308#[cfg(all(
309    target_arch = "aarch64",
310    not(any(feature = "core-simd", feature = "scalar-math"))
311))]
312mod neon;
313
314#[cfg(target_arch = "spirv")]
315mod spirv;
316
317#[cfg(all(
318    target_feature = "sse2",
319    not(any(feature = "core-simd", feature = "scalar-math"))
320))]
321mod sse2;
322
323#[cfg(all(
324    target_feature = "simd128",
325    not(any(feature = "core-simd", feature = "scalar-math"))
326))]
327mod wasm;
328
329#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
330mod coresimd;
331
332#[cfg(all(
333    target_feature = "sse2",
334    not(any(feature = "core-simd", feature = "scalar-math"))
335))]
336use align16::Align16;
337
338/** `bool` vector mask types. */
339pub mod bool;
340pub use self::bool::*;
341
342/** `f32` vector, quaternion and matrix types. */
343pub mod f32;
344pub use self::f32::*;
345
346/** `f64` vector, quaternion and matrix types. */
347pub mod f64;
348pub use self::f64::*;
349
350/** `i8` vector types. */
351pub mod i8;
352pub use self::i8::*;
353
354/** `u8` vector types. */
355pub mod u8;
356pub use self::u8::*;
357
358/** `i16` vector types. */
359pub mod i16;
360pub use self::i16::*;
361
362/** `u16` vector types. */
363pub mod u16;
364pub use self::u16::*;
365
366/** `i32` vector types. */
367pub mod i32;
368pub use self::i32::*;
369
370/** `u32` vector types. */
371pub mod u32;
372pub use self::u32::*;
373
374/** `i64` vector types. */
375pub mod i64;
376pub use self::i64::*;
377
378/** `u64` vector types. */
379pub mod u64;
380pub use self::u64::*;
381
382/** `usize` vector types. */
383pub mod usize;
384pub use self::usize::*;
385
386/** `isize` vector types. */
387pub mod isize;
388pub use self::isize::*;
389
390/** Traits adding swizzle methods to all vector types. */
391pub mod swizzles;
392pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
393
394/** Rotation Helper */
395pub use euler::EulerRot;
396
397/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
398mod float;
399pub use float::FloatExt;