Coverage Report

Created: 2026-01-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.34.1/src/lib.rs
Line
Count
Source
1
/*!
2
# nalgebra
3
4
**nalgebra** is a linear algebra library written for Rust targeting:
5
6
* General-purpose linear algebra (still lacks a lot of features…)
7
* Real-time computer graphics.
8
* Real-time computer physics.
9
10
## Using **nalgebra**
11
You will need the last stable build of the [rust compiler](https://www.rust-lang.org)
12
and the official package manager: [cargo](https://github.com/rust-lang/cargo).
13
14
Simply add the following to your `Cargo.toml` file:
15
16
```ignore
17
[dependencies]
18
// TODO: replace the * by the latest version.
19
nalgebra = "*"
20
```
21
22
23
Most useful functionalities of **nalgebra** are grouped in the root module `nalgebra::`.
24
25
However, the recommended way to use **nalgebra** is to import types and traits
26
explicitly, and call free-functions using the `na::` prefix:
27
28
```
29
#[macro_use]
30
extern crate approx; // For the macro assert_relative_eq!
31
extern crate nalgebra as na;
32
use na::{Vector3, Rotation3};
33
34
fn main() {
35
    let axis  = Vector3::x_axis();
36
    let angle = 1.57;
37
    let b     = Rotation3::from_axis_angle(&axis, angle);
38
39
    assert_relative_eq!(b.axis().unwrap(), axis);
40
    assert_relative_eq!(b.angle(), angle);
41
}
42
```
43
44
45
## Features
46
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
47
an optimized set of tools for computer graphics and physics. Those features include:
48
49
* A single parametrizable type [`Matrix`] for vectors, (square or rectangular) matrices, and
50
  slices with dimensions known either at compile-time (using type-level integers) or at runtime.
51
* Matrices and vectors with compile-time sizes are statically allocated while dynamic ones are
52
  allocated on the heap.
53
* Convenient aliases for low-dimensional matrices and vectors: [`Vector1`] to
54
  [`Vector6`] and [`Matrix1x1`](Matrix1) to [`Matrix6x6`](Matrix6), including rectangular
55
  matrices like [`Matrix2x5`].
56
* Points sizes known at compile time, and convenience aliases: [`Point1`] to
57
  [`Point6`].
58
* Translation (seen as a transformation that composes by multiplication):
59
  [`Translation2`], [`Translation3`].
60
* Rotation matrices: [`Rotation2`], [`Rotation3`].
61
* Quaternions: [`Quaternion`], [`UnitQuaternion`] (for 3D rotation).
62
* Unit complex numbers can be used for 2D rotation: [`UnitComplex`].
63
* Algebraic entities with a norm equal to one: [`Unit<T>`](Unit), e.g., `Unit<Vector3<f32>>`.
64
* Isometries (translation ⨯ rotation): [`Isometry2`], [`Isometry3`]
65
* Similarity transformations (translation ⨯ rotation ⨯ uniform scale):
66
  [`Similarity2`], [`Similarity3`].
67
* Affine transformations stored as a homogeneous matrix:
68
  [`Affine2`], [`Affine3`].
69
* Projective (i.e. invertible) transformations stored as a homogeneous matrix:
70
  [`Projective2`], [`Projective3`].
71
* General transformations that does not have to be invertible, stored as a homogeneous matrix:
72
  [`Transform2`], [`Transform3`].
73
* 3D projections for computer graphics: [`Perspective3`],
74
  [`Orthographic3`].
75
* Matrix factorizations: [`Cholesky`], [`QR`], [`LU`], [`FullPivLU`],
76
  [`SVD`], [`Schur`], [`Hessenberg`], [`SymmetricEigen`].
77
* Insertion and removal of rows of columns of a matrix.
78
*/
79
80
#![deny(
81
    missing_docs,
82
    nonstandard_style,
83
    unused_variables,
84
    unused_mut,
85
    unused_parens,
86
    rust_2018_idioms,
87
    rust_2024_compatibility,
88
    future_incompatible,
89
    missing_copy_implementations
90
)]
91
#![cfg_attr(not(feature = "rkyv-serialize-no-std"), deny(unused_results))] // TODO: deny this globally once bytecheck stops generating unused results.
92
#![doc(
93
    html_favicon_url = "https://nalgebra.rs/img/favicon.ico",
94
    html_root_url = "https://docs.rs/nalgebra/0.25.0"
95
)]
96
#![cfg_attr(not(feature = "std"), no_std)]
97
// only enables the `doc_cfg` feature when
98
// the `docsrs` configuration attribute is defined
99
#![cfg_attr(docsrs, feature(doc_cfg))]
100
101
/// Generates an appropriate deprecation note with a suggestion for replacement.
102
///
103
/// Used for deprecating slice types in various locations throughout the library.
104
/// See #1076 for more information.
105
macro_rules! slice_deprecation_note {
106
    ($replacement:ident) => {
107
        concat!("Use ", stringify!($replacement),
108
            r###" instead. See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076) for more information."###)
109
    }
110
}
111
112
pub(crate) use slice_deprecation_note;
113
114
#[cfg(feature = "rand-no-std")]
115
extern crate rand_package as rand;
116
117
#[cfg(feature = "serde-serialize-no-std")]
118
#[macro_use]
119
extern crate serde;
120
121
#[macro_use]
122
extern crate approx;
123
extern crate num_traits as num;
124
125
#[cfg(all(feature = "alloc", not(feature = "std")))]
126
#[cfg_attr(test, macro_use)]
127
extern crate alloc;
128
129
#[cfg(not(feature = "std"))]
130
extern crate core as std;
131
132
#[macro_use]
133
#[cfg(feature = "io")]
134
extern crate pest_derive;
135
136
pub mod base;
137
#[cfg(feature = "debug")]
138
pub mod debug;
139
pub mod geometry;
140
#[cfg(feature = "io")]
141
pub mod io;
142
pub mod linalg;
143
#[cfg(feature = "proptest-support")]
144
pub mod proptest;
145
#[cfg(feature = "sparse")]
146
pub mod sparse;
147
mod third_party;
148
149
pub use crate::base::*;
150
pub use crate::geometry::*;
151
pub use crate::linalg::*;
152
#[cfg(feature = "sparse")]
153
pub use crate::sparse::*;
154
#[cfg(feature = "std")]
155
#[deprecated(
156
    note = "The 'core' module is being renamed to 'base' to avoid conflicts with the 'core' crate."
157
)]
158
pub use base as core;
159
160
#[cfg(feature = "macros")]
161
pub use nalgebra_macros::{dmatrix, dvector, matrix, point, stack, vector};
162
163
use simba::scalar::SupersetOf;
164
use std::cmp::{self, Ordering, PartialOrd};
165
166
use num::{One, Signed, Zero};
167
168
use base::allocator::Allocator;
169
pub use num_complex::Complex;
170
pub use simba::scalar::{
171
    ClosedAddAssign, ClosedDivAssign, ClosedMulAssign, ClosedSubAssign, ComplexField, Field,
172
    RealField,
173
};
174
pub use simba::simd::{SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdValue};
175
176
/// Gets the multiplicative identity element.
177
///
178
/// # See also:
179
///
180
/// * [`origin()`](crate::OPoint::origin)
181
/// * [`zero()`]
182
#[inline]
183
pub fn one<T: One>() -> T {
184
    T::one()
185
}
186
187
/// Gets the additive identity element.
188
///
189
/// # See also:
190
///
191
/// * [`one()`]
192
/// * [`origin()`](crate::OPoint::origin)
193
#[inline]
194
pub fn zero<T: Zero>() -> T {
195
    T::zero()
196
}
197
198
/*
199
 *
200
 * Ordering
201
 *
202
 */
203
// XXX: this is very naive and could probably be optimized for specific types.
204
// XXX: also, we might just want to use divisions, but assuming `val` is usually not far from `min`
205
// or `max`, would it still be more efficient?
206
/// Wraps `val` into the range `[min, max]` using modular arithmetics.
207
///
208
/// The range must not be empty.
209
#[must_use]
210
#[inline]
211
pub fn wrap<T>(mut val: T, min: T, max: T) -> T
212
where
213
    T: Copy + PartialOrd + ClosedAddAssign + ClosedSubAssign,
214
{
215
    assert!(min < max, "Invalid wrapping bounds.");
216
    let width = max - min;
217
218
    if val < min {
219
        val += width;
220
221
        while val < min {
222
            val += width
223
        }
224
    } else if val > max {
225
        val -= width;
226
227
        while val > max {
228
            val -= width
229
        }
230
    }
231
232
    val
233
}
234
235
/// Returns a reference to the input value clamped to the interval `[min, max]`.
236
///
237
/// In particular:
238
///     * If `min < val < max`, this returns `val`.
239
///     * If `val <= min`, this returns `min`.
240
///     * If `val >= max`, this returns `max`.
241
#[must_use]
242
#[inline]
243
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
244
    if val > min {
245
        if val < max { val } else { max }
246
    } else {
247
        min
248
    }
249
}
250
251
/// Same as `cmp::max`.
252
#[inline]
253
0
pub fn max<T: Ord>(a: T, b: T) -> T {
254
0
    cmp::max(a, b)
255
0
}
256
257
/// Same as `cmp::min`.
258
#[inline]
259
4.75k
pub fn min<T: Ord>(a: T, b: T) -> T {
260
4.75k
    cmp::min(a, b)
261
4.75k
}
262
263
/// The absolute value of `a`.
264
///
265
/// Deprecated: Use [`Matrix::abs()`] or [`ComplexField::abs()`] instead.
266
#[deprecated(note = "use the inherent method `Matrix::abs` or `ComplexField::abs` instead")]
267
#[inline]
268
pub fn abs<T: Signed>(a: &T) -> T {
269
    a.abs()
270
}
271
272
/// Returns the infimum of `a` and `b`.
273
#[deprecated(note = "use the inherent method `Matrix::inf` instead")]
274
#[inline]
275
pub fn inf<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
276
where
277
    T: Scalar + SimdPartialOrd,
278
    DefaultAllocator: Allocator<R, C>,
279
{
280
    a.inf(b)
281
}
282
283
/// Returns the supremum of `a` and `b`.
284
#[deprecated(note = "use the inherent method `Matrix::sup` instead")]
285
#[inline]
286
pub fn sup<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
287
where
288
    T: Scalar + SimdPartialOrd,
289
    DefaultAllocator: Allocator<R, C>,
290
{
291
    a.sup(b)
292
}
293
294
/// Returns simultaneously the infimum and supremum of `a` and `b`.
295
#[deprecated(note = "use the inherent method `Matrix::inf_sup` instead")]
296
#[inline]
297
pub fn inf_sup<T, R: Dim, C: Dim>(
298
    a: &OMatrix<T, R, C>,
299
    b: &OMatrix<T, R, C>,
300
) -> (OMatrix<T, R, C>, OMatrix<T, R, C>)
301
where
302
    T: Scalar + SimdPartialOrd,
303
    DefaultAllocator: Allocator<R, C>,
304
{
305
    a.inf_sup(b)
306
}
307
308
/// Compare `a` and `b` using a partial ordering relation.
309
#[inline]
310
pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> Option<Ordering> {
311
    a.partial_cmp(b)
312
}
313
314
/// Returns `true` iff `a` and `b` are comparable and `a < b`.
315
#[inline]
316
pub fn partial_lt<T: PartialOrd>(a: &T, b: &T) -> bool {
317
    a.lt(b)
318
}
319
320
/// Returns `true` iff `a` and `b` are comparable and `a <= b`.
321
#[inline]
322
pub fn partial_le<T: PartialOrd>(a: &T, b: &T) -> bool {
323
    a.le(b)
324
}
325
326
/// Returns `true` iff `a` and `b` are comparable and `a > b`.
327
#[inline]
328
pub fn partial_gt<T: PartialOrd>(a: &T, b: &T) -> bool {
329
    a.gt(b)
330
}
331
332
/// Returns `true` iff `a` and `b` are comparable and `a >= b`.
333
#[inline]
334
pub fn partial_ge<T: PartialOrd>(a: &T, b: &T) -> bool {
335
    a.ge(b)
336
}
337
338
/// Return the minimum of `a` and `b` if they are comparable.
339
#[inline]
340
pub fn partial_min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
341
    if let Some(ord) = a.partial_cmp(b) {
342
        match ord {
343
            Ordering::Greater => Some(b),
344
            _ => Some(a),
345
        }
346
    } else {
347
        None
348
    }
349
}
350
351
/// Return the maximum of `a` and `b` if they are comparable.
352
#[inline]
353
pub fn partial_max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
354
    if let Some(ord) = a.partial_cmp(b) {
355
        match ord {
356
            Ordering::Less => Some(b),
357
            _ => Some(a),
358
        }
359
    } else {
360
        None
361
    }
362
}
363
364
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
365
/// `min` or `max`.
366
#[inline]
367
pub fn partial_clamp<'a, T: PartialOrd>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> {
368
    if let (Some(cmp_min), Some(cmp_max)) = (value.partial_cmp(min), value.partial_cmp(max)) {
369
        if cmp_min == Ordering::Less {
370
            Some(min)
371
        } else if cmp_max == Ordering::Greater {
372
            Some(max)
373
        } else {
374
            Some(value)
375
        }
376
    } else {
377
        None
378
    }
379
}
380
381
/// Sorts two values in increasing order using a partial ordering.
382
#[inline]
383
pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &'a T)> {
384
    if let Some(ord) = a.partial_cmp(b) {
385
        match ord {
386
            Ordering::Less => Some((a, b)),
387
            _ => Some((b, a)),
388
        }
389
    } else {
390
        None
391
    }
392
}
393
394
/*
395
 *
396
 * Point operations.
397
 *
398
 */
399
/// The center of two points.
400
///
401
/// # See also:
402
///
403
/// * [`distance()`]
404
/// * [`distance_squared()`]
405
#[inline]
406
pub fn center<T: SimdComplexField, const D: usize>(
407
    p1: &Point<T, D>,
408
    p2: &Point<T, D>,
409
) -> Point<T, D> {
410
    ((&p1.coords + &p2.coords) * convert::<_, T>(0.5)).into()
411
}
412
413
/// The distance between two points.
414
///
415
/// # See also:
416
///
417
/// * [`center()`]
418
/// * [`distance_squared()`]
419
#[inline]
420
pub fn distance<T: SimdComplexField, const D: usize>(
421
    p1: &Point<T, D>,
422
    p2: &Point<T, D>,
423
) -> T::SimdRealField {
424
    (&p2.coords - &p1.coords).norm()
425
}
426
427
/// The squared distance between two points.
428
///
429
/// # See also:
430
///
431
/// * [`center()`]
432
/// * [`distance()`]
433
#[inline]
434
pub fn distance_squared<T: SimdComplexField, const D: usize>(
435
    p1: &Point<T, D>,
436
    p2: &Point<T, D>,
437
) -> T::SimdRealField {
438
    (&p2.coords - &p1.coords).norm_squared()
439
}
440
441
/*
442
 * Cast
443
 */
444
/// Converts an object from one type to an equivalent or more general one.
445
///
446
/// See also [`try_convert()`] for conversion to more specific types.
447
///
448
/// # See also:
449
///
450
/// * [`convert_ref()`]
451
/// * [`convert_ref_unchecked()`]
452
/// * [`is_convertible()`]
453
/// * [`try_convert()`]
454
/// * [`try_convert_ref()`]
455
#[inline]
456
0
pub fn convert<From, To: SupersetOf<From>>(t: From) -> To {
457
0
    To::from_subset(&t)
458
0
}
459
460
/// Attempts to convert an object to a more specific one.
461
///
462
/// See also [`convert()`] for conversion to more general types.
463
///
464
/// # See also:
465
///
466
/// * [`convert()`]
467
/// * [`convert_ref()`]
468
/// * [`convert_ref_unchecked()`]
469
/// * [`is_convertible()`]
470
/// * [`try_convert_ref()`]
471
#[inline]
472
pub fn try_convert<From: SupersetOf<To>, To>(t: From) -> Option<To> {
473
    t.to_subset()
474
}
475
476
/// Indicates if [`try_convert()`] will succeed without
477
/// actually performing the conversion.
478
///
479
/// # See also:
480
///
481
/// * [`convert()`]
482
/// * [`convert_ref()`]
483
/// * [`convert_ref_unchecked()`]
484
/// * [`try_convert()`]
485
/// * [`try_convert_ref()`]
486
#[inline]
487
pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool {
488
    t.is_in_subset()
489
}
490
491
/// Use with care! Same as [`try_convert()`] but
492
/// without any property checks.
493
///
494
/// # See also:
495
///
496
/// * [`convert()`]
497
/// * [`convert_ref()`]
498
/// * [`convert_ref_unchecked()`]
499
/// * [`is_convertible()`]
500
/// * [`try_convert()`]
501
/// * [`try_convert_ref()`]
502
#[inline]
503
pub fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
504
    t.to_subset_unchecked()
505
}
506
507
/// Converts an object from one type to an equivalent or more general one.
508
///
509
/// # See also:
510
///
511
/// * [`convert()`]
512
/// * [`convert_ref_unchecked()`]
513
/// * [`is_convertible()`]
514
/// * [`try_convert()`]
515
/// * [`try_convert_ref()`]
516
#[inline]
517
pub fn convert_ref<From, To: SupersetOf<From>>(t: &From) -> To {
518
    To::from_subset(t)
519
}
520
521
/// Attempts to convert an object to a more specific one.
522
///
523
/// # See also:
524
///
525
/// * [`convert()`]
526
/// * [`convert_ref()`]
527
/// * [`convert_ref_unchecked()`]
528
/// * [`is_convertible()`]
529
/// * [`try_convert()`]
530
#[inline]
531
pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> {
532
    t.to_subset()
533
}
534
535
/// Use with care! Same as [`try_convert()`] but
536
/// without any property checks.
537
///
538
/// # See also:
539
///
540
/// * [`convert()`]
541
/// * [`convert_ref()`]
542
/// * [`is_convertible()`]
543
/// * [`try_convert()`]
544
/// * [`try_convert_ref()`]
545
#[inline]
546
pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
547
    t.to_subset_unchecked()
548
}