forked from M-Labs/nalgebra
Merge pull request #195 from sebcrozet/refactor
Various refactoring and renaming.
This commit is contained in:
commit
fc08caabbe
33
CHANGELOG.md
33
CHANGELOG.md
@ -5,7 +5,7 @@ documented here.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [0.9.0] - WIP
|
||||
## Modified
|
||||
### Modified
|
||||
* Renamed:
|
||||
- `::from_col_vector` -> `::from_column_vector`
|
||||
- `::from_col_iter` -> `::from_column_iter`
|
||||
@ -13,9 +13,38 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- `.set_col` -> `.set_column`
|
||||
- `::canonical_basis_with_dim` -> `::canonical_basis_with_dimension`
|
||||
- `::from_elem` -> `::from_element`
|
||||
- `DiagMut` -> `DiagonalMut`
|
||||
- `UnitQuaternion::new` becomes `UnitQuaternion::from_scaled_axis` or
|
||||
`UnitQuaternion::from_axisangle`. The new `::new` method now requires a
|
||||
not-normalized quaternion.
|
||||
|
||||
Methods names starting with `new_with_` now start with `from_`. This is more
|
||||
idiomatic in Rust.
|
||||
|
||||
The `Norm` trait now uses an associated type instead of a type parameter.
|
||||
Other similar trait changes are to be expected in the future, e.g., for the
|
||||
`Diagonal` trait.
|
||||
|
||||
Methods marked `unsafe` for reasons unrelated to memory safety are no
|
||||
longer unsafe. Instead, their name end with `_unchecked`. In particular:
|
||||
* `Rotation3::new_with_matrix` -> `Rotation3::new_with_matrix_unchecked`
|
||||
* `PerspectiveMatrix3::new_with_matrix` -> `PerspectiveMatrix3::new_with_matrix_unchecked`
|
||||
* `OrthographicMatrix3::new_with_matrix` -> `OrthographicMatrix3::new_with_matrix_unchecked`
|
||||
|
||||
### Added
|
||||
- A `Unit<T>` type that wraps normalized values. In particular,
|
||||
`UnitQuaternion<N>` is now an alias for `Unit<Quaternion<N>>`.
|
||||
- `.ln()`, `.exp()` and `.powf(..)` for quaternions and unit quaternions.
|
||||
- `::from_parts(...)` to build a quaternion from its scalar and vector
|
||||
parts.
|
||||
- The `Norm` trait now has a `try_normalize()` that returns `None` if the
|
||||
norm is too small.
|
||||
- The `BaseFloat` and `FloatVector` traits now inherit from `ApproxEq` as
|
||||
well. It is clear that performing computations with floats requires
|
||||
approximate equality.
|
||||
|
||||
## [0.8.0]
|
||||
## Modified
|
||||
### Modified
|
||||
* Almost everything (types, methods, and traits) now use full names instead
|
||||
of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are abvious.
|
||||
Note however that:
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nalgebra"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
authors = [ "Sébastien Crozet <developer@crozet.re>" ] # FIXME: add the contributors.
|
||||
|
||||
description = "Linear algebra library for computer physics, computer graphics and general low-dimensional linear algebra for Rust."
|
||||
@ -24,6 +24,7 @@ generic_sizes = [ "generic-array", "typenum" ]
|
||||
rustc-serialize = "0.3.*"
|
||||
rand = "0.3.*"
|
||||
num = "0.1.*"
|
||||
# algebra = "*"
|
||||
|
||||
[dependencies.generic-array]
|
||||
optional = true
|
||||
|
16
README.md
16
README.md
@ -1,4 +1,16 @@
|
||||
[![Build Status](https://travis-ci.org/sebcrozet/nalgebra.svg?branch=master)](https://travis-ci.org/sebcrozet/nalgebra)
|
||||
<p align="center">
|
||||
<a href="https://crates.io/crates/nalgebra">
|
||||
<img src="http://meritbadge.herokuapp.com/nalgebra?style=flat-square" alt="crates.io">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/sebcrozet/nalgebra">
|
||||
<img src="https://travis-ci.org/sebcrozet/nalgebra.svg?branch=master" alt="Build status">
|
||||
</a>
|
||||
</p>
|
||||
<p align = "center">
|
||||
<strong>
|
||||
<a href="http://nalgebra.org/doc/nalgebra">Documentation</a> | <a href="http://nphysics.org">Forum</a>
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
nalgebra
|
||||
========
|
||||
@ -9,8 +21,6 @@ nalgebra
|
||||
* Real time computer graphics.
|
||||
* Real time computer physics.
|
||||
|
||||
An on-line version of this documentation is available [here](http://nalgebra.org/doc/nalgebra).
|
||||
|
||||
## Using **nalgebra**
|
||||
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`. This
|
||||
module re-exports everything and includes free functions for all traits methods performing
|
||||
|
@ -11,9 +11,9 @@ use na::{UnitQuaternion, Rotation2, Rotation3, Vector1, Vector3};
|
||||
#[path="common/macros.rs"]
|
||||
mod macros;
|
||||
|
||||
bench_construction!(_bench_quaternion_from_axisangle, UnitQuaternion::new, axisangle: Vector3<f32>);
|
||||
bench_construction!(_bench_quaternion_from_axisangle, UnitQuaternion::from_scaled_axis, axisangle: Vector3<f32>);
|
||||
bench_construction!(_bench_rot2_from_axisangle, Rotation2::new, axisangle: Vector1<f32>);
|
||||
bench_construction!(_bench_rot3_from_axisangle, Rotation3::new, axisangle: Vector3<f32>);
|
||||
|
||||
bench_construction!(_bench_quaternion_from_euler_angles, UnitQuaternion::new_with_euler_angles, roll: f32, pitch: f32, yaw: f32);
|
||||
bench_construction!(_bench_rot3_from_euler_angles, Rotation3::new_with_euler_angles, roll: f32, pitch: f32, yaw: f32);
|
||||
bench_construction!(_bench_quaternion_from_euler_angles, UnitQuaternion::from_euler_angles, roll: f32, pitch: f32, yaw: f32);
|
||||
bench_construction!(_bench_rot3_from_euler_angles, Rotation3::from_euler_angles, roll: f32, pitch: f32, yaw: f32);
|
||||
|
@ -63,6 +63,13 @@ bench_unop!(_bench_vec4_normalize, Vector4<f32>, normalize);
|
||||
|
||||
#[cfg(feature = "generic_sizes")]
|
||||
mod bench_vecn {
|
||||
extern crate test;
|
||||
extern crate rand;
|
||||
extern crate nalgebra as na;
|
||||
|
||||
use rand::{IsaacRng, Rng};
|
||||
use test::Bencher;
|
||||
use std::ops::{Add, Sub, Mul, Div};
|
||||
use typenum::{U2, U3, U4};
|
||||
use na::VectorN;
|
||||
|
||||
|
164
src/lib.rs
164
src/lib.rs
@ -154,7 +154,8 @@ pub use structs::{
|
||||
Point1, Point2, Point3, Point4, Point5, Point6,
|
||||
Perspective3, PerspectiveMatrix3,
|
||||
Orthographic3, OrthographicMatrix3,
|
||||
Quaternion, UnitQuaternion
|
||||
Quaternion, UnitQuaternion,
|
||||
Unit
|
||||
};
|
||||
|
||||
pub use linalg::{
|
||||
@ -173,7 +174,7 @@ mod macros;
|
||||
// mod chol;
|
||||
|
||||
/// Change the input value to ensure it is on the range `[min, max]`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
|
||||
if val > min {
|
||||
if val < max {
|
||||
@ -189,74 +190,74 @@ pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
|
||||
}
|
||||
|
||||
/// Same as `cmp::max`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn max<T: Ord>(a: T, b: T) -> T {
|
||||
cmp::max(a, b)
|
||||
}
|
||||
|
||||
/// Same as `cmp::min`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn min<T: Ord>(a: T, b: T) -> T {
|
||||
cmp::min(a, b)
|
||||
}
|
||||
|
||||
/// Returns the infimum of `a` and `b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inf<T: PartialOrder>(a: &T, b: &T) -> T {
|
||||
PartialOrder::inf(a, b)
|
||||
}
|
||||
|
||||
/// Returns the supremum of `a` and `b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn sup<T: PartialOrder>(a: &T, b: &T) -> T {
|
||||
PartialOrder::sup(a, b)
|
||||
}
|
||||
|
||||
/// Compare `a` and `b` using a partial ordering relation.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_cmp<T: PartialOrder>(a: &T, b: &T) -> PartialOrdering {
|
||||
PartialOrder::partial_cmp(a, b)
|
||||
}
|
||||
|
||||
/// Returns `true` iff `a` and `b` are comparable and `a < b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_lt<T: PartialOrder>(a: &T, b: &T) -> bool {
|
||||
PartialOrder::partial_lt(a, b)
|
||||
}
|
||||
|
||||
/// Returns `true` iff `a` and `b` are comparable and `a <= b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_le<T: PartialOrder>(a: &T, b: &T) -> bool {
|
||||
PartialOrder::partial_le(a, b)
|
||||
}
|
||||
|
||||
/// Returns `true` iff `a` and `b` are comparable and `a > b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_gt<T: PartialOrder>(a: &T, b: &T) -> bool {
|
||||
PartialOrder::partial_gt(a, b)
|
||||
}
|
||||
|
||||
/// Returns `true` iff `a` and `b` are comparable and `a >= b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_ge<T: PartialOrder>(a: &T, b: &T) -> bool {
|
||||
PartialOrder::partial_ge(a, b)
|
||||
}
|
||||
|
||||
/// Return the minimum of `a` and `b` if they are comparable.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_min<'a, T: PartialOrder>(a: &'a T, b: &'a T) -> Option<&'a T> {
|
||||
PartialOrder::partial_min(a, b)
|
||||
}
|
||||
|
||||
/// Return the maximum of `a` and `b` if they are comparable.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_max<'a, T: PartialOrder>(a: &'a T, b: &'a T) -> Option<&'a T> {
|
||||
PartialOrder::partial_max(a, b)
|
||||
}
|
||||
|
||||
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
|
||||
/// `min` or `max`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn partial_clamp<'a, T: PartialOrder>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> {
|
||||
PartialOrder::partial_clamp(value, min, max)
|
||||
}
|
||||
@ -270,7 +271,7 @@ pub fn partial_clamp<'a, T: PartialOrder>(value: &'a T, min: &'a T, max: &'a T)
|
||||
/// Create a special identity object.
|
||||
///
|
||||
/// Same as `Identity::new()`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn identity() -> Identity {
|
||||
Identity::new()
|
||||
}
|
||||
@ -278,13 +279,13 @@ pub fn identity() -> Identity {
|
||||
/// Create a zero-valued value.
|
||||
///
|
||||
/// This is the same as `std::num::zero()`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn zero<T: Zero>() -> T {
|
||||
Zero::zero()
|
||||
}
|
||||
|
||||
/// Tests is a value is iqual to zero.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn is_zero<T: Zero>(val: &T) -> bool {
|
||||
val.is_zero()
|
||||
}
|
||||
@ -292,7 +293,7 @@ pub fn is_zero<T: Zero>(val: &T) -> bool {
|
||||
/// Create a one-valued value.
|
||||
///
|
||||
/// This is the same as `std::num::one()`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn one<T: One>() -> T {
|
||||
One::one()
|
||||
}
|
||||
@ -304,7 +305,7 @@ pub fn one<T: One>() -> T {
|
||||
//
|
||||
|
||||
/// Returns the trivial origin of an affine space.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn origin<P: Origin>() -> P {
|
||||
Origin::origin()
|
||||
}
|
||||
@ -312,26 +313,23 @@ pub fn origin<P: Origin>() -> P {
|
||||
/// Returns the center of two points.
|
||||
#[inline]
|
||||
pub fn center<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> P
|
||||
where <P as PointAsVector>::Vector: Norm<N>
|
||||
{
|
||||
let _2 = one::<N>() + one();
|
||||
(*a + b.to_vector()) / _2
|
||||
where <P as PointAsVector>::Vector: Norm<NormType = N> {
|
||||
(*a + b.to_vector()) / ::cast(2.0)
|
||||
}
|
||||
|
||||
/*
|
||||
* FloatPoint
|
||||
*/
|
||||
/// Returns the distance between two points.
|
||||
#[inline(always)]
|
||||
pub fn distance<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N where <P as PointAsVector>::Vector: Norm<N> {
|
||||
#[inline]
|
||||
pub fn distance<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N where <P as PointAsVector>::Vector: Norm<NormType = N> {
|
||||
a.distance(b)
|
||||
}
|
||||
|
||||
/// Returns the squared distance between two points.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn distance_squared<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N
|
||||
where <P as PointAsVector>::Vector: Norm<N>
|
||||
{
|
||||
where <P as PointAsVector>::Vector: Norm<NormType = N> {
|
||||
a.distance_squared(b)
|
||||
}
|
||||
|
||||
@ -352,7 +350,7 @@ pub fn distance_squared<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N
|
||||
/// assert!(trans == Vector3::new(1.0, 1.0, 1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn translation<V, M: Translation<V>>(m: &M) -> V {
|
||||
m.translation()
|
||||
}
|
||||
@ -370,13 +368,13 @@ pub fn translation<V, M: Translation<V>>(m: &M) -> V {
|
||||
/// assert!(itrans == Vector3::new(-1.0, -1.0, -1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_translation<V, M: Translation<V>>(m: &M) -> V {
|
||||
m.inverse_translation()
|
||||
}
|
||||
|
||||
/// Applies the translation `v` to a copy of `m`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
|
||||
Translation::append_translation(m, v)
|
||||
}
|
||||
@ -400,7 +398,7 @@ pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
|
||||
/// assert!(tp == Point3::new(3.0, 3.0, 3.0))
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
|
||||
m.translate(p)
|
||||
}
|
||||
@ -419,7 +417,7 @@ pub fn translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
|
||||
///
|
||||
/// assert!(na::approx_eq(&tp, &Point3::new(1.0, 1.0, 1.0)))
|
||||
/// }
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
|
||||
m.inverse_translate(p)
|
||||
}
|
||||
@ -440,7 +438,7 @@ pub fn inverse_translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
|
||||
/// assert!(na::approx_eq(&na::rotation(&t), &Vector3::new(1.0, 1.0, 1.0)));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
m.rotation()
|
||||
}
|
||||
@ -458,7 +456,7 @@ pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
/// assert!(na::approx_eq(&na::inverse_rotation(&t), &Vector3::new(-1.0, -1.0, -1.0)));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
m.inverse_rotation()
|
||||
}
|
||||
@ -478,7 +476,7 @@ pub fn inverse_rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
/// assert!(na::approx_eq(&na::rotation(&rt), &Vector3::new(1.0, 1.0, 1.0)))
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
|
||||
Rotation::append_rotation(m, v)
|
||||
}
|
||||
@ -498,7 +496,7 @@ pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
|
||||
/// assert!(na::approx_eq(&na::rotation(&rt), &Vector3::new(1.0, 1.0, 1.0)))
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn prepend_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
|
||||
Rotation::prepend_rotation(m, v)
|
||||
}
|
||||
@ -522,7 +520,7 @@ pub fn prepend_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
|
||||
/// assert!(na::approx_eq(&tv, &Vector3::new(0.0, 1.0, 0.0)))
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
m.rotate(v)
|
||||
}
|
||||
@ -543,7 +541,7 @@ pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
/// assert!(na::approx_eq(&tv, &Vector3::new(0.0, -1.0, 0.0)))
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
m.inverse_rotate(v)
|
||||
}
|
||||
@ -553,7 +551,7 @@ pub fn inverse_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
*/
|
||||
|
||||
/// Rotates a copy of `m` by `amount` using `center` as the pivot point.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn append_rotation_wrt_point<LV: Neg<Output = LV> + Copy,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
@ -564,7 +562,7 @@ pub fn append_rotation_wrt_point<LV: Neg<Output = LV> + Copy,
|
||||
}
|
||||
|
||||
/// Rotates a copy of `m` by `amount` using `m.translation()` as the pivot point.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn append_rotation_wrt_center<LV: Neg<Output = LV> + Copy,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
@ -577,13 +575,13 @@ pub fn append_rotation_wrt_center<LV: Neg<Output = LV> + Copy,
|
||||
* RotationTo
|
||||
*/
|
||||
/// Computes the angle of the rotation needed to transfom `a` to `b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn angle_between<V: RotationTo>(a: &V, b: &V) -> V::AngleType {
|
||||
a.angle_to(b)
|
||||
}
|
||||
|
||||
/// Computes the rotation needed to transform `a` to `b`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn rotation_between<V: RotationTo>(a: &V, b: &V) -> V::DeltaRotationType {
|
||||
a.rotation_to(b)
|
||||
}
|
||||
@ -593,7 +591,7 @@ pub fn rotation_between<V: RotationTo>(a: &V, b: &V) -> V::DeltaRotationType {
|
||||
*/
|
||||
|
||||
/// Builds a rotation matrix from `r`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn to_rotation_matrix<N, LV, AV, R, M>(r: &R) -> M
|
||||
where R: RotationMatrix<N, LV, AV, Output = M>,
|
||||
M: SquareMatrix<N, LV> + Rotation<AV> + Copy,
|
||||
@ -608,7 +606,7 @@ pub fn to_rotation_matrix<N, LV, AV, R, M>(r: &R) -> M
|
||||
*/
|
||||
|
||||
/// Applies a rotation using the absolute values of its components.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
|
||||
m.absolute_rotate(v)
|
||||
}
|
||||
@ -618,19 +616,19 @@ pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
|
||||
*/
|
||||
|
||||
/// Gets the transformation applicable by `m`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn transformation<T, M: Transformation<T>>(m: &M) -> T {
|
||||
m.transformation()
|
||||
}
|
||||
|
||||
/// Gets the inverse transformation applicable by `m`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_transformation<T, M: Transformation<T>>(m: &M) -> T {
|
||||
m.inverse_transformation()
|
||||
}
|
||||
|
||||
/// Gets a transformed copy of `m`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M {
|
||||
Transformation::append_transformation(m, t)
|
||||
}
|
||||
@ -640,13 +638,13 @@ pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M {
|
||||
*/
|
||||
|
||||
/// Applies a transformation to a vector.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
|
||||
m.transform(v)
|
||||
}
|
||||
|
||||
/// Applies an inverse transformation to a vector.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse_transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
|
||||
m.inverse_transform(v)
|
||||
}
|
||||
@ -656,7 +654,7 @@ pub fn inverse_transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
|
||||
*/
|
||||
|
||||
/// Computes the dot product of two vectors.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
|
||||
Dot::dot(a, b)
|
||||
}
|
||||
@ -666,28 +664,34 @@ pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
|
||||
*/
|
||||
|
||||
/// Computes the L2 norm of a vector.
|
||||
#[inline(always)]
|
||||
pub fn norm<V: Norm<N>, N: BaseFloat>(v: &V) -> N {
|
||||
#[inline]
|
||||
pub fn norm<V: Norm>(v: &V) -> V::NormType {
|
||||
Norm::norm(v)
|
||||
}
|
||||
|
||||
/// Computes the squared L2 norm of a vector.
|
||||
#[inline(always)]
|
||||
pub fn norm_squared<V: Norm<N>, N: BaseFloat>(v: &V) -> N {
|
||||
#[inline]
|
||||
pub fn norm_squared<V: Norm>(v: &V) -> V::NormType {
|
||||
Norm::norm_squared(v)
|
||||
}
|
||||
|
||||
/// Gets the normalized version of a vector.
|
||||
#[inline(always)]
|
||||
pub fn normalize<V: Norm<N>, N: BaseFloat>(v: &V) -> V {
|
||||
#[inline]
|
||||
pub fn normalize<V: Norm>(v: &V) -> V {
|
||||
Norm::normalize(v)
|
||||
}
|
||||
|
||||
/// Gets the normalized version of a vector or `None` if its norm is smaller than `min_norm`.
|
||||
#[inline]
|
||||
pub fn try_normalize<V: Norm>(v: &V, min_norm: V::NormType) -> Option<V> {
|
||||
Norm::try_normalize(v, min_norm)
|
||||
}
|
||||
|
||||
/*
|
||||
* Determinant<N>
|
||||
*/
|
||||
/// Computes the determinant of a square matrix.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn determinant<M: Determinant<N>, N>(m: &M) -> N {
|
||||
Determinant::determinant(m)
|
||||
}
|
||||
@ -697,7 +701,7 @@ pub fn determinant<M: Determinant<N>, N>(m: &M) -> N {
|
||||
*/
|
||||
|
||||
/// Computes the cross product of two vectors.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cross<LV: Cross>(a: &LV, b: &LV) -> LV::CrossProductType {
|
||||
Cross::cross(a, b)
|
||||
}
|
||||
@ -708,7 +712,7 @@ pub fn cross<LV: Cross>(a: &LV, b: &LV) -> LV::CrossProductType {
|
||||
|
||||
/// Given a vector, computes the matrix which, when multiplied by another vector, computes a cross
|
||||
/// product.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M {
|
||||
CrossMatrix::cross_matrix(v)
|
||||
}
|
||||
@ -718,7 +722,7 @@ pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M {
|
||||
*/
|
||||
|
||||
/// Converts a matrix or vector to homogeneous coordinates.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res {
|
||||
ToHomogeneous::to_homogeneous(m)
|
||||
}
|
||||
@ -730,7 +734,7 @@ pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res {
|
||||
/// Converts a matrix or vector from homogeneous coordinates.
|
||||
///
|
||||
/// w-normalization is appied.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res {
|
||||
FromHomogeneous::from(m)
|
||||
}
|
||||
@ -742,7 +746,7 @@ pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res {
|
||||
/// Samples the unit sphere living on the dimension as the samples types.
|
||||
///
|
||||
/// The number of sampling point is implementation-specific. It is always uniform.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn sample_sphere<V: UniformSphereSample, F: FnMut(V)>(f: F) {
|
||||
UniformSphereSample::sample(f)
|
||||
}
|
||||
@ -757,13 +761,13 @@ pub fn sample_sphere<V: UniformSphereSample, F: FnMut(V)>(f: F) {
|
||||
* AproxEq<N>
|
||||
*/
|
||||
/// Tests approximate equality.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn approx_eq<T: ApproxEq<N>, N>(a: &T, b: &T) -> bool {
|
||||
ApproxEq::approx_eq(a, b)
|
||||
}
|
||||
|
||||
/// Tests approximate equality using a custom epsilon.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn approx_eq_eps<T: ApproxEq<N>, N>(a: &T, b: &T, eps: &N) -> bool {
|
||||
ApproxEq::approx_eq_eps(a, b, eps)
|
||||
}
|
||||
@ -774,7 +778,7 @@ pub fn approx_eq_eps<T: ApproxEq<N>, N>(a: &T, b: &T, eps: &N) -> bool {
|
||||
*/
|
||||
|
||||
/// Computes a component-wise absolute value.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn abs<M: Absolute<Res>, Res>(m: &M) -> Res {
|
||||
Absolute::abs(m)
|
||||
}
|
||||
@ -784,7 +788,7 @@ pub fn abs<M: Absolute<Res>, Res>(m: &M) -> Res {
|
||||
*/
|
||||
|
||||
/// Gets an inverted copy of a matrix.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn inverse<M: Inverse>(m: &M) -> Option<M> {
|
||||
Inverse::inverse(m)
|
||||
}
|
||||
@ -794,7 +798,7 @@ pub fn inverse<M: Inverse>(m: &M) -> Option<M> {
|
||||
*/
|
||||
|
||||
/// Gets a transposed copy of a matrix.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn transpose<M: Transpose>(m: &M) -> M {
|
||||
Transpose::transpose(m)
|
||||
}
|
||||
@ -804,7 +808,7 @@ pub fn transpose<M: Transpose>(m: &M) -> M {
|
||||
*/
|
||||
|
||||
/// Computes the outer product of two vectors.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn outer<V: Outer>(a: &V, b: &V) -> V::OuterProductType {
|
||||
Outer::outer(a, b)
|
||||
}
|
||||
@ -814,7 +818,7 @@ pub fn outer<V: Outer>(a: &V, b: &V) -> V::OuterProductType {
|
||||
*/
|
||||
|
||||
/// Computes the covariance of a set of observations.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn covariance<M: Covariance<Res>, Res>(observations: &M) -> Res {
|
||||
Covariance::covariance(observations)
|
||||
}
|
||||
@ -824,7 +828,7 @@ pub fn covariance<M: Covariance<Res>, Res>(observations: &M) -> Res {
|
||||
*/
|
||||
|
||||
/// Computes the mean of a set of observations.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
|
||||
Mean::mean(observations)
|
||||
}
|
||||
@ -833,7 +837,7 @@ pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
|
||||
* EigenQR<N, V>
|
||||
*/
|
||||
/// Computes the eigenvalues and eigenvectors of a square matrix usin the QR algorithm.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn eigen_qr<N, V, M>(m: &M, eps: &N, niter: usize) -> (M, V)
|
||||
where V: Mul<M, Output = V>,
|
||||
M: EigenQR<N, V> {
|
||||
@ -850,7 +854,7 @@ pub fn eigen_qr<N, V, M>(m: &M, eps: &N, niter: usize) -> (M, V)
|
||||
* Eye
|
||||
*/
|
||||
/// Construct the identity matrix for a given dimension
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn new_identity<M: Eye>(dimension: usize) -> M {
|
||||
Eye::new_identity(dimension)
|
||||
}
|
||||
@ -862,7 +866,7 @@ pub fn new_identity<M: Eye>(dimension: usize) -> M {
|
||||
/// Create an object by repeating a value.
|
||||
///
|
||||
/// Same as `Identity::new()`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn repeat<N, T: Repeat<N>>(val: N) -> T {
|
||||
Repeat::repeat(val)
|
||||
}
|
||||
@ -872,13 +876,13 @@ pub fn repeat<N, T: Repeat<N>>(val: N) -> T {
|
||||
*/
|
||||
|
||||
/// Computes the canonical basis for a given dimension.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn canonical_basis<V: Basis, F: FnMut(V) -> bool>(f: F) {
|
||||
Basis::canonical_basis(f)
|
||||
}
|
||||
|
||||
/// Computes the basis of the orthonormal subspace of a given vector.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn orthonormal_subspace_basis<V: Basis, F: FnMut(V) -> bool>(v: &V, f: F) {
|
||||
Basis::orthonormal_subspace_basis(v, f)
|
||||
}
|
||||
@ -901,7 +905,7 @@ pub fn canonical_basis_element<V: Basis>(i: usize) -> Option<V> {
|
||||
* Diagonal<V>
|
||||
*/
|
||||
/// Gets the diagonal of a square matrix.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn diagonal<M: Diagonal<V>, V>(m: &M) -> V {
|
||||
m.diagonal()
|
||||
}
|
||||
@ -912,13 +916,13 @@ pub fn diagonal<M: Diagonal<V>, V>(m: &M) -> V {
|
||||
/// Gets the dimension an object lives in.
|
||||
///
|
||||
/// Same as `Dimension::dimension::(None::<V>)`.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn dimension<V: Dimension>() -> usize {
|
||||
Dimension::dimension(None::<V>)
|
||||
}
|
||||
|
||||
/// Gets the indexable range of an object.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn shape<V: Shape<I>, I>(v: &V) -> I {
|
||||
v.shape()
|
||||
}
|
||||
@ -940,7 +944,7 @@ pub fn shape<V: Shape<I>, I>(v: &V) -> I {
|
||||
/// range of an i32 when a cast from i64 to i32 is done).
|
||||
/// * A cast does not affect the dimension of an algebraic object. Note that this prevents an
|
||||
/// isometric transform to be cast to a raw matrix. Use `to_homogeneous` for that special purpose.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cast<T, U: Cast<T>>(t: T) -> U {
|
||||
Cast::from(t)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use traits::operations::{Transpose, ApproxEq};
|
||||
use traits::structure::{ColumnSlice, Eye, Indexable, Diagonal, SquareMatrix, BaseFloat, Cast};
|
||||
use traits::structure::{ColumnSlice, Eye, Indexable, SquareMatrix, BaseFloat, Cast};
|
||||
use traits::geometry::Norm;
|
||||
use std::cmp;
|
||||
use std::ops::{Mul, Add, Sub};
|
||||
@ -40,7 +40,7 @@ pub fn householder_matrix<N, V, M>(dimension: usize, start: usize, vector: V) ->
|
||||
/// * `m` - matrix to decompose
|
||||
pub fn qr<N, V, M>(m: &M) -> (M, M)
|
||||
where N: BaseFloat,
|
||||
V: Indexable<usize, N> + Norm<N>,
|
||||
V: Indexable<usize, N> + Norm<NormType = N>,
|
||||
M: Copy + Eye + ColumnSlice<V> + Transpose + Indexable<(usize, usize), N> +
|
||||
Mul<M, Output = M> {
|
||||
let (rows, cols) = m.shape();
|
||||
@ -75,7 +75,7 @@ pub fn qr<N, V, M>(m: &M) -> (M, M)
|
||||
pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: usize) -> (M, V)
|
||||
where N: BaseFloat,
|
||||
V: Mul<M, Output = V>,
|
||||
VS: Indexable<usize, N> + Norm<N>,
|
||||
VS: Indexable<usize, N> + Norm<NormType = N>,
|
||||
M: Indexable<(usize, usize), N> + SquareMatrix<N, V> + Add<M, Output = M> +
|
||||
Sub<M, Output = M> + ColumnSlice<VS> +
|
||||
ApproxEq<N> + Copy {
|
||||
@ -264,12 +264,12 @@ pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: usize) -> (M, V)
|
||||
pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
|
||||
where N: BaseFloat,
|
||||
V: Mul<M, Output = V>,
|
||||
VS: Indexable<usize, N> + Norm<N>,
|
||||
VS: Indexable<usize, N> + Norm<NormType = N>,
|
||||
M: Indexable<(usize, usize), N> + SquareMatrix<N, V> + Add<M, Output = M> +
|
||||
Sub<M, Output = M> + ColumnSlice<VS> +
|
||||
ApproxEq<N> + Copy {
|
||||
|
||||
let mut out = m.clone().transpose();
|
||||
let mut out = m.transpose();
|
||||
|
||||
if !ApproxEq::approx_eq(&out, &m) {
|
||||
return Err("Cholesky: Input matrix is not symmetric");
|
||||
@ -302,7 +302,7 @@ pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(out);
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Hessenberg
|
||||
@ -316,11 +316,11 @@ pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
|
||||
/// * Second return value `h` - Matrix m in Hessenberg form
|
||||
pub fn hessenberg<N, V, M>(m: &M) -> (M, M)
|
||||
where N: BaseFloat,
|
||||
V: Indexable<usize, N> + Norm<N>,
|
||||
V: Indexable<usize, N> + Norm<NormType = N>,
|
||||
M: Copy + Eye + ColumnSlice<V> + Transpose + Indexable<(usize, usize), N> +
|
||||
Mul<M, Output = M> {
|
||||
|
||||
let mut h = m.clone();
|
||||
let mut h = *m;
|
||||
let (rows, cols) = h.shape();
|
||||
|
||||
let mut q : M = Eye::new_identity(cols);
|
||||
@ -347,5 +347,5 @@ pub fn hessenberg<N, V, M>(m: &M) -> (M, M)
|
||||
}
|
||||
}
|
||||
|
||||
return (q, h);
|
||||
(q, h)
|
||||
}
|
||||
|
351
src/structs/common_macros.rs
Normal file
351
src/structs/common_macros.rs
Normal file
@ -0,0 +1,351 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! pointwise_mul(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Mul<N, Output = N>> Mul<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN * right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: MulAssign<N>> MulAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN *= right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pointwise_div(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Div<N, Output = N>> Div<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN / right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: DivAssign<N>> DivAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN /= right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pointwise_add(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Add<N, Output = N>> Add<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN + right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AddAssign<N>> AddAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN += right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! pointwise_sub(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Sub<N, Output = N>> Sub<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN - right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<N: SubAssign<N>> SubAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN -= right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! pointwise_scalar_mul(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + Mul<N, Output = N>> Mul<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN * right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + MulAssign<N>> MulAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: N) {
|
||||
$( self.$compN *= right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$t<f32>> for f32 {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self * right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$t<f64>> for f64 {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self * right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! pointwise_scalar_div(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + Div<N, Output = N>> Div<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN / right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + DivAssign<N>> DivAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, right: N) {
|
||||
$( self.$compN /= right; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! pointwise_scalar_add(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + Add<N, Output = N>> Add<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN + right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + AddAssign<N>> AddAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, right: N) {
|
||||
$( self.$compN += right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$t<f32>> for f32 {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self + right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$t<f64>> for f64 {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self + right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pointwise_scalar_sub(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + Sub<N, Output = N>> Sub<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN - right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + SubAssign<N>> SubAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, right: N) {
|
||||
$( self.$compN -= right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<$t<f32>> for f32 {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self - right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<$t<f64>> for f64 {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self - right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! componentwise_neg(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Neg<Output = N> + Copy> Neg for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> $t<N> {
|
||||
$t::new($(-self.$compN ),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! componentwise_repeat(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy> Repeat<N> for $t<N> {
|
||||
fn repeat(val: N) -> $t<N> {
|
||||
$t {
|
||||
$($compN: val ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! componentwise_absolute(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Absolute<N>> Absolute<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn abs(m: &$t<N>) -> $t<N> {
|
||||
$t::new($(::abs(&m.$compN) ),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! componentwise_zero(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
impl<N: Zero> Zero for $t<N> {
|
||||
#[inline]
|
||||
fn zero() -> $t<N> {
|
||||
$t {
|
||||
$($compN: ::zero() ),+
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
$(::is_zero(&self.$compN) )&&+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! componentwise_one(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
impl<N: BaseNum> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t {
|
||||
$($compN: ::one() ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Implements Arbitrary by setting each components to Arbitrary::arbitrary.
|
||||
macro_rules! componentwise_arbitrary(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary> Arbitrary for $t<N> {
|
||||
#[inline]
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t { $($compN: Arbitrary::arbitrary(g),)* }
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Implements Rand by setting each components to Rand::rand.
|
||||
macro_rules! componentwise_rand(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
impl<N: Rand> Rand for $t<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||
$t { $($compN: Rand::rand(rng), )* }
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! component_basis_element(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
/*
|
||||
*
|
||||
* Element of the canonical basis.
|
||||
*
|
||||
*/
|
||||
impl<N: Zero + One> $t<N> {
|
||||
$(
|
||||
/// Create the element of the canonical basis having this component set to one and
|
||||
/// all the others set to zero.
|
||||
#[inline]
|
||||
pub fn $compN() -> $t<N> {
|
||||
let mut res: $t<N> = ::zero();
|
||||
|
||||
res.$compN = ::one();
|
||||
|
||||
res
|
||||
}
|
||||
)+
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// A function to create a new element from its component values.
|
||||
macro_rules! component_new(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N> $t<N> {
|
||||
/// Creation from component values.
|
||||
#[inline]
|
||||
pub fn new($($compN: N ),+) -> $t<N> {
|
||||
$t {
|
||||
$($compN: $compN ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
@ -9,7 +9,8 @@ use rand::{self, Rand};
|
||||
use num::{Zero, One};
|
||||
use structs::dvector::{DVector, DVector1, DVector2, DVector3, DVector4, DVector5, DVector6};
|
||||
use traits::operations::{ApproxEq, Inverse, Transpose, Mean, Covariance};
|
||||
use traits::structure::{Cast, Column, ColumnSlice, Row, RowSlice, Diagonal, DiagMut, Eye, Indexable, Shape, BaseNum};
|
||||
use traits::structure::{Cast, Column, ColumnSlice, Row, RowSlice, Diagonal, DiagonalMut, Eye,
|
||||
Indexable, Shape, BaseNum};
|
||||
#[cfg(feature="arbitrary")]
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
@ -109,7 +110,7 @@ impl<N: Clone + Copy> DMatrix<N> {
|
||||
|
||||
impl<N> DMatrix<N> {
|
||||
/// Builds a matrix filled with the results of a function applied to each of its component coordinates.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn from_fn<F: FnMut(usize, usize) -> N>(nrows: usize, ncols: usize, mut f: F) -> DMatrix<N> {
|
||||
DMatrix {
|
||||
nrows: nrows,
|
||||
@ -133,7 +134,7 @@ dmat_impl!(DMatrix, DVector);
|
||||
pub struct DMatrix1<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
mij: [N; 1 * 1],
|
||||
mij: [N; 1],
|
||||
}
|
||||
|
||||
small_dmat_impl!(DMatrix1, DVector1, 1, 0);
|
||||
|
@ -84,9 +84,8 @@ macro_rules! dmat_impl(
|
||||
fn new_identity(dimension: usize) -> $dmatrix<N> {
|
||||
let mut res = $dmatrix::new_zeros(dimension, dimension);
|
||||
|
||||
for i in 0..dimension {
|
||||
let _1: N = ::one();
|
||||
res[(i, i)] = _1;
|
||||
for i in 0 .. dimension {
|
||||
res[(i, i)] = ::one::<N>();
|
||||
}
|
||||
|
||||
res
|
||||
@ -94,7 +93,7 @@ macro_rules! dmat_impl(
|
||||
}
|
||||
|
||||
impl<N> $dmatrix<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn offset(&self, i: usize, j: usize) -> usize {
|
||||
i + j * self.nrows
|
||||
}
|
||||
@ -774,9 +773,8 @@ macro_rules! dmat_impl(
|
||||
// We can init from slice thanks to the matrix being column-major.
|
||||
let start = self.offset(row_start, column_id);
|
||||
let stop = self.offset(row_end, column_id);
|
||||
let slice = $dvector::from_slice(row_end - row_start, &self.mij[start .. stop]);
|
||||
|
||||
slice
|
||||
$dvector::from_slice(row_end - row_start, &self.mij[start .. stop])
|
||||
}
|
||||
}
|
||||
|
||||
@ -824,12 +822,12 @@ macro_rules! dmat_impl(
|
||||
let mut slice : $dvector<N> = unsafe {
|
||||
$dvector::new_uninitialized(column_end - column_start)
|
||||
};
|
||||
let mut slice_idx = 0;
|
||||
|
||||
for column_id in column_start .. column_end {
|
||||
unsafe {
|
||||
let slice_idx = column_id - column_start;
|
||||
slice.unsafe_set(slice_idx, self.unsafe_at((row_id, column_id)));
|
||||
}
|
||||
slice_idx += 1;
|
||||
}
|
||||
|
||||
slice
|
||||
@ -860,7 +858,7 @@ macro_rules! dmat_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Clone + Zero> DiagMut<$dvector<N>> for $dmatrix<N> {
|
||||
impl<N: Copy + Clone + Zero> DiagonalMut<$dvector<N>> for $dmatrix<N> {
|
||||
#[inline]
|
||||
fn set_diagonal(&mut self, diagonal: &$dvector<N>) {
|
||||
let smallest_dim = cmp::min(self.nrows, self.ncols);
|
||||
@ -1140,7 +1138,7 @@ macro_rules! small_dmat_from_impl(
|
||||
}
|
||||
|
||||
/// Builds a matrix using an initialization function.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn from_fn<F: FnMut(usize, usize) -> N>(nrows: usize, ncols: usize, mut f: F) -> $dmatrix<N> {
|
||||
assert!(nrows <= $dimension);
|
||||
assert!(ncols <= $dimension);
|
||||
|
@ -56,9 +56,9 @@ impl<N: Clone> DVector<N> {
|
||||
|
||||
impl<N> DVector<N> {
|
||||
/// Builds a vector filled with the results of a function applied to each of its component coordinates.
|
||||
#[inline(always)]
|
||||
pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, mut f: F) -> DVector<N> {
|
||||
DVector { at: (0 .. dimension).map(|i| f(i)).collect() }
|
||||
#[inline]
|
||||
pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, f: F) -> DVector<N> {
|
||||
DVector { at: (0 .. dimension).map(f).collect() }
|
||||
}
|
||||
|
||||
/// The vector length.
|
||||
|
@ -191,7 +191,7 @@ macro_rules! small_dvec_from_impl (
|
||||
|
||||
impl<N: Zero> $dvector<N> {
|
||||
/// Builds a vector filled with the result of a function.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, mut f: F) -> $dvector<N> {
|
||||
assert!(dimension <= $dimension);
|
||||
|
||||
|
@ -44,7 +44,7 @@ pub struct Isometry3<N> {
|
||||
pub translation: Vector3<N>
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat> Isometry3<N> {
|
||||
impl<N: BaseFloat> Isometry3<N> {
|
||||
/// Creates an isometry that corresponds to the local frame of an observer standing at the
|
||||
/// point `eye` and looking toward `target`.
|
||||
///
|
||||
@ -59,7 +59,7 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
|
||||
#[inline]
|
||||
pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Isometry3<N> {
|
||||
let new_rotation_matrix = Rotation3::new_observer_frame(&(*target - *eye), up);
|
||||
Isometry3::new_with_rotation_matrix(eye.as_vector().clone(), new_rotation_matrix)
|
||||
Isometry3::from_rotation_matrix(eye.to_vector(), new_rotation_matrix)
|
||||
}
|
||||
|
||||
/// Builds a right-handed look-at view matrix.
|
||||
@ -74,10 +74,10 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_rh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Isometry3<N> {
|
||||
let rotation = Rotation3::look_at_rh(&(*target - *eye), up);
|
||||
let trans = rotation * (-*eye);
|
||||
let rotation = Rotation3::look_at_rh(&(*target - *eye), up);
|
||||
let trans = rotation * (-*eye);
|
||||
|
||||
Isometry3::new_with_rotation_matrix(trans.to_vector(), rotation)
|
||||
Isometry3::from_rotation_matrix(trans.to_vector(), rotation)
|
||||
}
|
||||
|
||||
/// Builds a left-handed look-at view matrix.
|
||||
@ -92,53 +92,15 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_lh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Isometry3<N> {
|
||||
let rotation = Rotation3::look_at_lh(&(*target - *eye), up);
|
||||
let trans = rotation * (-*eye);
|
||||
let rotation = Rotation3::look_at_lh(&(*target - *eye), up);
|
||||
let trans = rotation * (-*eye);
|
||||
|
||||
Isometry3::new_with_rotation_matrix(trans.to_vector(), rotation)
|
||||
Isometry3::from_rotation_matrix(trans.to_vector(), rotation)
|
||||
}
|
||||
}
|
||||
|
||||
isometry_impl!(Isometry2, Rotation2, Vector2, Vector1);
|
||||
rotation_matrix_impl!(Isometry2, Rotation2, Vector2, Vector1);
|
||||
rotation_impl!(Isometry2, Rotation2, Vector1);
|
||||
isometry_impl!(Isometry2, Rotation2, Vector2, Vector1, Point2, Matrix3);
|
||||
dim_impl!(Isometry2, 2);
|
||||
one_impl!(Isometry2);
|
||||
absolute_rotate_impl!(Isometry2, Vector2);
|
||||
rand_impl!(Isometry2);
|
||||
approx_eq_impl!(Isometry2);
|
||||
to_homogeneous_impl!(Isometry2, Matrix3);
|
||||
inverse_impl!(Isometry2);
|
||||
transform_impl!(Isometry2, Point2);
|
||||
transformation_impl!(Isometry2);
|
||||
rotate_impl!(Isometry2, Vector2);
|
||||
translation_impl!(Isometry2, Vector2);
|
||||
translate_impl!(Isometry2, Point2);
|
||||
isometry_mul_isometry_impl!(Isometry2);
|
||||
isometry_mul_rotation_impl!(Isometry2, Rotation2);
|
||||
isometry_mul_point_impl!(Isometry2, Point2);
|
||||
isometry_mul_vec_impl!(Isometry2, Vector2);
|
||||
arbitrary_isometry_impl!(Isometry2);
|
||||
isometry_display_impl!(Isometry2);
|
||||
|
||||
isometry_impl!(Isometry3, Rotation3, Vector3, Vector3);
|
||||
rotation_matrix_impl!(Isometry3, Rotation3, Vector3, Vector3);
|
||||
rotation_impl!(Isometry3, Rotation3, Vector3);
|
||||
isometry_impl!(Isometry3, Rotation3, Vector3, Vector3, Point3, Matrix4);
|
||||
dim_impl!(Isometry3, 3);
|
||||
one_impl!(Isometry3);
|
||||
absolute_rotate_impl!(Isometry3, Vector3);
|
||||
rand_impl!(Isometry3);
|
||||
approx_eq_impl!(Isometry3);
|
||||
to_homogeneous_impl!(Isometry3, Matrix4);
|
||||
inverse_impl!(Isometry3);
|
||||
transform_impl!(Isometry3, Point3);
|
||||
transformation_impl!(Isometry3);
|
||||
rotate_impl!(Isometry3, Vector3);
|
||||
translation_impl!(Isometry3, Vector3);
|
||||
translate_impl!(Isometry3, Point3);
|
||||
isometry_mul_isometry_impl!(Isometry3);
|
||||
isometry_mul_rotation_impl!(Isometry3, Rotation3);
|
||||
isometry_mul_point_impl!(Isometry3, Point3);
|
||||
isometry_mul_vec_impl!(Isometry3, Vector3);
|
||||
arbitrary_isometry_impl!(Isometry3);
|
||||
isometry_display_impl!(Isometry3);
|
||||
|
@ -1,74 +1,69 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! isometry_impl(
|
||||
($t: ident, $submatrix: ident, $subvector: ident, $subrotvector: ident) => (
|
||||
($t: ident, $rotmatrix: ident, $vector: ident, $rotvector: ident, $point: ident,
|
||||
$homogeneous: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/// Creates a new isometry from an axis-angle rotation, and a vector.
|
||||
#[inline]
|
||||
pub fn new(translation: $subvector<N>, rotation: $subrotvector<N>) -> $t<N> {
|
||||
pub fn new(translation: $vector<N>, rotation: $rotvector<N>) -> $t<N> {
|
||||
$t {
|
||||
rotation: $submatrix::new(rotation),
|
||||
rotation: $rotmatrix::new(rotation),
|
||||
translation: translation
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new isometry from a rotation matrix and a vector.
|
||||
#[inline]
|
||||
pub fn new_with_rotation_matrix(translation: $subvector<N>, rotation: $submatrix<N>) -> $t<N> {
|
||||
pub fn from_rotation_matrix(translation: $vector<N>, rotation: $rotmatrix<N>) -> $t<N> {
|
||||
$t {
|
||||
rotation: rotation,
|
||||
translation: translation
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_matrix_impl(
|
||||
($t: ident, $trotation: ident, $tlv: ident, $tav: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* RotationMatrix
|
||||
*
|
||||
*/
|
||||
impl<N: Cast<f64> + BaseFloat>
|
||||
RotationMatrix<N, $tlv<N>, $tav<N>> for $t<N> {
|
||||
type Output = $trotation<N>;
|
||||
RotationMatrix<N, $vector<N>, $rotvector<N>> for $t<N> {
|
||||
type Output = $rotmatrix<N>;
|
||||
|
||||
#[inline]
|
||||
fn to_rotation_matrix(&self) -> $trotation<N> {
|
||||
fn to_rotation_matrix(&self) -> $rotmatrix<N> {
|
||||
self.rotation
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident) => (
|
||||
/*
|
||||
*
|
||||
* One
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new_with_rotation_matrix(::zero(), ::one())
|
||||
$t::from_rotation_matrix(::zero(), ::one())
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! isometry_mul_isometry_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Isometry × Isometry
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
self.translation + self.rotation * right.translation,
|
||||
self.rotation * right.rotation)
|
||||
}
|
||||
@ -81,192 +76,208 @@ macro_rules! isometry_mul_isometry_impl(
|
||||
self.rotation *= right.rotation;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! isometry_mul_rotation_impl(
|
||||
($t: ident, $rotation: ident) => (
|
||||
impl<N: BaseFloat> Mul<$rotation<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Isometry × Rotation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Mul<$rotmatrix<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $rotation<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(self.translation, self.rotation * right)
|
||||
fn mul(self, right: $rotmatrix<N>) -> $t<N> {
|
||||
$t::from_rotation_matrix(self.translation, self.rotation * right)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $rotation<N> {
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $rotmatrix<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
self * right.translation,
|
||||
self * right.rotation)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> MulAssign<$rotation<N>> for $t<N> {
|
||||
impl<N: BaseFloat> MulAssign<$rotmatrix<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $rotation<N>) {
|
||||
fn mul_assign(&mut self, right: $rotmatrix<N>) {
|
||||
self.rotation *= right
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! isometry_mul_point_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
/*
|
||||
*
|
||||
* Isometry × Point
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$point<N>> for $t<N> {
|
||||
type Output = $point<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
fn mul(self, right: $point<N>) -> $point<N> {
|
||||
self.rotation * right + self.translation
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! isometry_mul_vec_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
/*
|
||||
*
|
||||
* Isometry × Vector
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$vector<N>> for $t<N> {
|
||||
type Output = $vector<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
fn mul(self, right: $vector<N>) -> $vector<N> {
|
||||
self.rotation * right
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! translation_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseFloat> Translation<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Translation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Translation<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn translation(&self) -> $tv<N> {
|
||||
fn translation(&self) -> $vector<N> {
|
||||
self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_translation(&self) -> $tv<N> {
|
||||
fn inverse_translation(&self) -> $vector<N> {
|
||||
-self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_translation_mut(&mut self, t: &$tv<N>) {
|
||||
fn append_translation_mut(&mut self, t: &$vector<N>) {
|
||||
self.translation = *t + self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_translation(&self, t: &$tv<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(*t + self.translation, self.rotation)
|
||||
fn append_translation(&self, t: &$vector<N>) -> $t<N> {
|
||||
$t::from_rotation_matrix(*t + self.translation, self.rotation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_translation_mut(&mut self, t: &$tv<N>) {
|
||||
fn prepend_translation_mut(&mut self, t: &$vector<N>) {
|
||||
self.translation = self.translation + self.rotation * *t
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_translation(&self, t: &$tv<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(self.translation + self.rotation * *t, self.rotation)
|
||||
fn prepend_translation(&self, t: &$vector<N>) -> $t<N> {
|
||||
$t::from_rotation_matrix(self.translation + self.rotation * *t, self.rotation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_translation(&mut self, t: $tv<N>) {
|
||||
fn set_translation(&mut self, t: $vector<N>) {
|
||||
self.translation = t
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! translate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Copy + Add<N, Output = N> + Sub<N, Output = N>> Translate<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Translate
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Add<N, Output = N> + Sub<N, Output = N>> Translate<$point<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn translate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn translate(&self, v: &$point<N>) -> $point<N> {
|
||||
*v + self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_translate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn inverse_translate(&self, v: &$point<N>) -> $point<N> {
|
||||
*v - self.translation
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_impl(
|
||||
($t: ident, $trotation: ident, $tav: ident) => (
|
||||
impl<N: Cast<f64> + BaseFloat> Rotation<$tav<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotation
|
||||
*
|
||||
*/
|
||||
impl<N: Cast<f64> + BaseFloat> Rotation<$rotvector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> $tav<N> {
|
||||
fn rotation(&self) -> $rotvector<N> {
|
||||
self.rotation.rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_rotation(&self) -> $tav<N> {
|
||||
fn inverse_rotation(&self) -> $rotvector<N> {
|
||||
self.rotation.inverse_rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_rotation_mut(&mut self, rotation: &$tav<N>) {
|
||||
let delta = $trotation::new(*rotation);
|
||||
fn append_rotation_mut(&mut self, rotation: &$rotvector<N>) {
|
||||
let delta = $rotmatrix::new(*rotation);
|
||||
|
||||
self.rotation = delta * self.rotation;
|
||||
self.translation = delta * self.translation;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_rotation(&self, rotation: &$tav<N>) -> $t<N> {
|
||||
let delta = $trotation::new(*rotation);
|
||||
fn append_rotation(&self, rotation: &$rotvector<N>) -> $t<N> {
|
||||
let delta = $rotmatrix::new(*rotation);
|
||||
|
||||
$t::new_with_rotation_matrix(delta * self.translation, delta * self.rotation)
|
||||
$t::from_rotation_matrix(delta * self.translation, delta * self.rotation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation_mut(&mut self, rotation: &$tav<N>) {
|
||||
let delta = $trotation::new(*rotation);
|
||||
fn prepend_rotation_mut(&mut self, rotation: &$rotvector<N>) {
|
||||
let delta = $rotmatrix::new(*rotation);
|
||||
|
||||
self.rotation = self.rotation * delta;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation(&self, rotation: &$tav<N>) -> $t<N> {
|
||||
let delta = $trotation::new(*rotation);
|
||||
fn prepend_rotation(&self, rotation: &$rotvector<N>) -> $t<N> {
|
||||
let delta = $rotmatrix::new(*rotation);
|
||||
|
||||
$t::new_with_rotation_matrix(self.translation, self.rotation * delta)
|
||||
$t::from_rotation_matrix(self.translation, self.rotation * delta)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rotation: $tav<N>) {
|
||||
fn set_rotation(&mut self, rotation: $rotvector<N>) {
|
||||
// FIXME: should the translation be changed too?
|
||||
self.rotation.set_rotation(rotation)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Rotate<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotate
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Rotate<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn rotate(&self, v: &$vector<N>) -> $vector<N> {
|
||||
self.rotation.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn inverse_rotate(&self, v: &$vector<N>) -> $vector<N> {
|
||||
self.rotation.inverse_rotate(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! transformation_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Transformation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Transformation<$t<N>> for $t<N> {
|
||||
fn transformation(&self) -> $t<N> {
|
||||
*self
|
||||
@ -297,27 +308,31 @@ macro_rules! transformation_impl(
|
||||
*self = t
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! transform_impl(
|
||||
($t: ident, $tp: ident) => (
|
||||
impl<N: BaseNum> Transform<$tp<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Transform
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Transform<$point<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.rotation.transform(p) + self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn inverse_transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.rotation.inverse_transform(&(*p - self.translation))
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! inverse_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Inverse
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum + Neg<Output = N>> Inverse for $t<N> {
|
||||
#[inline]
|
||||
fn inverse_mut(&mut self) -> bool {
|
||||
@ -335,28 +350,32 @@ macro_rules! inverse_impl(
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! to_homogeneous_impl(
|
||||
($t: ident, $th: ident) => (
|
||||
impl<N: BaseNum> ToHomogeneous<$th<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $th<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* ToHomogeneous
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> ToHomogeneous<$homogeneous<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $homogeneous<N> {
|
||||
let mut res = self.rotation.to_homogeneous();
|
||||
|
||||
// copy the translation
|
||||
let dimension = Dimension::dimension(None::<$th<N>>);
|
||||
let dimension = Dimension::dimension(None::<$homogeneous<N>>);
|
||||
|
||||
res.set_column(dimension - 1, self.translation.as_point().to_homogeneous().to_vector());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! approx_eq_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* ApproxEq
|
||||
*
|
||||
*/
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
@ -380,47 +399,55 @@ macro_rules! approx_eq_impl(
|
||||
ApproxEq::approx_eq_ulps(&self.translation, &other.translation, ulps)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rand_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Rand
|
||||
*
|
||||
*/
|
||||
impl<N: Rand + BaseFloat> Rand for $t<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||
$t::new(rng.gen(), rng.gen())
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! absolute_rotate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseFloat> AbsoluteRotate<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* AbsoluteRotate
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> AbsoluteRotate<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn absolute_rotate(&self, v: &$vector<N>) -> $vector<N> {
|
||||
self.rotation.absolute_rotate(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! arbitrary_isometry_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Arbitrary
|
||||
*
|
||||
*/
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
Arbitrary::arbitrary(g),
|
||||
Arbitrary::arbitrary(g)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! isometry_display_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Display
|
||||
*
|
||||
*/
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "Isometry {{"));
|
||||
@ -441,3 +468,14 @@ macro_rules! isometry_display_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -14,7 +14,7 @@ use structs::point::{Point1, Point4, Point5, Point6};
|
||||
use structs::dvector::{DVector1, DVector2, DVector3, DVector4, DVector5, DVector6};
|
||||
|
||||
use traits::structure::{Cast, Row, Column, Iterable, IterableMut, Dimension, Indexable, Eye, ColumnSlice,
|
||||
RowSlice, Diagonal, DiagMut, Shape, BaseFloat, BaseNum, Repeat};
|
||||
RowSlice, Diagonal, DiagonalMut, Shape, BaseFloat, BaseNum, Repeat};
|
||||
use traits::operations::{Absolute, Transpose, Inverse, Outer, EigenQR, Mean};
|
||||
use traits::geometry::{ToHomogeneous, FromHomogeneous, Origin};
|
||||
use linalg;
|
||||
@ -50,45 +50,20 @@ pub struct Matrix1<N> {
|
||||
|
||||
eye_impl!(Matrix1, 1, m11);
|
||||
|
||||
mat_impl!(Matrix1, m11);
|
||||
repeat_impl!(Matrix1, m11);
|
||||
conversion_impl!(Matrix1, 1);
|
||||
mat_cast_impl!(Matrix1, m11);
|
||||
add_impl!(Matrix1, m11);
|
||||
sub_impl!(Matrix1, m11);
|
||||
scalar_add_impl!(Matrix1, m11);
|
||||
scalar_sub_impl!(Matrix1, m11);
|
||||
scalar_mul_impl!(Matrix1, m11);
|
||||
scalar_div_impl!(Matrix1, m11);
|
||||
absolute_impl!(Matrix1, m11);
|
||||
zero_impl!(Matrix1, m11);
|
||||
matrix_impl!(Matrix1, 1, Vector1, DVector1, m11);
|
||||
one_impl!(Matrix1, ::one);
|
||||
iterable_impl!(Matrix1, 1);
|
||||
iterable_mut_impl!(Matrix1, 1);
|
||||
at_fast_impl!(Matrix1, 1);
|
||||
dim_impl!(Matrix1, 1);
|
||||
indexable_impl!(Matrix1, 1);
|
||||
index_impl!(Matrix1, 1);
|
||||
mat_mul_mat_impl!(Matrix1, 1);
|
||||
mat_mul_vec_impl!(Matrix1, Vector1, 1, ::zero);
|
||||
vec_mul_mat_impl!(Matrix1, Vector1, 1, ::zero);
|
||||
mat_mul_point_impl!(Matrix1, Point1, 1, Origin::origin);
|
||||
point_mul_mat_impl!(Matrix1, Point1, 1, Origin::origin);
|
||||
// (specialized); inverse_impl!(Matrix1, 1);
|
||||
transpose_impl!(Matrix1, 1);
|
||||
approx_eq_impl!(Matrix1);
|
||||
row_impl!(Matrix1, Vector1, 1);
|
||||
column_impl!(Matrix1, Vector1, 1);
|
||||
column_slice_impl!(Matrix1, Vector1, DVector1, 1);
|
||||
row_slice_impl!(Matrix1, Vector1, DVector1, 1);
|
||||
diag_impl!(Matrix1, Vector1, 1);
|
||||
to_homogeneous_impl!(Matrix1, Matrix2, 1, 2);
|
||||
from_homogeneous_impl!(Matrix1, Matrix2, 1, 2);
|
||||
outer_impl!(Vector1, Matrix1);
|
||||
eigen_qr_impl!(Matrix1, Vector1);
|
||||
arbitrary_impl!(Matrix1, m11);
|
||||
rand_impl!(Matrix1, m11);
|
||||
mean_impl!(Matrix1, Vector1, 1);
|
||||
componentwise_arbitrary!(Matrix1, m11);
|
||||
componentwise_rand!(Matrix1, m11);
|
||||
mat_display_impl!(Matrix1, 1);
|
||||
|
||||
/// Square matrix of dimension 2.
|
||||
@ -101,49 +76,20 @@ pub struct Matrix2<N> {
|
||||
|
||||
eye_impl!(Matrix2, 2, m11, m22);
|
||||
|
||||
mat_impl!(Matrix2, m11, m12,
|
||||
m21, m22);
|
||||
repeat_impl!(Matrix2, m11, m12,
|
||||
m21, m22);
|
||||
conversion_impl!(Matrix2, 2);
|
||||
mat_cast_impl!(Matrix2, m11, m12,
|
||||
m21, m22);
|
||||
add_impl!(Matrix2, m11, m12, m21, m22);
|
||||
sub_impl!(Matrix2, m11, m12, m21, m22);
|
||||
scalar_add_impl!(Matrix2, m11, m12, m21, m22);
|
||||
scalar_sub_impl!(Matrix2, m11, m12, m21, m22);
|
||||
scalar_mul_impl!(Matrix2, m11, m12, m21, m22);
|
||||
scalar_div_impl!(Matrix2, m11, m12, m21, m22);
|
||||
absolute_impl!(Matrix2, m11, m12,
|
||||
m21, m22);
|
||||
zero_impl!(Matrix2, m11, m12,
|
||||
m21, m22);
|
||||
matrix_impl!(Matrix2, 2, Vector2, DVector2, m11, m12,
|
||||
m21, m22);
|
||||
one_impl!(Matrix2, ::one, ::zero,
|
||||
::zero, ::one);
|
||||
iterable_impl!(Matrix2, 2);
|
||||
iterable_mut_impl!(Matrix2, 2);
|
||||
dim_impl!(Matrix2, 2);
|
||||
indexable_impl!(Matrix2, 2);
|
||||
index_impl!(Matrix2, 2);
|
||||
at_fast_impl!(Matrix2, 2);
|
||||
// (specialized); mul_impl!(Matrix2, 2);
|
||||
// (specialized); rmul_impl!(Matrix2, Vector2, 2);
|
||||
// (specialized); lmul_impl!(Matrix2, Vector2, 2);
|
||||
// (specialized); inverse_impl!(Matrix2, 2);
|
||||
transpose_impl!(Matrix2, 2);
|
||||
approx_eq_impl!(Matrix2);
|
||||
row_impl!(Matrix2, Vector2, 2);
|
||||
column_impl!(Matrix2, Vector2, 2);
|
||||
column_slice_impl!(Matrix2, Vector2, DVector2, 2);
|
||||
row_slice_impl!(Matrix2, Vector2, DVector2, 2);
|
||||
diag_impl!(Matrix2, Vector2, 2);
|
||||
to_homogeneous_impl!(Matrix2, Matrix3, 2, 3);
|
||||
from_homogeneous_impl!(Matrix2, Matrix3, 2, 3);
|
||||
outer_impl!(Vector2, Matrix2);
|
||||
eigen_qr_impl!(Matrix2, Vector2);
|
||||
arbitrary_impl!(Matrix2, m11, m12, m21, m22);
|
||||
rand_impl!(Matrix2, m11, m12, m21, m22);
|
||||
mean_impl!(Matrix2, Vector2, 2);
|
||||
componentwise_arbitrary!(Matrix2, m11, m12, m21, m22);
|
||||
componentwise_rand!(Matrix2, m11, m12, m21, m22);
|
||||
mat_display_impl!(Matrix2, 2);
|
||||
|
||||
/// Square matrix of dimension 3.
|
||||
@ -157,91 +103,30 @@ pub struct Matrix3<N> {
|
||||
|
||||
eye_impl!(Matrix3, 3, m11, m22, m33);
|
||||
|
||||
mat_impl!(Matrix3, m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33);
|
||||
repeat_impl!(Matrix3, m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33);
|
||||
conversion_impl!(Matrix3, 3);
|
||||
mat_cast_impl!(Matrix3, m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33);
|
||||
add_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
sub_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
scalar_add_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
scalar_sub_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
scalar_mul_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
scalar_div_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
absolute_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
zero_impl!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
matrix_impl!(Matrix3, 3, Vector3, DVector3, m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33);
|
||||
one_impl!(Matrix3, ::one , ::zero, ::zero,
|
||||
::zero, ::one , ::zero,
|
||||
::zero, ::zero, ::one);
|
||||
iterable_impl!(Matrix3, 3);
|
||||
iterable_mut_impl!(Matrix3, 3);
|
||||
dim_impl!(Matrix3, 3);
|
||||
indexable_impl!(Matrix3, 3);
|
||||
index_impl!(Matrix3, 3);
|
||||
at_fast_impl!(Matrix3, 3);
|
||||
// (specialized); mul_impl!(Matrix3, 3);
|
||||
// (specialized); rmul_impl!(Matrix3, Vector3, 3);
|
||||
// (specialized); lmul_impl!(Matrix3, Vector3, 3);
|
||||
// (specialized); inverse_impl!(Matrix3, 3);
|
||||
transpose_impl!(Matrix3, 3);
|
||||
approx_eq_impl!(Matrix3);
|
||||
// (specialized); row_impl!(Matrix3, Vector3, 3);
|
||||
// (specialized); column_impl!(Matrix3, Vector3, 3);
|
||||
column_slice_impl!(Matrix3, Vector3, DVector3, 3);
|
||||
row_slice_impl!(Matrix3, Vector3, DVector3, 3);
|
||||
diag_impl!(Matrix3, Vector3, 3);
|
||||
to_homogeneous_impl!(Matrix3, Matrix4, 3, 4);
|
||||
from_homogeneous_impl!(Matrix3, Matrix4, 3, 4);
|
||||
outer_impl!(Vector3, Matrix3);
|
||||
eigen_qr_impl!(Matrix3, Vector3);
|
||||
arbitrary_impl!(Matrix3,
|
||||
componentwise_arbitrary!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
rand_impl!(Matrix3,
|
||||
componentwise_rand!(Matrix3,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
);
|
||||
mean_impl!(Matrix3, Vector3, 3);
|
||||
mat_display_impl!(Matrix3, 3);
|
||||
|
||||
/// Square matrix of dimension 4.
|
||||
@ -256,68 +141,7 @@ pub struct Matrix4<N> {
|
||||
|
||||
eye_impl!(Matrix4, 4, m11, m22, m33, m44);
|
||||
|
||||
mat_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
repeat_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
conversion_impl!(Matrix4, 4);
|
||||
mat_cast_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
add_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
sub_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
scalar_add_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
scalar_sub_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
scalar_mul_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
scalar_div_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
absolute_impl!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
zero_impl!(Matrix4,
|
||||
matrix_impl!(Matrix4, 4, Vector4, DVector4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
@ -327,42 +151,28 @@ one_impl!(Matrix4, ::one , ::zero, ::zero, ::zero,
|
||||
::zero, ::one , ::zero, ::zero,
|
||||
::zero, ::zero, ::one , ::zero,
|
||||
::zero, ::zero, ::zero, ::one);
|
||||
iterable_impl!(Matrix4, 4);
|
||||
iterable_mut_impl!(Matrix4, 4);
|
||||
dim_impl!(Matrix4, 4);
|
||||
indexable_impl!(Matrix4, 4);
|
||||
index_impl!(Matrix4, 4);
|
||||
at_fast_impl!(Matrix4, 4);
|
||||
mat_mul_mat_impl!(Matrix4, 4);
|
||||
mat_mul_vec_impl!(Matrix4, Vector4, 4, ::zero);
|
||||
vec_mul_mat_impl!(Matrix4, Vector4, 4, ::zero);
|
||||
mat_mul_point_impl!(Matrix4, Point4, 4, Origin::origin);
|
||||
point_mul_mat_impl!(Matrix4, Point4, 4, Origin::origin);
|
||||
inverse_impl!(Matrix4, 4);
|
||||
transpose_impl!(Matrix4, 4);
|
||||
approx_eq_impl!(Matrix4);
|
||||
row_impl!(Matrix4, Vector4, 4);
|
||||
column_impl!(Matrix4, Vector4, 4);
|
||||
column_slice_impl!(Matrix4, Vector4, DVector4, 4);
|
||||
row_slice_impl!(Matrix4, Vector4, DVector4, 4);
|
||||
diag_impl!(Matrix4, Vector4, 4);
|
||||
to_homogeneous_impl!(Matrix4, Matrix5, 4, 5);
|
||||
from_homogeneous_impl!(Matrix4, Matrix5, 4, 5);
|
||||
outer_impl!(Vector4, Matrix4);
|
||||
eigen_qr_impl!(Matrix4, Vector4);
|
||||
arbitrary_impl!(Matrix4,
|
||||
componentwise_arbitrary!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
rand_impl!(Matrix4,
|
||||
componentwise_rand!(Matrix4,
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
mean_impl!(Matrix4, Vector4, 4);
|
||||
mat_display_impl!(Matrix4, 4);
|
||||
|
||||
/// Square matrix of dimension 5.
|
||||
@ -378,36 +188,7 @@ pub struct Matrix5<N> {
|
||||
|
||||
eye_impl!(Matrix5, 5, m11, m22, m33, m44, m55);
|
||||
|
||||
mat_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
repeat_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
conversion_impl!(Matrix5, 5);
|
||||
mat_cast_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
absolute_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
zero_impl!(Matrix5,
|
||||
matrix_impl!(Matrix5, 5, Vector5, DVector5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
@ -421,86 +202,30 @@ one_impl!(Matrix5,
|
||||
::zero, ::zero, ::zero, ::one , ::zero,
|
||||
::zero, ::zero, ::zero, ::zero, ::one
|
||||
);
|
||||
add_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
sub_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
scalar_add_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
scalar_sub_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
scalar_mul_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
scalar_div_impl!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
iterable_impl!(Matrix5, 5);
|
||||
iterable_mut_impl!(Matrix5, 5);
|
||||
dim_impl!(Matrix5, 5);
|
||||
indexable_impl!(Matrix5, 5);
|
||||
index_impl!(Matrix5, 5);
|
||||
at_fast_impl!(Matrix5, 5);
|
||||
mat_mul_mat_impl!(Matrix5, 5);
|
||||
mat_mul_vec_impl!(Matrix5, Vector5, 5, ::zero);
|
||||
vec_mul_mat_impl!(Matrix5, Vector5, 5, ::zero);
|
||||
mat_mul_point_impl!(Matrix5, Point5, 5, Origin::origin);
|
||||
point_mul_mat_impl!(Matrix5, Point5, 5, Origin::origin);
|
||||
inverse_impl!(Matrix5, 5);
|
||||
transpose_impl!(Matrix5, 5);
|
||||
approx_eq_impl!(Matrix5);
|
||||
row_impl!(Matrix5, Vector5, 5);
|
||||
column_impl!(Matrix5, Vector5, 5);
|
||||
column_slice_impl!(Matrix5, Vector5, DVector5, 5);
|
||||
row_slice_impl!(Matrix5, Vector5, DVector5, 5);
|
||||
diag_impl!(Matrix5, Vector5, 5);
|
||||
to_homogeneous_impl!(Matrix5, Matrix6, 5, 6);
|
||||
from_homogeneous_impl!(Matrix5, Matrix6, 5, 6);
|
||||
outer_impl!(Vector5, Matrix5);
|
||||
eigen_qr_impl!(Matrix5, Vector5);
|
||||
arbitrary_impl!(Matrix5,
|
||||
componentwise_arbitrary!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
rand_impl!(Matrix5,
|
||||
componentwise_rand!(Matrix5,
|
||||
m11, m12, m13, m14, m15,
|
||||
m21, m22, m23, m24, m25,
|
||||
m31, m32, m33, m34, m35,
|
||||
m41, m42, m43, m44, m45,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
mean_impl!(Matrix5, Vector5, 5);
|
||||
mat_display_impl!(Matrix5, 5);
|
||||
|
||||
/// Square matrix of dimension 6.
|
||||
@ -517,7 +242,7 @@ pub struct Matrix6<N> {
|
||||
|
||||
eye_impl!(Matrix6, 6, m11, m22, m33, m44, m55, m66);
|
||||
|
||||
mat_impl!(Matrix6,
|
||||
matrix_impl!(Matrix6, 6, Vector6, DVector6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
@ -525,78 +250,6 @@ mat_impl!(Matrix6,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
repeat_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
conversion_impl!(Matrix6, 6);
|
||||
mat_cast_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
add_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
sub_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
scalar_add_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
scalar_sub_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
scalar_mul_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
scalar_div_impl!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
m41, m42, m43, m44, m45, m46,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
absolute_impl!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36, m41, m42, m43, m44, m45, m46, m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66);
|
||||
|
||||
zero_impl!(Matrix6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36, m41, m42, m43, m44, m45, m46, m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66);
|
||||
|
||||
one_impl!(Matrix6,
|
||||
::one , ::zero, ::zero, ::zero, ::zero, ::zero,
|
||||
@ -606,28 +259,15 @@ one_impl!(Matrix6,
|
||||
::zero, ::zero, ::zero, ::zero, ::one , ::zero,
|
||||
::zero, ::zero, ::zero, ::zero, ::zero, ::one
|
||||
);
|
||||
iterable_impl!(Matrix6, 6);
|
||||
iterable_mut_impl!(Matrix6, 6);
|
||||
dim_impl!(Matrix6, 6);
|
||||
indexable_impl!(Matrix6, 6);
|
||||
index_impl!(Matrix6, 6);
|
||||
at_fast_impl!(Matrix6, 6);
|
||||
mat_mul_mat_impl!(Matrix6, 6);
|
||||
mat_mul_vec_impl!(Matrix6, Vector6, 6, ::zero);
|
||||
vec_mul_mat_impl!(Matrix6, Vector6, 6, ::zero);
|
||||
mat_mul_point_impl!(Matrix6, Point6, 6, Origin::origin);
|
||||
point_mul_mat_impl!(Matrix6, Point6, 6, Origin::origin);
|
||||
inverse_impl!(Matrix6, 6);
|
||||
transpose_impl!(Matrix6, 6);
|
||||
approx_eq_impl!(Matrix6);
|
||||
row_impl!(Matrix6, Vector6, 6);
|
||||
column_impl!(Matrix6, Vector6, 6);
|
||||
column_slice_impl!(Matrix6, Vector6, DVector6, 6);
|
||||
row_slice_impl!(Matrix6, Vector6, DVector6, 6);
|
||||
diag_impl!(Matrix6, Vector6, 6);
|
||||
outer_impl!(Vector6, Matrix6);
|
||||
eigen_qr_impl!(Matrix6, Vector6);
|
||||
arbitrary_impl!(Matrix6,
|
||||
componentwise_arbitrary!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
@ -635,7 +275,7 @@ arbitrary_impl!(Matrix6,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
rand_impl!(Matrix6,
|
||||
componentwise_rand!(Matrix6,
|
||||
m11, m12, m13, m14, m15, m16,
|
||||
m21, m22, m23, m24, m25, m26,
|
||||
m31, m32, m33, m34, m35, m36,
|
||||
@ -643,5 +283,4 @@ rand_impl!(Matrix6,
|
||||
m51, m52, m53, m54, m55, m56,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
mean_impl!(Matrix6, Vector6, 6);
|
||||
mat_display_impl!(Matrix6, 6);
|
||||
|
@ -1,20 +1,22 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! mat_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N> $t<N> {
|
||||
#[inline]
|
||||
pub fn new($($compN: N ),+) -> $t<N> {
|
||||
$t {
|
||||
$($compN: $compN ),+
|
||||
macro_rules! matrix_impl(
|
||||
($t: ident, $dimension: expr, $vector: ident, $dvector: ident, $($compN: ident),+) => (
|
||||
impl<N> $t<N> {
|
||||
#[inline]
|
||||
pub fn new($($compN: N ),+) -> $t<N> {
|
||||
$t {
|
||||
$($compN: $compN ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! conversion_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Conversions (AsRef, AsMut, From)
|
||||
*
|
||||
*/
|
||||
impl<N> AsRef<[[N; $dimension]; $dimension]> for $t<N> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[[N; $dimension]; $dimension] {
|
||||
@ -58,11 +60,13 @@ macro_rules! conversion_impl(
|
||||
tref.clone()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! at_fast_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Unsafe indexing.
|
||||
*
|
||||
*/
|
||||
impl<N: Copy> $t<N> {
|
||||
#[inline]
|
||||
pub unsafe fn at_fast(&self, (i, j): (usize, usize)) -> N {
|
||||
@ -76,331 +80,77 @@ macro_rules! at_fast_impl(
|
||||
.get_unchecked_mut(i + j * $dimension)) = val
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_cast_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Cast
|
||||
*
|
||||
*/
|
||||
impl<Nin: Copy, Nout: Copy + Cast<Nin>> Cast<$t<Nin>> for $t<Nout> {
|
||||
#[inline]
|
||||
fn from(v: $t<Nin>) -> $t<Nout> {
|
||||
$t::new($(Cast::from(v.$compN)),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! add_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Add<N, Output = N>> Add<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
/*
|
||||
*
|
||||
* Iterable
|
||||
*
|
||||
*/
|
||||
impl<N> Iterable<N> for $t<N> {
|
||||
#[inline]
|
||||
fn add(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN + right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AddAssign<N>> AddAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN += right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sub_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Sub<N, Output = N>> Sub<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<N>) -> $t<N> {
|
||||
$t::new($(self.$compN - right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<N: SubAssign<N>> SubAssign<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, right: $t<N>) {
|
||||
$( self.$compN -= right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_mul_scalar_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Mul<N, Output = N>> Mul<N> for N {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN * *right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: MulAssign<N>> MulAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: N) {
|
||||
$( self.$compN *= *right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$t<f32>> for f32 {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self * right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$t<f64>> for f64 {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self * right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_div_scalar_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Div<N, Output = N>> Div<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN / *right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: DivAssign<N>> DivAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, right: N) {
|
||||
$( self.$compN /= *right; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_add_scalar_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Add<N, Output = N>> Add<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: N) -> $t<N> {
|
||||
$t::new($(self.$compN + *right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AddAssign<N>> AddAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, right: N) {
|
||||
$( self.$compN += *right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$t<f32>> for f32 {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self + right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$t<f64>> for f64 {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self + right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_sub_scalar_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Sub<N, Output = N>> Sub<N> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: &N) -> $t<N> {
|
||||
$t::new($(self.$compN - *right),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: SubAssign<N>> SubAssign<N> for $t<N> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, right: N) {
|
||||
$( self.$compN -= *right; )+
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<f32> for $t<f32> {
|
||||
type Output = $t<f32>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<f32>) -> $t<f32> {
|
||||
$t::new($(self - right.$compN),+)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<f64> for $t<f64> {
|
||||
type Output = $t<f64>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $t<f64>) -> $t<f64> {
|
||||
$t::new($(self - right.$compN),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! eye_impl(
|
||||
($t: ident, $dimension: expr, $($comp_diagN: ident),+) => (
|
||||
impl<N: Zero + One> Eye for $t<N> {
|
||||
fn new_identity(dimension: usize) -> $t<N> {
|
||||
assert!(dimension == $dimension);
|
||||
let mut eye: $t<N> = ::zero();
|
||||
$(eye.$comp_diagN = ::one();)+
|
||||
eye
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! repeat_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy> Repeat<N> for $t<N> {
|
||||
fn repeat(val: N) -> $t<N> {
|
||||
$t {
|
||||
$($compN: val ),+
|
||||
fn iter(&self) -> Iter<N> {
|
||||
unsafe {
|
||||
mem::transmute::<&$t<N>, &[N; $dimension * $dimension]>(self).iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! absolute_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
impl<N: Absolute<N>> Absolute<$t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn abs(m: &$t<N>) -> $t<N> {
|
||||
$t::new($(::abs(&m.$compN) ),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! iterable_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Iterable<N> for $t<N> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N> {
|
||||
unsafe {
|
||||
mem::transmute::<&'l $t<N>, &'l [N; $dimension * $dimension]>(self).iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! iterable_mut_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> IterableMut<N> for $t<N> {
|
||||
#[inline]
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
|
||||
unsafe {
|
||||
mem::transmute::<&'l mut $t<N>, &'l mut [N; $dimension * $dimension]>(self).iter_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident, $($valueN: expr),+ ) => (
|
||||
impl<N: Copy + BaseNum> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new($($valueN() ),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! zero_impl(
|
||||
($t: ident, $($compN: ident),+ ) => (
|
||||
impl<N: Zero> Zero for $t<N> {
|
||||
#[inline]
|
||||
fn zero() -> $t<N> {
|
||||
$t {
|
||||
$($compN: ::zero() ),+
|
||||
impl<N> IterableMut<N> for $t<N> {
|
||||
#[inline]
|
||||
fn iter_mut(& mut self) -> IterMut<N> {
|
||||
unsafe {
|
||||
mem::transmute::<&mut $t<N>, &mut [N; $dimension * $dimension]>(self).iter_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
$(::is_zero(&self.$compN) )&&+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! indexable_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Shape<(usize, usize)> for $t<N> {
|
||||
#[inline]
|
||||
fn shape(&self) -> (usize, usize) {
|
||||
($dimension, $dimension)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy> Indexable<(usize, usize), N> for $t<N> {
|
||||
#[inline]
|
||||
fn swap(&mut self, (i1, j1): (usize, usize), (i2, j2): (usize, usize)) {
|
||||
unsafe {
|
||||
mem::transmute::<&mut $t<N>, &mut [N; $dimension * $dimension]>(self)
|
||||
.swap(i1 + j1 * $dimension, i2 + j2 * $dimension)
|
||||
/*
|
||||
*
|
||||
* Shape/Indexable/Index
|
||||
*
|
||||
*/
|
||||
impl<N> Shape<(usize, usize)> for $t<N> {
|
||||
#[inline]
|
||||
fn shape(&self) -> (usize, usize) {
|
||||
($dimension, $dimension)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, (i, j): (usize, usize)) -> N {
|
||||
(*mem::transmute::<&$t<N>, &[N; $dimension * $dimension]>(self).get_unchecked(i + j * $dimension))
|
||||
impl<N: Copy> Indexable<(usize, usize), N> for $t<N> {
|
||||
#[inline]
|
||||
fn swap(&mut self, (i1, j1): (usize, usize), (i2, j2): (usize, usize)) {
|
||||
unsafe {
|
||||
mem::transmute::<&mut $t<N>, &mut [N; $dimension * $dimension]>(self)
|
||||
.swap(i1 + j1 * $dimension, i2 + j2 * $dimension)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, (i, j): (usize, usize)) -> N {
|
||||
(*mem::transmute::<&$t<N>, &[N; $dimension * $dimension]>(self).get_unchecked(i + j * $dimension))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, (i, j): (usize, usize), val: N) {
|
||||
(*mem::transmute::<&mut $t<N>, &mut [N; $dimension * $dimension]>(self).get_unchecked_mut(i + j * $dimension)) = val
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, (i, j): (usize, usize), val: N) {
|
||||
(*mem::transmute::<&mut $t<N>, &mut [N; $dimension * $dimension]>(self).get_unchecked_mut(i + j * $dimension)) = val
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! index_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Index<(usize, usize)> for $t<N> {
|
||||
type Output = N;
|
||||
|
||||
@ -418,96 +168,167 @@ macro_rules! index_impl(
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! column_slice_impl(
|
||||
($t: ident, $tv: ident, $slice: ident, $dimension: expr) => (
|
||||
impl<N: Clone + Copy + Zero> ColumnSlice<$slice<N>> for $t<N> {
|
||||
fn column_slice(&self, cid: usize, rstart: usize, rend: usize) -> $slice<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Row/Column
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Zero> Column<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn ncols(&self) -> usize {
|
||||
Dimension::dimension(None::<$t<N>>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_column(&mut self, column: usize, v: $vector<N>) {
|
||||
for (i, e) in v.iter().enumerate() {
|
||||
self[(i, column)] = *e;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn column(&self, column: usize) -> $vector<N> {
|
||||
let mut res: $vector<N> = ::zero();
|
||||
|
||||
for (i, e) in res.iter_mut().enumerate() {
|
||||
*e = self[(i, column)];
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Copy + Zero> ColumnSlice<$dvector<N>> for $t<N> {
|
||||
fn column_slice(&self, cid: usize, rstart: usize, rend: usize) -> $dvector<N> {
|
||||
let column = self.column(cid);
|
||||
|
||||
$slice::from_slice(rend - rstart, &column.as_ref()[rstart .. rend])
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! row_impl(
|
||||
($t: ident, $tv: ident, $dimension: expr) => (
|
||||
impl<N: Copy + Zero> Row<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn nrows(&self) -> usize {
|
||||
Dimension::dimension(None::<$t<N>>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_row(&mut self, row: usize, v: $tv<N>) {
|
||||
for (i, e) in v.iter().enumerate() {
|
||||
self[(row, i)] = *e;
|
||||
$dvector::from_slice(rend - rstart, &column.as_ref()[rstart .. rend])
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn row(&self, row: usize) -> $tv<N> {
|
||||
let mut res: $tv<N> = ::zero();
|
||||
|
||||
for (i, e) in res.iter_mut().enumerate() {
|
||||
*e = self[(row, i)];
|
||||
impl<N: Copy + Zero> Row<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn nrows(&self) -> usize {
|
||||
Dimension::dimension(None::<$t<N>>)
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
#[inline]
|
||||
fn set_row(&mut self, row: usize, v: $vector<N>) {
|
||||
for (i, e) in v.iter().enumerate() {
|
||||
self[(row, i)] = *e;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! row_slice_impl(
|
||||
($t: ident, $tv: ident, $slice: ident, $dimension: expr) => (
|
||||
impl<N: Clone + Copy + Zero> RowSlice<$slice<N>> for $t<N> {
|
||||
fn row_slice(&self, rid: usize, cstart: usize, cend: usize) -> $slice<N> {
|
||||
#[inline]
|
||||
fn row(&self, row: usize) -> $vector<N> {
|
||||
let mut res: $vector<N> = ::zero();
|
||||
|
||||
for (i, e) in res.iter_mut().enumerate() {
|
||||
*e = self[(row, i)];
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Copy + Zero> RowSlice<$dvector<N>> for $t<N> {
|
||||
fn row_slice(&self, rid: usize, cstart: usize, cend: usize) -> $dvector<N> {
|
||||
let row = self.row(rid);
|
||||
|
||||
$slice::from_slice(cend - cstart, &row.as_ref()[cstart .. cend])
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! column_impl(
|
||||
($t: ident, $tv: ident, $dimension: expr) => (
|
||||
impl<N: Copy + Zero> Column<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn ncols(&self) -> usize {
|
||||
Dimension::dimension(None::<$t<N>>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_column(&mut self, column: usize, v: $tv<N>) {
|
||||
for (i, e) in v.iter().enumerate() {
|
||||
self[(i, column)] = *e;
|
||||
$dvector::from_slice(cend - cstart, &row.as_ref()[cstart .. cend])
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn column(&self, column: usize) -> $tv<N> {
|
||||
let mut res: $tv<N> = ::zero();
|
||||
|
||||
for (i, e) in res.iter_mut().enumerate() {
|
||||
*e = self[(i, column)];
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! diag_impl(
|
||||
($t: ident, $tv: ident, $dimension: expr) => (
|
||||
impl<N: Copy + Zero> Diagonal<$tv<N>> for $t<N> {
|
||||
/*
|
||||
*
|
||||
* Transpose
|
||||
*
|
||||
*/
|
||||
impl<N: Copy> Transpose for $t<N> {
|
||||
#[inline]
|
||||
fn from_diagonal(diagonal: &$tv<N>) -> $t<N> {
|
||||
fn transpose(&self) -> $t<N> {
|
||||
let mut res = *self;
|
||||
|
||||
res.transpose_mut();
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_mut(&mut self) {
|
||||
for i in 1 .. $dimension {
|
||||
for j in 0 .. i {
|
||||
self.swap((i, j), (j, i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* ApproxEq
|
||||
*
|
||||
*/
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_ulps(_: Option<$t<N>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||
let mut zip = self.iter().zip(other.iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &$t<N>, ulps: u32) -> bool {
|
||||
let mut zip = self.iter().zip(other.iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Mean
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum + Cast<f64> + Clone> Mean<$vector<N>> for $t<N> {
|
||||
fn mean(&self) -> $vector<N> {
|
||||
let mut res: $vector<N> = ::zero();
|
||||
let normalizer: N = Cast::from(1.0f64 / $dimension as f64);
|
||||
|
||||
for i in 0 .. $dimension {
|
||||
for j in 0 .. $dimension {
|
||||
unsafe {
|
||||
let acc = res.unsafe_at(j) + self.unsafe_at((i, j)) * normalizer;
|
||||
res.unsafe_set(j, acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Diagonal
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Zero> Diagonal<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn from_diagonal(diagonal: &$vector<N>) -> $t<N> {
|
||||
let mut res: $t<N> = ::zero();
|
||||
|
||||
res.set_diagonal(diagonal);
|
||||
@ -516,8 +337,8 @@ macro_rules! diag_impl(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn diagonal(&self) -> $tv<N> {
|
||||
let mut diagonal: $tv<N> = ::zero();
|
||||
fn diagonal(&self) -> $vector<N> {
|
||||
let mut diagonal: $vector<N> = ::zero();
|
||||
|
||||
for i in 0 .. $dimension {
|
||||
unsafe { diagonal.unsafe_set(i, self.unsafe_at((i, i))) }
|
||||
@ -527,17 +348,61 @@ macro_rules! diag_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Zero> DiagMut<$tv<N>> for $t<N> {
|
||||
impl<N: Copy + Zero> DiagonalMut<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn set_diagonal(&mut self, diagonal: &$tv<N>) {
|
||||
fn set_diagonal(&mut self, diagonal: &$vector<N>) {
|
||||
for i in 0 .. $dimension {
|
||||
unsafe { self.unsafe_set((i, i), diagonal.unsafe_at(i)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Outer
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero> Outer for $vector<N> {
|
||||
type OuterProductType = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn outer(&self, other: &$vector<N>) -> $t<N> {
|
||||
let mut res: $t<N> = ::zero();
|
||||
|
||||
for i in 0 .. ::dimension::<$vector<N>>() {
|
||||
for j in 0 .. ::dimension::<$vector<N>>() {
|
||||
res[(i, j)] = self[i] * other[j]
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Componentwise unary operations.
|
||||
*
|
||||
*/
|
||||
componentwise_repeat!($t, $($compN),+);
|
||||
componentwise_absolute!($t, $($compN),+);
|
||||
componentwise_zero!($t, $($compN),+);
|
||||
|
||||
/*
|
||||
*
|
||||
* Pointwise binary operations.
|
||||
*
|
||||
*/
|
||||
pointwise_add!($t, $($compN),+);
|
||||
pointwise_sub!($t, $($compN),+);
|
||||
pointwise_scalar_add!($t, $($compN),+);
|
||||
pointwise_scalar_sub!($t, $($compN),+);
|
||||
pointwise_scalar_div!($t, $($compN),+);
|
||||
pointwise_scalar_mul!($t, $($compN),+);
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! mat_mul_mat_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N: Copy + BaseNum> Mul<$t<N>> for $t<N> {
|
||||
@ -727,56 +592,6 @@ macro_rules! inverse_impl(
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! transpose_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N: Copy> Transpose for $t<N> {
|
||||
#[inline]
|
||||
fn transpose(&self) -> $t<N> {
|
||||
let mut res = *self;
|
||||
|
||||
res.transpose_mut();
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_mut(&mut self) {
|
||||
for i in 1..$dimension {
|
||||
for j in 0..i {
|
||||
self.swap((i, j), (j, i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! approx_eq_impl(
|
||||
($t: ident) => (
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_ulps(_: Option<$t<N>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||
let mut zip = self.iter().zip(other.iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &$t<N>, ulps: u32) -> bool {
|
||||
let mut zip = self.iter().zip(other.iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! to_homogeneous_impl(
|
||||
($t: ident, $t2: ident, $dimension: expr, $dim2: expr) => (
|
||||
@ -785,8 +600,8 @@ macro_rules! to_homogeneous_impl(
|
||||
fn to_homogeneous(&self) -> $t2<N> {
|
||||
let mut res: $t2<N> = ::one();
|
||||
|
||||
for i in 0..$dimension {
|
||||
for j in 0..$dimension {
|
||||
for i in 0 .. $dimension {
|
||||
for j in 0 .. $dimension {
|
||||
res[(i, j)] = self[(i, j)]
|
||||
}
|
||||
}
|
||||
@ -804,8 +619,8 @@ macro_rules! from_homogeneous_impl(
|
||||
fn from(m: &$t2<N>) -> $t<N> {
|
||||
let mut res: $t<N> = ::one();
|
||||
|
||||
for i in 0..$dimension {
|
||||
for j in 0..$dimension {
|
||||
for i in 0 .. $dimension {
|
||||
for j in 0 .. $dimension {
|
||||
res[(i, j)] = m[(i, j)]
|
||||
}
|
||||
}
|
||||
@ -819,24 +634,6 @@ macro_rules! from_homogeneous_impl(
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! outer_impl(
|
||||
($t: ident, $m: ident) => (
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero> Outer for $t<N> {
|
||||
type OuterProductType = $m<N>;
|
||||
|
||||
#[inline]
|
||||
fn outer(&self, other: &$t<N>) -> $m<N> {
|
||||
let mut res: $m<N> = ::zero();
|
||||
for i in 0..Dimension::dimension(None::<$t<N>>) {
|
||||
for j in 0..Dimension::dimension(None::<$t<N>>) {
|
||||
res[(i, j)] = self[i] * other[j]
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! eigen_qr_impl(
|
||||
($t: ident, $v: ident) => (
|
||||
@ -850,27 +647,6 @@ macro_rules! eigen_qr_impl(
|
||||
);
|
||||
|
||||
|
||||
macro_rules! mean_impl(
|
||||
($t: ident, $v: ident, $dimension: expr) => (
|
||||
impl<N: BaseNum + Cast<f64> + Clone> Mean<$v<N>> for $t<N> {
|
||||
fn mean(&self) -> $v<N> {
|
||||
let mut res: $v<N> = ::zero();
|
||||
let normalizer: N = Cast::from(1.0f64 / $dimension as f64);
|
||||
|
||||
for i in 0 .. $dimension {
|
||||
for j in 0 .. $dimension {
|
||||
unsafe {
|
||||
let acc = res.unsafe_at(j) + self.unsafe_at((i, j)) * normalizer;
|
||||
res.unsafe_set(j, acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_display_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
@ -924,3 +700,39 @@ macro_rules! mat_display_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident, $($valueN: expr),+ ) => (
|
||||
impl<N: Copy + BaseNum> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new($($valueN() ),+)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! eye_impl(
|
||||
($t: ident, $dimension: expr, $($comp_diagN: ident),+) => (
|
||||
impl<N: Zero + One> Eye for $t<N> {
|
||||
fn new_identity(dimension: usize) -> $t<N> {
|
||||
assert!(dimension == $dimension);
|
||||
let mut eye: $t<N> = ::zero();
|
||||
$(eye.$comp_diagN = ::one();)+
|
||||
eye
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -11,10 +11,12 @@ pub use self::similarity::{Similarity2, Similarity3};
|
||||
pub use self::perspective::{Perspective3, PerspectiveMatrix3};
|
||||
pub use self::orthographic::{Orthographic3, OrthographicMatrix3};
|
||||
pub use self::quaternion::{Quaternion, UnitQuaternion};
|
||||
pub use self::unit::Unit;
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
pub use self::vectorn::VectorN;
|
||||
|
||||
mod common_macros;
|
||||
mod dmatrix_macros;
|
||||
mod dmatrix;
|
||||
mod vectorn_macros;
|
||||
@ -37,6 +39,7 @@ mod similarity_macros;
|
||||
mod similarity;
|
||||
mod perspective;
|
||||
mod orthographic;
|
||||
mod unit;
|
||||
|
||||
// Specialization for some 1d, 2d and 3d operations.
|
||||
#[doc(hidden)]
|
||||
|
@ -71,41 +71,41 @@ impl<N: Arbitrary + BaseFloat> Arbitrary for Orthographic3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> Orthographic3<N> {
|
||||
impl<N: BaseFloat> Orthographic3<N> {
|
||||
/// The smallest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn left(&self) -> N {
|
||||
self.left.clone()
|
||||
self.left
|
||||
}
|
||||
|
||||
/// The largest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn right(&self) -> N {
|
||||
self.right.clone()
|
||||
self.right
|
||||
}
|
||||
|
||||
/// The smallest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn bottom(&self) -> N {
|
||||
self.bottom.clone()
|
||||
self.bottom
|
||||
}
|
||||
|
||||
/// The largest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn top(&self) -> N {
|
||||
self.top.clone()
|
||||
self.top
|
||||
}
|
||||
|
||||
/// The near plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn znear(&self) -> N {
|
||||
self.znear.clone()
|
||||
self.znear
|
||||
}
|
||||
|
||||
/// The far plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn zfar(&self) -> N {
|
||||
self.zfar.clone()
|
||||
self.zfar
|
||||
}
|
||||
|
||||
/// Sets the smallest x-coordinate of the view cuboid.
|
||||
@ -183,23 +183,20 @@ impl<N: BaseFloat> OrthographicMatrix3<N> {
|
||||
}
|
||||
|
||||
/// Creates a new orthographic projection matrix from an aspect ratio and the vertical field of view.
|
||||
pub fn new_with_fov(aspect: N, vfov: N, znear: N, zfar: N) -> OrthographicMatrix3<N> {
|
||||
pub fn from_fov(aspect: N, vfov: N, znear: N, zfar: N) -> OrthographicMatrix3<N> {
|
||||
assert!(znear < zfar, "The far plane must be farther than the near plane.");
|
||||
assert!(!::is_zero(&aspect));
|
||||
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let width = zfar * (vfov / _2).tan();
|
||||
let half: N = ::cast(0.5);
|
||||
let width = zfar * (vfov * half).tan();
|
||||
let height = width / aspect;
|
||||
|
||||
OrthographicMatrix3::new(-width / _2, width / _2, -height / _2, height / _2, znear, zfar)
|
||||
OrthographicMatrix3::new(-width * half, width * half, -height * half, height * half, znear, zfar)
|
||||
}
|
||||
|
||||
/// Creates a new orthographic matrix from a 4D matrix.
|
||||
///
|
||||
/// This is unsafe because the input matrix is not checked to be a orthographic projection.
|
||||
#[inline]
|
||||
pub unsafe fn new_with_matrix(matrix: Matrix4<N>) -> OrthographicMatrix3<N> {
|
||||
pub fn from_matrix_unchecked(matrix: Matrix4<N>) -> OrthographicMatrix3<N> {
|
||||
OrthographicMatrix3 {
|
||||
matrix: matrix
|
||||
}
|
||||
@ -207,7 +204,7 @@ impl<N: BaseFloat> OrthographicMatrix3<N> {
|
||||
|
||||
/// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection.
|
||||
#[inline]
|
||||
pub fn as_matrix<'a>(&'a self) -> &'a Matrix4<N> {
|
||||
pub fn as_matrix(&self) -> &Matrix4<N> {
|
||||
&self.matrix
|
||||
}
|
||||
|
||||
@ -334,11 +331,11 @@ impl<N: BaseFloat> OrthographicMatrix3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> OrthographicMatrix3<N> {
|
||||
impl<N: BaseFloat> OrthographicMatrix3<N> {
|
||||
/// Returns the 4D matrix (using homogeneous coordinates) of this projection.
|
||||
#[inline]
|
||||
pub fn to_matrix<'a>(&'a self) -> Matrix4<N> {
|
||||
self.matrix.clone()
|
||||
pub fn to_matrix(&self) -> Matrix4<N> {
|
||||
self.matrix
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +348,7 @@ impl<N: Arbitrary + BaseFloat> Arbitrary for OrthographicMatrix3<N> {
|
||||
}
|
||||
|
||||
|
||||
/// Similarityple helper function for rejection sampling
|
||||
/// Simple helper function for rejection sampling
|
||||
#[cfg(feature="arbitrary")]
|
||||
#[inline]
|
||||
pub fn reject<G: Gen, F: FnMut(&T) -> bool, T: Arbitrary>(g: &mut G, f: F) -> T {
|
||||
|
@ -63,29 +63,29 @@ impl<N: Arbitrary + BaseFloat> Arbitrary for Perspective3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> Perspective3<N> {
|
||||
impl<N: BaseFloat> Perspective3<N> {
|
||||
/// Gets the `width / height` aspect ratio.
|
||||
#[inline]
|
||||
pub fn aspect(&self) -> N {
|
||||
self.aspect.clone()
|
||||
self.aspect
|
||||
}
|
||||
|
||||
/// Gets the y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn fovy(&self) -> N {
|
||||
self.fovy.clone()
|
||||
self.fovy
|
||||
}
|
||||
|
||||
/// Gets the near plane offset of the view frustrum.
|
||||
#[inline]
|
||||
pub fn znear(&self) -> N {
|
||||
self.znear.clone()
|
||||
self.znear
|
||||
}
|
||||
|
||||
/// Gets the far plane offset of the view frustrum.
|
||||
#[inline]
|
||||
pub fn zfar(&self) -> N {
|
||||
self.zfar.clone()
|
||||
self.zfar
|
||||
}
|
||||
|
||||
/// Sets the `width / height` aspect ratio of the view frustrum.
|
||||
@ -154,10 +154,8 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
}
|
||||
|
||||
/// Creates a new perspective projection matrix from a 4D matrix.
|
||||
///
|
||||
/// This is unsafe because the input matrix is not checked to be a perspective projection.
|
||||
#[inline]
|
||||
pub unsafe fn new_with_matrix(matrix: Matrix4<N>) -> PerspectiveMatrix3<N> {
|
||||
pub fn from_matrix_unchecked(matrix: Matrix4<N>) -> PerspectiveMatrix3<N> {
|
||||
PerspectiveMatrix3 {
|
||||
matrix: matrix
|
||||
}
|
||||
@ -165,7 +163,7 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
|
||||
/// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection.
|
||||
#[inline]
|
||||
pub fn as_matrix<'a>(&'a self) -> &'a Matrix4<N> {
|
||||
pub fn as_matrix(&self) -> &Matrix4<N> {
|
||||
&self.matrix
|
||||
}
|
||||
|
||||
@ -178,30 +176,23 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
/// Gets the y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn fovy(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
(_1 / self.matrix.m22).atan() * _2
|
||||
(::one::<N>() / self.matrix.m22).atan() * ::cast(2.0)
|
||||
}
|
||||
|
||||
/// Gets the near plane offset of the view frustrum.
|
||||
#[inline]
|
||||
pub fn znear(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let ratio = (-self.matrix.m33 + _1) / (-self.matrix.m33 - _1);
|
||||
let ratio = (-self.matrix.m33 + ::one::<N>()) / (-self.matrix.m33 - ::one::<N>());
|
||||
|
||||
self.matrix.m34 / (_2 * ratio) - self.matrix.m34 / _2
|
||||
self.matrix.m34 / (ratio * ::cast(2.0)) - self.matrix.m34 / ::cast(2.0)
|
||||
}
|
||||
|
||||
/// Gets the far plane offset of the view frustrum.
|
||||
#[inline]
|
||||
pub fn zfar(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let ratio = (-self.matrix.m33 + _1) / (-self.matrix.m33 - _1);
|
||||
let ratio = (-self.matrix.m33 + ::one()) / (-self.matrix.m33 - ::one());
|
||||
|
||||
(self.matrix.m34 - ratio * self.matrix.m34) / _2
|
||||
(self.matrix.m34 - ratio * self.matrix.m34) / ::cast(2.0)
|
||||
}
|
||||
|
||||
// FIXME: add a method to retrieve znear and zfar simultaneously?
|
||||
@ -217,11 +208,8 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
/// Updates this projection with a new y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn set_fovy(&mut self, fovy: N) {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
let old_m22 = self.matrix.m22.clone();
|
||||
self.matrix.m22 = _1 / (fovy / _2).tan();
|
||||
let old_m22 = self.matrix.m22;
|
||||
self.matrix.m22 = ::one::<N>() / (fovy / ::cast(2.0)).tan();
|
||||
self.matrix.m11 = self.matrix.m11 * (self.matrix.m22 / old_m22);
|
||||
}
|
||||
|
||||
@ -242,18 +230,15 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
/// Updates this projection matrix with new near and far plane offsets of the view frustrum.
|
||||
#[inline]
|
||||
pub fn set_znear_and_zfar(&mut self, znear: N, zfar: N) {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
self.matrix.m33 = (zfar + znear) / (znear - zfar);
|
||||
self.matrix.m34 = zfar * znear * _2 / (znear - zfar);
|
||||
self.matrix.m34 = zfar * znear * ::cast(2.0) / (znear - zfar);
|
||||
}
|
||||
|
||||
/// Projects a point.
|
||||
#[inline]
|
||||
pub fn project_point(&self, p: &Point3<N>) -> Point3<N> {
|
||||
let _1: N = ::one();
|
||||
let inverse_denom = -_1 / p.z;
|
||||
let inverse_denom = -::one::<N>() / p.z;
|
||||
|
||||
Point3::new(
|
||||
self.matrix.m11 * p.x * inverse_denom,
|
||||
self.matrix.m22 * p.y * inverse_denom,
|
||||
@ -264,8 +249,8 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
/// Projects a vector.
|
||||
#[inline]
|
||||
pub fn project_vector(&self, p: &Vector3<N>) -> Vector3<N> {
|
||||
let _1: N = ::one();
|
||||
let inverse_denom = -_1 / p.z;
|
||||
let inverse_denom = -::one::<N>() / p.z;
|
||||
|
||||
Vector3::new(
|
||||
self.matrix.m11 * p.x * inverse_denom,
|
||||
self.matrix.m22 * p.y * inverse_denom,
|
||||
@ -274,11 +259,11 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> PerspectiveMatrix3<N> {
|
||||
impl<N: BaseFloat> PerspectiveMatrix3<N> {
|
||||
/// Returns the 4D matrix (using homogeneous coordinates) of this projection.
|
||||
#[inline]
|
||||
pub fn to_matrix<'a>(&'a self) -> Matrix4<N> {
|
||||
self.matrix.clone()
|
||||
pub fn to_matrix(&self) -> Matrix4<N> {
|
||||
self.matrix
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,38 +27,9 @@ pub struct Point1<N> {
|
||||
pub x: N
|
||||
}
|
||||
|
||||
new_impl!(Point1, x);
|
||||
origin_impl!(Point1, x);
|
||||
pord_impl!(Point1, x,);
|
||||
scalar_mul_impl!(Point1, x);
|
||||
scalar_div_impl!(Point1, x);
|
||||
scalar_add_impl!(Point1, x);
|
||||
scalar_sub_impl!(Point1, x);
|
||||
vec_cast_impl!(Point1, x);
|
||||
conversion_impl!(Point1, 1);
|
||||
index_impl!(Point1);
|
||||
indexable_impl!(Point1, 1);
|
||||
at_fast_impl!(Point1, 1);
|
||||
repeat_impl!(Point1, val, x);
|
||||
dim_impl!(Point1, 1);
|
||||
container_impl!(Point1);
|
||||
point_as_vec_impl!(Point1, Vector1, x);
|
||||
point_sub_impl!(Point1, Vector1);
|
||||
neg_impl!(Point1, x);
|
||||
point_add_vec_impl!(Point1, Vector1, x);
|
||||
point_sub_vec_impl!(Point1, Vector1, x);
|
||||
approx_eq_impl!(Point1, x);
|
||||
point_impl!(Point1, Vector1, Point2, y | x);
|
||||
vectorlike_impl!(Point1, 1, x);
|
||||
from_iterator_impl!(Point1, iterator);
|
||||
bounded_impl!(Point1, x);
|
||||
axpy_impl!(Point1, x);
|
||||
iterable_impl!(Point1, 1);
|
||||
iterable_mut_impl!(Point1, 1);
|
||||
point_to_homogeneous_impl!(Point1, Point2, y, x);
|
||||
point_from_homogeneous_impl!(Point1, Point2, y, x);
|
||||
num_float_point_impl!(Point1, Vector1);
|
||||
arbitrary_point_impl!(Point1, x);
|
||||
rand_impl!(Point1, x);
|
||||
point_display_impl!(Point1);
|
||||
|
||||
/// Point of dimension 2.
|
||||
///
|
||||
@ -73,38 +44,9 @@ pub struct Point2<N> {
|
||||
pub y: N
|
||||
}
|
||||
|
||||
new_impl!(Point2, x, y);
|
||||
origin_impl!(Point2, x, y);
|
||||
pord_impl!(Point2, x, y);
|
||||
scalar_mul_impl!(Point2, x, y);
|
||||
scalar_div_impl!(Point2, x, y);
|
||||
scalar_add_impl!(Point2, x, y);
|
||||
scalar_sub_impl!(Point2, x, y);
|
||||
vec_cast_impl!(Point2, x, y);
|
||||
conversion_impl!(Point2, 2);
|
||||
index_impl!(Point2);
|
||||
indexable_impl!(Point2, 2);
|
||||
at_fast_impl!(Point2, 2);
|
||||
repeat_impl!(Point2, val, x, y);
|
||||
dim_impl!(Point2, 2);
|
||||
container_impl!(Point2);
|
||||
point_as_vec_impl!(Point2, Vector2, x, y);
|
||||
point_sub_impl!(Point2, Vector2);
|
||||
neg_impl!(Point2, x, y);
|
||||
point_add_vec_impl!(Point2, Vector2, x, y);
|
||||
point_sub_vec_impl!(Point2, Vector2, x, y);
|
||||
approx_eq_impl!(Point2, x, y);
|
||||
point_impl!(Point2, Vector2, Point3, z | x, y);
|
||||
vectorlike_impl!(Point2, 2, x, y);
|
||||
from_iterator_impl!(Point2, iterator, iterator);
|
||||
bounded_impl!(Point2, x, y);
|
||||
axpy_impl!(Point2, x, y);
|
||||
iterable_impl!(Point2, 2);
|
||||
iterable_mut_impl!(Point2, 2);
|
||||
point_to_homogeneous_impl!(Point2, Point3, z, x, y);
|
||||
point_from_homogeneous_impl!(Point2, Point3, z, x, y);
|
||||
num_float_point_impl!(Point2, Vector2);
|
||||
arbitrary_point_impl!(Point2, x, y);
|
||||
rand_impl!(Point2, x, y);
|
||||
point_display_impl!(Point2);
|
||||
|
||||
/// Point of dimension 3.
|
||||
///
|
||||
@ -121,38 +63,9 @@ pub struct Point3<N> {
|
||||
pub z: N
|
||||
}
|
||||
|
||||
new_impl!(Point3, x, y, z);
|
||||
origin_impl!(Point3, x, y, z);
|
||||
pord_impl!(Point3, x, y, z);
|
||||
scalar_mul_impl!(Point3, x, y, z);
|
||||
scalar_div_impl!(Point3, x, y, z);
|
||||
scalar_add_impl!(Point3, x, y, z);
|
||||
scalar_sub_impl!(Point3, x, y, z);
|
||||
vec_cast_impl!(Point3, x, y, z);
|
||||
conversion_impl!(Point3, 3);
|
||||
index_impl!(Point3);
|
||||
indexable_impl!(Point3, 3);
|
||||
at_fast_impl!(Point3, 3);
|
||||
repeat_impl!(Point3, val, x, y, z);
|
||||
dim_impl!(Point3, 3);
|
||||
container_impl!(Point3);
|
||||
point_as_vec_impl!(Point3, Vector3, x, y, z);
|
||||
point_sub_impl!(Point3, Vector3);
|
||||
neg_impl!(Point3, x, y, z);
|
||||
point_add_vec_impl!(Point3, Vector3, x, y, z);
|
||||
point_sub_vec_impl!(Point3, Vector3, x, y, z);
|
||||
approx_eq_impl!(Point3, x, y, z);
|
||||
point_impl!(Point3, Vector3, Point4, w | x, y, z);
|
||||
vectorlike_impl!(Point3, 3, x, y, z);
|
||||
from_iterator_impl!(Point3, iterator, iterator, iterator);
|
||||
bounded_impl!(Point3, x, y, z);
|
||||
axpy_impl!(Point3, x, y, z);
|
||||
iterable_impl!(Point3, 3);
|
||||
iterable_mut_impl!(Point3, 3);
|
||||
point_to_homogeneous_impl!(Point3, Point4, w, x, y, z);
|
||||
point_from_homogeneous_impl!(Point3, Point4, w, x, y, z);
|
||||
num_float_point_impl!(Point3, Vector3);
|
||||
arbitrary_point_impl!(Point3, x, y, z);
|
||||
rand_impl!(Point3, x, y, z);
|
||||
point_display_impl!(Point3);
|
||||
|
||||
/// Point of dimension 4.
|
||||
///
|
||||
@ -171,38 +84,9 @@ pub struct Point4<N> {
|
||||
pub w: N
|
||||
}
|
||||
|
||||
new_impl!(Point4, x, y, z, w);
|
||||
origin_impl!(Point4, x, y, z, w);
|
||||
pord_impl!(Point4, x, y, z, w);
|
||||
scalar_mul_impl!(Point4, x, y, z, w);
|
||||
scalar_div_impl!(Point4, x, y, z, w);
|
||||
scalar_add_impl!(Point4, x, y, z, w);
|
||||
scalar_sub_impl!(Point4, x, y, z, w);
|
||||
vec_cast_impl!(Point4, x, y, z, w);
|
||||
conversion_impl!(Point4, 4);
|
||||
index_impl!(Point4);
|
||||
indexable_impl!(Point4, 4);
|
||||
at_fast_impl!(Point4, 4);
|
||||
repeat_impl!(Point4, val, x, y, z, w);
|
||||
dim_impl!(Point4, 4);
|
||||
container_impl!(Point4);
|
||||
point_as_vec_impl!(Point4, Vector4, x, y, z, w);
|
||||
point_sub_impl!(Point4, Vector4);
|
||||
neg_impl!(Point4, x, y, z, w);
|
||||
point_add_vec_impl!(Point4, Vector4, x, y, z, w);
|
||||
point_sub_vec_impl!(Point4, Vector4, x, y, z, w);
|
||||
approx_eq_impl!(Point4, x, y, z, w);
|
||||
point_impl!(Point4, Vector4, Point5, a | x, y, z, w);
|
||||
vectorlike_impl!(Point4, 4, x, y, z, w);
|
||||
from_iterator_impl!(Point4, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Point4, x, y, z, w);
|
||||
axpy_impl!(Point4, x, y, z, w);
|
||||
iterable_impl!(Point4, 4);
|
||||
iterable_mut_impl!(Point4, 4);
|
||||
point_to_homogeneous_impl!(Point4, Point5, a, x, y, z, w);
|
||||
point_from_homogeneous_impl!(Point4, Point5, a, x, y, z, w);
|
||||
num_float_point_impl!(Point4, Vector4);
|
||||
arbitrary_point_impl!(Point4, x, y, z, w);
|
||||
rand_impl!(Point4, x, y, z, w);
|
||||
point_display_impl!(Point4);
|
||||
|
||||
/// Point of dimension 5.
|
||||
///
|
||||
@ -223,38 +107,9 @@ pub struct Point5<N> {
|
||||
pub a: N
|
||||
}
|
||||
|
||||
new_impl!(Point5, x, y, z, w, a);
|
||||
origin_impl!(Point5, x, y, z, w, a);
|
||||
pord_impl!(Point5, x, y, z, w, a);
|
||||
scalar_mul_impl!(Point5, x, y, z, w, a);
|
||||
scalar_div_impl!(Point5, x, y, z, w, a);
|
||||
scalar_add_impl!(Point5, x, y, z, w, a);
|
||||
scalar_sub_impl!(Point5, x, y, z, w, a);
|
||||
vec_cast_impl!(Point5, x, y, z, w, a);
|
||||
conversion_impl!(Point5, 5);
|
||||
index_impl!(Point5);
|
||||
indexable_impl!(Point5, 5);
|
||||
at_fast_impl!(Point5, 5);
|
||||
repeat_impl!(Point5, val, x, y, z, w, a);
|
||||
dim_impl!(Point5, 5);
|
||||
container_impl!(Point5);
|
||||
point_as_vec_impl!(Point5, Vector5, x, y, z, w, a);
|
||||
point_sub_impl!(Point5, Vector5);
|
||||
neg_impl!(Point5, x, y, z, w, a);
|
||||
point_add_vec_impl!(Point5, Vector5, x, y, z, w, a);
|
||||
point_sub_vec_impl!(Point5, Vector5, x, y, z, w, a);
|
||||
approx_eq_impl!(Point5, x, y, z, w, a);
|
||||
point_impl!(Point5, Vector5, Point6, b | x, y, z, w, a);
|
||||
vectorlike_impl!(Point5, 5, x, y, z, w, a);
|
||||
from_iterator_impl!(Point5, iterator, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Point5, x, y, z, w, a);
|
||||
axpy_impl!(Point5, x, y, z, w, a);
|
||||
iterable_impl!(Point5, 5);
|
||||
iterable_mut_impl!(Point5, 5);
|
||||
point_to_homogeneous_impl!(Point5, Point6, b, x, y, z, w, a);
|
||||
point_from_homogeneous_impl!(Point5, Point6, b, x, y, z, w, a);
|
||||
num_float_point_impl!(Point5, Vector5);
|
||||
arbitrary_point_impl!(Point5, x, y, z, w, a);
|
||||
rand_impl!(Point5, x, y, z, w, a);
|
||||
point_display_impl!(Point5);
|
||||
|
||||
/// Point of dimension 6.
|
||||
///
|
||||
@ -277,33 +132,6 @@ pub struct Point6<N> {
|
||||
pub b: N
|
||||
}
|
||||
|
||||
new_impl!(Point6, x, y, z, w, a, b);
|
||||
origin_impl!(Point6, x, y, z, w, a, b);
|
||||
pord_impl!(Point6, x, y, z, w, a, b);
|
||||
scalar_mul_impl!(Point6, x, y, z, w, a, b);
|
||||
scalar_div_impl!(Point6, x, y, z, w, a, b);
|
||||
scalar_add_impl!(Point6, x, y, z, w, a, b);
|
||||
scalar_sub_impl!(Point6, x, y, z, w, a, b);
|
||||
vec_cast_impl!(Point6, x, y, z, w, a, b);
|
||||
conversion_impl!(Point6, 6);
|
||||
index_impl!(Point6);
|
||||
indexable_impl!(Point6, 6);
|
||||
at_fast_impl!(Point6, 6);
|
||||
repeat_impl!(Point6, val, x, y, z, w, a, b);
|
||||
dim_impl!(Point6, 6);
|
||||
container_impl!(Point6);
|
||||
point_as_vec_impl!(Point6, Vector6, x, y, z, w, a, b);
|
||||
point_sub_impl!(Point6, Vector6);
|
||||
neg_impl!(Point6, x, y, z, w, a, b);
|
||||
point_add_vec_impl!(Point6, Vector6, x, y, z, w, a, b);
|
||||
point_sub_vec_impl!(Point6, Vector6, x, y, z, w, a, b);
|
||||
approx_eq_impl!(Point6, x, y, z, w, a, b);
|
||||
point_impl!(Point6, Vector6 | x, y, z, w, a, b);
|
||||
vectorlike_impl!(Point6, 6, x, y, z, w, a, b);
|
||||
from_iterator_impl!(Point6, iterator, iterator, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Point6, x, y, z, w, a, b);
|
||||
axpy_impl!(Point6, x, y, z, w, a, b);
|
||||
iterable_impl!(Point6, 6);
|
||||
iterable_mut_impl!(Point6, 6);
|
||||
num_float_point_impl!(Point6, Vector6);
|
||||
arbitrary_point_impl!(Point6, x, y, z, w, a, b);
|
||||
rand_impl!(Point6, x, y, z, w, a, b);
|
||||
point_display_impl!(Point6);
|
||||
|
@ -1,7 +1,13 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! origin_impl(
|
||||
($t: ident, $($compN: ident),+) => (
|
||||
macro_rules! point_impl(
|
||||
($t: ident, $tv: ident | $($compN: ident),+) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Origin.
|
||||
*
|
||||
*/
|
||||
impl<N: Zero> Origin for $t<N> {
|
||||
#[inline]
|
||||
fn origin() -> $t<N> {
|
||||
@ -15,11 +21,13 @@ macro_rules! origin_impl(
|
||||
$(self.$compN.is_zero() )&&+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_sub_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Point - Point
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Sub<N, Output = N>> Sub<$t<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
@ -28,11 +36,13 @@ macro_rules! point_sub_impl(
|
||||
*self.as_vector() - *right.as_vector()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_add_vec_impl(
|
||||
($t: ident, $tv: ident, $($compN: ident),+) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Point + Vector
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Add<N, Output = N>> Add<$tv<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
@ -48,11 +58,13 @@ macro_rules! point_add_vec_impl(
|
||||
$( self.$compN += right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_sub_vec_impl(
|
||||
($t: ident, $tv: ident, $($compN: ident),+) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Point - Vector
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Sub<N, Output = N>> Sub<$tv<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
@ -68,11 +80,14 @@ macro_rules! point_sub_vec_impl(
|
||||
$( self.$compN -= right.$compN; )+
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_as_vec_impl(
|
||||
($t: ident, $tv: ident, $($compN: ident),+) => (
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Point as vector.
|
||||
*
|
||||
*/
|
||||
impl<N> $t<N> {
|
||||
/// Converts this point to its associated vector.
|
||||
#[inline]
|
||||
@ -84,7 +99,7 @@ macro_rules! point_as_vec_impl(
|
||||
|
||||
/// Converts a reference to this point to a reference to its associated vector.
|
||||
#[inline]
|
||||
pub fn as_vector<'a>(&'a self) -> &'a $tv<N> {
|
||||
pub fn as_vector(&self) -> &$tv<N> {
|
||||
unsafe {
|
||||
mem::transmute(self)
|
||||
}
|
||||
@ -105,7 +120,7 @@ macro_rules! point_as_vec_impl(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_vector<'a>(&'a self) -> &'a $tv<N> {
|
||||
fn as_vector(&self) -> &$tv<N> {
|
||||
self.as_vector()
|
||||
}
|
||||
|
||||
@ -114,40 +129,14 @@ macro_rules! point_as_vec_impl(
|
||||
self.set_coords(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_to_homogeneous_impl(
|
||||
($t: ident, $t2: ident, $extra: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + One + Zero> ToHomogeneous<$t2<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $t2<N> {
|
||||
let mut res: $t2<N> = Origin::origin();
|
||||
|
||||
$( res.$compN = self.$compN; )+
|
||||
res.$extra = ::one();
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_from_homogeneous_impl(
|
||||
($t: ident, $t2: ident, $extra: ident, $($compN: ident),+) => (
|
||||
impl<N: Copy + Div<N, Output = N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N> {
|
||||
fn from(v: &$t2<N>) -> $t<N> {
|
||||
let mut res: $t<N> = Origin::origin();
|
||||
|
||||
$( res.$compN = v.$compN / v.$extra; )+
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! num_float_point_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
/*
|
||||
*
|
||||
* NumPoint / FloatPoint
|
||||
*
|
||||
*/
|
||||
impl<N> NumPoint<N> for $t<N>
|
||||
where N: BaseNum {
|
||||
}
|
||||
@ -155,25 +144,13 @@ macro_rules! num_float_point_impl(
|
||||
impl<N> FloatPoint<N> for $t<N>
|
||||
where N: BaseFloat + ApproxEq<N> {
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! arbitrary_point_impl(
|
||||
($t: ident, $($compN: ident),*) => (
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary> Arbitrary for $t<N> {
|
||||
#[inline]
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t {
|
||||
$($compN: Arbitrary::arbitrary(g),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_display_impl(
|
||||
($t: ident) => (
|
||||
/*
|
||||
*
|
||||
* Display
|
||||
*
|
||||
*/
|
||||
impl<N: fmt::Display> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// FIXME: differenciate them from vectors ?
|
||||
@ -190,5 +167,34 @@ macro_rules! point_display_impl(
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
);
|
||||
($t: ident, $tv: ident, $th: ident, $comp_extra: ident | $($compN: ident),+) => (
|
||||
point_impl!($t, $tv | $($compN),+);
|
||||
|
||||
/*
|
||||
*
|
||||
* ToHomogeneous / FromHomogeneous
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + One + Zero> ToHomogeneous<$th<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $th<N> {
|
||||
let mut res: $th<N> = Origin::origin();
|
||||
|
||||
$( res.$compN = self.$compN; )+
|
||||
res.$comp_extra = ::one();
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Div<N, Output = N> + One + Zero> FromHomogeneous<$th<N>> for $t<N> {
|
||||
fn from(v: &$th<N>) -> $t<N> {
|
||||
let mut res: $t<N> = Origin::origin();
|
||||
|
||||
$( res.$compN = v.$compN / v.$comp_extra; )+
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -7,7 +7,7 @@ use std::ops::{Add, Sub, Mul, Div, Neg, AddAssign, SubAssign, MulAssign, DivAssi
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
use structs::{Vector3, Point3, Rotation3, Matrix3};
|
||||
use structs::{Vector3, Point3, Rotation3, Matrix3, Unit};
|
||||
use traits::operations::{ApproxEq, Inverse, PartialOrder, PartialOrdering, Axpy};
|
||||
use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dimension, Shape, BaseFloat, BaseNum,
|
||||
Bounded, Repeat};
|
||||
@ -31,35 +31,21 @@ pub struct Quaternion<N> {
|
||||
pub k: N
|
||||
}
|
||||
|
||||
impl<N> Quaternion<N> {
|
||||
/// Creates a new quaternion from its components.
|
||||
#[inline]
|
||||
pub fn new(w: N, i: N, j: N, k: N) -> Quaternion<N> {
|
||||
Quaternion {
|
||||
w: w,
|
||||
i: i,
|
||||
j: j,
|
||||
k: k
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy> Quaternion<N> {
|
||||
/// The vector part `(i, j, k)` of this quaternion.
|
||||
#[inline]
|
||||
pub fn vector<'a>(&'a self) -> &'a Vector3<N> {
|
||||
// FIXME: do this require a `repr(C)` ?
|
||||
unsafe {
|
||||
mem::transmute(&self.i)
|
||||
}
|
||||
pub fn vector(&self) -> &Vector3<N> {
|
||||
unsafe { mem::transmute(&self.i) }
|
||||
}
|
||||
|
||||
/// The scalar part `w` of this quaternion.
|
||||
#[inline]
|
||||
pub fn scalar<'a>(&'a self) -> &'a N {
|
||||
&self.w
|
||||
pub fn scalar(&self) -> N {
|
||||
self.w
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<Output = N> + Copy> Quaternion<N> {
|
||||
impl<N: BaseNum + Neg<Output = N>> Quaternion<N> {
|
||||
/// Compute the conjugate of this quaternion.
|
||||
#[inline]
|
||||
pub fn conjugate(&self) -> Quaternion<N> {
|
||||
@ -75,7 +61,46 @@ impl<N: Neg<Output = N> + Copy> Quaternion<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + ApproxEq<N>> Inverse for Quaternion<N> {
|
||||
impl<N: BaseFloat> Quaternion<N> {
|
||||
/// Creates a new quaternion from its scalar and vector parts.
|
||||
pub fn from_parts(scalar: N, vector: Vector3<N>) -> Quaternion<N> {
|
||||
Quaternion::new(scalar, vector.x, vector.y, vector.z)
|
||||
}
|
||||
|
||||
/// Creates a new quaternion from its polar decomposition.
|
||||
///
|
||||
/// Note that `axis` is assumed to be a unit vector.
|
||||
pub fn from_polar_decomposition(scale: N, theta: N, axis: Unit<Vector3<N>>)
|
||||
-> Quaternion<N> {
|
||||
let rot = UnitQuaternion::from_axisangle(axis, theta * ::cast(2.0));
|
||||
|
||||
rot.unwrap() * scale
|
||||
}
|
||||
|
||||
/// The polar decomposition of this quaternion.
|
||||
///
|
||||
/// Returns, from left to right: the quaternion norm, the half rotation angle, the rotation
|
||||
/// axis. If the rotation angle is zero, the rotation axis is set to the `y` axis.
|
||||
pub fn polar_decomposition(&self) -> (N, N, Unit<Vector3<N>>) {
|
||||
let default_axis = Unit::from_unit_value_unchecked(Vector3::y());
|
||||
|
||||
if let Some((q, n)) = Unit::try_new_and_get(*self, ::zero()) {
|
||||
if let Some(axis) = Unit::try_new(self.vector(), ::zero()) {
|
||||
let angle = q.angle() / ::cast(2.0);
|
||||
|
||||
(n, angle, axis)
|
||||
}
|
||||
else {
|
||||
(n, ::zero(), default_axis)
|
||||
}
|
||||
}
|
||||
else {
|
||||
(::zero(), ::zero(), default_axis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Inverse for Quaternion<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Quaternion<N>> {
|
||||
let mut res = *self;
|
||||
@ -97,17 +122,16 @@ impl<N: BaseFloat + ApproxEq<N>> Inverse for Quaternion<N> {
|
||||
}
|
||||
else {
|
||||
self.conjugate_mut();
|
||||
self.w = self.w / norm_squared;
|
||||
self.i = self.i / norm_squared;
|
||||
self.j = self.j / norm_squared;
|
||||
self.k = self.k / norm_squared;
|
||||
*self /= norm_squared;
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Norm<N> for Quaternion<N> {
|
||||
impl<N: BaseFloat> Norm for Quaternion<N> {
|
||||
type NormType = N;
|
||||
|
||||
#[inline]
|
||||
fn norm_squared(&self) -> N {
|
||||
self.w * self.w + self.i * self.i + self.j * self.j + self.k * self.k
|
||||
@ -115,21 +139,42 @@ impl<N: BaseFloat> Norm<N> for Quaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn normalize(&self) -> Quaternion<N> {
|
||||
let n = self.norm();
|
||||
Quaternion::new(self.w / n, self.i / n, self.j / n, self.k / n)
|
||||
let n = ::norm(self);
|
||||
*self / n
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_mut(&mut self) -> N {
|
||||
let n = Norm::norm(self);
|
||||
|
||||
self.w = self.w / n;
|
||||
self.i = self.i / n;
|
||||
self.j = self.j / n;
|
||||
self.k = self.k / n;
|
||||
let n = ::norm(self);
|
||||
*self /= n;
|
||||
|
||||
n
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_normalize(&self, min_norm: N) -> Option<Quaternion<N>> {
|
||||
let n = ::norm(self);
|
||||
|
||||
if n <= min_norm {
|
||||
None
|
||||
}
|
||||
else {
|
||||
Some(*self / n)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_normalize_mut(&mut self, min_norm: N) -> Option<N> {
|
||||
let n = ::norm(self);
|
||||
|
||||
if n <= min_norm {
|
||||
None
|
||||
}
|
||||
else {
|
||||
*self /= n;
|
||||
Some(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Mul<Quaternion<N>> for Quaternion<N>
|
||||
@ -154,7 +199,7 @@ impl<N> MulAssign<Quaternion<N>> for Quaternion<N>
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N> + BaseFloat> Div<Quaternion<N>> for Quaternion<N> {
|
||||
impl<N: BaseFloat> Div<Quaternion<N>> for Quaternion<N> {
|
||||
type Output = Quaternion<N>;
|
||||
|
||||
#[inline]
|
||||
@ -163,140 +208,162 @@ impl<N: ApproxEq<N> + BaseFloat> Div<Quaternion<N>> for Quaternion<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N> + BaseFloat> DivAssign<Quaternion<N>> for Quaternion<N> {
|
||||
impl<N: BaseFloat> DivAssign<Quaternion<N>> for Quaternion<N> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, right: Quaternion<N>) {
|
||||
*self *= right.inverse().expect("Unable to invert the denominator.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Quaternion<N> {
|
||||
/// Compute the exponential of a quaternion.
|
||||
#[inline]
|
||||
pub fn exp(&self) -> Self {
|
||||
let v = *self.vector();
|
||||
let nn = v.norm_squared();
|
||||
|
||||
if nn.is_zero() {
|
||||
::one()
|
||||
}
|
||||
else {
|
||||
let n = nn.sqrt();
|
||||
let nv = v / n * n.sin();
|
||||
Quaternion::from_parts(n.cos(), nv) * self.scalar().exp()
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the natural logarithm of a quaternion.
|
||||
#[inline]
|
||||
pub fn ln(&self) -> Self {
|
||||
let n = self.norm();
|
||||
let v = self.vector();
|
||||
let s = self.scalar();
|
||||
|
||||
Quaternion::from_parts(n.ln(), v.normalize() * (s / n).acos())
|
||||
}
|
||||
|
||||
/// Raise the quaternion to a given floating power.
|
||||
#[inline]
|
||||
pub fn powf(&self, n: N) -> Self {
|
||||
(self.ln() * n).exp()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> One for Quaternion<T> where T: Copy + One + Zero + Sub<T, Output = T> + Add<T, Output = T> {
|
||||
#[inline]
|
||||
fn one() -> Self {
|
||||
Quaternion::new(T::one(), T::zero(), T::zero(), T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Display> fmt::Display for Quaternion<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Quaternion {} − ({}, {}, {})", self.w, self.i, self.j, self.k)
|
||||
}
|
||||
}
|
||||
|
||||
rand_impl!(Quaternion, w, i, j, k);
|
||||
/// A unit quaternions. May be used to represent a rotation.
|
||||
pub type UnitQuaternion<N> = Unit<Quaternion<N>>;
|
||||
|
||||
|
||||
/// A unit quaternion that can represent a 3D rotation.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct UnitQuaternion<N> {
|
||||
q: Quaternion<N>
|
||||
impl<N> UnitQuaternion<N> {
|
||||
/// The underlying quaternion.
|
||||
///
|
||||
/// Same as `self.as_ref()`.
|
||||
#[inline]
|
||||
pub fn quaternion(&self) -> &Quaternion<N> {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> UnitQuaternion<N> {
|
||||
/// Creates a new unit quaternion from the axis-angle representation of a rotation.
|
||||
/// Creates a new quaternion from a unit vector (the rotation axis) and an angle
|
||||
/// (the rotation angle).
|
||||
#[inline]
|
||||
pub fn new(axisangle: Vector3<N>) -> UnitQuaternion<N> {
|
||||
let sqang = Norm::norm_squared(&axisangle);
|
||||
pub fn from_axisangle(axis: Unit<Vector3<N>>, angle: N) -> UnitQuaternion<N> {
|
||||
let (sang, cang) = (angle / ::cast(2.0)).sin_cos();
|
||||
|
||||
if ::is_zero(&sqang) {
|
||||
::one()
|
||||
}
|
||||
else {
|
||||
let ang = sqang.sqrt();
|
||||
let (s, c) = (ang / Cast::from(2.0)).sin_cos();
|
||||
let q = Quaternion::from_parts(cang, axis.unwrap() * sang);
|
||||
Unit::from_unit_value_unchecked(q)
|
||||
}
|
||||
|
||||
let s_ang = s / ang;
|
||||
|
||||
unsafe {
|
||||
UnitQuaternion::new_with_unit_quaternion(
|
||||
Quaternion::new(
|
||||
c,
|
||||
axisangle.x * s_ang,
|
||||
axisangle.y * s_ang,
|
||||
axisangle.z * s_ang)
|
||||
)
|
||||
}
|
||||
}
|
||||
/// Same as `::from_axisangle` with the axis multiplied with the angle.
|
||||
#[inline]
|
||||
pub fn from_scaled_axis(axis: Vector3<N>) -> UnitQuaternion<N> {
|
||||
let two: N = ::cast(2.0);
|
||||
let q = Quaternion::from_parts(::zero(), axis / two).exp();
|
||||
UnitQuaternion::from_unit_value_unchecked(q)
|
||||
}
|
||||
|
||||
/// Creates a new unit quaternion from a quaternion.
|
||||
///
|
||||
/// The input quaternion will be normalized.
|
||||
#[inline]
|
||||
pub fn new_with_quaternion(q: Quaternion<N>) -> UnitQuaternion<N> {
|
||||
UnitQuaternion { q: q.normalize() }
|
||||
pub fn from_quaternion(q: &Quaternion<N>) -> UnitQuaternion<N> {
|
||||
Unit::new(&q)
|
||||
}
|
||||
|
||||
/// Creates a new unit quaternion from Euler angles.
|
||||
///
|
||||
/// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
|
||||
#[inline]
|
||||
pub fn new_with_euler_angles(roll: N, pitch: N, yaw: N) -> UnitQuaternion<N> {
|
||||
let _0_5: N = Cast::from(0.5);
|
||||
let (sr, cr) = (roll * _0_5).sin_cos();
|
||||
let (sp, cp) = (pitch * _0_5).sin_cos();
|
||||
let (sy, cy) = (yaw * _0_5).sin_cos();
|
||||
pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> UnitQuaternion<N> {
|
||||
let (sr, cr) = (roll * ::cast(0.5)).sin_cos();
|
||||
let (sp, cp) = (pitch * ::cast(0.5)).sin_cos();
|
||||
let (sy, cy) = (yaw * ::cast(0.5)).sin_cos();
|
||||
|
||||
unsafe {
|
||||
UnitQuaternion::new_with_unit_quaternion(
|
||||
Quaternion::new(
|
||||
let q = Quaternion::new(
|
||||
cr * cp * cy + sr * sp * sy,
|
||||
sr * cp * cy - cr * sp * sy,
|
||||
cr * sp * cy + sr * cp * sy,
|
||||
cr * cp * sy - sr * sp * cy)
|
||||
)
|
||||
}
|
||||
cr * cp * sy - sr * sp * cy);
|
||||
|
||||
Unit::from_unit_value_unchecked(q)
|
||||
}
|
||||
|
||||
/// The rotation angle of this unit quaternion.
|
||||
#[inline]
|
||||
pub fn angle(&self) -> N {
|
||||
self.as_ref().scalar().acos() * ::cast(2.0)
|
||||
}
|
||||
|
||||
/// The rotation axis of this unit quaternion or `None` if the rotation is zero.
|
||||
#[inline]
|
||||
pub fn axis(&self) -> Option<Unit<Vector3<N>>> {
|
||||
Unit::try_new(self.as_ref().vector(), ::zero())
|
||||
}
|
||||
|
||||
/// Builds a rotation matrix from this quaternion.
|
||||
pub fn to_rotation_matrix(&self) -> Rotation3<N> {
|
||||
let _2: N = Cast::from(2.0);
|
||||
let ww = self.q.w * self.q.w;
|
||||
let ii = self.q.i * self.q.i;
|
||||
let jj = self.q.j * self.q.j;
|
||||
let kk = self.q.k * self.q.k;
|
||||
let ij = _2 * self.q.i * self.q.j;
|
||||
let wk = _2 * self.q.w * self.q.k;
|
||||
let wj = _2 * self.q.w * self.q.j;
|
||||
let ik = _2 * self.q.i * self.q.k;
|
||||
let jk = _2 * self.q.j * self.q.k;
|
||||
let wi = _2 * self.q.w * self.q.i;
|
||||
let ww = self.as_ref().w * self.as_ref().w;
|
||||
let ii = self.as_ref().i * self.as_ref().i;
|
||||
let jj = self.as_ref().j * self.as_ref().j;
|
||||
let kk = self.as_ref().k * self.as_ref().k;
|
||||
let ij = self.as_ref().i * self.as_ref().j * ::cast(2.0);
|
||||
let wk = self.as_ref().w * self.as_ref().k * ::cast(2.0);
|
||||
let wj = self.as_ref().w * self.as_ref().j * ::cast(2.0);
|
||||
let ik = self.as_ref().i * self.as_ref().k * ::cast(2.0);
|
||||
let jk = self.as_ref().j * self.as_ref().k * ::cast(2.0);
|
||||
let wi = self.as_ref().w * self.as_ref().i * ::cast(2.0);
|
||||
|
||||
unsafe {
|
||||
Rotation3::new_with_matrix(
|
||||
Matrix3::new(
|
||||
ww + ii - jj - kk, ij - wk, wj + ik,
|
||||
wk + ij, ww - ii + jj - kk, jk - wi,
|
||||
ik - wj, wi + jk, ww - ii - jj + kk
|
||||
)
|
||||
Rotation3::from_matrix_unchecked(
|
||||
Matrix3::new(
|
||||
ww + ii - jj - kk, ij - wk, wj + ik,
|
||||
wk + ij, ww - ii + jj - kk, jk - wi,
|
||||
ik - wj, wi + jk, ww - ii - jj + kk
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<N> UnitQuaternion<N> {
|
||||
/// Creates a new unit quaternion from a quaternion.
|
||||
///
|
||||
/// This is unsafe because the input quaternion will not be normalized.
|
||||
#[inline]
|
||||
pub unsafe fn new_with_unit_quaternion(q: Quaternion<N>) -> UnitQuaternion<N> {
|
||||
UnitQuaternion {
|
||||
q: q
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Quaternion` representation of this unit quaternion.
|
||||
#[inline]
|
||||
pub fn quaternion<'a>(&'a self) -> &'a Quaternion<N> {
|
||||
&self.q
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> One for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn one() -> UnitQuaternion<N> {
|
||||
unsafe {
|
||||
UnitQuaternion::new_with_unit_quaternion(Quaternion::new(::one(), ::zero(), ::zero(), ::zero()))
|
||||
}
|
||||
let one = Quaternion::new(::one(), ::zero(), ::zero(), ::zero());
|
||||
UnitQuaternion::from_unit_value_unchecked(one)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Neg<Output = N>> Inverse for UnitQuaternion<N> {
|
||||
impl<N: BaseNum + Neg<Output = N>> Inverse for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<UnitQuaternion<N>> {
|
||||
let mut cpy = *self;
|
||||
@ -307,7 +374,7 @@ impl<N: Copy + Neg<Output = N>> Inverse for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn inverse_mut(&mut self) -> bool {
|
||||
self.q.conjugate_mut();
|
||||
*self = Unit::from_unit_value_unchecked(self.as_ref().conjugate());
|
||||
|
||||
true
|
||||
}
|
||||
@ -316,7 +383,7 @@ impl<N: Copy + Neg<Output = N>> Inverse for UnitQuaternion<N> {
|
||||
impl<N: Rand + BaseFloat> Rand for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> UnitQuaternion<N> {
|
||||
UnitQuaternion::new(rng.gen())
|
||||
UnitQuaternion::new(&rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,28 +400,28 @@ impl<N: ApproxEq<N>> ApproxEq<N> for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &UnitQuaternion<N>, eps: &N) -> bool {
|
||||
ApproxEq::approx_eq_eps(&self.q, &other.q, eps)
|
||||
ApproxEq::approx_eq_eps(self.as_ref(), other.as_ref(), eps)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &UnitQuaternion<N>, ulps: u32) -> bool {
|
||||
ApproxEq::approx_eq_ulps(&self.q, &other.q, ulps)
|
||||
ApproxEq::approx_eq_ulps(self.as_ref(), other.as_ref(), ulps)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + ApproxEq<N>> Div<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
impl<N: BaseFloat> Div<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
type Output = UnitQuaternion<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, other: UnitQuaternion<N>) -> UnitQuaternion<N> {
|
||||
UnitQuaternion { q: self.q / other.q }
|
||||
Unit::from_unit_value_unchecked(self.unwrap() / other.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + ApproxEq<N>> DivAssign<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
impl<N: BaseFloat> DivAssign<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: UnitQuaternion<N>) {
|
||||
self.q /= other.q
|
||||
*self = Unit::from_unit_value_unchecked(*self.as_ref() / *other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,14 +430,14 @@ impl<N: BaseNum> Mul<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: UnitQuaternion<N>) -> UnitQuaternion<N> {
|
||||
UnitQuaternion { q: self.q * right.q }
|
||||
Unit::from_unit_value_unchecked(self.unwrap() * right.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> MulAssign<UnitQuaternion<N>> for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: UnitQuaternion<N>) {
|
||||
self.q *= right.q
|
||||
*self = Unit::from_unit_value_unchecked(*self.as_ref() * *right.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,13 +446,10 @@ impl<N: BaseNum> Mul<Vector3<N>> for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: Vector3<N>) -> Vector3<N> {
|
||||
let _2: N = ::one::<N>() + ::one();
|
||||
let mut t = ::cross(self.q.vector(), &right);
|
||||
t.x = t.x * _2;
|
||||
t.y = t.y * _2;
|
||||
t.z = t.z * _2;
|
||||
let two: N = ::one::<N>() + ::one();
|
||||
let t = ::cross(self.as_ref().vector(), &right) * two;
|
||||
|
||||
Vector3::new(t.x * self.q.w, t.y * self.q.w, t.z * self.q.w) + ::cross(self.q.vector(), &t) + right
|
||||
t * self.as_ref().w + ::cross(self.as_ref().vector(), &t) + right
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,15 +501,11 @@ impl<N: BaseNum + Neg<Output = N>> MulAssign<UnitQuaternion<N>> for Point3<N> {
|
||||
impl<N: BaseFloat> Rotation<Vector3<N>> for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vector3<N> {
|
||||
let _2 = ::one::<N>() + ::one();
|
||||
let mut v = *self.q.vector();
|
||||
let ang = _2 * v.normalize_mut().atan2(self.q.w);
|
||||
|
||||
if ::is_zero(&ang) {
|
||||
::zero()
|
||||
if let Some(v) = self.axis() {
|
||||
v.unwrap() * self.angle()
|
||||
}
|
||||
else {
|
||||
Vector3::new(v.x * ang, v.y * ang, v.z * ang)
|
||||
::zero()
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +521,7 @@ impl<N: BaseFloat> Rotation<Vector3<N>> for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn append_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> {
|
||||
*self * UnitQuaternion::new(*amount)
|
||||
*self * UnitQuaternion::from_scaled_axis(*amount)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -471,12 +531,12 @@ impl<N: BaseFloat> Rotation<Vector3<N>> for UnitQuaternion<N> {
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> {
|
||||
UnitQuaternion::new(*amount) * *self
|
||||
UnitQuaternion::from_scaled_axis(*amount) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, v: Vector3<N>) {
|
||||
*self = UnitQuaternion::new(v)
|
||||
*self = UnitQuaternion::from_scaled_axis(v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -513,16 +573,15 @@ impl<N: BaseNum + Neg<Output = N>> Rotate<Point3<N>> for UnitQuaternion<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + ApproxEq<N>> RotationTo for UnitQuaternion<N> {
|
||||
impl<N: BaseFloat> RotationTo for UnitQuaternion<N> {
|
||||
type AngleType = N;
|
||||
type DeltaRotationType = UnitQuaternion<N>;
|
||||
|
||||
#[inline]
|
||||
fn angle_to(&self, other: &Self) -> N {
|
||||
let delta = self.rotation_to(other);
|
||||
let _2 = ::one::<N>() + ::one();
|
||||
|
||||
_2 * delta.q.vector().norm().atan2(delta.q.w)
|
||||
delta.as_ref().w.acos() * ::cast(2.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -557,42 +616,69 @@ impl<N: BaseNum + Neg<Output = N>> Transform<Point3<N>> for UnitQuaternion<N> {
|
||||
|
||||
impl<N: fmt::Display> fmt::Display for UnitQuaternion<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Unit quaternion {} − ({}, {}, {})", self.q.w, self.q.i, self.q.j, self.q.k)
|
||||
write!(f, "Unit quaternion {} − ({}, {}, {})",
|
||||
self.as_ref().w, self.as_ref().i, self.as_ref().j, self.as_ref().k)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Dimension
|
||||
*
|
||||
*/
|
||||
impl<N> Dimension for UnitQuaternion<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<UnitQuaternion<N>>) -> usize {
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuaternion<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> UnitQuaternion<N> {
|
||||
UnitQuaternion::new(Arbitrary::arbitrary(g))
|
||||
UnitQuaternion::new(&Arbitrary::arbitrary(g))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> UnitQuaternion<N> {
|
||||
/// Compute the exponential of a quaternion.
|
||||
///
|
||||
/// Note that this function yields a `Quaternion<N>` because it looses the unit property.
|
||||
pub fn exp(&self) -> Quaternion<N> {
|
||||
self.as_ref().exp()
|
||||
}
|
||||
|
||||
pord_impl!(Quaternion, w, i, j, k);
|
||||
vec_axis_impl!(Quaternion, w, i, j, k);
|
||||
vec_cast_impl!(Quaternion, w, i, j, k);
|
||||
conversion_impl!(Quaternion, 4);
|
||||
index_impl!(Quaternion);
|
||||
indexable_impl!(Quaternion, 4);
|
||||
at_fast_impl!(Quaternion, 4);
|
||||
repeat_impl!(Quaternion, val, w, i, j, k);
|
||||
dim_impl!(Quaternion, 3);
|
||||
container_impl!(Quaternion);
|
||||
add_impl!(Quaternion, w, i, j, k);
|
||||
sub_impl!(Quaternion, w, i, j, k);
|
||||
scalar_add_impl!(Quaternion, w, i, j, k);
|
||||
scalar_sub_impl!(Quaternion, w, i, j, k);
|
||||
scalar_mul_impl!(Quaternion, w, i, j, k);
|
||||
scalar_div_impl!(Quaternion, w, i, j, k);
|
||||
neg_impl!(Quaternion, w, i, j, k);
|
||||
zero_one_impl!(Quaternion, w, i, j, k);
|
||||
approx_eq_impl!(Quaternion, w, i, j, k);
|
||||
/// Compute the natural logarithm of a quaternion.
|
||||
///
|
||||
/// Note that this function yields a `Quaternion<N>` because it looses the unit property. The
|
||||
/// vector part of the return value corresponds to the axis-angle representation (divided by
|
||||
/// 2.0) of this unit quaternion.
|
||||
pub fn ln(&self) -> Quaternion<N> {
|
||||
if let Some(v) = self.axis() {
|
||||
Quaternion::from_parts(::zero(), v.unwrap() * self.angle())
|
||||
}
|
||||
else {
|
||||
::zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// Raise this unit quaternion to a given floating power.
|
||||
///
|
||||
/// If this unit quaternion represents a rotation by `theta`, then the resulting quaternion
|
||||
/// rotates by `n * theta`.
|
||||
pub fn powf(&self, n: N) -> Self {
|
||||
if let Some(v) = self.axis() {
|
||||
UnitQuaternion::from_axisangle(v, self.angle() * n)
|
||||
}
|
||||
else {
|
||||
::one()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentwise_zero!(Quaternion, w, i, j, k);
|
||||
component_basis_element!(Quaternion, w, i, j, k);
|
||||
pointwise_add!(Quaternion, w, i, j, k);
|
||||
pointwise_sub!(Quaternion, w, i, j, k);
|
||||
from_iterator_impl!(Quaternion, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Quaternion, w, i, j, k);
|
||||
axpy_impl!(Quaternion, w, i, j, k);
|
||||
iterable_impl!(Quaternion, 4);
|
||||
iterable_mut_impl!(Quaternion, 4);
|
||||
arbitrary_impl!(Quaternion, w, i, j, k);
|
||||
|
||||
dim_impl!(UnitQuaternion, 3);
|
||||
vectorlike_impl!(Quaternion, 4, w, i, j, k);
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Rotations matrices.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Mul, Neg, MulAssign, Index};
|
||||
use std::ops::{Mul, MulAssign, Index};
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, RotationTo, Transform,
|
||||
@ -22,21 +22,21 @@ pub struct Rotation2<N> {
|
||||
submatrix: Matrix2<N>
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat + Neg<Output = N>> Rotation2<N> {
|
||||
impl<N: BaseFloat> Rotation2<N> {
|
||||
/// Builds a 2 dimensional rotation matrix from an angle in radian.
|
||||
pub fn new(angle: Vector1<N>) -> Rotation2<N> {
|
||||
let (sia, coa) = angle.x.sin_cos();
|
||||
|
||||
Rotation2 {
|
||||
submatrix: Matrix2::new(coa.clone(), -sia, sia, coa)
|
||||
submatrix: Matrix2::new(coa, -sia, sia, coa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> Rotation<Vector1<N>> for Rotation2<N> {
|
||||
impl<N: BaseFloat> Rotation<Vector1<N>> for Rotation2<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vector1<N> {
|
||||
Vector1::new((-self.submatrix.m12).atan2(self.submatrix.m11.clone()))
|
||||
Vector1::new((-self.submatrix.m12).atan2(self.submatrix.m11))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -51,7 +51,7 @@ impl<N: BaseFloat + Clone> Rotation<Vector1<N>> for Rotation2<N> {
|
||||
|
||||
#[inline]
|
||||
fn append_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> {
|
||||
Rotation2::new(rotation.clone()) * *self
|
||||
Rotation2::new(*rotation) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -61,7 +61,7 @@ impl<N: BaseFloat + Clone> Rotation<Vector1<N>> for Rotation2<N> {
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> {
|
||||
*self * Rotation2::new(rotation.clone())
|
||||
*self * Rotation2::new(*rotation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -105,13 +105,6 @@ impl<N: BaseFloat> AbsoluteRotate<Vector2<N>> for Rotation2<N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + Clone + BaseFloat + Neg<Output = N>> Arbitrary for Rotation2<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Rotation2<N> {
|
||||
Rotation2::new(Arbitrary::arbitrary(g))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 3d rotation
|
||||
@ -124,7 +117,7 @@ pub struct Rotation3<N> {
|
||||
}
|
||||
|
||||
|
||||
impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
impl<N: BaseFloat> Rotation3<N> {
|
||||
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
|
||||
///
|
||||
/// # Arguments
|
||||
@ -137,37 +130,34 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
else {
|
||||
let mut axis = axisangle;
|
||||
let angle = axis.normalize_mut();
|
||||
let _1: N = ::one();
|
||||
let ux = axis.x.clone();
|
||||
let uy = axis.y.clone();
|
||||
let uz = axis.z.clone();
|
||||
let ux = axis.x;
|
||||
let uy = axis.y;
|
||||
let uz = axis.z;
|
||||
let sqx = ux * ux;
|
||||
let sqy = uy * uy;
|
||||
let sqz = uz * uz;
|
||||
let (sin, cos) = angle.sin_cos();
|
||||
let one_m_cos = _1 - cos;
|
||||
let one_m_cos = ::one::<N>() - cos;
|
||||
|
||||
Rotation3 {
|
||||
submatrix: Matrix3::new(
|
||||
(sqx + (_1 - sqx) * cos),
|
||||
(sqx + (::one::<N>() - sqx) * cos),
|
||||
(ux * uy * one_m_cos - uz * sin),
|
||||
(ux * uz * one_m_cos + uy * sin),
|
||||
|
||||
(ux * uy * one_m_cos + uz * sin),
|
||||
(sqy + (_1 - sqy) * cos),
|
||||
(sqy + (::one::<N>() - sqy) * cos),
|
||||
(uy * uz * one_m_cos - ux * sin),
|
||||
|
||||
(ux * uz * one_m_cos - uy * sin),
|
||||
(uy * uz * one_m_cos + ux * sin),
|
||||
(sqz + (_1 - sqz) * cos))
|
||||
(sqz + (::one::<N>() - sqz) * cos))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a rotation matrix from an orthogonal matrix.
|
||||
///
|
||||
/// This is unsafe because the orthogonality of `matrix` is not checked.
|
||||
pub unsafe fn new_with_matrix(matrix: Matrix3<N>) -> Rotation3<N> {
|
||||
pub fn from_matrix_unchecked(matrix: Matrix3<N>) -> Rotation3<N> {
|
||||
Rotation3 {
|
||||
submatrix: matrix
|
||||
}
|
||||
@ -176,24 +166,22 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
/// Creates a new rotation from Euler angles.
|
||||
///
|
||||
/// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
|
||||
pub fn new_with_euler_angles(roll: N, pitch: N, yaw: N) -> Rotation3<N> {
|
||||
pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Rotation3<N> {
|
||||
let (sr, cr) = roll.sin_cos();
|
||||
let (sp, cp) = pitch.sin_cos();
|
||||
let (sy, cy) = yaw.sin_cos();
|
||||
|
||||
unsafe {
|
||||
Rotation3::new_with_matrix(
|
||||
Matrix3::new(
|
||||
cy * cp, cy * sp * sr - sy * cr, cy * sp * cr + sy * sr,
|
||||
sy * cp, sy * sp * sr + cy * cr, sy * sp * cr - cy * sr,
|
||||
-sp, cp * sr, cp * cr
|
||||
Rotation3::from_matrix_unchecked(
|
||||
Matrix3::new(
|
||||
cy * cp, cy * sp * sr - sy * cr, cy * sp * cr + sy * sr,
|
||||
sy * cp, sy * sp * sr + cy * cr, sy * sp * cr - cy * sr,
|
||||
-sp, cp * sr, cp * cr
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
impl<N: BaseFloat> Rotation3<N> {
|
||||
/// Creates a rotation that corresponds to the local frame of an observer standing at the
|
||||
/// origin and looking toward `dir`.
|
||||
///
|
||||
@ -210,12 +198,10 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
let xaxis = Norm::normalize(&Cross::cross(up, &zaxis));
|
||||
let yaxis = Norm::normalize(&Cross::cross(&zaxis, &xaxis));
|
||||
|
||||
unsafe {
|
||||
Rotation3::new_with_matrix(Matrix3::new(
|
||||
xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
|
||||
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
|
||||
xaxis.z , yaxis.z , zaxis.z))
|
||||
}
|
||||
Rotation3::from_matrix_unchecked(Matrix3::new(
|
||||
xaxis.x, yaxis.x, zaxis.x,
|
||||
xaxis.y, yaxis.y, zaxis.y,
|
||||
xaxis.z, yaxis.z, zaxis.z))
|
||||
}
|
||||
|
||||
|
||||
@ -250,17 +236,13 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat + Cast<f64>>
|
||||
Rotation<Vector3<N>> for Rotation3<N> {
|
||||
impl<N: BaseFloat> Rotation<Vector3<N>> for Rotation3<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vector3<N> {
|
||||
let angle = ((self.submatrix.m11 + self.submatrix.m22 + self.submatrix.m33 - ::one()) / Cast::from(2.0)).acos();
|
||||
|
||||
if angle != angle {
|
||||
// FIXME: handle that correctly
|
||||
::zero()
|
||||
}
|
||||
else if ::is_zero(&angle) {
|
||||
if !angle.is_finite() || ::is_zero(&angle) {
|
||||
// FIXME: handle the non-finite case robustly.
|
||||
::zero()
|
||||
}
|
||||
else {
|
||||
@ -296,7 +278,7 @@ Rotation<Vector3<N>> for Rotation3<N> {
|
||||
|
||||
#[inline]
|
||||
fn append_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> {
|
||||
Rotation3::new(axisangle.clone()) * *self
|
||||
Rotation3::new(*axisangle) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -306,7 +288,7 @@ Rotation<Vector3<N>> for Rotation3<N> {
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> {
|
||||
*self * Rotation3::new(axisangle.clone())
|
||||
*self * Rotation3::new(*axisangle)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -331,7 +313,7 @@ impl<N: BaseFloat> RotationTo for Rotation3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Rand + BaseFloat> Rand for Rotation3<N> {
|
||||
impl<N: Rand + BaseFloat> Rand for Rotation3<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Rotation3<N> {
|
||||
Rotation3::new(rng.gen())
|
||||
@ -348,60 +330,13 @@ impl<N: BaseFloat> AbsoluteRotate<Vector3<N>> for Rotation3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + Clone + BaseFloat> Arbitrary for Rotation3<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Rotation3<N> {
|
||||
Rotation3::new(Arbitrary::arbitrary(g))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common implementations.
|
||||
*/
|
||||
|
||||
submat_impl!(Rotation2, Matrix2);
|
||||
rotate_impl!(Rotation2, Vector2, Point2);
|
||||
transform_impl!(Rotation2, Vector2, Point2);
|
||||
rotation_impl!(Rotation2, Matrix2, Vector2, Vector1, Point2, Matrix3);
|
||||
dim_impl!(Rotation2, 2);
|
||||
rotation_mul_rotation_impl!(Rotation2);
|
||||
rotation_mul_vec_impl!(Rotation2, Vector2);
|
||||
vec_mul_rotation_impl!(Rotation2, Vector2);
|
||||
rotation_mul_point_impl!(Rotation2, Point2);
|
||||
point_mul_rotation_impl!(Rotation2, Point2);
|
||||
one_impl!(Rotation2);
|
||||
eye_impl!(Rotation2);
|
||||
rotation_matrix_impl!(Rotation2, Vector2, Vector1);
|
||||
column_impl!(Rotation2, Vector2);
|
||||
row_impl!(Rotation2, Vector2);
|
||||
index_impl!(Rotation2);
|
||||
absolute_impl!(Rotation2, Matrix2);
|
||||
to_homogeneous_impl!(Rotation2, Matrix3);
|
||||
inverse_impl!(Rotation2);
|
||||
transpose_impl!(Rotation2);
|
||||
approx_eq_impl!(Rotation2);
|
||||
diag_impl!(Rotation2, Vector2);
|
||||
rotation_display_impl!(Rotation2);
|
||||
|
||||
submat_impl!(Rotation3, Matrix3);
|
||||
rotate_impl!(Rotation3, Vector3, Point3);
|
||||
transform_impl!(Rotation3, Vector3, Point3);
|
||||
rotation_impl!(Rotation3, Matrix3, Vector3, Vector3, Point3, Matrix4);
|
||||
dim_impl!(Rotation3, 3);
|
||||
rotation_mul_rotation_impl!(Rotation3);
|
||||
rotation_mul_vec_impl!(Rotation3, Vector3);
|
||||
vec_mul_rotation_impl!(Rotation3, Vector3);
|
||||
rotation_mul_point_impl!(Rotation3, Point3);
|
||||
point_mul_rotation_impl!(Rotation3, Point3);
|
||||
one_impl!(Rotation3);
|
||||
eye_impl!(Rotation3);
|
||||
rotation_matrix_impl!(Rotation3, Vector3, Vector3);
|
||||
column_impl!(Rotation3, Vector3);
|
||||
row_impl!(Rotation3, Vector3);
|
||||
index_impl!(Rotation3);
|
||||
absolute_impl!(Rotation3, Matrix3);
|
||||
to_homogeneous_impl!(Rotation3, Matrix4);
|
||||
inverse_impl!(Rotation3);
|
||||
transpose_impl!(Rotation3);
|
||||
approx_eq_impl!(Rotation3);
|
||||
diag_impl!(Rotation3, Vector3);
|
||||
rotation_display_impl!(Rotation3);
|
||||
|
@ -1,87 +1,83 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! submat_impl(
|
||||
($t: ident, $submatrix: ident) => (
|
||||
macro_rules! rotation_impl(
|
||||
($t: ident, $submatrix: ident, $vector: ident, $rotvector: ident, $point: ident, $homogeneous: ident) => (
|
||||
impl<N> $t<N> {
|
||||
/// This rotation's underlying matrix.
|
||||
#[inline]
|
||||
pub fn submatrix<'r>(&'r self) -> &'r $submatrix<N> {
|
||||
pub fn submatrix(&self) -> &$submatrix<N> {
|
||||
&self.submatrix
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotate_impl(
|
||||
($t: ident, $tv: ident, $tp: ident) => (
|
||||
impl<N: BaseNum> Rotate<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotate Vector and Point
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Rotate<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn rotate(&self, v: &$vector<N>) -> $vector<N> {
|
||||
*self * *v
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn inverse_rotate(&self, v: &$vector<N>) -> $vector<N> {
|
||||
*v * *self
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Rotate<$tp<N>> for $t<N> {
|
||||
impl<N: BaseNum> Rotate<$point<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn rotate(&self, p: &$point<N>) -> $point<N> {
|
||||
*self * *p
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_rotate(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn inverse_rotate(&self, p: &$point<N>) -> $point<N> {
|
||||
*p * *self
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! transform_impl(
|
||||
($t: ident, $tv: ident, $tp: ident) => (
|
||||
impl<N: BaseNum> Transform<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Transform Vector and Point
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Transform<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn transform(&self, v: &$vector<N>) -> $vector<N> {
|
||||
self.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
fn inverse_transform(&self, v: &$vector<N>) -> $vector<N> {
|
||||
self.inverse_rotate(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Transform<$tp<N>> for $t<N> {
|
||||
impl<N: BaseNum> Transform<$point<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.rotate(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn inverse_transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.inverse_rotate(p)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_matrix_impl(
|
||||
($t: ident, $tlv: ident, $tav: ident) => (
|
||||
impl<N: Zero + BaseNum + Cast<f64> + BaseFloat> RotationMatrix<N, $tlv<N>, $tav<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotation Matrix
|
||||
*
|
||||
*/
|
||||
impl<N: Zero + BaseNum + Cast<f64> + BaseFloat> RotationMatrix<N, $vector<N>, $rotvector<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
@ -89,22 +85,26 @@ macro_rules! rotation_matrix_impl(
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* One
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t { submatrix: ::one() }
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! eye_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Eye
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Eye for $t<N> {
|
||||
#[inline]
|
||||
fn new_identity(dimension: usize) -> $t<N> {
|
||||
@ -116,27 +116,31 @@ macro_rules! eye_impl(
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! diag_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Copy + Zero> Diagonal<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Diagonal
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Zero> Diagonal<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn from_diagonal(diagonal: &$tv<N>) -> $t<N> {
|
||||
fn from_diagonal(diagonal: &$vector<N>) -> $t<N> {
|
||||
$t { submatrix: Diagonal::from_diagonal(diagonal) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn diagonal(&self) -> $tv<N> {
|
||||
fn diagonal(&self) -> $vector<N> {
|
||||
self.submatrix.diagonal()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_mul_rotation_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotation * Rotation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
@ -152,56 +156,75 @@ macro_rules! rotation_mul_rotation_impl(
|
||||
self.submatrix *= right.submatrix
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_mul_vec_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
/*
|
||||
*
|
||||
* Rotation * Vector
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$vector<N>> for $t<N> {
|
||||
type Output = $vector<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
fn mul(self, right: $vector<N>) -> $vector<N> {
|
||||
self.submatrix * right
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_mul_point_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
rotation_mul_vec_impl!($t, $tv);
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! vec_mul_rotation_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
||||
type Output = $tv<N>;
|
||||
impl<N: BaseNum> Mul<$t<N>> for $vector<N> {
|
||||
type Output = $vector<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $tv<N> {
|
||||
fn mul(self, right: $t<N>) -> $vector<N> {
|
||||
self * right.submatrix
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + BaseNum> MulAssign<$t<N>> for $tv<N> {
|
||||
impl<N: Copy + BaseNum> MulAssign<$t<N>> for $vector<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $t<N>) {
|
||||
*self *= right.submatrix
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! point_mul_rotation_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
vec_mul_rotation_impl!($t, $tv);
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! inverse_impl(
|
||||
($t: ident) => (
|
||||
/*
|
||||
*
|
||||
* Rotation * Point
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$point<N>> for $t<N> {
|
||||
type Output = $point<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $point<N>) -> $point<N> {
|
||||
self.submatrix * right
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Mul<$t<N>> for $point<N> {
|
||||
type Output = $point<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $point<N> {
|
||||
self * right.submatrix
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + BaseNum> MulAssign<$t<N>> for $point<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $t<N>) {
|
||||
*self *= right.submatrix
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Inverse
|
||||
*
|
||||
*/
|
||||
impl<N: Copy> Inverse for $t<N> {
|
||||
#[inline]
|
||||
fn inverse_mut(&mut self) -> bool {
|
||||
@ -217,11 +240,13 @@ macro_rules! inverse_impl(
|
||||
Some(self.transpose())
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! transpose_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Transpose
|
||||
*
|
||||
*/
|
||||
impl<N: Copy> Transpose for $t<N> {
|
||||
#[inline]
|
||||
fn transpose(&self) -> $t<N> {
|
||||
@ -233,51 +258,57 @@ macro_rules! transpose_impl(
|
||||
self.submatrix.transpose_mut()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! row_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Copy + Zero> Row<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Row
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Zero> Row<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn nrows(&self) -> usize {
|
||||
self.submatrix.nrows()
|
||||
}
|
||||
#[inline]
|
||||
fn row(&self, i: usize) -> $tv<N> {
|
||||
fn row(&self, i: usize) -> $vector<N> {
|
||||
self.submatrix.row(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_row(&mut self, i: usize, row: $tv<N>) {
|
||||
fn set_row(&mut self, i: usize, row: $vector<N>) {
|
||||
self.submatrix.set_row(i, row);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! column_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Copy + Zero> Column<$tv<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Column
|
||||
*
|
||||
*/
|
||||
impl<N: Copy + Zero> Column<$vector<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn ncols(&self) -> usize {
|
||||
self.submatrix.ncols()
|
||||
}
|
||||
#[inline]
|
||||
fn column(&self, i: usize) -> $tv<N> {
|
||||
fn column(&self, i: usize) -> $vector<N> {
|
||||
self.submatrix.column(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_column(&mut self, i: usize, column: $tv<N>) {
|
||||
fn set_column(&mut self, i: usize, column: $vector<N>) {
|
||||
self.submatrix.set_column(i, column);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! index_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Index
|
||||
*
|
||||
*/
|
||||
impl<N> Index<(usize, usize)> for $t<N> {
|
||||
type Output = N;
|
||||
|
||||
@ -285,22 +316,26 @@ macro_rules! index_impl(
|
||||
&self.submatrix[i]
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! to_homogeneous_impl(
|
||||
($t: ident, $tm: ident) => (
|
||||
impl<N: BaseNum> ToHomogeneous<$tm<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* ToHomogeneous
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> ToHomogeneous<$homogeneous<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn to_homogeneous(&self) -> $tm<N> {
|
||||
fn to_homogeneous(&self) -> $homogeneous<N> {
|
||||
self.submatrix.to_homogeneous()
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! approx_eq_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* ApproxEq
|
||||
*
|
||||
*/
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
@ -327,22 +362,27 @@ macro_rules! approx_eq_impl(
|
||||
ApproxEq::approx_eq_ulps(&self.submatrix, &other.submatrix, ulps)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! absolute_impl(
|
||||
($t: ident, $tm: ident) => (
|
||||
impl<N: Absolute<N>> Absolute<$tm<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Absolute
|
||||
*
|
||||
*/
|
||||
impl<N: Absolute<N>> Absolute<$submatrix<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn abs(m: &$t<N>) -> $tm<N> {
|
||||
fn abs(m: &$t<N>) -> $submatrix<N> {
|
||||
Absolute::abs(&m.submatrix)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rotation_display_impl(
|
||||
($t: ident) => (
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Display
|
||||
*
|
||||
*/
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let precision = f.precision().unwrap_or(3);
|
||||
@ -352,5 +392,29 @@ macro_rules! rotation_display_impl(
|
||||
writeln!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Arbitrary
|
||||
*
|
||||
*/
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t::new(Arbitrary::arbitrary(g))
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dimension: expr) => (
|
||||
impl<N> Dimension for $t<N> {
|
||||
#[inline]
|
||||
fn dimension(_: Option<$t<N>>) -> usize {
|
||||
$dimension
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -6,7 +6,7 @@ use num::One;
|
||||
use structs::matrix::{Matrix3, Matrix4};
|
||||
use traits::structure::{Dimension, Column, BaseFloat, BaseNum};
|
||||
use traits::operations::{Inverse, ApproxEq};
|
||||
use traits::geometry::{Rotation, Transform, Transformation, Translation, ToHomogeneous};
|
||||
use traits::geometry::{Transform, Transformation, ToHomogeneous};
|
||||
|
||||
use structs::vector::{Vector1, Vector2, Vector3};
|
||||
use structs::point::{Point2, Point3};
|
||||
@ -49,38 +49,9 @@ pub struct Similarity3<N> {
|
||||
pub isometry: Isometry3<N>
|
||||
}
|
||||
|
||||
sim_impl!(Similarity2, Isometry2, Rotation2, Vector2, Vector1);
|
||||
dim_impl!(Similarity2, 2);
|
||||
sim_scale_impl!(Similarity2);
|
||||
sim_one_impl!(Similarity2);
|
||||
sim_mul_sim_impl!(Similarity2);
|
||||
sim_mul_isometry_impl!(Similarity2, Isometry2);
|
||||
sim_mul_rotation_impl!(Similarity2, Rotation2);
|
||||
sim_mul_point_vec_impl!(Similarity2, Point2);
|
||||
sim_mul_point_vec_impl!(Similarity2, Vector2);
|
||||
transformation_impl!(Similarity2);
|
||||
sim_transform_impl!(Similarity2, Point2);
|
||||
sim_inverse_impl!(Similarity2);
|
||||
sim_to_homogeneous_impl!(Similarity2, Matrix3);
|
||||
sim_approx_eq_impl!(Similarity2);
|
||||
sim_rand_impl!(Similarity2);
|
||||
sim_arbitrary_impl!(Similarity2);
|
||||
sim_display_impl!(Similarity2);
|
||||
|
||||
sim_impl!(Similarity3, Isometry3, Rotation3, Vector3, Vector3);
|
||||
similarity_impl!(Similarity2, Isometry2, Rotation2, Vector2, Vector1, Point2, Matrix3);
|
||||
dim_impl!(Similarity2, 2);
|
||||
|
||||
similarity_impl!(Similarity3, Isometry3, Rotation3, Vector3, Vector3, Point3, Matrix4);
|
||||
dim_impl!(Similarity3, 3);
|
||||
sim_scale_impl!(Similarity3);
|
||||
sim_one_impl!(Similarity3);
|
||||
sim_mul_sim_impl!(Similarity3);
|
||||
sim_mul_isometry_impl!(Similarity3, Isometry3);
|
||||
sim_mul_rotation_impl!(Similarity3, Rotation3);
|
||||
sim_mul_point_vec_impl!(Similarity3, Point3);
|
||||
sim_mul_point_vec_impl!(Similarity3, Vector3);
|
||||
transformation_impl!(Similarity3);
|
||||
sim_transform_impl!(Similarity3, Point3);
|
||||
sim_inverse_impl!(Similarity3);
|
||||
sim_to_homogeneous_impl!(Similarity3, Matrix4);
|
||||
sim_approx_eq_impl!(Similarity3);
|
||||
sim_rand_impl!(Similarity3);
|
||||
sim_arbitrary_impl!(Similarity3);
|
||||
sim_display_impl!(Similarity3);
|
||||
|
@ -1,13 +1,22 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! sim_impl(
|
||||
($t: ident, $isometry: ident, $rotation_matrix: ident, $subvector: ident, $subrotvector: ident) => (
|
||||
macro_rules! similarity_impl(
|
||||
($t: ident,
|
||||
$isometry: ident, $rotation_matrix: ident,
|
||||
$vector: ident, $rotvector: ident,
|
||||
$point: ident,
|
||||
$homogeneous_matrix: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/*
|
||||
*
|
||||
* Constructors.
|
||||
*
|
||||
*/
|
||||
/// Creates a new similarity transformation from a vector, an axis-angle rotation, and a scale factor.
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new(translation: $subvector<N>, rotation: $subrotvector<N>, scale: N) -> $t<N> {
|
||||
pub fn new(translation: $vector<N>, rotation: $rotvector<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
@ -20,12 +29,12 @@ macro_rules! sim_impl(
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new_with_rotation_matrix(translation: $subvector<N>, rotation: $rotation_matrix<N>, scale: N) -> $t<N> {
|
||||
pub fn from_rotation_matrix(translation: $vector<N>, rotation: $rotation_matrix<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
scale: scale,
|
||||
isometry: $isometry::new_with_rotation_matrix(translation, rotation)
|
||||
isometry: $isometry::from_rotation_matrix(translation, rotation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +42,7 @@ macro_rules! sim_impl(
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new_with_isometry(isometry: $isometry<N>, scale: N) -> $t<N> {
|
||||
pub fn from_isometry(isometry: $isometry<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
@ -41,13 +50,12 @@ macro_rules! sim_impl(
|
||||
isometry: isometry
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_scale_impl(
|
||||
($t: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/*
|
||||
*
|
||||
* Methods related to scaling.
|
||||
*
|
||||
*/
|
||||
/// The scale factor of this similarity transformation.
|
||||
#[inline]
|
||||
pub fn scale(&self) -> N {
|
||||
@ -72,7 +80,7 @@ macro_rules! sim_scale_impl(
|
||||
#[inline]
|
||||
pub fn append_scale(&self, s: &N) -> $t<N> {
|
||||
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation.");
|
||||
$t::new_with_rotation_matrix(self.isometry.translation * *s, self.isometry.rotation, self.scale * *s)
|
||||
$t::from_rotation_matrix(self.isometry.translation * *s, self.isometry.rotation, self.scale * *s)
|
||||
}
|
||||
|
||||
/// Prepends in-place a scale to this similarity transformation.
|
||||
@ -86,7 +94,7 @@ macro_rules! sim_scale_impl(
|
||||
#[inline]
|
||||
pub fn prepend_scale(&self, s: &N) -> $t<N> {
|
||||
assert!(!s.is_zero(), "A similarity transformation scale must not be zero.");
|
||||
$t::new_with_isometry(self.isometry, self.scale * *s)
|
||||
$t::from_isometry(self.isometry, self.scale * *s)
|
||||
}
|
||||
|
||||
/// Sets the scale of this similarity transformation.
|
||||
@ -96,28 +104,67 @@ macro_rules! sim_scale_impl(
|
||||
self.scale = s
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_one_impl(
|
||||
($t: ident) => (
|
||||
/*
|
||||
*
|
||||
* One Impl.
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new_with_isometry(::one(), ::one())
|
||||
$t::from_isometry(::one(), ::one())
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_sim_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Transformation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Transformation<$t<N>> for $t<N> {
|
||||
fn transformation(&self) -> $t<N> {
|
||||
*self
|
||||
}
|
||||
|
||||
fn inverse_transformation(&self) -> $t<N> {
|
||||
// inversion will never fails
|
||||
Inverse::inverse(self).unwrap()
|
||||
}
|
||||
|
||||
fn append_transformation_mut(&mut self, t: &$t<N>) {
|
||||
*self = *t * *self
|
||||
}
|
||||
|
||||
fn append_transformation(&self, t: &$t<N>) -> $t<N> {
|
||||
*t * *self
|
||||
}
|
||||
|
||||
fn prepend_transformation_mut(&mut self, t: &$t<N>) {
|
||||
*self = *self * *t
|
||||
}
|
||||
|
||||
fn prepend_transformation(&self, t: &$t<N>) -> $t<N> {
|
||||
*self * *t
|
||||
}
|
||||
|
||||
fn set_transformation(&mut self, t: $t<N>) {
|
||||
*self = t
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Similarity × Similarity
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
self.isometry.translation + self.isometry.rotation * (right.isometry.translation * self.scale),
|
||||
self.isometry.rotation * right.isometry.rotation,
|
||||
self.scale * right.scale)
|
||||
@ -132,115 +179,130 @@ macro_rules! sim_mul_sim_impl(
|
||||
self.scale *= right.scale;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_isometry_impl(
|
||||
($t: ident, $ti: ident) => (
|
||||
impl<N: BaseFloat> Mul<$ti<N>> for $t<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* Similarity × Isometry
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Mul<$isometry<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $ti<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
fn mul(self, right: $isometry<N>) -> $t<N> {
|
||||
$t::from_rotation_matrix(
|
||||
self.isometry.translation + self.isometry.rotation * (right.translation * self.scale),
|
||||
self.isometry.rotation * right.rotation,
|
||||
self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> MulAssign<$ti<N>> for $t<N> {
|
||||
impl<N: BaseFloat> MulAssign<$isometry<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $ti<N>) {
|
||||
fn mul_assign(&mut self, right: $isometry<N>) {
|
||||
self.isometry.translation += self.isometry.rotation * (right.translation * self.scale);
|
||||
self.isometry.rotation *= right.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $ti<N> {
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $isometry<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
self.translation + self.rotation * right.isometry.translation,
|
||||
self.rotation * right.isometry.rotation,
|
||||
right.scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_rotation_impl(
|
||||
($t: ident, $tr: ident) => (
|
||||
impl<N: BaseFloat> Mul<$tr<N>> for $t<N> {
|
||||
/*
|
||||
*
|
||||
* Similarity × Rotation
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat> Mul<$rotation_matrix<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tr<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
fn mul(self, right: $rotation_matrix<N>) -> $t<N> {
|
||||
$t::from_rotation_matrix(
|
||||
self.isometry.translation,
|
||||
self.isometry.rotation * right,
|
||||
self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> MulAssign<$tr<N>> for $t<N> {
|
||||
impl<N: BaseFloat> MulAssign<$rotation_matrix<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $tr<N>) {
|
||||
fn mul_assign(&mut self, right: $rotation_matrix<N>) {
|
||||
self.isometry.rotation *= right;
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $tr<N> {
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $rotation_matrix<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotation_matrix(
|
||||
$t::from_rotation_matrix(
|
||||
self * right.isometry.translation,
|
||||
self * right.isometry.rotation,
|
||||
right.scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_point_vec_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
/*
|
||||
*
|
||||
* Similarity × { Point, Vector }
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Mul<$vector<N>> for $t<N> {
|
||||
type Output = $vector<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
fn mul(self, right: $vector<N>) -> $vector<N> {
|
||||
self.isometry * (right * self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Mul<$point<N>> for $t<N> {
|
||||
type Output = $point<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $point<N>) -> $point<N> {
|
||||
self.isometry * (right * self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: there is no viable pre-multiplication definition because of the translation
|
||||
// component.
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_transform_impl(
|
||||
($t: ident, $tp: ident) => (
|
||||
impl<N: BaseNum> Transform<$tp<N>> for $t<N> {
|
||||
/*
|
||||
*
|
||||
* Similarity × Point
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> Transform<$point<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.isometry.transform(&(*p * self.scale))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse_transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
fn inverse_transform(&self, p: &$point<N>) -> $point<N> {
|
||||
self.isometry.inverse_transform(p) / self.scale
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_inverse_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Inverse
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum + Neg<Output = N>> Inverse for $t<N> {
|
||||
#[inline]
|
||||
fn inverse_mut(&mut self) -> bool {
|
||||
@ -263,28 +325,32 @@ macro_rules! sim_inverse_impl(
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_to_homogeneous_impl(
|
||||
($t: ident, $th: ident) => (
|
||||
impl<N: BaseNum> ToHomogeneous<$th<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $th<N> {
|
||||
|
||||
/*
|
||||
*
|
||||
* ToHomogeneous
|
||||
*
|
||||
*/
|
||||
impl<N: BaseNum> ToHomogeneous<$homogeneous_matrix<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $homogeneous_matrix<N> {
|
||||
let mut res = (*self.isometry.rotation.submatrix() * self.scale).to_homogeneous();
|
||||
|
||||
// copy the translation
|
||||
let dimension = Dimension::dimension(None::<$th<N>>);
|
||||
let dimension = Dimension::dimension(None::<$homogeneous_matrix<N>>);
|
||||
|
||||
res.set_column(dimension - 1, self.isometry.translation.as_point().to_homogeneous().to_vector());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_approx_eq_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* ApproxEq
|
||||
*
|
||||
*/
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
@ -308,11 +374,13 @@ macro_rules! sim_approx_eq_impl(
|
||||
ApproxEq::approx_eq_ulps(&self.isometry, &other.isometry, ulps)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_rand_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Rand
|
||||
*
|
||||
*/
|
||||
impl<N: Rand + BaseFloat> Rand for $t<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||
@ -321,28 +389,32 @@ macro_rules! sim_rand_impl(
|
||||
scale = rng.gen();
|
||||
}
|
||||
|
||||
$t::new_with_isometry(rng.gen(), scale)
|
||||
$t::from_isometry(rng.gen(), scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_arbitrary_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Arbitrary
|
||||
*
|
||||
*/
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t::new_with_isometry(
|
||||
$t::from_isometry(
|
||||
Arbitrary::arbitrary(g),
|
||||
Arbitrary::arbitrary(g)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_display_impl(
|
||||
($t: ident) => (
|
||||
|
||||
/*
|
||||
*
|
||||
* Display
|
||||
*
|
||||
*/
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "Similarity transformation {{"));
|
||||
|
@ -3,7 +3,7 @@ use structs::vector::{Vector2, Vector3};
|
||||
use structs::point::{Point2, Point3};
|
||||
use structs::matrix::{Matrix1, Matrix2, Matrix3};
|
||||
use traits::operations::{Inverse, Determinant, ApproxEq};
|
||||
use traits::structure::{Row, Column, BaseNum};
|
||||
use traits::structure::BaseNum;
|
||||
|
||||
// some specializations:
|
||||
impl<N: BaseNum + ApproxEq<N>> Inverse for Matrix1<N> {
|
||||
@ -24,9 +24,8 @@ impl<N: BaseNum + ApproxEq<N>> Inverse for Matrix1<N> {
|
||||
false
|
||||
}
|
||||
else {
|
||||
let _1: N = ::one();
|
||||
self.m11 = ::one::<N>() / Determinant::determinant(self);
|
||||
|
||||
self.m11 = _1 / Determinant::determinant(self);
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -130,85 +129,6 @@ impl<N: BaseNum> Determinant<N> for Matrix3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy> Row<Vector3<N>> for Matrix3<N> {
|
||||
#[inline]
|
||||
fn nrows(&self) -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn row(&self, i: usize) -> Vector3<N> {
|
||||
match i {
|
||||
0 => Vector3::new(self.m11, self.m12, self.m13),
|
||||
1 => Vector3::new(self.m21, self.m22, self.m23),
|
||||
2 => Vector3::new(self.m31, self.m32, self.m33),
|
||||
_ => panic!(format!("Index out of range: 3d matrices do not have {} rows.", i))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_row(&mut self, i: usize, r: Vector3<N>) {
|
||||
match i {
|
||||
0 => {
|
||||
self.m11 = r.x;
|
||||
self.m12 = r.y;
|
||||
self.m13 = r.z;
|
||||
},
|
||||
1 => {
|
||||
self.m21 = r.x;
|
||||
self.m22 = r.y;
|
||||
self.m23 = r.z;
|
||||
},
|
||||
2 => {
|
||||
self.m31 = r.x;
|
||||
self.m32 = r.y;
|
||||
self.m33 = r.z;
|
||||
},
|
||||
_ => panic!(format!("Index out of range: 3d matrices do not have {} rows.", i))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy> Column<Vector3<N>> for Matrix3<N> {
|
||||
#[inline]
|
||||
fn ncols(&self) -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn column(&self, i: usize) -> Vector3<N> {
|
||||
match i {
|
||||
0 => Vector3::new(self.m11, self.m21, self.m31),
|
||||
1 => Vector3::new(self.m12, self.m22, self.m32),
|
||||
2 => Vector3::new(self.m13, self.m23, self.m33),
|
||||
_ => panic!(format!("Index out of range: 3d matrices do not have {} cols.", i))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_column(&mut self, i: usize, r: Vector3<N>) {
|
||||
match i {
|
||||
0 => {
|
||||
self.m11 = r.x;
|
||||
self.m21 = r.y;
|
||||
self.m31 = r.z;
|
||||
},
|
||||
1 => {
|
||||
self.m12 = r.x;
|
||||
self.m22 = r.y;
|
||||
self.m32 = r.z;
|
||||
},
|
||||
2 => {
|
||||
self.m13 = r.x;
|
||||
self.m23 = r.y;
|
||||
self.m33 = r.z;
|
||||
},
|
||||
_ => panic!(format!("Index out of range: 3d matrices do not have {} cols.", i))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Matrix3<N> {
|
||||
type Output = Matrix3<N>;
|
||||
@ -234,7 +154,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Matr
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Matrix2<N> {
|
||||
type Output = Matrix2<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Matrix2<N>) -> Matrix2<N> {
|
||||
Matrix2::new(
|
||||
self.m11 * right.m11 + self.m12 * right.m21,
|
||||
@ -249,7 +169,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Matr
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector3<N>> for Matrix3<N> {
|
||||
type Output = Vector3<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Vector3<N>) -> Vector3<N> {
|
||||
Vector3::new(
|
||||
self.m11 * right.x + self.m12 * right.y + self.m13 * right.z,
|
||||
@ -262,7 +182,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector3<N>> for Matr
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Vector3<N> {
|
||||
type Output = Vector3<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Matrix3<N>) -> Vector3<N> {
|
||||
Vector3::new(
|
||||
self.x * right.m11 + self.y * right.m21 + self.z * right.m31,
|
||||
@ -275,7 +195,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Vect
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Vector2<N> {
|
||||
type Output = Vector2<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Matrix2<N>) -> Vector2<N> {
|
||||
Vector2::new(
|
||||
self.x * right.m11 + self.y * right.m21,
|
||||
@ -287,7 +207,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Vect
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector2<N>> for Matrix2<N> {
|
||||
type Output = Vector2<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Vector2<N>) -> Vector2<N> {
|
||||
Vector2::new(
|
||||
self.m11 * right.x + self.m12 * right.y,
|
||||
@ -299,7 +219,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector2<N>> for Matr
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point3<N>> for Matrix3<N> {
|
||||
type Output = Point3<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Point3<N>) -> Point3<N> {
|
||||
Point3::new(
|
||||
self.m11 * right.x + self.m12 * right.y + self.m13 * right.z,
|
||||
@ -312,7 +232,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point3<N>> for Matri
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Point3<N> {
|
||||
type Output = Point3<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Matrix3<N>) -> Point3<N> {
|
||||
Point3::new(
|
||||
self.x * right.m11 + self.y * right.m21 + self.z * right.m31,
|
||||
@ -325,7 +245,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Poin
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Point2<N> {
|
||||
type Output = Point2<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Matrix2<N>) -> Point2<N> {
|
||||
Point2::new(
|
||||
self.x * right.m11 + self.y * right.m21,
|
||||
@ -337,7 +257,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Poin
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point2<N>> for Matrix2<N> {
|
||||
type Output = Point2<N>;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul(self, right: Point2<N>) -> Point2<N> {
|
||||
Point2::new(
|
||||
self.m11 * right.x + self.m12 * right.y,
|
||||
@ -350,7 +270,7 @@ impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point2<N>> for Matri
|
||||
macro_rules! impl_mul_assign_from_mul(
|
||||
($tleft: ident, $tright: ident) => (
|
||||
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> MulAssign<$tright<N>> for $tleft<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, right: $tright<N>) {
|
||||
// NOTE: there is probably no interesting optimization compared to the not-inplace
|
||||
// operation.
|
||||
|
@ -5,7 +5,7 @@ use traits::structure::Cast;
|
||||
macro_rules! primitive_cast_impl(
|
||||
($from: ty, $to: ty) => (
|
||||
impl Cast<$from> for $to {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn from(t: $from) -> $to {
|
||||
t as $to
|
||||
}
|
||||
|
@ -115,12 +115,12 @@ impl<N: Copy> Row<Vector1<N>> for Vector2<N> {
|
||||
}
|
||||
|
||||
impl<N: One> Basis for Vector1<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn canonical_basis<F: FnMut(Vector1<N>) -> bool>(mut f: F) {
|
||||
f(Vector1::new(::one()));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn orthonormal_subspace_basis<F: FnMut(Vector1<N>) -> bool>(_: &Vector1<N>, _: F) { }
|
||||
|
||||
#[inline]
|
||||
@ -135,7 +135,7 @@ impl<N: One> Basis for Vector1<N> {
|
||||
}
|
||||
|
||||
impl<N: Copy + One + Zero + Neg<Output = N>> Basis for Vector2<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn canonical_basis<F: FnMut(Vector2<N>) -> bool>(mut f: F) {
|
||||
if !f(Vector2::new(::one(), ::zero())) { return };
|
||||
f(Vector2::new(::zero(), ::one()));
|
||||
@ -161,21 +161,21 @@ impl<N: Copy + One + Zero + Neg<Output = N>> Basis for Vector2<N> {
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Basis for Vector3<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn canonical_basis<F: FnMut(Vector3<N>) -> bool>(mut f: F) {
|
||||
if !f(Vector3::new(::one(), ::zero(), ::zero())) { return };
|
||||
if !f(Vector3::new(::zero(), ::one(), ::zero())) { return };
|
||||
f(Vector3::new(::zero(), ::zero(), ::one()));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn orthonormal_subspace_basis<F: FnMut(Vector3<N>) -> bool>(n: &Vector3<N>, mut f: F) {
|
||||
let a =
|
||||
if n.x.abs() > n.y.abs() {
|
||||
Norm::normalize(&Vector3::new(n.z, ::zero(), -n.x))
|
||||
::normalize(&Vector3::new(n.z, ::zero(), -n.x))
|
||||
}
|
||||
else {
|
||||
Norm::normalize(&Vector3::new(::zero(), -n.z, n.y))
|
||||
::normalize(&Vector3::new(::zero(), -n.z, n.y))
|
||||
};
|
||||
|
||||
if !f(Cross::cross(&a, n)) { return };
|
||||
@ -272,14 +272,14 @@ static SAMPLES_3_F64: [Vector3<f64>; 42] = [
|
||||
|
||||
impl<N> UniformSphereSample for Vector1<N>
|
||||
where Vector1<N>: One {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn sample<F: FnMut(Vector1<N>)>(mut f: F) {
|
||||
f(::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Cast<f64> + Copy> UniformSphereSample for Vector2<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn sample<F: FnMut(Vector2<N>)>(mut f: F) {
|
||||
for sample in SAMPLES_2_F64.iter() {
|
||||
f(Cast::from(*sample))
|
||||
@ -288,7 +288,7 @@ impl<N: Cast<f64> + Copy> UniformSphereSample for Vector2<N> {
|
||||
}
|
||||
|
||||
impl<N: Cast<f64> + Copy> UniformSphereSample for Vector3<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn sample<F: FnMut(Vector3<N>)>(mut f: F) {
|
||||
for sample in SAMPLES_3_F64.iter() {
|
||||
f(Cast::from(*sample))
|
||||
@ -297,7 +297,7 @@ impl<N: Cast<f64> + Copy> UniformSphereSample for Vector3<N> {
|
||||
}
|
||||
|
||||
impl<N: Cast<f64> + Copy> UniformSphereSample for Vector4<N> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn sample<F: FnMut(Vector4<N>)>(_: F) {
|
||||
panic!("UniformSphereSample::<Vector4<N>>::sample : Not yet implemented.")
|
||||
// for sample in SAMPLES_3_F32.iter() {
|
||||
|
78
src/structs/unit.rs
Normal file
78
src/structs/unit.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use traits::geometry::Norm;
|
||||
|
||||
|
||||
/// A wrapper that ensures the undelying algebraic entity has a unit norm.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Unit<T> {
|
||||
v: T
|
||||
}
|
||||
|
||||
impl<T: Norm> Unit<T> {
|
||||
/// Normalize the given value and return it wrapped on a `Unit` structure.
|
||||
#[inline]
|
||||
pub fn new(v: &T) -> Self {
|
||||
Unit { v: v.normalize() }
|
||||
}
|
||||
|
||||
/// Attempts to normalize the given value and return it wrapped on a `Unit` structure.
|
||||
///
|
||||
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
||||
#[inline]
|
||||
pub fn try_new(v: &T, min_norm: T::NormType) -> Option<Self> {
|
||||
v.try_normalize(min_norm).map(|v| Unit { v: v })
|
||||
}
|
||||
|
||||
/// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
|
||||
#[inline]
|
||||
pub fn new_and_get(mut v: T) -> (Self, T::NormType) {
|
||||
let n = v.normalize_mut();
|
||||
|
||||
(Unit { v: v }, n)
|
||||
}
|
||||
|
||||
/// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
|
||||
///
|
||||
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
||||
#[inline]
|
||||
pub fn try_new_and_get(mut v: T, min_norm: T::NormType) -> Option<(Self, T::NormType)> {
|
||||
if let Some(n) = v.try_normalize_mut(min_norm) {
|
||||
Some((Unit { v: v }, n))
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalizes this value again. This is useful when repeated computations
|
||||
/// might cause a drift in the norm because of float inaccuracies.
|
||||
///
|
||||
/// Returns the norm beform re-normalization (should be close to `1.0`).
|
||||
#[inline]
|
||||
pub fn renormalize(&mut self) -> T::NormType {
|
||||
self.v.normalize_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Unit<T> {
|
||||
/// Wraps the given value, assuming it is already normalized.
|
||||
///
|
||||
/// This function is not safe because `v` is not verified to be actually normalized.
|
||||
#[inline]
|
||||
pub fn from_unit_value_unchecked(v: T) -> Self {
|
||||
Unit { v: v }
|
||||
}
|
||||
|
||||
/// Retrieves the underlying value.
|
||||
#[inline]
|
||||
pub fn unwrap(self) -> T {
|
||||
self.v
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for Unit<T> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.v
|
||||
}
|
||||
}
|
@ -29,50 +29,14 @@ pub struct Vector1<N> {
|
||||
pub x: N
|
||||
}
|
||||
|
||||
new_impl!(Vector1, x);
|
||||
pord_impl!(Vector1, x,);
|
||||
vec_axis_impl!(Vector1, x);
|
||||
vec_cast_impl!(Vector1, x);
|
||||
conversion_impl!(Vector1, 1);
|
||||
index_impl!(Vector1);
|
||||
indexable_impl!(Vector1, 1);
|
||||
at_fast_impl!(Vector1, 1);
|
||||
repeat_impl!(Vector1, val, x);
|
||||
dim_impl!(Vector1, 1);
|
||||
container_impl!(Vector1);
|
||||
// (specialized); basis_impl!(Vector1, 1);
|
||||
add_impl!(Vector1, x);
|
||||
sub_impl!(Vector1, x);
|
||||
mul_impl!(Vector1, x);
|
||||
div_impl!(Vector1, x);
|
||||
scalar_add_impl!(Vector1, x);
|
||||
scalar_sub_impl!(Vector1, x);
|
||||
scalar_mul_impl!(Vector1, x);
|
||||
scalar_div_impl!(Vector1, x);
|
||||
neg_impl!(Vector1, x);
|
||||
dot_impl!(Vector1, x);
|
||||
translation_impl!(Vector1);
|
||||
norm_impl!(Vector1, x);
|
||||
approx_eq_impl!(Vector1, x);
|
||||
zero_one_impl!(Vector1, x);
|
||||
vector_impl!(Vector1, Point1, x);
|
||||
vectorlike_impl!(Vector1, 1, x);
|
||||
from_iterator_impl!(Vector1, iterator);
|
||||
bounded_impl!(Vector1, x);
|
||||
axpy_impl!(Vector1, x);
|
||||
iterable_impl!(Vector1, 1);
|
||||
iterable_mut_impl!(Vector1, 1);
|
||||
// (specialized); basis_impl!(Vector1, 1);
|
||||
vec_to_homogeneous_impl!(Vector1, Vector2, y, x);
|
||||
vec_from_homogeneous_impl!(Vector1, Vector2, y, x);
|
||||
translate_impl!(Vector1, Point1);
|
||||
rotate_impl!(Vector1);
|
||||
rotate_impl!(Point1);
|
||||
transform_impl!(Vector1, Point1);
|
||||
vec_as_point_impl!(Vector1, Point1, x);
|
||||
num_float_vec_impl!(Vector1);
|
||||
absolute_vec_impl!(Vector1, x);
|
||||
arbitrary_impl!(Vector1, x);
|
||||
rand_impl!(Vector1, x);
|
||||
mean_impl!(Vector1);
|
||||
vec_display_impl!(Vector1);
|
||||
|
||||
|
||||
|
||||
/// Vector of dimension 2.
|
||||
///
|
||||
@ -87,50 +51,14 @@ pub struct Vector2<N> {
|
||||
pub y: N
|
||||
}
|
||||
|
||||
new_impl!(Vector2, x, y);
|
||||
pord_impl!(Vector2, x, y);
|
||||
vec_axis_impl!(Vector2, x, y);
|
||||
vec_cast_impl!(Vector2, x, y);
|
||||
conversion_impl!(Vector2, 2);
|
||||
index_impl!(Vector2);
|
||||
indexable_impl!(Vector2, 2);
|
||||
at_fast_impl!(Vector2, 2);
|
||||
repeat_impl!(Vector2, val, x, y);
|
||||
dim_impl!(Vector2, 2);
|
||||
container_impl!(Vector2);
|
||||
// (specialized); basis_impl!(Vector2, 1);
|
||||
add_impl!(Vector2, x, y);
|
||||
sub_impl!(Vector2, x, y);
|
||||
mul_impl!(Vector2, x, y);
|
||||
div_impl!(Vector2, x, y);
|
||||
scalar_add_impl!(Vector2, x, y);
|
||||
scalar_sub_impl!(Vector2, x, y);
|
||||
scalar_mul_impl!(Vector2, x, y);
|
||||
scalar_div_impl!(Vector2, x, y);
|
||||
neg_impl!(Vector2, x, y);
|
||||
dot_impl!(Vector2, x, y);
|
||||
translation_impl!(Vector2);
|
||||
norm_impl!(Vector2, x, y);
|
||||
approx_eq_impl!(Vector2, x, y);
|
||||
zero_one_impl!(Vector2, x, y);
|
||||
vector_impl!(Vector2, Point2, x, y);
|
||||
vectorlike_impl!(Vector2, 2, x, y);
|
||||
from_iterator_impl!(Vector2, iterator, iterator);
|
||||
bounded_impl!(Vector2, x, y);
|
||||
axpy_impl!(Vector2, x, y);
|
||||
iterable_impl!(Vector2, 2);
|
||||
iterable_mut_impl!(Vector2, 2);
|
||||
// (specialized); basis_impl!(Vector2, 1);
|
||||
vec_to_homogeneous_impl!(Vector2, Vector3, z, x, y);
|
||||
vec_from_homogeneous_impl!(Vector2, Vector3, z, x, y);
|
||||
translate_impl!(Vector2, Point2);
|
||||
rotate_impl!(Vector2);
|
||||
rotate_impl!(Point2);
|
||||
transform_impl!(Vector2, Point2);
|
||||
vec_as_point_impl!(Vector2, Point2, x, y);
|
||||
num_float_vec_impl!(Vector2);
|
||||
absolute_vec_impl!(Vector2, x, y);
|
||||
arbitrary_impl!(Vector2, x, y);
|
||||
rand_impl!(Vector2, x, y);
|
||||
mean_impl!(Vector2);
|
||||
vec_display_impl!(Vector2);
|
||||
|
||||
|
||||
|
||||
/// Vector of dimension 3.
|
||||
///
|
||||
@ -147,50 +75,12 @@ pub struct Vector3<N> {
|
||||
pub z: N
|
||||
}
|
||||
|
||||
new_impl!(Vector3, x, y, z);
|
||||
pord_impl!(Vector3, x, y, z);
|
||||
vec_axis_impl!(Vector3, x, y, z);
|
||||
vec_cast_impl!(Vector3, x, y, z);
|
||||
conversion_impl!(Vector3, 3);
|
||||
index_impl!(Vector3);
|
||||
indexable_impl!(Vector3, 3);
|
||||
at_fast_impl!(Vector3, 3);
|
||||
repeat_impl!(Vector3, val, x, y, z);
|
||||
dim_impl!(Vector3, 3);
|
||||
container_impl!(Vector3);
|
||||
// (specialized); basis_impl!(Vector3, 1);
|
||||
add_impl!(Vector3, x, y, z);
|
||||
sub_impl!(Vector3, x, y, z);
|
||||
mul_impl!(Vector3, x, y, z);
|
||||
div_impl!(Vector3, x, y, z);
|
||||
scalar_add_impl!(Vector3, x, y, z);
|
||||
scalar_sub_impl!(Vector3, x, y, z);
|
||||
scalar_mul_impl!(Vector3, x, y, z);
|
||||
scalar_div_impl!(Vector3, x, y, z);
|
||||
neg_impl!(Vector3, x, y, z);
|
||||
dot_impl!(Vector3, x, y, z);
|
||||
translation_impl!(Vector3);
|
||||
norm_impl!(Vector3, x, y ,z);
|
||||
approx_eq_impl!(Vector3, x, y, z);
|
||||
zero_one_impl!(Vector3, x, y, z);
|
||||
vector_impl!(Vector3, Point3, x, y, z);
|
||||
vectorlike_impl!(Vector3, 3, x, y, z);
|
||||
from_iterator_impl!(Vector3, iterator, iterator, iterator);
|
||||
bounded_impl!(Vector3, x, y, z);
|
||||
axpy_impl!(Vector3, x, y, z);
|
||||
iterable_impl!(Vector3, 3);
|
||||
iterable_mut_impl!(Vector3, 3);
|
||||
// (specialized); basis_impl!(Vector3, 1);
|
||||
vec_to_homogeneous_impl!(Vector3, Vector4, w, x, y, z);
|
||||
vec_from_homogeneous_impl!(Vector3, Vector4, w, x, y, z);
|
||||
translate_impl!(Vector3, Point3);
|
||||
rotate_impl!(Vector3);
|
||||
rotate_impl!(Point3);
|
||||
transform_impl!(Vector3, Point3);
|
||||
vec_as_point_impl!(Vector3, Point3, x, y, z);
|
||||
num_float_vec_impl!(Vector3);
|
||||
absolute_vec_impl!(Vector3, x, y, z);
|
||||
arbitrary_impl!(Vector3, x, y, z);
|
||||
rand_impl!(Vector3, x, y, z);
|
||||
mean_impl!(Vector3);
|
||||
vec_display_impl!(Vector3);
|
||||
|
||||
|
||||
/// Vector of dimension 4.
|
||||
@ -210,50 +100,14 @@ pub struct Vector4<N> {
|
||||
pub w: N
|
||||
}
|
||||
|
||||
new_impl!(Vector4, x, y, z, w);
|
||||
pord_impl!(Vector4, x, y, z, w);
|
||||
vec_axis_impl!(Vector4, x, y, z, w);
|
||||
vec_cast_impl!(Vector4, x, y, z, w);
|
||||
conversion_impl!(Vector4, 4);
|
||||
index_impl!(Vector4);
|
||||
indexable_impl!(Vector4, 4);
|
||||
at_fast_impl!(Vector4, 4);
|
||||
repeat_impl!(Vector4, val, x, y, z, w);
|
||||
dim_impl!(Vector4, 4);
|
||||
container_impl!(Vector4);
|
||||
basis_impl!(Vector4, 4);
|
||||
add_impl!(Vector4, x, y, z, w);
|
||||
sub_impl!(Vector4, x, y, z, w);
|
||||
mul_impl!(Vector4, x, y, z, w);
|
||||
div_impl!(Vector4, x, y, z, w);
|
||||
scalar_add_impl!(Vector4, x, y, z, w);
|
||||
scalar_sub_impl!(Vector4, x, y, z, w);
|
||||
scalar_mul_impl!(Vector4, x, y, z, w);
|
||||
scalar_div_impl!(Vector4, x, y, z, w);
|
||||
neg_impl!(Vector4, x, y, z, w);
|
||||
dot_impl!(Vector4, x, y, z, w);
|
||||
translation_impl!(Vector4);
|
||||
norm_impl!(Vector4, x, y, z, w);
|
||||
approx_eq_impl!(Vector4, x, y, z, w);
|
||||
zero_one_impl!(Vector4, x, y, z, w);
|
||||
vector_impl!(Vector4, Point4, x, y, z, w);
|
||||
vectorlike_impl!(Vector4, 4, x, y, z, w);
|
||||
from_iterator_impl!(Vector4, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Vector4, x, y, z, w);
|
||||
axpy_impl!(Vector4, x, y, z, w);
|
||||
iterable_impl!(Vector4, 4);
|
||||
iterable_mut_impl!(Vector4, 4);
|
||||
basis_impl!(Vector4, 4);
|
||||
vec_to_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w);
|
||||
vec_from_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w);
|
||||
translate_impl!(Vector4, Point4);
|
||||
rotate_impl!(Vector4);
|
||||
rotate_impl!(Point4);
|
||||
transform_impl!(Vector4, Point4);
|
||||
vec_as_point_impl!(Vector4, Point4, x, y, z, w);
|
||||
num_float_vec_impl!(Vector4);
|
||||
absolute_vec_impl!(Vector4, x, y, z, w);
|
||||
arbitrary_impl!(Vector4, x, y, z, w);
|
||||
rand_impl!(Vector4, x, y, z, w);
|
||||
mean_impl!(Vector4);
|
||||
vec_display_impl!(Vector4);
|
||||
|
||||
|
||||
|
||||
/// Vector of dimension 5.
|
||||
///
|
||||
@ -274,50 +128,13 @@ pub struct Vector5<N> {
|
||||
pub a: N
|
||||
}
|
||||
|
||||
new_impl!(Vector5, x, y, z, w, a);
|
||||
pord_impl!(Vector5, x, y, z, w, a);
|
||||
vec_axis_impl!(Vector5, x, y, z, w, a);
|
||||
vec_cast_impl!(Vector5, x, y, z, w, a);
|
||||
conversion_impl!(Vector5, 5);
|
||||
index_impl!(Vector5);
|
||||
indexable_impl!(Vector5, 5);
|
||||
at_fast_impl!(Vector5, 5);
|
||||
repeat_impl!(Vector5, val, x, y, z, w, a);
|
||||
dim_impl!(Vector5, 5);
|
||||
container_impl!(Vector5);
|
||||
basis_impl!(Vector5, 5);
|
||||
add_impl!(Vector5, x, y, z, w, a);
|
||||
sub_impl!(Vector5, x, y, z, w, a);
|
||||
mul_impl!(Vector5, x, y, z, w, a);
|
||||
div_impl!(Vector5, x, y, z, w, a);
|
||||
scalar_add_impl!(Vector5, x, y, z, w, a);
|
||||
scalar_sub_impl!(Vector5, x, y, z, w, a);
|
||||
scalar_mul_impl!(Vector5, x, y, z, w, a);
|
||||
scalar_div_impl!(Vector5, x, y, z, w, a);
|
||||
neg_impl!(Vector5, x, y, z, w, a);
|
||||
dot_impl!(Vector5, x, y, z, w, a);
|
||||
translation_impl!(Vector5);
|
||||
norm_impl!(Vector5, x, y, z, w, a);
|
||||
approx_eq_impl!(Vector5, x, y, z, w, a);
|
||||
zero_one_impl!(Vector5, x, y, z, w, a);
|
||||
vector_impl!(Vector5, Point5, x, y, z, w, a);
|
||||
vectorlike_impl!(Vector5, 5, x, y, z, w, a);
|
||||
from_iterator_impl!(Vector5, iterator, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Vector5, x, y, z, w, a);
|
||||
axpy_impl!(Vector5, x, y, z, w, a);
|
||||
iterable_impl!(Vector5, 5);
|
||||
iterable_mut_impl!(Vector5, 5);
|
||||
basis_impl!(Vector5, 5);
|
||||
vec_to_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a);
|
||||
vec_from_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a);
|
||||
translate_impl!(Vector5, Point5);
|
||||
rotate_impl!(Vector5);
|
||||
rotate_impl!(Point5);
|
||||
transform_impl!(Vector5, Point5);
|
||||
vec_as_point_impl!(Vector5, Point5, x, y, z, w, a);
|
||||
num_float_vec_impl!(Vector5);
|
||||
absolute_vec_impl!(Vector5, x, y, z, w, a);
|
||||
arbitrary_impl!(Vector5, x, y, z, w, a);
|
||||
rand_impl!(Vector5, x, y, z, w, a);
|
||||
mean_impl!(Vector5);
|
||||
vec_display_impl!(Vector5);
|
||||
|
||||
|
||||
/// Vector of dimension 6.
|
||||
///
|
||||
@ -340,45 +157,8 @@ pub struct Vector6<N> {
|
||||
pub b: N
|
||||
}
|
||||
|
||||
new_impl!(Vector6, x, y, z, w, a, b);
|
||||
pord_impl!(Vector6, x, y, z, w, a, b);
|
||||
vec_axis_impl!(Vector6, x, y, z, w, a, b);
|
||||
vec_cast_impl!(Vector6, x, y, z, w, a, b);
|
||||
conversion_impl!(Vector6, 6);
|
||||
index_impl!(Vector6);
|
||||
indexable_impl!(Vector6, 6);
|
||||
at_fast_impl!(Vector6, 6);
|
||||
repeat_impl!(Vector6, val, x, y, z, w, a, b);
|
||||
dim_impl!(Vector6, 6);
|
||||
container_impl!(Vector6);
|
||||
basis_impl!(Vector6, 6);
|
||||
add_impl!(Vector6, x, y, z, w, a, b);
|
||||
sub_impl!(Vector6, x, y, z, w, a, b);
|
||||
mul_impl!(Vector6, x, y, z, w, a, b);
|
||||
div_impl!(Vector6, x, y, z, w, a, b);
|
||||
scalar_add_impl!(Vector6, x, y, z, w, a, b);
|
||||
scalar_sub_impl!(Vector6, x, y, z, w, a, b);
|
||||
scalar_mul_impl!(Vector6, x, y, z, w, a, b);
|
||||
scalar_div_impl!(Vector6, x, y, z, w, a, b);
|
||||
neg_impl!(Vector6, x, y, z, w, a, b);
|
||||
dot_impl!(Vector6, x, y, z, w, a, b);
|
||||
translation_impl!(Vector6);
|
||||
norm_impl!(Vector6, x, y, z, w, a, b);
|
||||
approx_eq_impl!(Vector6, x, y, z, w, a, b);
|
||||
zero_one_impl!(Vector6, x, y, z, w, a, b);
|
||||
vector_impl!(Vector6, Point6, x, y, z, w, a, b);
|
||||
vectorlike_impl!(Vector6, 6, x, y, z, w, a, b);
|
||||
from_iterator_impl!(Vector6, iterator, iterator, iterator, iterator, iterator, iterator);
|
||||
bounded_impl!(Vector6, x, y, z, w, a, b);
|
||||
axpy_impl!(Vector6, x, y, z, w, a, b);
|
||||
iterable_impl!(Vector6, 6);
|
||||
iterable_mut_impl!(Vector6, 6);
|
||||
translate_impl!(Vector6, Point6);
|
||||
rotate_impl!(Vector6);
|
||||
rotate_impl!(Point6);
|
||||
transform_impl!(Vector6, Point6);
|
||||
vec_as_point_impl!(Vector6, Point6, x, y, z, w, a, b);
|
||||
num_float_vec_impl!(Vector6);
|
||||
absolute_vec_impl!(Vector6, x, y, z, w, a, b);
|
||||
arbitrary_impl!(Vector6, x, y, z, w, a, b);
|
||||
rand_impl!(Vector6, x, y, z, w, a, b);
|
||||
mean_impl!(Vector6);
|
||||
vec_display_impl!(Vector6);
|
||||
|
||||
basis_impl!(Vector6, 6);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -93,14 +93,14 @@ macro_rules! vecn_dvec_common_impl(
|
||||
*/
|
||||
impl<N $(, $param : ArrayLength<N>)*> Iterable<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N> {
|
||||
fn iter(&self) -> Iter<N> {
|
||||
self.as_ref().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param : ArrayLength<N>)*> IterableMut<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
|
||||
fn iter_mut(&mut self) -> IterMut<N> {
|
||||
self.as_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
@ -253,6 +253,24 @@ macro_rules! vecn_dvec_common_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Div<$vecn<N $(, $param)*>> for &'a $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
|
||||
self.clone() / right
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Div<N> for &'a $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: N) -> $vecn<N $(, $param)*> {
|
||||
self.clone() / right
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param: ArrayLength<N>)*> DivAssign<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*>
|
||||
where N: Copy + DivAssign<N> + Zero $(, $param : ArrayLength<N>)* {
|
||||
#[inline]
|
||||
@ -495,10 +513,12 @@ macro_rules! vecn_dvec_common_impl(
|
||||
* Norm.
|
||||
*
|
||||
*/
|
||||
impl<N: BaseFloat $(, $param : ArrayLength<N>)*> Norm<N> for $vecn<N $(, $param)*> {
|
||||
impl<N: BaseFloat $(, $param : ArrayLength<N>)*> Norm for $vecn<N $(, $param)*> {
|
||||
type NormType = N;
|
||||
|
||||
#[inline]
|
||||
fn norm_squared(&self) -> N {
|
||||
Dot::dot(self, self)
|
||||
::dot(self, self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -510,13 +530,35 @@ macro_rules! vecn_dvec_common_impl(
|
||||
|
||||
#[inline]
|
||||
fn normalize_mut(&mut self) -> N {
|
||||
let l = Norm::norm(self);
|
||||
let n = ::norm(self);
|
||||
*self /= n;
|
||||
|
||||
for n in self.as_mut().iter_mut() {
|
||||
*n = *n / l;
|
||||
n
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_normalize(&self, min_norm: N) -> Option<$vecn<N $(, $param)*>> {
|
||||
let n = ::norm(self);
|
||||
|
||||
if n <= min_norm {
|
||||
None
|
||||
}
|
||||
else {
|
||||
Some(self / n)
|
||||
}
|
||||
}
|
||||
|
||||
l
|
||||
#[inline]
|
||||
fn try_normalize_mut(&mut self, min_norm: N) -> Option<N> {
|
||||
let n = ::norm(self);
|
||||
|
||||
if n <= min_norm {
|
||||
None
|
||||
}
|
||||
else {
|
||||
*self /= n;
|
||||
Some(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Traits of operations having a well-known or explicit geometric meaning.
|
||||
|
||||
use std::ops::{Neg, Mul};
|
||||
use num::Float;
|
||||
use traits::structure::{BaseFloat, SquareMatrix};
|
||||
|
||||
/// Trait of object which represent a translation, and to wich new translation
|
||||
@ -224,23 +225,41 @@ pub trait Dot<N> {
|
||||
}
|
||||
|
||||
/// Traits of objects having an euclidian norm.
|
||||
pub trait Norm<N: BaseFloat> {
|
||||
pub trait Norm: Sized {
|
||||
/// The scalar type for the norm (i.e. the undelying field).
|
||||
type NormType : BaseFloat;
|
||||
|
||||
/// Computes the norm of `self`.
|
||||
#[inline]
|
||||
fn norm(&self) -> N {
|
||||
fn norm(&self) -> Self::NormType {
|
||||
self.norm_squared().sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared norm of `self`.
|
||||
///
|
||||
/// This is usually faster than computing the norm itself.
|
||||
fn norm_squared(&self) -> N;
|
||||
fn norm_squared(&self) -> Self::NormType;
|
||||
|
||||
/// Gets the normalized version of a copy of `v`.
|
||||
///
|
||||
/// Might return an invalid result if the vector is zero or close to zero.
|
||||
fn normalize(&self) -> Self;
|
||||
|
||||
/// Normalizes `self`.
|
||||
fn normalize_mut(&mut self) -> N;
|
||||
///
|
||||
/// The result might be invalid if the vector is zero or close to zero.
|
||||
fn normalize_mut(&mut self) -> Self::NormType;
|
||||
|
||||
/// Gets the normalized version of a copy of `v` or `None` if the vector has a norm smaller
|
||||
/// or equal to `min_norm`. In particular, `.try_normalize(0.0)` returns `None` if the norm is
|
||||
/// exactly zero.
|
||||
fn try_normalize(&self, min_norm: Self::NormType) -> Option<Self>;
|
||||
|
||||
/// Normalized `v` or does nothing if the vector has a norm smaller
|
||||
/// or equal to `min_norm`.
|
||||
///
|
||||
/// Returns the old norm or `None` if the normalization failed.
|
||||
fn try_normalize_mut(&mut self, min_norm: Self::NormType) -> Option<Self::NormType>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,7 @@ pub use traits::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogene
|
||||
|
||||
pub use traits::structure::{FloatVector, FloatPoint, Basis, Cast, Column, Dimension, Indexable, Iterable,
|
||||
IterableMut, Matrix, SquareMatrix, Row, NumVector, NumPoint, PointAsVector, ColumnSlice,
|
||||
RowSlice, Diagonal, DiagMut, Eye, Repeat, Shape, BaseFloat, BaseNum,
|
||||
RowSlice, Diagonal, DiagonalMut, Eye, Repeat, Shape, BaseFloat, BaseNum,
|
||||
Bounded};
|
||||
|
||||
pub use traits::operations::{Absolute, ApproxEq, Axpy, Covariance, Determinant, Inverse, Mean, Outer, PartialOrder, Transpose,
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Low level operations on vectors and matrices.
|
||||
|
||||
use num::{Float, Signed};
|
||||
use std::{mem, f32, f64};
|
||||
use num::Signed;
|
||||
use std::ops::Mul;
|
||||
use std::cmp::Ordering;
|
||||
use traits::structure::SquareMatrix;
|
||||
@ -136,16 +137,14 @@ pub trait PartialOrder {
|
||||
if v_min.is_not_comparable() || v_max.is_not_comparable() {
|
||||
None
|
||||
}
|
||||
else if v_min.is_lt() {
|
||||
Some(min)
|
||||
}
|
||||
else if v_max.is_gt() {
|
||||
Some(max)
|
||||
}
|
||||
else {
|
||||
if v_min.is_lt() {
|
||||
Some(min)
|
||||
}
|
||||
else if v_max.is_gt() {
|
||||
Some(max)
|
||||
}
|
||||
else {
|
||||
Some(self)
|
||||
}
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,8 +194,8 @@ impl ApproxEq<f32> for f32 {
|
||||
|
||||
// IEEE754 floats are in the same order as 2s complement isizes
|
||||
// so this trick (subtracting the isizes) works.
|
||||
let iself: i32 = unsafe { ::std::mem::transmute(*self) };
|
||||
let iother: i32 = unsafe { ::std::mem::transmute(*other) };
|
||||
let iself: i32 = unsafe { mem::transmute(*self) };
|
||||
let iother: i32 = unsafe { mem::transmute(*other) };
|
||||
|
||||
(iself - iother).abs() < ulps as i32
|
||||
}
|
||||
@ -224,8 +223,8 @@ impl ApproxEq<f64> for f64 {
|
||||
// Otherwise, differing signs should be not-equal, even if within ulps
|
||||
if self.signum() != other.signum() { return false; }
|
||||
|
||||
let iself: i64 = unsafe { ::std::mem::transmute(*self) };
|
||||
let iother: i64 = unsafe { ::std::mem::transmute(*other) };
|
||||
let iself: i64 = unsafe { mem::transmute(*self) };
|
||||
let iother: i64 = unsafe { mem::transmute(*other) };
|
||||
|
||||
(iself - iother).abs() < ulps as i64
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use std::ops::{Add, Sub, Mul, Div, Rem,
|
||||
AddAssign, SubAssign, MulAssign, DivAssign, RemAssign,
|
||||
Index, IndexMut, Neg};
|
||||
use num::{Float, Zero, One};
|
||||
use traits::operations::{Axpy, Transpose, Inverse, Absolute};
|
||||
use traits::operations::{Axpy, Transpose, Inverse, Absolute, ApproxEq};
|
||||
use traits::geometry::{Dot, Norm, Origin};
|
||||
|
||||
/// Basic integral numeric trait.
|
||||
@ -21,7 +21,7 @@ pub trait BaseNum: Copy + Zero + One +
|
||||
}
|
||||
|
||||
/// Basic floating-point number numeric trait.
|
||||
pub trait BaseFloat: Float + Cast<f64> + BaseNum + Neg {
|
||||
pub trait BaseFloat: Float + Cast<f64> + BaseNum + ApproxEq<Self> + Neg {
|
||||
/// Archimedes' constant.
|
||||
fn pi() -> Self;
|
||||
/// 2.0 * pi.
|
||||
@ -176,7 +176,7 @@ pub trait Diagonal<V> {
|
||||
}
|
||||
|
||||
/// Trait to set the diagonal of square matrices.
|
||||
pub trait DiagMut<V>: Diagonal<V> {
|
||||
pub trait DiagonalMut<V>: Diagonal<V> {
|
||||
/// Sets the diagonal of this matrix.
|
||||
fn set_diagonal(&mut self, diagonal: &V);
|
||||
}
|
||||
@ -211,7 +211,7 @@ pub trait Indexable<I, N>: Shape<I> + IndexMut<I, Output = N> {
|
||||
/// Traits of objects which can be iterated through like a vector.
|
||||
pub trait Iterable<N> {
|
||||
/// Gets a vector-like read-only iterator.
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N>;
|
||||
fn iter(&self) -> Iter<N>;
|
||||
}
|
||||
|
||||
/// This is a workaround of current Rust limitations.
|
||||
@ -219,7 +219,7 @@ pub trait Iterable<N> {
|
||||
/// Traits of mutable objects which can be iterated through like a vector.
|
||||
pub trait IterableMut<N> {
|
||||
/// Gets a vector-like read-write iterator.
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N>;
|
||||
fn iter_mut(&mut self) -> IterMut<N>;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -243,7 +243,7 @@ pub trait NumVector<N>: Add<Self, Output = Self> + Sub<Self, Output = Self> +
|
||||
}
|
||||
|
||||
/// Trait of vector with components implementing the `BaseFloat` trait.
|
||||
pub trait FloatVector<N: BaseFloat>: NumVector<N> + Norm<N> + Neg<Output = Self> + Basis {
|
||||
pub trait FloatVector<N: BaseFloat>: NumVector<N> + Norm<NormType = N> + Neg<Output = Self> + Basis + ApproxEq<N> {
|
||||
}
|
||||
|
||||
/*
|
||||
@ -258,7 +258,7 @@ pub trait PointAsVector {
|
||||
fn to_vector(self) -> Self::Vector;
|
||||
|
||||
/// Converts a reference to this point to a reference to its associated vector.
|
||||
fn as_vector<'a>(&'a self) -> &'a Self::Vector;
|
||||
fn as_vector(&self) -> &Self::Vector;
|
||||
|
||||
// NOTE: this is used in some places to overcome some limitations untill the trait reform is
|
||||
// done on rustc.
|
||||
@ -289,7 +289,7 @@ pub trait NumPoint<N>:
|
||||
|
||||
/// Trait of points with components implementing the `BaseFloat` trait.
|
||||
pub trait FloatPoint<N: BaseFloat>: NumPoint<N> + Sized
|
||||
where <Self as PointAsVector>::Vector: Norm<N> {
|
||||
where <Self as PointAsVector>::Vector: Norm<NormType = N> {
|
||||
/// Computes the square distance between two points.
|
||||
#[inline]
|
||||
fn distance_squared(&self, other: &Self) -> N {
|
||||
|
@ -1,7 +1,7 @@
|
||||
extern crate nalgebra as na;
|
||||
extern crate rand;
|
||||
|
||||
use na::{Point3, Vector3, Rotation3, UnitQuaternion, Rotation};
|
||||
use na::{Point3, Quaternion, Vector3, Rotation3, UnitQuaternion, Rotation, one};
|
||||
use rand::random;
|
||||
|
||||
#[test]
|
||||
@ -9,7 +9,7 @@ fn test_quaternion_as_matrix() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let axis_angle: Vector3<f64> = random();
|
||||
|
||||
assert!(na::approx_eq(&UnitQuaternion::new(axis_angle).to_rotation_matrix(), &Rotation3::new(axis_angle)))
|
||||
assert!(na::approx_eq(&UnitQuaternion::from_scaled_axis(axis_angle).to_rotation_matrix(), &Rotation3::new(axis_angle)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,16 +17,16 @@ fn test_quaternion_as_matrix() {
|
||||
fn test_quaternion_mul_vec_or_point_as_matrix() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let axis_angle: Vector3<f64> = random();
|
||||
let vector: Vector3<f64> = random();
|
||||
let point: Point3<f64> = random();
|
||||
let vector: Vector3<f64> = random();
|
||||
let point: Point3<f64> = random();
|
||||
|
||||
let matrix = Rotation3::new(axis_angle);
|
||||
let quaternion = UnitQuaternion::new(axis_angle);
|
||||
let matrix = Rotation3::new(axis_angle);
|
||||
let quaternion = UnitQuaternion::from_scaled_axis(axis_angle);
|
||||
|
||||
assert!(na::approx_eq(&(matrix * vector), &(quaternion * vector)));
|
||||
assert!(na::approx_eq(&(matrix * point), &(quaternion * point)));
|
||||
assert!(na::approx_eq(&(matrix * point), &(quaternion * point)));
|
||||
assert!(na::approx_eq(&(vector * matrix), &(vector * quaternion)));
|
||||
assert!(na::approx_eq(&(point * matrix), &(point * quaternion)));
|
||||
assert!(na::approx_eq(&(point * matrix), &(point * quaternion)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,8 +39,8 @@ fn test_quaternion_div_quaternion() {
|
||||
let r1 = Rotation3::new(axis_angle1);
|
||||
let r2 = na::inverse(&Rotation3::new(axis_angle2)).unwrap();
|
||||
|
||||
let q1 = UnitQuaternion::new(axis_angle1);
|
||||
let q2 = UnitQuaternion::new(axis_angle2);
|
||||
let q1 = UnitQuaternion::from_scaled_axis(axis_angle1);
|
||||
let q2 = UnitQuaternion::from_scaled_axis(axis_angle2);
|
||||
|
||||
assert!(na::approx_eq(&(q1 / q2).to_rotation_matrix(), &(r1 * r2)))
|
||||
}
|
||||
@ -51,7 +51,7 @@ fn test_quaternion_to_axis_angle() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let axis_angle: Vector3<f64> = random();
|
||||
|
||||
let q = UnitQuaternion::new(axis_angle);
|
||||
let q = UnitQuaternion::from_scaled_axis(axis_angle);
|
||||
|
||||
println!("{:?} {:?}", q.rotation(), axis_angle);
|
||||
assert!(na::approx_eq(&q.rotation(), &axis_angle))
|
||||
@ -63,8 +63,8 @@ fn test_quaternion_euler_angles() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let angles: Vector3<f64> = random();
|
||||
|
||||
let q = UnitQuaternion::new_with_euler_angles(angles.x, angles.y, angles.z);
|
||||
let m = Rotation3::new_with_euler_angles(angles.x, angles.y, angles.z);
|
||||
let q = UnitQuaternion::from_euler_angles(angles.x, angles.y, angles.z);
|
||||
let m = Rotation3::from_euler_angles(angles.x, angles.y, angles.z);
|
||||
|
||||
assert!(na::approx_eq(&q.to_rotation_matrix(), &m))
|
||||
}
|
||||
@ -90,3 +90,32 @@ fn test_quaternion_angle_between() {
|
||||
|
||||
assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quaternion_exp_zero_is_one() {
|
||||
let q = Quaternion::new(0., 0., 0., 0.);
|
||||
assert!(na::approx_eq(&q.exp(), &one()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quaternion_neutral() {
|
||||
for _ in 0 .. 10000 {
|
||||
let q1: Quaternion<f32> = random();
|
||||
let qi: Quaternion<f32> = one();
|
||||
let q2 = q1 * qi;
|
||||
let q3 = qi * q1;
|
||||
|
||||
assert!(na::approx_eq(&q1, &q2) && na::approx_eq(&q2, &q3))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quaternion_polar_decomposition() {
|
||||
for _ in 0 .. 10000 {
|
||||
let q1: Quaternion<f32> = random();
|
||||
let decomp = q1.polar_decomposition();
|
||||
let q2 = Quaternion::from_polar_decomposition(decomp.0, decomp.1, decomp.2);
|
||||
|
||||
assert!(na::approx_eq(&q1, &q2))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user