/*! # nalgebra **nalgebra** is a linear algebra library written for Rust targeting: * General-purpose linear algebra (still lacks a lot of features…) * Real time computer graphics. * Real time computer physics. ## Using **nalgebra** You will need the last stable build of the [rust compiler](http://www.rust-lang.org) and the official package manager: [cargo](https://github.com/rust-lang/cargo). Simply add the following to your `Cargo.toml` file: ```.ignore [dependencies] nalgebra = "0.13" ``` Most useful functionalities of **nalgebra** are grouped in the root module `nalgebra::`. However, the recommended way to use **nalgebra** is to import types and traits explicitly, and call free-functions using the `na::` prefix: ```.rust #[macro_use] extern crate approx; // For the macro relative_eq! extern crate nalgebra as na; use na::{Vector3, Rotation3}; fn main() { let axis = Vector3::x_axis(); let angle = 1.57; let b = Rotation3::from_axis_angle(&axis, angle); relative_eq!(b.axis().unwrap(), axis); relative_eq!(b.angle(), angle); } ``` ## Features **nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with an optimized set of tools for computer graphics and physics. Those features include: * A single parametrizable type `Matrix` for vectors, (square or rectangular) matrices, and slices with dimensions known either at compile-time (using type-level integers) or at runtime. * Matrices and vectors with compile-time sizes are statically allocated while dynamic ones are allocated on the heap. * Convenient aliases for low-dimensional matrices and vectors: `Vector1` to `Vector6` and `Matrix1x1` to `Matrix6x6` (including rectangular matrices like `Matrix2x5`. * Points sizes known at compile time, and convenience aliases: `Point1` to `Point6`. * Translation (seen as a transformation that composes by multiplication): `Translation2`, `Translation3`. * Rotation matrices: `Rotation2`, `Rotation3`. * Quaternions: `Quaternion`, `UnitQuaternion` (for 3D rotation). * Unit complex numbers can be used for 2D rotation: `UnitComplex`. * Algebraic entities with a norm equal to one: `Unit`, e.g., `Unit>`. * Isometries (translation ⨯ rotation): `Isometry2`, `Isometry3` * Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Similarity2`, `Similarity3`. * Affine transformations stored as an homogeneous matrix: `Affine2`, `Affine3`. * Projective (i.e. invertible) transformations stored as an homogeneous matrix: `Projective2`, `Projective3`. * General transformations that does not have to be invertible, stored as an homogeneous matrix: `Transform2`, `Transform3`. * 3D projections for computer graphics: `Perspective3`, `Orthographic3`. * Linear algebra decompositions: Cholesky, QR, LU, SVD, Schur, symmetric-eigendecomposition,. * Implements traits from the [alga](https://crates.io/crates/alga) crate for generic programming. */ // #![feature(plugin)] // // #![plugin(clippy)] #![deny(non_camel_case_types)] #![deny(unused_parens)] #![deny(non_upper_case_globals)] #![deny(unused_qualifications)] #![deny(unused_results)] #![deny(missing_docs)] #![doc(html_root_url = "http://nalgebra.org/rustdoc")] #[cfg(feature = "arbitrary")] extern crate quickcheck; #[cfg(feature = "serde")] extern crate serde; #[cfg(feature = "serde")] #[macro_use] extern crate serde_derive; extern crate num_traits as num; extern crate num_complex; extern crate rand; #[macro_use] extern crate approx; extern crate typenum; extern crate generic_array; extern crate matrixmultiply; extern crate alga; pub mod core; pub mod linalg; pub mod geometry; #[cfg(feature = "debug")] pub mod debug; pub use core::*; pub use linalg::*; pub use geometry::*; use std::cmp::{self, PartialOrd, Ordering}; use num::Signed; use alga::general::{Identity, SupersetOf, MeetSemilattice, JoinSemilattice, Lattice, Inverse, Multiplicative, Additive, AdditiveGroup}; use alga::linear::SquareMatrix as AlgaSquareMatrix; use alga::linear::{InnerSpace, NormedSpace, FiniteDimVectorSpace, EuclideanSpace}; pub use alga::general::{Real, Id}; /* * * Multiplicative identity. * */ /// Gets the ubiquitous multiplicative identity element. /// /// Same as `Id::new()`. #[inline] pub fn id() -> Id { Id::new() } /// Gets the multiplicative identity element. #[inline] pub fn one>() -> T { T::identity() } /// Gets the additive identity element. #[inline] pub fn zero>() -> T { T::identity() } /// Gets the origin of the given point. #[inline] pub fn origin() -> P { P::origin() } /* * * Dimension * */ /// The dimension of the given algebraic entity seen as a vector space. #[inline] pub fn dimension() -> usize { V::dimension() } /* * * Ordering * */ // XXX: this is very naive and could probably be optimized for specific types. // XXX: also, we might just want to use divisions, but assuming `val` is usually not far from `min` // or `max`, would it still be more efficient? /// Wraps `val` into the range `[min, max]` using modular arithmetics. /// /// The range must not be empty. #[inline] pub fn wrap(mut val: T, min: T, max: T) -> T where T: Copy + PartialOrd + AdditiveGroup { assert!(min < max, "Invalid wrapping bounds."); let width = max - min; if val < min { val += width; while val < min { val += width } val } else if val > max { val -= width; while val > max { val -= width } val } else { val } } /// Returns a reference to the input value clamped to the interval `[min, max]`. /// /// In particular: /// * If `min < val < max`, this returns `val`. /// * If `val <= min`, this retuns `min`. /// * If `val >= max`, this retuns `max`. #[inline] pub fn clamp(val: T, min: T, max: T) -> T { if val > min { if val < max { val } else { max } } else { min } } /// Same as `cmp::max`. #[inline] pub fn max(a: T, b: T) -> T { cmp::max(a, b) } /// Same as `cmp::min`. #[inline] pub fn min(a: T, b: T) -> T { cmp::min(a, b) } /// The absolute value of `a`. #[inline] pub fn abs(a: &T) -> T { a.abs() } /// Returns the infimum of `a` and `b`. #[inline] pub fn inf(a: &T, b: &T) -> T { a.meet(b) } /// Returns the supremum of `a` and `b`. #[inline] pub fn sup(a: &T, b: &T) -> T { a.join(b) } /// Returns simultaneously the infimum and supremum of `a` and `b`. #[inline] pub fn inf_sup(a: &T, b: &T) -> (T, T) { a.meet_join(b) } /// Compare `a` and `b` using a partial ordering relation. #[inline] pub fn partial_cmp(a: &T, b: &T) -> Option { a.partial_cmp(b) } /// Returns `true` iff `a` and `b` are comparable and `a < b`. #[inline] pub fn partial_lt(a: &T, b: &T) -> bool { a.lt(b) } /// Returns `true` iff `a` and `b` are comparable and `a <= b`. #[inline] pub fn partial_le(a: &T, b: &T) -> bool { a.le(b) } /// Returns `true` iff `a` and `b` are comparable and `a > b`. #[inline] pub fn partial_gt(a: &T, b: &T) -> bool { a.gt(b) } /// Returns `true` iff `a` and `b` are comparable and `a >= b`. #[inline] pub fn partial_ge(a: &T, b: &T) -> bool { a.ge(b) } /// Return the minimum of `a` and `b` if they are comparable. #[inline] pub fn partial_min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> { if let Some(ord) = a.partial_cmp(b) { match ord { Ordering::Greater => Some(b), _ => Some(a), } } else { None } } /// Return the maximum of `a` and `b` if they are comparable. #[inline] pub fn partial_max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> { if let Some(ord) = a.partial_cmp(b) { match ord { Ordering::Less => Some(b), _ => Some(a), } } else { None } } /// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to /// `min` or `max`. #[inline] pub fn partial_clamp<'a, T: PartialOrd>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> { if let (Some(cmp_min), Some(cmp_max)) = (value.partial_cmp(min), value.partial_cmp(max)) { if cmp_min == Ordering::Less { Some(min) } else if cmp_max == Ordering::Greater { Some(max) } else { Some(value) } } else { None } } /// Sorts two values in increasing order using a partial ordering. #[inline] pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &'a T)> { if let Some(ord) = a.partial_cmp(b) { match ord { Ordering::Less => Some((a, b)), _ => Some((b, a)), } } else { None } } /* * Inverse */ /// Tries to gets an inverted copy of a square matrix. #[inline] pub fn try_inverse(m: &M) -> Option { m.try_inverse() } /// Computes the multiplicative inverse of an (always invertible) algebraic entity. #[inline] pub fn inverse>(m: &M) -> M { m.inverse() } /* * Inner vector space */ /// Computes the dot product of two vectors. #[inline] pub fn dot(a: &V, b: &V) -> V::Field { a.dot(b) } /// Computes the smallest angle between two vectors. #[inline] pub fn angle(a: &V, b: &V) -> V::Real { a.angle(b) } /* * Normed space */ /// Computes the L2 (euclidean) norm of a vector. #[inline] pub fn norm(v: &V) -> V::Field { v.norm() } /// Computes the squared L2 (euclidean) norm of the vector `v`. #[inline] pub fn norm_squared(v: &V) -> V::Field { v.norm_squared() } /// Computes the normalized version of the vector `v`. #[inline] pub fn normalize(v: &V) -> V { v.normalize() } /// Computes the normalized version of the vector `v` or returns `None` if its norm is smaller than `min_norm`. #[inline] pub fn try_normalize(v: &V, min_norm: V::Field) -> Option { v.try_normalize(min_norm) } /* * * Point operations. * */ /// The center of two points. #[inline] pub fn center(p1: &P, p2: &P) -> P { P::from_coordinates((p1.coordinates() + p2.coordinates()) * convert(0.5)) } /// The distance between two points. #[inline] pub fn distance(p1: &P, p2: &P) -> P::Real { (p2.coordinates() - p1.coordinates()).norm() } /// The squared distance between two points. #[inline] pub fn distance_squared(p1: &P, p2: &P) -> P::Real { (p2.coordinates() - p1.coordinates()).norm_squared() } /* * Cast */ /// Converts an object from one type to an equivalent or more general one. /// /// See also `::try_convert` for conversion to more specific types. #[inline] pub fn convert>(t: From) -> To { To::from_subset(&t) } /// Attempts to convert an object to a more specific one. /// /// See also `::convert` for conversion to more general types. #[inline] pub fn try_convert, To>(t: From) -> Option { t.to_subset() } /// Indicates if `::try_convert` will succeed without actually performing the conversion. #[inline] pub fn is_convertible, To>(t: &From) -> bool { t.is_in_subset() } /// Use with care! Same as `try_convert` but without any property checks. #[inline] pub unsafe fn convert_unchecked, To>(t: From) -> To { t.to_subset_unchecked() } /// Converts an object from one type to an equivalent or more general one. #[inline] pub fn convert_ref>(t: &From) -> To { To::from_subset(t) } /// Attempts to convert an object to a more specific one. #[inline] pub fn try_convert_ref, To>(t: &From) -> Option { t.to_subset() } /// Use with care! Same as `try_convert` but without any property checks. #[inline] pub unsafe fn convert_ref_unchecked, To>(t: &From) -> To { t.to_subset_unchecked() }