Merge pull request #195 from sebcrozet/refactor

Various refactoring and renaming.
This commit is contained in:
Sébastien Crozet 2016-08-16 13:42:40 +02:00 committed by GitHub
commit fc08caabbe
38 changed files with 2697 additions and 3254 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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)
}

View File

@ -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)
}

View 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 ),+
}
}
}
);
);

View File

@ -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);

View File

@ -85,8 +85,7 @@ macro_rules! dmat_impl(
let mut res = $dmatrix::new_zeros(dimension, dimension);
for i in 0 .. dimension {
let _1: N = ::one();
res[(i, i)] = _1;
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);

View File

@ -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.

View File

@ -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);

View File

@ -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.
@ -77,7 +77,7 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
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.
@ -95,50 +95,12 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
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);

View File

@ -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
}
}
)
);

View File

@ -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,
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,
matrix_impl!(Matrix3, 3, Vector3, DVector3, 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
);
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);

View File

@ -1,7 +1,7 @@
#![macro_use]
macro_rules! mat_impl(
($t: ident, $($compN: ident),+) => (
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> {
@ -10,11 +10,13 @@ macro_rules! mat_impl(
}
}
}
)
);
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,300 +80,50 @@ 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>;
#[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 ),+
}
}
}
)
);
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) => (
/*
*
* Iterable
*
*/
impl<N> Iterable<N> for $t<N> {
#[inline]
fn iter<'l>(&'l self) -> Iter<'l, N> {
fn iter(&self) -> Iter<N> {
unsafe {
mem::transmute::<&'l $t<N>, &'l [N; $dimension * $dimension]>(self).iter()
mem::transmute::<&$t<N>, &[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> {
fn iter_mut(& mut self) -> IterMut<N> {
unsafe {
mem::transmute::<&'l mut $t<N>, &'l mut [N; $dimension * $dimension]>(self).iter_mut()
mem::transmute::<&mut $t<N>, &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() ),+
}
}
#[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) => (
/*
*
* Shape/Indexable/Index
*
*/
impl<N> Shape<(usize, usize)> for $t<N> {
#[inline]
fn shape(&self) -> (usize, usize) {
@ -396,11 +150,7 @@ macro_rules! indexable_impl(
(*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,80 +168,29 @@ 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> {
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;
}
}
#[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)];
}
res
}
}
)
);
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> {
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> {
/*
*
* 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: $tv<N>) {
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) -> $tv<N> {
let mut res: $tv<N> = ::zero();
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)];
@ -500,14 +199,136 @@ macro_rules! column_impl(
res
}
}
)
);
macro_rules! diag_impl(
($t: ident, $tv: ident, $dimension: expr) => (
impl<N: Copy + Zero> Diagonal<$tv<N>> for $t<N> {
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);
$dvector::from_slice(rend - rstart, &column.as_ref()[rstart .. rend])
}
}
impl<N: Copy + Zero> Row<$vector<N>> for $t<N> {
#[inline]
fn from_diagonal(diagonal: &$tv<N>) -> $t<N> {
fn nrows(&self) -> usize {
Dimension::dimension(None::<$t<N>>)
}
#[inline]
fn set_row(&mut self, row: usize, v: $vector<N>) {
for (i, e) in v.iter().enumerate() {
self[(row, i)] = *e;
}
}
#[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);
$dvector::from_slice(cend - cstart, &row.as_ref()[cstart .. cend])
}
}
/*
*
* Transpose
*
*/
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))
}
}
}
}
/*
*
* 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) => (
@ -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
}
}
)
);

View File

@ -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)]

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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);

View File

@ -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
}
}
)
);

View File

@ -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,101 +208,144 @@ 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()
let q = Quaternion::from_parts(cang, axis.unwrap() * sang);
Unit::from_unit_value_unchecked(q)
}
else {
let ang = sqang.sqrt();
let (s, c) = (ang / Cast::from(2.0)).sin_cos();
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(
Rotation3::from_matrix_unchecked(
Matrix3::new(
ww + ii - jj - kk, ij - wk, wj + ik,
wk + ij, ww - ii + jj - kk, jk - wi,
@ -266,37 +354,16 @@ impl<N: BaseFloat> UnitQuaternion<N> {
)
}
}
}
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);

View File

@ -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,13 +166,12 @@ 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(
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,
@ -191,9 +180,8 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
)
}
}
}
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,13 +198,11 @@ 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(),
Rotation3::from_matrix_unchecked(Matrix3::new(
xaxis.x, yaxis.x, zaxis.x,
xaxis.y, yaxis.y, zaxis.y,
xaxis.z, yaxis.z, zaxis.z))
}
}
/// Builds a right-handed look-at view matrix without translation.
@ -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);

View File

@ -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
}
}
)
);

View File

@ -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);

View File

@ -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 {{"));

View File

@ -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.

View File

@ -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
}

View File

@ -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
View 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
}
}

View File

@ -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

View File

@ -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
}
l
#[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)
}
}
#[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)
}
}
}

View File

@ -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>;
}
/**

View File

@ -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,

View File

@ -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,8 +137,7 @@ pub trait PartialOrder {
if v_min.is_not_comparable() || v_max.is_not_comparable() {
None
}
else {
if v_min.is_lt() {
else if v_min.is_lt() {
Some(min)
}
else if v_max.is_gt() {
@ -148,7 +148,6 @@ pub trait PartialOrder {
}
}
}
}
/// Trait for testing approximate equality
pub trait ApproxEq<Eps>: Sized {
@ -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
}

View File

@ -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 {

View File

@ -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)))
}
}
@ -21,7 +21,7 @@ fn test_quaternion_mul_vec_or_point_as_matrix() {
let point: Point3<f64> = random();
let matrix = Rotation3::new(axis_angle);
let quaternion = UnitQuaternion::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)));
@ -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))
}
}