Skip to main content

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