2017-02-13 01:17:09 +08:00
|
|
|
|
/*!
|
|
|
|
|
# nalgebra
|
|
|
|
|
|
|
|
|
|
**nalgebra** is a linear algebra library written for Rust targeting:
|
|
|
|
|
|
|
|
|
|
* General-purpose linear algebra (still lacks a lot of features…)
|
2019-04-18 00:31:13 +08:00
|
|
|
|
* Real-time computer graphics.
|
|
|
|
|
* Real-time computer physics.
|
2017-02-13 01:17:09 +08:00
|
|
|
|
|
|
|
|
|
## Using **nalgebra**
|
2019-06-12 02:56:50 +08:00
|
|
|
|
You will need the last stable build of the [rust compiler](https://www.rust-lang.org)
|
2017-02-13 01:17:09 +08:00
|
|
|
|
and the official package manager: [cargo](https://github.com/rust-lang/cargo).
|
|
|
|
|
|
|
|
|
|
Simply add the following to your `Cargo.toml` file:
|
|
|
|
|
|
|
|
|
|
```.ignore
|
|
|
|
|
[dependencies]
|
2021-01-29 20:56:40 +08:00
|
|
|
|
// TODO: replace the * by the latest version.
|
|
|
|
|
nalgebra = "*"
|
2017-02-13 01:17:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2017-08-14 01:53:04 +08:00
|
|
|
|
`Matrix1x1` to `Matrix6x6`, including rectangular matrices like `Matrix2x5`.
|
2020-02-23 23:30:11 +08:00
|
|
|
|
* Points sizes known at compile time, and convenience aliases: `Point1` to `Point6`.
|
2017-02-13 01:17:09 +08:00
|
|
|
|
* 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<T>`, e.g., `Unit<Vector3<f32>>`.
|
|
|
|
|
* Isometries (translation ⨯ rotation): `Isometry2`, `Isometry3`
|
|
|
|
|
* Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Similarity2`, `Similarity3`.
|
2020-02-23 23:30:11 +08:00
|
|
|
|
* Affine transformations stored as a homogeneous matrix: `Affine2`, `Affine3`.
|
|
|
|
|
* Projective (i.e. invertible) transformations stored as a homogeneous matrix: `Projective2`,
|
2017-02-13 01:17:09 +08:00
|
|
|
|
`Projective3`.
|
2020-02-23 23:30:11 +08:00
|
|
|
|
* General transformations that does not have to be invertible, stored as a homogeneous matrix:
|
2017-02-13 01:17:09 +08:00
|
|
|
|
`Transform2`, `Transform3`.
|
|
|
|
|
* 3D projections for computer graphics: `Perspective3`, `Orthographic3`.
|
2019-03-23 18:46:56 +08:00
|
|
|
|
* Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `Schur`, `Hessenberg`, `SymmetricEigen`.
|
2017-08-14 01:53:04 +08:00
|
|
|
|
* Insertion and removal of rows of columns of a matrix.
|
2017-02-13 01:17:09 +08:00
|
|
|
|
*/
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
// #![feature(plugin)]
|
|
|
|
|
//
|
|
|
|
|
// #![plugin(clippy)]
|
2017-02-13 01:17:09 +08:00
|
|
|
|
|
|
|
|
|
#![deny(non_camel_case_types)]
|
|
|
|
|
#![deny(unused_parens)]
|
|
|
|
|
#![deny(non_upper_case_globals)]
|
|
|
|
|
#![deny(unused_qualifications)]
|
|
|
|
|
#![deny(unused_results)]
|
2020-04-06 00:02:03 +08:00
|
|
|
|
#![deny(missing_docs)]
|
2018-10-21 04:27:18 +08:00
|
|
|
|
#![doc(
|
2019-06-12 02:56:50 +08:00
|
|
|
|
html_favicon_url = "https://nalgebra.org/img/favicon.ico",
|
2021-01-29 20:56:40 +08:00
|
|
|
|
html_root_url = "https://docs.rs/nalgebra/0.24.0"
|
2018-10-21 04:27:18 +08:00
|
|
|
|
)]
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#![cfg_attr(not(feature = "std"), no_std)]
|
2018-05-24 23:17:34 +08:00
|
|
|
|
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
|
2016-08-30 03:16:15 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[cfg(feature = "arbitrary")]
|
|
|
|
|
extern crate quickcheck;
|
2017-08-14 20:32:02 +08:00
|
|
|
|
|
2020-07-12 16:47:16 +08:00
|
|
|
|
#[cfg(feature = "serde-serialize")]
|
2017-02-13 01:17:09 +08:00
|
|
|
|
#[macro_use]
|
2020-07-12 16:47:16 +08:00
|
|
|
|
extern crate serde;
|
2017-08-14 20:32:02 +08:00
|
|
|
|
|
2017-09-18 20:31:17 +08:00
|
|
|
|
#[cfg(feature = "abomonation-serialize")]
|
2017-08-14 18:07:06 +08:00
|
|
|
|
extern crate abomonation;
|
2017-08-14 20:32:02 +08:00
|
|
|
|
|
2017-07-25 23:04:12 +08:00
|
|
|
|
#[cfg(feature = "mint")]
|
|
|
|
|
extern crate mint;
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate approx;
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(feature = "std")]
|
2017-08-03 01:37:44 +08:00
|
|
|
|
extern crate matrixmultiply;
|
2020-03-18 00:58:36 +08:00
|
|
|
|
extern crate num_traits as num;
|
2019-10-12 02:01:36 +08:00
|
|
|
|
#[cfg(feature = "std")]
|
|
|
|
|
extern crate rand_distr;
|
2016-08-30 03:16:15 +08:00
|
|
|
|
|
2018-05-24 23:17:34 +08:00
|
|
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
|
|
|
extern crate alloc;
|
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
|
|
extern crate core as std;
|
|
|
|
|
|
2018-11-07 01:32:20 +08:00
|
|
|
|
#[cfg(feature = "io")]
|
|
|
|
|
extern crate pest;
|
|
|
|
|
#[macro_use]
|
|
|
|
|
#[cfg(feature = "io")]
|
|
|
|
|
extern crate pest_derive;
|
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
pub mod base;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[cfg(feature = "debug")]
|
|
|
|
|
pub mod debug;
|
2018-04-27 13:53:08 +08:00
|
|
|
|
pub mod geometry;
|
2018-11-07 01:32:20 +08:00
|
|
|
|
#[cfg(feature = "io")]
|
|
|
|
|
pub mod io;
|
2018-04-27 13:53:08 +08:00
|
|
|
|
pub mod linalg;
|
2018-10-21 04:27:18 +08:00
|
|
|
|
#[cfg(feature = "sparse")]
|
|
|
|
|
pub mod sparse;
|
2013-10-06 22:54:09 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
pub use crate::base::*;
|
|
|
|
|
pub use crate::geometry::*;
|
|
|
|
|
pub use crate::linalg::*;
|
2018-10-21 04:27:18 +08:00
|
|
|
|
#[cfg(feature = "sparse")]
|
2019-03-23 21:29:07 +08:00
|
|
|
|
pub use crate::sparse::*;
|
2020-03-18 00:58:36 +08:00
|
|
|
|
#[cfg(feature = "std")]
|
|
|
|
|
#[deprecated(
|
|
|
|
|
note = "The 'core' module is being renamed to 'base' to avoid conflicts with the 'core' crate."
|
|
|
|
|
)]
|
|
|
|
|
pub use base as core;
|
2013-10-06 22:54:09 +08:00
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use simba::scalar::SupersetOf;
|
2018-02-02 19:26:35 +08:00
|
|
|
|
use std::cmp::{self, Ordering, PartialOrd};
|
2013-10-14 16:22:32 +08:00
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use num::{One, Signed, Zero};
|
2017-02-13 01:17:09 +08:00
|
|
|
|
|
2020-03-21 19:16:46 +08:00
|
|
|
|
use base::allocator::Allocator;
|
|
|
|
|
pub use num_complex::Complex;
|
|
|
|
|
pub use simba::scalar::{
|
|
|
|
|
ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, ComplexField, Field, RealField,
|
|
|
|
|
};
|
2020-03-25 02:06:28 +08:00
|
|
|
|
pub use simba::simd::{SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField};
|
2013-10-14 16:22:32 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Gets the multiplicative identity element.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [`origin`](../nalgebra/fn.origin.html)
|
|
|
|
|
/// * [`zero`](fn.zero.html)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn one<T: One>() -> T {
|
|
|
|
|
T::one()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2013-10-14 16:22:32 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Gets the additive identity element.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [`one`](fn.one.html)
|
|
|
|
|
/// * [`origin`](../nalgebra/fn.origin.html)
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn zero<T: Zero>() -> T {
|
|
|
|
|
T::zero()
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2013-10-06 22:54:09 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* 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<T>(mut val: T, min: T, max: T) -> T
|
2020-08-26 02:47:07 +08:00
|
|
|
|
where
|
|
|
|
|
T: Copy + PartialOrd + ClosedAdd + ClosedSub,
|
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
assert!(min < max, "Invalid wrapping bounds.");
|
|
|
|
|
let width = max - min;
|
2013-05-15 05:08:29 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
if val < min {
|
|
|
|
|
val += width;
|
2016-03-25 02:37:56 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
while val < min {
|
|
|
|
|
val += width
|
|
|
|
|
}
|
2013-05-15 05:08:29 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
val
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else if val > max {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
val -= width;
|
2015-01-10 08:36:13 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
while val > max {
|
|
|
|
|
val -= width
|
|
|
|
|
}
|
2013-05-15 05:08:29 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
val
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
val
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-22 16:58:21 +08:00
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Returns a reference to the input value clamped to the interval `[min, max]`.
|
|
|
|
|
///
|
|
|
|
|
/// In particular:
|
|
|
|
|
/// * If `min < val < max`, this returns `val`.
|
2018-09-24 12:48:42 +08:00
|
|
|
|
/// * If `val <= min`, this returns `min`.
|
|
|
|
|
/// * If `val >= max`, this returns `max`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2014-10-22 01:43:25 +08:00
|
|
|
|
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
|
2014-09-29 01:20:22 +08:00
|
|
|
|
if val > min {
|
|
|
|
|
if val < max {
|
|
|
|
|
val
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2014-09-29 01:20:22 +08:00
|
|
|
|
max
|
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2014-09-29 01:20:22 +08:00
|
|
|
|
min
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Same as `cmp::max`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2014-09-29 01:20:22 +08:00
|
|
|
|
pub fn max<T: Ord>(a: T, b: T) -> T {
|
|
|
|
|
cmp::max(a, b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Same as `cmp::min`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2014-09-29 01:20:22 +08:00
|
|
|
|
pub fn min<T: Ord>(a: T, b: T) -> T {
|
|
|
|
|
cmp::min(a, b)
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The absolute value of `a`.
|
2018-12-11 04:54:54 +08:00
|
|
|
|
///
|
2019-03-25 18:21:41 +08:00
|
|
|
|
/// Deprecated: Use [Matrix::abs] or [RealField::abs] instead.
|
2020-03-25 02:06:28 +08:00
|
|
|
|
#[deprecated(note = "use the inherent method `Matrix::abs` or `RealField::abs` instead")]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn abs<T: Signed>(a: &T) -> T {
|
|
|
|
|
a.abs()
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-25 02:06:28 +08:00
|
|
|
|
/// Returns the infimum of `a` and `b`.
|
|
|
|
|
#[deprecated(note = "use the inherent method `Matrix::inf` instead")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn inf<N, R: Dim, C: Dim>(a: &MatrixMN<N, R, C>, b: &MatrixMN<N, R, C>) -> MatrixMN<N, R, C>
|
|
|
|
|
where
|
|
|
|
|
N: Scalar + SimdPartialOrd,
|
|
|
|
|
DefaultAllocator: Allocator<N, R, C>,
|
|
|
|
|
{
|
|
|
|
|
a.inf(b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the supremum of `a` and `b`.
|
|
|
|
|
#[deprecated(note = "use the inherent method `Matrix::sup` instead")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn sup<N, R: Dim, C: Dim>(a: &MatrixMN<N, R, C>, b: &MatrixMN<N, R, C>) -> MatrixMN<N, R, C>
|
|
|
|
|
where
|
|
|
|
|
N: Scalar + SimdPartialOrd,
|
|
|
|
|
DefaultAllocator: Allocator<N, R, C>,
|
|
|
|
|
{
|
|
|
|
|
a.sup(b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns simultaneously the infimum and supremum of `a` and `b`.
|
|
|
|
|
#[deprecated(note = "use the inherent method `Matrix::inf_sup` instead")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn inf_sup<N, R: Dim, C: Dim>(
|
|
|
|
|
a: &MatrixMN<N, R, C>,
|
|
|
|
|
b: &MatrixMN<N, R, C>,
|
|
|
|
|
) -> (MatrixMN<N, R, C>, MatrixMN<N, R, C>)
|
|
|
|
|
where
|
|
|
|
|
N: Scalar + SimdPartialOrd,
|
|
|
|
|
DefaultAllocator: Allocator<N, R, C>,
|
|
|
|
|
{
|
|
|
|
|
a.inf_sup(b)
|
|
|
|
|
}
|
2014-09-29 01:20:22 +08:00
|
|
|
|
|
|
|
|
|
/// Compare `a` and `b` using a partial ordering relation.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> Option<Ordering> {
|
|
|
|
|
a.partial_cmp(b)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` iff `a` and `b` are comparable and `a < b`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn partial_lt<T: PartialOrd>(a: &T, b: &T) -> bool {
|
|
|
|
|
a.lt(b)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` iff `a` and `b` are comparable and `a <= b`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn partial_le<T: PartialOrd>(a: &T, b: &T) -> bool {
|
|
|
|
|
a.le(b)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` iff `a` and `b` are comparable and `a > b`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn partial_gt<T: PartialOrd>(a: &T, b: &T) -> bool {
|
|
|
|
|
a.gt(b)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` iff `a` and `b` are comparable and `a >= b`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn partial_ge<T: PartialOrd>(a: &T, b: &T) -> bool {
|
|
|
|
|
a.ge(b)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the minimum of `a` and `b` if they are comparable.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
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),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
_ => Some(a),
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
None
|
|
|
|
|
}
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the maximum of `a` and `b` if they are comparable.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
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),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
_ => Some(a),
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
None
|
|
|
|
|
}
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
|
|
|
|
|
/// `min` or `max`.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
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)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else if cmp_max == Ordering::Greater {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Some(max)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
Some(value)
|
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
None
|
|
|
|
|
}
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Sorts two values in increasing order using a partial ordering.
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
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)),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
_ => Some((b, a)),
|
2016-12-05 05:44:42 +08:00
|
|
|
|
}
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
None
|
|
|
|
|
}
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2016-12-05 05:44:42 +08:00
|
|
|
|
*
|
|
|
|
|
* Point operations.
|
|
|
|
|
*
|
2014-09-29 01:20:22 +08:00
|
|
|
|
*/
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The center of two points.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [distance](fn.distance.html)
|
|
|
|
|
/// * [distance_squared](fn.distance_squared.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn center<N: SimdComplexField, D: DimName>(p1: &Point<N, D>, p2: &Point<N, D>) -> Point<N, D>
|
2020-08-26 02:47:07 +08:00
|
|
|
|
where
|
|
|
|
|
DefaultAllocator: Allocator<N, D>,
|
|
|
|
|
{
|
2020-03-21 19:16:46 +08:00
|
|
|
|
((&p1.coords + &p2.coords) * convert::<_, N>(0.5)).into()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The distance between two points.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [center](fn.center.html)
|
|
|
|
|
/// * [distance_squared](fn.distance_squared.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn distance<N: SimdComplexField, D: DimName>(
|
|
|
|
|
p1: &Point<N, D>,
|
|
|
|
|
p2: &Point<N, D>,
|
|
|
|
|
) -> N::SimdRealField
|
|
|
|
|
where
|
|
|
|
|
DefaultAllocator: Allocator<N, D>,
|
|
|
|
|
{
|
|
|
|
|
(&p2.coords - &p1.coords).norm()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// The squared distance between two points.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [center](fn.center.html)
|
|
|
|
|
/// * [distance](fn.distance.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn distance_squared<N: SimdComplexField, D: DimName>(
|
|
|
|
|
p1: &Point<N, D>,
|
|
|
|
|
p2: &Point<N, D>,
|
|
|
|
|
) -> N::SimdRealField
|
|
|
|
|
where
|
|
|
|
|
DefaultAllocator: Allocator<N, D>,
|
|
|
|
|
{
|
|
|
|
|
(&p2.coords - &p1.coords).norm_squared()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2016-12-05 05:44:42 +08:00
|
|
|
|
* Cast
|
2014-09-29 01:20:22 +08:00
|
|
|
|
*/
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Converts an object from one type to an equivalent or more general one.
|
2017-07-29 02:12:07 +08:00
|
|
|
|
///
|
2018-09-26 17:39:30 +08:00
|
|
|
|
/// See also [`try_convert`](fn.try_convert.html) for conversion to more specific types.
|
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn convert<From, To: SupersetOf<From>>(t: From) -> To {
|
|
|
|
|
To::from_subset(&t)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Attempts to convert an object to a more specific one.
|
2017-07-29 02:12:07 +08:00
|
|
|
|
///
|
2018-09-26 17:39:30 +08:00
|
|
|
|
/// See also [`convert`](fn.convert.html) for conversion to more general types.
|
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn try_convert<From: SupersetOf<To>, To>(t: From) -> Option<To> {
|
|
|
|
|
t.to_subset()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 17:39:30 +08:00
|
|
|
|
/// Indicates if [`try_convert`](fn.try_convert.html) will succeed without
|
|
|
|
|
/// actually performing the conversion.
|
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool {
|
|
|
|
|
t.is_in_subset()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 17:39:30 +08:00
|
|
|
|
/// Use with care! Same as [`try_convert`](fn.try_convert.html) but
|
|
|
|
|
/// without any property checks.
|
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
t.to_subset_unchecked()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Converts an object from one type to an equivalent or more general one.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn convert_ref<From, To: SupersetOf<From>>(t: &From) -> To {
|
|
|
|
|
To::from_subset(t)
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
/// Attempts to convert an object to a more specific one.
|
2018-09-26 17:39:30 +08:00
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [convert_ref_unchecked](fn.convert_ref_unchecked.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> {
|
|
|
|
|
t.to_subset()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 17:39:30 +08:00
|
|
|
|
/// Use with care! Same as [`try_convert`](fn.try_convert.html) but
|
|
|
|
|
/// without any property checks.
|
|
|
|
|
///
|
|
|
|
|
/// # See also:
|
|
|
|
|
///
|
|
|
|
|
/// * [convert](fn.convert.html)
|
|
|
|
|
/// * [convert_ref](fn.convert_ref.html)
|
|
|
|
|
/// * [is_convertible](../nalgebra/fn.is_convertible.html)
|
|
|
|
|
/// * [try_convert](fn.try_convert.html)
|
|
|
|
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
2016-05-06 21:08:06 +08:00
|
|
|
|
#[inline]
|
2020-03-21 19:16:46 +08:00
|
|
|
|
pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
t.to_subset_unchecked()
|
2014-09-29 01:20:22 +08:00
|
|
|
|
}
|