nalgebra/lib.rs
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**
11You will need the last stable build of the [rust compiler](https://www.rust-lang.org)
12and the official package manager: [cargo](https://github.com/rust-lang/cargo).
13
14Simply add the following to your `Cargo.toml` file:
15
16```ignore
17[dependencies]
18// TODO: replace the * by the latest version.
19nalgebra = "*"
20```
21
22
23Most useful functionalities of **nalgebra** are grouped in the root module `nalgebra::`.
24
25However, the recommended way to use **nalgebra** is to import types and traits
26explicitly, and call free-functions using the `na::` prefix:
27
28```
29#[macro_use]
30extern crate approx; // For the macro assert_relative_eq!
31extern crate nalgebra as na;
32use na::{Vector3, Rotation3};
33
34fn 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
47an 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.
105macro_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
112pub(crate) use slice_deprecation_note;
113
114#[cfg(feature = "rand-no-std")]
115extern crate rand_package as rand;
116
117#[cfg(feature = "serde-serialize-no-std")]
118#[macro_use]
119extern crate serde;
120
121#[macro_use]
122extern crate approx;
123extern crate num_traits as num;
124
125#[cfg(all(feature = "alloc", not(feature = "std")))]
126#[cfg_attr(test, macro_use)]
127extern crate alloc;
128
129#[cfg(not(feature = "std"))]
130extern crate core as std;
131
132#[macro_use]
133#[cfg(feature = "io")]
134extern crate pest_derive;
135
136pub mod base;
137#[cfg(feature = "debug")]
138pub mod debug;
139pub mod geometry;
140#[cfg(feature = "io")]
141pub mod io;
142pub mod linalg;
143#[cfg(feature = "proptest-support")]
144pub mod proptest;
145#[cfg(feature = "sparse")]
146pub mod sparse;
147mod third_party;
148
149pub use crate::base::*;
150pub use crate::geometry::*;
151pub use crate::linalg::*;
152#[cfg(feature = "sparse")]
153pub 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)]
158pub use base as core;
159
160#[cfg(feature = "macros")]
161pub use nalgebra_macros::{dmatrix, dvector, matrix, point, stack, vector};
162
163use simba::scalar::SupersetOf;
164use std::cmp::{self, Ordering, PartialOrd};
165
166use num::{One, Signed, Zero};
167
168use base::allocator::Allocator;
169pub use num_complex::Complex;
170pub use simba::scalar::{
171 ClosedAddAssign, ClosedDivAssign, ClosedMulAssign, ClosedSubAssign, ComplexField, Field,
172 RealField,
173};
174pub 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]
183pub 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]
194pub 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]
211pub fn wrap<T>(mut val: T, min: T, max: T) -> T
212where
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]
243pub 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]
253pub fn max<T: Ord>(a: T, b: T) -> T {
254 cmp::max(a, b)
255}
256
257/// Same as `cmp::min`.
258#[inline]
259pub fn min<T: Ord>(a: T, b: T) -> T {
260 cmp::min(a, b)
261}
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]
268pub 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]
275pub fn inf<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
276where
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]
286pub fn sup<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
287where
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]
297pub 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>)
301where
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]
310pub 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]
316pub 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]
322pub 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]
328pub 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]
334pub 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]
340pub 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]
353pub 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]
367pub 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]
383pub 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]
406pub 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]
420pub 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]
434pub 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]
456pub fn convert<From, To: SupersetOf<From>>(t: From) -> To {
457 To::from_subset(&t)
458}
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]
472pub 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]
487pub 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]
503pub 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]
517pub 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]
531pub 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]
546pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
547 t.to_subset_unchecked()
548}