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 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    relative_eq!(b.axis().unwrap(), axis);
40    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 slices
50  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 `Vector6` and
54  `Matrix1x1` to `Matrix6x6`, including rectangular matrices like `Matrix2x5`.
55* Points sizes known at compile time, and convenience aliases: `Point1` to `Point6`.
56* Translation (seen as a transformation that composes by multiplication): `Translation2`,
57  `Translation3`.
58* Rotation matrices: `Rotation2`, `Rotation3`.
59* Quaternions: `Quaternion`, `UnitQuaternion` (for 3D rotation).
60* Unit complex numbers can be used for 2D rotation: `UnitComplex`.
61* Algebraic entities with a norm equal to one: `Unit<T>`, e.g., `Unit<Vector3<f32>>`.
62* Isometries (translation ⨯ rotation): `Isometry2`, `Isometry3`
63* Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Similarity2`, `Similarity3`.
64* Affine transformations stored as a homogeneous matrix: `Affine2`, `Affine3`.
65* Projective (i.e. invertible) transformations stored as a homogeneous matrix: `Projective2`,
66  `Projective3`.
67* General transformations that does not have to be invertible, stored as a homogeneous matrix:
68  `Transform2`, `Transform3`.
69* 3D projections for computer graphics: `Perspective3`, `Orthographic3`.
70* Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `Schur`, `Hessenberg`, `SymmetricEigen`.
71* Insertion and removal of rows of columns of a matrix.
72*/
73
74#![deny(
75    missing_docs,
76    nonstandard_style,
77    unused_variables,
78    unused_mut,
79    unused_parens,
80    unused_qualifications,
81    unused_results,
82    rust_2018_idioms,
83    rust_2018_compatibility,
84    future_incompatible,
85    missing_copy_implementations
86)]
87#![doc(
88    html_favicon_url = "https://nalgebra.org/img/favicon.ico",
89    html_root_url = "https://docs.rs/nalgebra/0.25.0"
90)]
91#![cfg_attr(not(feature = "std"), no_std)]
92
93#[cfg(feature = "rand-no-std")]
94extern crate rand_package as rand;
95
96#[cfg(feature = "serde-serialize-no-std")]
97#[macro_use]
98extern crate serde;
99
100#[macro_use]
101extern crate approx;
102extern crate num_traits as num;
103
104#[cfg(all(feature = "alloc", not(feature = "std")))]
105#[cfg_attr(test, macro_use)]
106extern crate alloc;
107
108#[cfg(not(feature = "std"))]
109extern crate core as std;
110
111#[cfg(feature = "io")]
112extern crate pest;
113#[macro_use]
114#[cfg(feature = "io")]
115extern crate pest_derive;
116
117pub mod base;
118#[cfg(feature = "debug")]
119pub mod debug;
120pub mod geometry;
121#[cfg(feature = "io")]
122pub mod io;
123pub mod linalg;
124#[cfg(feature = "proptest-support")]
125pub mod proptest;
126#[cfg(feature = "sparse")]
127pub mod sparse;
128mod third_party;
129
130pub use crate::base::*;
131pub use crate::geometry::*;
132pub use crate::linalg::*;
133#[cfg(feature = "sparse")]
134pub use crate::sparse::*;
135#[cfg(feature = "std")]
136#[deprecated(
137    note = "The 'core' module is being renamed to 'base' to avoid conflicts with the 'core' crate."
138)]
139pub use base as core;
140
141#[cfg(feature = "macros")]
142pub use nalgebra_macros::{dmatrix, dvector, matrix, point, vector};
143
144use simba::scalar::SupersetOf;
145use std::cmp::{self, Ordering, PartialOrd};
146
147use num::{One, Signed, Zero};
148
149use base::allocator::Allocator;
150pub use num_complex::Complex;
151pub use simba::scalar::{
152    ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, ComplexField, Field, RealField,
153};
154pub use simba::simd::{SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdValue};
155
156/// Gets the multiplicative identity element.
157///
158/// # See also:
159///
160/// * [`origin`](../nalgebra/fn.origin.html)
161/// * [`zero`](fn.zero.html)
162#[inline]
163pub fn one<T: One>() -> T {
164    T::one()
165}
166
167/// Gets the additive identity element.
168///
169/// # See also:
170///
171/// * [`one`](fn.one.html)
172/// * [`origin`](../nalgebra/fn.origin.html)
173#[inline]
174pub fn zero<T: Zero>() -> T {
175    T::zero()
176}
177
178/*
179 *
180 * Ordering
181 *
182 */
183// XXX: this is very naive and could probably be optimized for specific types.
184// XXX: also, we might just want to use divisions, but assuming `val` is usually not far from `min`
185// or `max`, would it still be more efficient?
186/// Wraps `val` into the range `[min, max]` using modular arithmetics.
187///
188/// The range must not be empty.
189#[must_use]
190#[inline]
191pub fn wrap<T>(mut val: T, min: T, max: T) -> T
192where
193    T: Copy + PartialOrd + ClosedAdd + ClosedSub,
194{
195    assert!(min < max, "Invalid wrapping bounds.");
196    let width = max - min;
197
198    if val < min {
199        val += width;
200
201        while val < min {
202            val += width
203        }
204    } else if val > max {
205        val -= width;
206
207        while val > max {
208            val -= width
209        }
210    }
211
212    val
213}
214
215/// Returns a reference to the input value clamped to the interval `[min, max]`.
216///
217/// In particular:
218///     * If `min < val < max`, this returns `val`.
219///     * If `val <= min`, this returns `min`.
220///     * If `val >= max`, this returns `max`.
221#[must_use]
222#[inline]
223pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
224    if val > min {
225        if val < max {
226            val
227        } else {
228            max
229        }
230    } else {
231        min
232    }
233}
234
235/// Same as `cmp::max`.
236#[inline]
237pub fn max<T: Ord>(a: T, b: T) -> T {
238    cmp::max(a, b)
239}
240
241/// Same as `cmp::min`.
242#[inline]
243pub fn min<T: Ord>(a: T, b: T) -> T {
244    cmp::min(a, b)
245}
246
247/// The absolute value of `a`.
248///
249/// Deprecated: Use [`Matrix::abs`] or [`RealField::abs`] instead.
250#[deprecated(note = "use the inherent method `Matrix::abs` or `RealField::abs` instead")]
251#[inline]
252pub fn abs<T: Signed>(a: &T) -> T {
253    a.abs()
254}
255
256/// Returns the infimum of `a` and `b`.
257#[deprecated(note = "use the inherent method `Matrix::inf` instead")]
258#[inline]
259pub fn inf<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
260where
261    T: Scalar + SimdPartialOrd,
262    DefaultAllocator: Allocator<T, R, C>,
263{
264    a.inf(b)
265}
266
267/// Returns the supremum of `a` and `b`.
268#[deprecated(note = "use the inherent method `Matrix::sup` instead")]
269#[inline]
270pub fn sup<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C>
271where
272    T: Scalar + SimdPartialOrd,
273    DefaultAllocator: Allocator<T, R, C>,
274{
275    a.sup(b)
276}
277
278/// Returns simultaneously the infimum and supremum of `a` and `b`.
279#[deprecated(note = "use the inherent method `Matrix::inf_sup` instead")]
280#[inline]
281pub fn inf_sup<T, R: Dim, C: Dim>(
282    a: &OMatrix<T, R, C>,
283    b: &OMatrix<T, R, C>,
284) -> (OMatrix<T, R, C>, OMatrix<T, R, C>)
285where
286    T: Scalar + SimdPartialOrd,
287    DefaultAllocator: Allocator<T, R, C>,
288{
289    a.inf_sup(b)
290}
291
292/// Compare `a` and `b` using a partial ordering relation.
293#[inline]
294pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> Option<Ordering> {
295    a.partial_cmp(b)
296}
297
298/// Returns `true` iff `a` and `b` are comparable and `a < b`.
299#[inline]
300pub fn partial_lt<T: PartialOrd>(a: &T, b: &T) -> bool {
301    a.lt(b)
302}
303
304/// Returns `true` iff `a` and `b` are comparable and `a <= b`.
305#[inline]
306pub fn partial_le<T: PartialOrd>(a: &T, b: &T) -> bool {
307    a.le(b)
308}
309
310/// Returns `true` iff `a` and `b` are comparable and `a > b`.
311#[inline]
312pub fn partial_gt<T: PartialOrd>(a: &T, b: &T) -> bool {
313    a.gt(b)
314}
315
316/// Returns `true` iff `a` and `b` are comparable and `a >= b`.
317#[inline]
318pub fn partial_ge<T: PartialOrd>(a: &T, b: &T) -> bool {
319    a.ge(b)
320}
321
322/// Return the minimum of `a` and `b` if they are comparable.
323#[inline]
324pub fn partial_min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
325    if let Some(ord) = a.partial_cmp(b) {
326        match ord {
327            Ordering::Greater => Some(b),
328            _ => Some(a),
329        }
330    } else {
331        None
332    }
333}
334
335/// Return the maximum of `a` and `b` if they are comparable.
336#[inline]
337pub fn partial_max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> {
338    if let Some(ord) = a.partial_cmp(b) {
339        match ord {
340            Ordering::Less => Some(b),
341            _ => Some(a),
342        }
343    } else {
344        None
345    }
346}
347
348/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
349/// `min` or `max`.
350#[inline]
351pub fn partial_clamp<'a, T: PartialOrd>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> {
352    if let (Some(cmp_min), Some(cmp_max)) = (value.partial_cmp(min), value.partial_cmp(max)) {
353        if cmp_min == Ordering::Less {
354            Some(min)
355        } else if cmp_max == Ordering::Greater {
356            Some(max)
357        } else {
358            Some(value)
359        }
360    } else {
361        None
362    }
363}
364
365/// Sorts two values in increasing order using a partial ordering.
366#[inline]
367pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &'a T)> {
368    if let Some(ord) = a.partial_cmp(b) {
369        match ord {
370            Ordering::Less => Some((a, b)),
371            _ => Some((b, a)),
372        }
373    } else {
374        None
375    }
376}
377
378/*
379 *
380 * Point operations.
381 *
382 */
383/// The center of two points.
384///
385/// # See also:
386///
387/// * [distance](fn.distance.html)
388/// * [`distance_squared`](fn.distance_squared.html)
389#[inline]
390pub fn center<T: SimdComplexField, const D: usize>(
391    p1: &Point<T, D>,
392    p2: &Point<T, D>,
393) -> Point<T, D> {
394    ((&p1.coords + &p2.coords) * convert::<_, T>(0.5)).into()
395}
396
397/// The distance between two points.
398///
399/// # See also:
400///
401/// * [center](fn.center.html)
402/// * [`distance_squared`](fn.distance_squared.html)
403#[inline]
404pub fn distance<T: SimdComplexField, const D: usize>(
405    p1: &Point<T, D>,
406    p2: &Point<T, D>,
407) -> T::SimdRealField {
408    (&p2.coords - &p1.coords).norm()
409}
410
411/// The squared distance between two points.
412///
413/// # See also:
414///
415/// * [center](fn.center.html)
416/// * [distance](fn.distance.html)
417#[inline]
418pub fn distance_squared<T: SimdComplexField, const D: usize>(
419    p1: &Point<T, D>,
420    p2: &Point<T, D>,
421) -> T::SimdRealField {
422    (&p2.coords - &p1.coords).norm_squared()
423}
424
425/*
426 * Cast
427 */
428/// Converts an object from one type to an equivalent or more general one.
429///
430/// See also [`try_convert`](fn.try_convert.html) for conversion to more specific types.
431///
432/// # See also:
433///
434/// * [`convert_ref`](fn.convert_ref.html)
435/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
436/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
437/// * [`try_convert`](fn.try_convert.html)
438/// * [`try_convert_ref`](fn.try_convert_ref.html)
439#[inline]
440pub fn convert<From, To: SupersetOf<From>>(t: From) -> To {
441    To::from_subset(&t)
442}
443
444/// Attempts to convert an object to a more specific one.
445///
446/// See also [`convert`](fn.convert.html) for conversion to more general types.
447///
448/// # See also:
449///
450/// * [convert](fn.convert.html)
451/// * [`convert_ref`](fn.convert_ref.html)
452/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
453/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
454/// * [`try_convert_ref`](fn.try_convert_ref.html)
455#[inline]
456pub fn try_convert<From: SupersetOf<To>, To>(t: From) -> Option<To> {
457    t.to_subset()
458}
459
460/// Indicates if [`try_convert`](fn.try_convert.html) will succeed without
461/// actually performing the conversion.
462///
463/// # See also:
464///
465/// * [convert](fn.convert.html)
466/// * [`convert_ref`](fn.convert_ref.html)
467/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
468/// * [`try_convert`](fn.try_convert.html)
469/// * [`try_convert_ref`](fn.try_convert_ref.html)
470#[inline]
471pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool {
472    t.is_in_subset()
473}
474
475/// Use with care! Same as [`try_convert`](fn.try_convert.html) but
476/// without any property checks.
477///
478/// # See also:
479///
480/// * [convert](fn.convert.html)
481/// * [`convert_ref`](fn.convert_ref.html)
482/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
483/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
484/// * [`try_convert`](fn.try_convert.html)
485/// * [`try_convert_ref`](fn.try_convert_ref.html)
486#[inline]
487pub fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
488    t.to_subset_unchecked()
489}
490
491/// Converts an object from one type to an equivalent or more general one.
492///
493/// # See also:
494///
495/// * [convert](fn.convert.html)
496/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
497/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
498/// * [`try_convert`](fn.try_convert.html)
499/// * [`try_convert_ref`](fn.try_convert_ref.html)
500#[inline]
501pub fn convert_ref<From, To: SupersetOf<From>>(t: &From) -> To {
502    To::from_subset(t)
503}
504
505/// Attempts to convert an object to a more specific one.
506///
507/// # See also:
508///
509/// * [convert](fn.convert.html)
510/// * [`convert_ref`](fn.convert_ref.html)
511/// * [`convert_ref_unchecked`](fn.convert_ref_unchecked.html)
512/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
513/// * [`try_convert`](fn.try_convert.html)
514#[inline]
515pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> {
516    t.to_subset()
517}
518
519/// Use with care! Same as [`try_convert`](fn.try_convert.html) but
520/// without any property checks.
521///
522/// # See also:
523///
524/// * [convert](fn.convert.html)
525/// * [`convert_ref`](fn.convert_ref.html)
526/// * [`is_convertible`](../nalgebra/fn.is_convertible.html)
527/// * [`try_convert`](fn.try_convert.html)
528/// * [`try_convert_ref`](fn.try_convert_ref.html)
529#[inline]
530pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
531    t.to_subset_unchecked()
532}