#![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;
#[cfg(feature = "abomonation")]
extern crate abomonation;
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};
#[inline]
pub fn id() -> Id {
Id::new()
}
#[inline]
pub fn one<T: Identity<Multiplicative>>() -> T {
T::identity()
}
#[inline]
pub fn zero<T: Identity<Additive>>() -> T {
T::identity()
}
#[inline]
pub fn origin<P: EuclideanSpace>() -> P {
P::origin()
}
#[inline]
pub fn dimension<V: FiniteDimVectorSpace>() -> usize {
V::dimension()
}
#[inline]
pub fn wrap<T>(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
}
}
#[inline]
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
if val > min {
if val < max {
val
}
else {
max
}
}
else {
min
}
}
#[inline]
pub fn max<T: Ord>(a: T, b: T) -> T {
cmp::max(a, b)
}
#[inline]
pub fn min<T: Ord>(a: T, b: T) -> T {
cmp::min(a, b)
}
#[inline]
pub fn abs<T: Signed>(a: &T) -> T {
a.abs()
}
#[inline]
pub fn inf<T: MeetSemilattice>(a: &T, b: &T) -> T {
a.meet(b)
}
#[inline]
pub fn sup<T: JoinSemilattice>(a: &T, b: &T) -> T {
a.join(b)
}
#[inline]
pub fn inf_sup<T: Lattice>(a: &T, b: &T) -> (T, T) {
a.meet_join(b)
}
#[inline]
pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> Option<Ordering> {
a.partial_cmp(b)
}
#[inline]
pub fn partial_lt<T: PartialOrd>(a: &T, b: &T) -> bool {
a.lt(b)
}
#[inline]
pub fn partial_le<T: PartialOrd>(a: &T, b: &T) -> bool {
a.le(b)
}
#[inline]
pub fn partial_gt<T: PartialOrd>(a: &T, b: &T) -> bool {
a.gt(b)
}
#[inline]
pub fn partial_ge<T: PartialOrd>(a: &T, b: &T) -> bool {
a.ge(b)
}
#[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
}
}
#[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
}
}
#[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
}
}
#[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
}
}
#[inline]
pub fn try_inverse<M: AlgaSquareMatrix>(m: &M) -> Option<M> {
m.try_inverse()
}
#[inline]
pub fn inverse<M: Inverse<Multiplicative>>(m: &M) -> M {
m.inverse()
}
#[inline]
pub fn dot<V: FiniteDimVectorSpace>(a: &V, b: &V) -> V::Field {
a.dot(b)
}
#[inline]
pub fn angle<V: InnerSpace>(a: &V, b: &V) -> V::Real {
a.angle(b)
}
#[inline]
pub fn norm<V: NormedSpace>(v: &V) -> V::Field {
v.norm()
}
#[inline]
pub fn norm_squared<V: NormedSpace>(v: &V) -> V::Field {
v.norm_squared()
}
#[inline]
pub fn normalize<V: NormedSpace>(v: &V) -> V {
v.normalize()
}
#[inline]
pub fn try_normalize<V: NormedSpace>(v: &V, min_norm: V::Field) -> Option<V> {
v.try_normalize(min_norm)
}
#[inline]
pub fn center<P: EuclideanSpace>(p1: &P, p2: &P) -> P {
P::from_coordinates((p1.coordinates() + p2.coordinates()) * convert(0.5))
}
#[inline]
pub fn distance<P: EuclideanSpace>(p1: &P, p2: &P) -> P::Real {
(p2.coordinates() - p1.coordinates()).norm()
}
#[inline]
pub fn distance_squared<P: EuclideanSpace>(p1: &P, p2: &P) -> P::Real {
(p2.coordinates() - p1.coordinates()).norm_squared()
}
#[inline]
pub fn convert<From, To: SupersetOf<From>>(t: From) -> To {
To::from_subset(&t)
}
#[inline]
pub fn try_convert<From: SupersetOf<To>, To>(t: From) -> Option<To> {
t.to_subset()
}
#[inline]
pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool {
t.is_in_subset()
}
#[inline]
pub unsafe fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
t.to_subset_unchecked()
}
#[inline]
pub fn convert_ref<From, To: SupersetOf<From>>(t: &From) -> To {
To::from_subset(t)
}
#[inline]
pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> {
t.to_subset()
}
#[inline]
pub unsafe fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
t.to_subset_unchecked()
}