• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitshifter / glam-rs / 18676206977

21 Oct 2025 07:25AM UTC coverage: 97.175%. Remained the same
18676206977

push

github

web-flow
add `arbitrary` trait implementations (#683)

52292 of 53812 relevant lines covered (97.18%)

3.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/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`] 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
* [`usize`](mod@usize) types
35
  * vectors: [`USizeVec2`], [`USizeVec3`] and [`USizeVec4`]
36
* [`bool`](mod@bool) types
37
  * vectors: [`BVec2`], [`BVec3`] and [`BVec4`]
38

39
## SIMD
40

41
`glam` is built with SIMD in mind. Many `f32` types use 128-bit SIMD vector types for storage
42
and/or implementation. The use of SIMD generally enables better performance than using primitive
43
numeric types such as `f32`.
44

45
Some `glam` types use SIMD for storage meaning they are 16 byte aligned, these types include
46
`Mat2`, `Mat3A`, `Mat4`, `Quat`, `Vec3A`, `Vec4`, `Affine2` an `Affine3A`. Types
47
with an `A` suffix are a SIMD alternative to a scalar type, e.g. `Vec3` uses `f32` storage and
48
`Vec3A` uses SIMD storage.
49

50
When SIMD is not available on the target the types will maintain 16 byte alignment and internal
51
padding so that object sizes and layouts will not change between architectures. There are scalar
52
math fallback implementations exist when SIMD is not available. It is intended to add support for
53
other SIMD architectures once they appear in stable Rust.
54

55
Currently only SSE2 on x86/x86_64, NEON on Aarch64, and simd128 on WASM are supported.
56

57
## Vec3A and Mat3A
58

59
`Vec3A` is a SIMD optimized version of the `Vec3` type, which due to 16 byte alignment results
60
in `Vec3A` containing 4 bytes of padding making it 16 bytes in size in total. `Mat3A` is composed
61
of three `Vec3A` columns.
62

63
| Type       | `f32` bytes | Align bytes | Size bytes | Padding |
64
|:-----------|------------:|------------:|-----------:|--------:|
65
|[`Vec3`]    |           12|            4|          12|        0|
66
|[`Vec3A`]   |           12|           16|          16|        4|
67
|[`Mat3`]    |           36|            4|          36|        0|
68
|[`Mat3A`]   |           36|           16|          48|       12|
69

70
Despite this wasted space the SIMD implementations tend to outperform `f32` implementations in
71
[**mathbench**](https://github.com/bitshifter/mathbench-rs) benchmarks.
72

73
`glam` treats [`Vec3`] as the default 3D vector type and [`Vec3A`] a special case for optimization.
74
When methods need to return a 3D vector they will generally return [`Vec3`].
75

76
There are [`From`] trait implementations for converting from [`Vec4`] to a [`Vec3A`] and between
77
[`Vec3`] and [`Vec3A`] (and vice versa).
78

79
```
80
use glam::{Vec3, Vec3A, Vec4};
81

82
let v4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
83

84
// Convert from `Vec4` to `Vec3A`, this is a no-op if SIMD is supported.
85
// We use an explicit method here instead of a From impl as data is lost in the conversion.
86
let v3a = Vec3A::from_vec4(v4);
87
assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
88

89
// Convert from `Vec3A` to `Vec3`.
90
let v3 = Vec3::from(v3a);
91
assert_eq!(Vec3::new(1.0, 2.0, 3.0), v3);
92

93
// Convert from `Vec3` to `Vec3A`.
94
let v3a = Vec3A::from(v3);
95
assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
96
```
97

98
## Affine2 and Affine3A
99

100
`Affine2` and `Affine3A` are composed of a linear transform matrix and a vector translation. The
101
represent 2D and 3D affine transformations which are commonly used in games.
102

103
The table below shows the performance advantage of `Affine2` over `Mat3A` and `Mat3A` over `Mat3`.
104

105
| operation          | `Mat3`      | `Mat3A`    | `Affine2`  |
106
|--------------------|-------------|------------|------------|
107
| inverse            | 11.4±0.09ns | 7.1±0.09ns | 5.4±0.06ns |
108
| mul self           | 10.5±0.04ns | 5.2±0.05ns | 4.0±0.05ns |
109
| transform point2   |  2.7±0.02ns | 2.7±0.03ns | 2.8±0.04ns |
110
| transform vector2  |  2.6±0.01ns | 2.6±0.03ns | 2.3±0.02ns |
111

112
Performance is much closer between `Mat4` and `Affine3A` with the affine type being faster to
113
invert.
114

115
| operation          | `Mat4`      | `Affine3A`  |
116
|--------------------|-------------|-------------|
117
| inverse            | 15.9±0.11ns | 10.8±0.06ns |
118
| mul self           |  7.3±0.05ns |  7.0±0.06ns |
119
| transform point3   |  3.6±0.02ns |  4.3±0.04ns |
120
| transform point3a  |  3.0±0.02ns |  3.0±0.04ns |
121
| transform vector3  |  4.1±0.02ns |  3.9±0.04ns |
122
| transform vector3a |  2.8±0.02ns |  2.8±0.02ns |
123

124
Benchmarks were taken on an Intel Core i7-4710HQ.
125

126
## Linear algebra conventions
127

128
`glam` interprets vectors as column matrices (also known as column vectors) meaning when
129
transforming a vector with a matrix the matrix goes on the left.
130

131
```
132
use glam::{Mat3, Vec3};
133
let m = Mat3::IDENTITY;
134
let x = Vec3::X;
135
let v = m * x;
136
assert_eq!(v, x);
137
```
138

139
Matrices are stored in memory in column-major order.
140

141
All angles are in radians. Rust provides the `f32::to_radians()` and `f64::to_radians()` methods to
142
convert from degrees.
143

144
## Direct element access
145

146
Because some types may internally be implemented using SIMD types, direct access to vector elements
147
is supported by implementing the [`Deref`] and [`DerefMut`] traits.
148

149
```
150
use glam::Vec3A;
151
let mut v = Vec3A::new(1.0, 2.0, 3.0);
152
assert_eq!(3.0, v.z);
153
v.z += 1.0;
154
assert_eq!(4.0, v.z);
155
```
156

157
[`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html
158
[`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
159

160
## glam assertions
161

162
`glam` does not enforce validity checks on method parameters at runtime. For example methods that
163
require normalized vectors as input such as `Quat::from_axis_angle(axis, angle)` will not check
164
that axis is a valid normalized vector. To help catch unintended misuse of `glam` the
165
`debug-glam-assert` or `glam-assert` features can be enabled to add checks ensure that inputs to
166
are valid.
167

168
## Vector swizzles
169

170
`glam` vector types have functions allowing elements of vectors to be reordered, this includes
171
creating a vector of a different size from the vectors elements.
172

173
The swizzle functions are implemented using traits to add them to each vector type. This is
174
primarily because there are a lot of swizzle functions which can obfuscate the other vector
175
functions in documentation and so on. The traits are [`Vec2Swizzles`], [`Vec3Swizzles`] and
176
[`Vec4Swizzles`].
177

178
Note that the [`Vec3Swizzles`] implementation for [`Vec3A`] will return a [`Vec3A`] for 3 element
179
swizzles, all other implementations will return [`Vec3`].
180

181
```
182
use glam::{swizzles::*, Vec2, Vec3, Vec3A, Vec4};
183

184
let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
185

186
// Reverse elements of `v`, if SIMD is supported this will use a vector shuffle.
187
let wzyx = v.wzyx();
188
assert_eq!(Vec4::new(4.0, 3.0, 2.0, 1.0), wzyx);
189

190
// Swizzle the yzw elements of `v` into a `Vec3`
191
let yzw = v.yzw();
192
assert_eq!(Vec3::new(2.0, 3.0, 4.0), yzw);
193

194
// To swizzle a `Vec4` into a `Vec3A` swizzle the `Vec4` first then convert to
195
// `Vec3A`. If SIMD is supported this will use a vector shuffle. The last
196
// element of the shuffled `Vec4` is ignored by the `Vec3A`.
197
let yzw = Vec3A::from_vec4(v.yzwx());
198
assert_eq!(Vec3A::new(2.0, 3.0, 4.0), yzw);
199

200
// You can swizzle from a `Vec4` to a `Vec2`
201
let xy = v.xy();
202
assert_eq!(Vec2::new(1.0, 2.0), xy);
203

204
// And back again
205
let yyxx = xy.yyxx();
206
assert_eq!(Vec4::new(2.0, 2.0, 1.0, 1.0), yyxx);
207
```
208

209
## SIMD and scalar consistency
210

211
`glam` types implement `serde` `Serialize` and `Deserialize` traits to ensure
212
that they will serialize and deserialize exactly the same whether or not
213
SIMD support is being used.
214

215
The SIMD versions implement the `core::fmt::Debug` and `core::fmt::Display`
216
traits so they print the same as the scalar version.
217

218
```
219
use glam::Vec4;
220
let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
221
assert_eq!(format!("{}", a), "[1, 2, 3, 4]");
222
```
223

224
## Feature gates
225

226
All `glam` dependencies are optional, however some are required for tests
227
and benchmarks.
228

229
* `std` - the default feature, has no dependencies.
230
* `arbitrary` - implementations of `Arbitrary` trait for all `glam` types.
231
* `approx` - traits and macros for approximate float comparisons
232
* `bytemuck` - for casting into slices of bytes
233
* `libm` - uses `libm` math functions instead of `std`
234
* `nostd-libm` - uses `libm` math functions if `std` is not available
235
* `mint` - for interoperating with other 3D math libraries
236
* `rand` - implementations of `Distribution` trait for all `glam` types.
237
* `rkyv` - implementations of `Archive`, `Serialize` and `Deserialize` for all
238
  `glam` types. Note that serialization is not interoperable with and without the
239
  `scalar-math` feature. It should work between all other builds of `glam`.
240
  Endian conversion is currently not supported
241
* `bytecheck` - to perform archive validation when using the `rkyv` feature
242
* `encase` - `encase` trait implementations for `glam` types.
243
* `serde` - implementations of `Serialize` and `Deserialize` for all `glam`
244
  types. Note that serialization should work between builds of `glam` with and without SIMD enabled
245
* `speedy` - implementations of `speedy`'s `Readable` and `Writable` for all `glam` types.
246
* `scalar-math` - disables SIMD support and uses native alignment for all types.
247
* `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters
248
  passed to `glam` to help catch runtime errors.
249
* `glam-assert` - adds assertions to all builds which check the validity of parameters passed to
250
  `glam` to help catch runtime errors.
251
* `cuda` - forces `glam` types to match expected cuda alignment
252
* `fast-math` - By default, glam attempts to provide bit-for-bit identical
253
  results on all platforms. Using this feature will enable platform specific
254
  optimizations that may not be identical to other platforms. **Intermediate
255
  libraries should not use this feature and defer the decision to the final
256
  binary build**.
257
* `core-simd` - enables SIMD support via the portable simd module. This is an
258
  unstable feature which requires a nightly Rust toolchain and `std` support.
259

260
## Minimum Supported Rust Version (MSRV)
261

262
The minimum supported Rust version is `1.68.2`.
263

264
*/
265
#![doc(html_root_url = "https://docs.rs/glam/0.30.8")]
266
#![cfg_attr(not(feature = "std"), no_std)]
267
#![cfg_attr(target_arch = "spirv", feature(repr_simd))]
268
#![deny(
269
    rust_2018_compatibility,
270
    rust_2018_idioms,
271
    future_incompatible,
272
    nonstandard_style
273
)]
274
// clippy doesn't like `to_array(&self)`
275
#![allow(clippy::wrong_self_convention)]
276
#![cfg_attr(
277
    all(feature = "core-simd", not(feature = "scalar-math")),
278
    feature(portable_simd)
279
)]
280

281
#[cfg(all(
282
    not(feature = "std"),
×
283
    not(feature = "libm"),
×
284
    not(feature = "nostd-libm")
×
285
))]
286
compile_error!(
×
287
    "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`."
288
);
289

290
#[macro_use]
291
mod macros;
292

293
mod align16;
294
mod deref;
295
mod euler;
296
mod features;
297

298
#[cfg(all(
299
    target_arch = "aarch64",
300
    not(any(feature = "core-simd", feature = "scalar-math"))
301
))]
302
mod neon;
303

304
#[cfg(target_arch = "spirv")]
305
mod spirv;
306

307
#[cfg(all(
308
    target_feature = "sse2",
309
    not(any(feature = "core-simd", feature = "scalar-math"))
310
))]
311
mod sse2;
312

313
#[cfg(all(
314
    target_feature = "simd128",
315
    not(any(feature = "core-simd", feature = "scalar-math"))
316
))]
317
mod wasm32;
318

319
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
320
mod coresimd;
321

322
#[cfg(all(
323
    target_feature = "sse2",
324
    not(any(feature = "core-simd", feature = "scalar-math"))
325
))]
326
use align16::Align16;
327

328
/** `bool` vector mask types. */
329
pub mod bool;
330
pub use self::bool::*;
331

332
/** `f32` vector, quaternion and matrix types. */
333
pub mod f32;
334
pub use self::f32::*;
335

336
/** `f64` vector, quaternion and matrix types. */
337
pub mod f64;
338
pub use self::f64::*;
339

340
/** `i8` vector types. */
341
pub mod i8;
342
pub use self::i8::*;
343

344
/** `u8` vector types. */
345
pub mod u8;
346
pub use self::u8::*;
347

348
/** `i16` vector types. */
349
pub mod i16;
350
pub use self::i16::*;
351

352
/** `u16` vector types. */
353
pub mod u16;
354
pub use self::u16::*;
355

356
/** `i32` vector types. */
357
pub mod i32;
358
pub use self::i32::*;
359

360
/** `u32` vector types. */
361
pub mod u32;
362
pub use self::u32::*;
363

364
/** `i64` vector types. */
365
pub mod i64;
366
pub use self::i64::*;
367

368
/** `u64` vector types. */
369
pub mod u64;
370
pub use self::u64::*;
371

372
/** `usize` vector types. */
373
pub mod usize;
374
pub use self::usize::*;
375

376
/** Traits adding swizzle methods to all vector types. */
377
pub mod swizzles;
378
pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
379

380
/** Rotation Helper */
381
pub use euler::EulerRot;
382

383
/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
384
mod float;
385
pub use float::FloatExt;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc