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/). This project adheres to [Semantic Versioning](http://semver.org/).
## [0.9.0] - WIP ## [0.9.0] - WIP
## Modified ### Modified
* Renamed: * Renamed:
- `::from_col_vector` -> `::from_column_vector` - `::from_col_vector` -> `::from_column_vector`
- `::from_col_iter` -> `::from_column_iter` - `::from_col_iter` -> `::from_column_iter`
@ -13,9 +13,38 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- `.set_col` -> `.set_column` - `.set_col` -> `.set_column`
- `::canonical_basis_with_dim` -> `::canonical_basis_with_dimension` - `::canonical_basis_with_dim` -> `::canonical_basis_with_dimension`
- `::from_elem` -> `::from_element` - `::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] ## [0.8.0]
## Modified ### Modified
* Almost everything (types, methods, and traits) now use full names instead * Almost everything (types, methods, and traits) now use full names instead
of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are abvious. of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are abvious.
Note however that: Note however that:

View File

@ -1,6 +1,6 @@
[package] [package]
name = "nalgebra" name = "nalgebra"
version = "0.8.2" version = "0.9.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] # FIXME: add the contributors. 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." 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.*" rustc-serialize = "0.3.*"
rand = "0.3.*" rand = "0.3.*"
num = "0.1.*" num = "0.1.*"
# algebra = "*"
[dependencies.generic-array] [dependencies.generic-array]
optional = true 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 nalgebra
======== ========
@ -9,8 +21,6 @@ nalgebra
* Real time computer graphics. * Real time computer graphics.
* Real time computer physics. * Real time computer physics.
An on-line version of this documentation is available [here](http://nalgebra.org/doc/nalgebra).
## Using **nalgebra** ## Using **nalgebra**
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`. This 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 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"] #[path="common/macros.rs"]
mod macros; 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_rot2_from_axisangle, Rotation2::new, axisangle: Vector1<f32>);
bench_construction!(_bench_rot3_from_axisangle, Rotation3::new, axisangle: Vector3<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_quaternion_from_euler_angles, UnitQuaternion::from_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_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")] #[cfg(feature = "generic_sizes")]
mod bench_vecn { 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 typenum::{U2, U3, U4};
use na::VectorN; use na::VectorN;

View File

@ -154,7 +154,8 @@ pub use structs::{
Point1, Point2, Point3, Point4, Point5, Point6, Point1, Point2, Point3, Point4, Point5, Point6,
Perspective3, PerspectiveMatrix3, Perspective3, PerspectiveMatrix3,
Orthographic3, OrthographicMatrix3, Orthographic3, OrthographicMatrix3,
Quaternion, UnitQuaternion Quaternion, UnitQuaternion,
Unit
}; };
pub use linalg::{ pub use linalg::{
@ -173,7 +174,7 @@ mod macros;
// mod chol; // mod chol;
/// Change the input value to ensure it is on the range `[min, max]`. /// 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 { pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
if val > min { if val > min {
if val < max { if val < max {
@ -189,74 +190,74 @@ pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
} }
/// Same as `cmp::max`. /// Same as `cmp::max`.
#[inline(always)] #[inline]
pub fn max<T: Ord>(a: T, b: T) -> T { pub fn max<T: Ord>(a: T, b: T) -> T {
cmp::max(a, b) cmp::max(a, b)
} }
/// Same as `cmp::min`. /// Same as `cmp::min`.
#[inline(always)] #[inline]
pub fn min<T: Ord>(a: T, b: T) -> T { pub fn min<T: Ord>(a: T, b: T) -> T {
cmp::min(a, b) cmp::min(a, b)
} }
/// Returns the infimum of `a` and `b`. /// Returns the infimum of `a` and `b`.
#[inline(always)] #[inline]
pub fn inf<T: PartialOrder>(a: &T, b: &T) -> T { pub fn inf<T: PartialOrder>(a: &T, b: &T) -> T {
PartialOrder::inf(a, b) PartialOrder::inf(a, b)
} }
/// Returns the supremum of `a` and `b`. /// Returns the supremum of `a` and `b`.
#[inline(always)] #[inline]
pub fn sup<T: PartialOrder>(a: &T, b: &T) -> T { pub fn sup<T: PartialOrder>(a: &T, b: &T) -> T {
PartialOrder::sup(a, b) PartialOrder::sup(a, b)
} }
/// Compare `a` and `b` using a partial ordering relation. /// Compare `a` and `b` using a partial ordering relation.
#[inline(always)] #[inline]
pub fn partial_cmp<T: PartialOrder>(a: &T, b: &T) -> PartialOrdering { pub fn partial_cmp<T: PartialOrder>(a: &T, b: &T) -> PartialOrdering {
PartialOrder::partial_cmp(a, b) PartialOrder::partial_cmp(a, b)
} }
/// Returns `true` iff `a` and `b` are comparable and `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 { pub fn partial_lt<T: PartialOrder>(a: &T, b: &T) -> bool {
PartialOrder::partial_lt(a, b) PartialOrder::partial_lt(a, b)
} }
/// Returns `true` iff `a` and `b` are comparable and `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 { pub fn partial_le<T: PartialOrder>(a: &T, b: &T) -> bool {
PartialOrder::partial_le(a, b) PartialOrder::partial_le(a, b)
} }
/// Returns `true` iff `a` and `b` are comparable and `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 { pub fn partial_gt<T: PartialOrder>(a: &T, b: &T) -> bool {
PartialOrder::partial_gt(a, b) PartialOrder::partial_gt(a, b)
} }
/// Returns `true` iff `a` and `b` are comparable and `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 { pub fn partial_ge<T: PartialOrder>(a: &T, b: &T) -> bool {
PartialOrder::partial_ge(a, b) PartialOrder::partial_ge(a, b)
} }
/// Return the minimum of `a` and `b` if they are comparable. /// 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> { pub fn partial_min<'a, T: PartialOrder>(a: &'a T, b: &'a T) -> Option<&'a T> {
PartialOrder::partial_min(a, b) PartialOrder::partial_min(a, b)
} }
/// Return the maximum of `a` and `b` if they are comparable. /// 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> { pub fn partial_max<'a, T: PartialOrder>(a: &'a T, b: &'a T) -> Option<&'a T> {
PartialOrder::partial_max(a, b) PartialOrder::partial_max(a, b)
} }
/// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to /// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to
/// `min` or `max`. /// `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> { 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) 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. /// Create a special identity object.
/// ///
/// Same as `Identity::new()`. /// Same as `Identity::new()`.
#[inline(always)] #[inline]
pub fn identity() -> Identity { pub fn identity() -> Identity {
Identity::new() Identity::new()
} }
@ -278,13 +279,13 @@ pub fn identity() -> Identity {
/// Create a zero-valued value. /// Create a zero-valued value.
/// ///
/// This is the same as `std::num::zero()`. /// This is the same as `std::num::zero()`.
#[inline(always)] #[inline]
pub fn zero<T: Zero>() -> T { pub fn zero<T: Zero>() -> T {
Zero::zero() Zero::zero()
} }
/// Tests is a value is iqual to zero. /// Tests is a value is iqual to zero.
#[inline(always)] #[inline]
pub fn is_zero<T: Zero>(val: &T) -> bool { pub fn is_zero<T: Zero>(val: &T) -> bool {
val.is_zero() val.is_zero()
} }
@ -292,7 +293,7 @@ pub fn is_zero<T: Zero>(val: &T) -> bool {
/// Create a one-valued value. /// Create a one-valued value.
/// ///
/// This is the same as `std::num::one()`. /// This is the same as `std::num::one()`.
#[inline(always)] #[inline]
pub fn one<T: One>() -> T { pub fn one<T: One>() -> T {
One::one() One::one()
} }
@ -304,7 +305,7 @@ pub fn one<T: One>() -> T {
// //
/// Returns the trivial origin of an affine space. /// Returns the trivial origin of an affine space.
#[inline(always)] #[inline]
pub fn origin<P: Origin>() -> P { pub fn origin<P: Origin>() -> P {
Origin::origin() Origin::origin()
} }
@ -312,26 +313,23 @@ pub fn origin<P: Origin>() -> P {
/// Returns the center of two points. /// Returns the center of two points.
#[inline] #[inline]
pub fn center<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> P pub fn center<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> P
where <P as PointAsVector>::Vector: Norm<N> where <P as PointAsVector>::Vector: Norm<NormType = N> {
{ (*a + b.to_vector()) / ::cast(2.0)
let _2 = one::<N>() + one();
(*a + b.to_vector()) / _2
} }
/* /*
* FloatPoint * FloatPoint
*/ */
/// Returns the distance between two points. /// Returns the distance between two points.
#[inline(always)] #[inline]
pub fn distance<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N where <P as PointAsVector>::Vector: Norm<N> { pub fn distance<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N where <P as PointAsVector>::Vector: Norm<NormType = N> {
a.distance(b) a.distance(b)
} }
/// Returns the squared distance between two points. /// Returns the squared distance between two points.
#[inline(always)] #[inline]
pub fn distance_squared<N: BaseFloat, P: FloatPoint<N>>(a: &P, b: &P) -> N 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) 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)); /// assert!(trans == Vector3::new(1.0, 1.0, 1.0));
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline]
pub fn translation<V, M: Translation<V>>(m: &M) -> V { pub fn translation<V, M: Translation<V>>(m: &M) -> V {
m.translation() 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)); /// assert!(itrans == Vector3::new(-1.0, -1.0, -1.0));
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline]
pub fn inverse_translation<V, M: Translation<V>>(m: &M) -> V { pub fn inverse_translation<V, M: Translation<V>>(m: &M) -> V {
m.inverse_translation() m.inverse_translation()
} }
/// Applies the translation `v` to a copy of `m`. /// 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 { pub fn append_translation<V, M: Translation<V>>(m: &M, v: &V) -> M {
Translation::append_translation(m, v) 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)) /// 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 { pub fn translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
m.translate(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))) /// 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 { pub fn inverse_translate<P, M: Translate<P>>(m: &M, p: &P) -> P {
m.inverse_translate(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))); /// 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 { pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
m.rotation() 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))); /// 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 { pub fn inverse_rotation<V, M: Rotation<V>>(m: &M) -> V {
m.inverse_rotation() 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))) /// 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 { pub fn append_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
Rotation::append_rotation(m, v) 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))) /// 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 { pub fn prepend_rotation<V, M: Rotation<V>>(m: &M, v: &V) -> M {
Rotation::prepend_rotation(m, v) 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))) /// 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 { pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
m.rotate(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))) /// 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 { pub fn inverse_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
m.inverse_rotate(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. /// 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, pub fn append_rotation_wrt_point<LV: Neg<Output = LV> + Copy,
AV, AV,
M: RotationWithTranslation<LV, 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. /// 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, pub fn append_rotation_wrt_center<LV: Neg<Output = LV> + Copy,
AV, AV,
M: RotationWithTranslation<LV, AV>>( M: RotationWithTranslation<LV, AV>>(
@ -577,13 +575,13 @@ pub fn append_rotation_wrt_center<LV: Neg<Output = LV> + Copy,
* RotationTo * RotationTo
*/ */
/// Computes the angle of the rotation needed to transfom `a` to `b`. /// 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 { pub fn angle_between<V: RotationTo>(a: &V, b: &V) -> V::AngleType {
a.angle_to(b) a.angle_to(b)
} }
/// Computes the rotation needed to transform `a` 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 { pub fn rotation_between<V: RotationTo>(a: &V, b: &V) -> V::DeltaRotationType {
a.rotation_to(b) 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`. /// Builds a rotation matrix from `r`.
#[inline(always)] #[inline]
pub fn to_rotation_matrix<N, LV, AV, R, M>(r: &R) -> M pub fn to_rotation_matrix<N, LV, AV, R, M>(r: &R) -> M
where R: RotationMatrix<N, LV, AV, Output = M>, where R: RotationMatrix<N, LV, AV, Output = M>,
M: SquareMatrix<N, LV> + Rotation<AV> + Copy, 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. /// 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 { pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
m.absolute_rotate(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`. /// Gets the transformation applicable by `m`.
#[inline(always)] #[inline]
pub fn transformation<T, M: Transformation<T>>(m: &M) -> T { pub fn transformation<T, M: Transformation<T>>(m: &M) -> T {
m.transformation() m.transformation()
} }
/// Gets the inverse transformation applicable by `m`. /// Gets the inverse transformation applicable by `m`.
#[inline(always)] #[inline]
pub fn inverse_transformation<T, M: Transformation<T>>(m: &M) -> T { pub fn inverse_transformation<T, M: Transformation<T>>(m: &M) -> T {
m.inverse_transformation() m.inverse_transformation()
} }
/// Gets a transformed copy of `m`. /// Gets a transformed copy of `m`.
#[inline(always)] #[inline]
pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M { pub fn append_transformation<T, M: Transformation<T>>(m: &M, t: &T) -> M {
Transformation::append_transformation(m, t) 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. /// Applies a transformation to a vector.
#[inline(always)] #[inline]
pub fn transform<V, M: Transform<V>>(m: &M, v: &V) -> V { pub fn transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
m.transform(v) m.transform(v)
} }
/// Applies an inverse transformation to a vector. /// Applies an inverse transformation to a vector.
#[inline(always)] #[inline]
pub fn inverse_transform<V, M: Transform<V>>(m: &M, v: &V) -> V { pub fn inverse_transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
m.inverse_transform(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. /// Computes the dot product of two vectors.
#[inline(always)] #[inline]
pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N { pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
Dot::dot(a, b) 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. /// Computes the L2 norm of a vector.
#[inline(always)] #[inline]
pub fn norm<V: Norm<N>, N: BaseFloat>(v: &V) -> N { pub fn norm<V: Norm>(v: &V) -> V::NormType {
Norm::norm(v) Norm::norm(v)
} }
/// Computes the squared L2 norm of a vector. /// Computes the squared L2 norm of a vector.
#[inline(always)] #[inline]
pub fn norm_squared<V: Norm<N>, N: BaseFloat>(v: &V) -> N { pub fn norm_squared<V: Norm>(v: &V) -> V::NormType {
Norm::norm_squared(v) Norm::norm_squared(v)
} }
/// Gets the normalized version of a vector. /// Gets the normalized version of a vector.
#[inline(always)] #[inline]
pub fn normalize<V: Norm<N>, N: BaseFloat>(v: &V) -> V { pub fn normalize<V: Norm>(v: &V) -> V {
Norm::normalize(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> * Determinant<N>
*/ */
/// Computes the determinant of a square matrix. /// Computes the determinant of a square matrix.
#[inline(always)] #[inline]
pub fn determinant<M: Determinant<N>, N>(m: &M) -> N { pub fn determinant<M: Determinant<N>, N>(m: &M) -> N {
Determinant::determinant(m) Determinant::determinant(m)
} }
@ -697,7 +701,7 @@ pub fn determinant<M: Determinant<N>, N>(m: &M) -> N {
*/ */
/// Computes the cross product of two vectors. /// Computes the cross product of two vectors.
#[inline(always)] #[inline]
pub fn cross<LV: Cross>(a: &LV, b: &LV) -> LV::CrossProductType { pub fn cross<LV: Cross>(a: &LV, b: &LV) -> LV::CrossProductType {
Cross::cross(a, b) 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 /// Given a vector, computes the matrix which, when multiplied by another vector, computes a cross
/// product. /// product.
#[inline(always)] #[inline]
pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M { pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M {
CrossMatrix::cross_matrix(v) 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. /// Converts a matrix or vector to homogeneous coordinates.
#[inline(always)] #[inline]
pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res { pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res {
ToHomogeneous::to_homogeneous(m) 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. /// Converts a matrix or vector from homogeneous coordinates.
/// ///
/// w-normalization is appied. /// w-normalization is appied.
#[inline(always)] #[inline]
pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res { pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res {
FromHomogeneous::from(m) 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. /// Samples the unit sphere living on the dimension as the samples types.
/// ///
/// The number of sampling point is implementation-specific. It is always uniform. /// 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) { pub fn sample_sphere<V: UniformSphereSample, F: FnMut(V)>(f: F) {
UniformSphereSample::sample(f) UniformSphereSample::sample(f)
} }
@ -757,13 +761,13 @@ pub fn sample_sphere<V: UniformSphereSample, F: FnMut(V)>(f: F) {
* AproxEq<N> * AproxEq<N>
*/ */
/// Tests approximate equality. /// Tests approximate equality.
#[inline(always)] #[inline]
pub fn approx_eq<T: ApproxEq<N>, N>(a: &T, b: &T) -> bool { pub fn approx_eq<T: ApproxEq<N>, N>(a: &T, b: &T) -> bool {
ApproxEq::approx_eq(a, b) ApproxEq::approx_eq(a, b)
} }
/// Tests approximate equality using a custom epsilon. /// 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 { pub fn approx_eq_eps<T: ApproxEq<N>, N>(a: &T, b: &T, eps: &N) -> bool {
ApproxEq::approx_eq_eps(a, b, eps) 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. /// Computes a component-wise absolute value.
#[inline(always)] #[inline]
pub fn abs<M: Absolute<Res>, Res>(m: &M) -> Res { pub fn abs<M: Absolute<Res>, Res>(m: &M) -> Res {
Absolute::abs(m) Absolute::abs(m)
} }
@ -784,7 +788,7 @@ pub fn abs<M: Absolute<Res>, Res>(m: &M) -> Res {
*/ */
/// Gets an inverted copy of a matrix. /// Gets an inverted copy of a matrix.
#[inline(always)] #[inline]
pub fn inverse<M: Inverse>(m: &M) -> Option<M> { pub fn inverse<M: Inverse>(m: &M) -> Option<M> {
Inverse::inverse(m) Inverse::inverse(m)
} }
@ -794,7 +798,7 @@ pub fn inverse<M: Inverse>(m: &M) -> Option<M> {
*/ */
/// Gets a transposed copy of a matrix. /// Gets a transposed copy of a matrix.
#[inline(always)] #[inline]
pub fn transpose<M: Transpose>(m: &M) -> M { pub fn transpose<M: Transpose>(m: &M) -> M {
Transpose::transpose(m) Transpose::transpose(m)
} }
@ -804,7 +808,7 @@ pub fn transpose<M: Transpose>(m: &M) -> M {
*/ */
/// Computes the outer product of two vectors. /// Computes the outer product of two vectors.
#[inline(always)] #[inline]
pub fn outer<V: Outer>(a: &V, b: &V) -> V::OuterProductType { pub fn outer<V: Outer>(a: &V, b: &V) -> V::OuterProductType {
Outer::outer(a, b) 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. /// Computes the covariance of a set of observations.
#[inline(always)] #[inline]
pub fn covariance<M: Covariance<Res>, Res>(observations: &M) -> Res { pub fn covariance<M: Covariance<Res>, Res>(observations: &M) -> Res {
Covariance::covariance(observations) 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. /// Computes the mean of a set of observations.
#[inline(always)] #[inline]
pub fn mean<N, M: Mean<N>>(observations: &M) -> N { pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
Mean::mean(observations) Mean::mean(observations)
} }
@ -833,7 +837,7 @@ pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
* EigenQR<N, V> * EigenQR<N, V>
*/ */
/// Computes the eigenvalues and eigenvectors of a square matrix usin the QR algorithm. /// 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) pub fn eigen_qr<N, V, M>(m: &M, eps: &N, niter: usize) -> (M, V)
where V: Mul<M, Output = V>, where V: Mul<M, Output = V>,
M: EigenQR<N, 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 * Eye
*/ */
/// Construct the identity matrix for a given dimension /// Construct the identity matrix for a given dimension
#[inline(always)] #[inline]
pub fn new_identity<M: Eye>(dimension: usize) -> M { pub fn new_identity<M: Eye>(dimension: usize) -> M {
Eye::new_identity(dimension) Eye::new_identity(dimension)
} }
@ -862,7 +866,7 @@ pub fn new_identity<M: Eye>(dimension: usize) -> M {
/// Create an object by repeating a value. /// Create an object by repeating a value.
/// ///
/// Same as `Identity::new()`. /// Same as `Identity::new()`.
#[inline(always)] #[inline]
pub fn repeat<N, T: Repeat<N>>(val: N) -> T { pub fn repeat<N, T: Repeat<N>>(val: N) -> T {
Repeat::repeat(val) 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. /// Computes the canonical basis for a given dimension.
#[inline(always)] #[inline]
pub fn canonical_basis<V: Basis, F: FnMut(V) -> bool>(f: F) { pub fn canonical_basis<V: Basis, F: FnMut(V) -> bool>(f: F) {
Basis::canonical_basis(f) Basis::canonical_basis(f)
} }
/// Computes the basis of the orthonormal subspace of a given vector. /// 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) { pub fn orthonormal_subspace_basis<V: Basis, F: FnMut(V) -> bool>(v: &V, f: F) {
Basis::orthonormal_subspace_basis(v, f) Basis::orthonormal_subspace_basis(v, f)
} }
@ -901,7 +905,7 @@ pub fn canonical_basis_element<V: Basis>(i: usize) -> Option<V> {
* Diagonal<V> * Diagonal<V>
*/ */
/// Gets the diagonal of a square matrix. /// Gets the diagonal of a square matrix.
#[inline(always)] #[inline]
pub fn diagonal<M: Diagonal<V>, V>(m: &M) -> V { pub fn diagonal<M: Diagonal<V>, V>(m: &M) -> V {
m.diagonal() m.diagonal()
} }
@ -912,13 +916,13 @@ pub fn diagonal<M: Diagonal<V>, V>(m: &M) -> V {
/// Gets the dimension an object lives in. /// Gets the dimension an object lives in.
/// ///
/// Same as `Dimension::dimension::(None::<V>)`. /// Same as `Dimension::dimension::(None::<V>)`.
#[inline(always)] #[inline]
pub fn dimension<V: Dimension>() -> usize { pub fn dimension<V: Dimension>() -> usize {
Dimension::dimension(None::<V>) Dimension::dimension(None::<V>)
} }
/// Gets the indexable range of an object. /// Gets the indexable range of an object.
#[inline(always)] #[inline]
pub fn shape<V: Shape<I>, I>(v: &V) -> I { pub fn shape<V: Shape<I>, I>(v: &V) -> I {
v.shape() 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). /// 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 /// * 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. /// 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 { pub fn cast<T, U: Cast<T>>(t: T) -> U {
Cast::from(t) Cast::from(t)
} }

View File

@ -1,5 +1,5 @@
use traits::operations::{Transpose, ApproxEq}; 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 traits::geometry::Norm;
use std::cmp; use std::cmp;
use std::ops::{Mul, Add, Sub}; 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 /// * `m` - matrix to decompose
pub fn qr<N, V, M>(m: &M) -> (M, M) pub fn qr<N, V, M>(m: &M) -> (M, M)
where N: BaseFloat, 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> + M: Copy + Eye + ColumnSlice<V> + Transpose + Indexable<(usize, usize), N> +
Mul<M, Output = M> { Mul<M, Output = M> {
let (rows, cols) = m.shape(); 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) pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: usize) -> (M, V)
where N: BaseFloat, where N: BaseFloat,
V: Mul<M, Output = V>, 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> + M: Indexable<(usize, usize), N> + SquareMatrix<N, V> + Add<M, Output = M> +
Sub<M, Output = M> + ColumnSlice<VS> + Sub<M, Output = M> + ColumnSlice<VS> +
ApproxEq<N> + Copy { 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> pub fn cholesky<N, V, VS, M>(m: &M) -> Result<M, &'static str>
where N: BaseFloat, where N: BaseFloat,
V: Mul<M, Output = V>, 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> + M: Indexable<(usize, usize), N> + SquareMatrix<N, V> + Add<M, Output = M> +
Sub<M, Output = M> + ColumnSlice<VS> + Sub<M, Output = M> + ColumnSlice<VS> +
ApproxEq<N> + Copy { ApproxEq<N> + Copy {
let mut out = m.clone().transpose(); let mut out = m.transpose();
if !ApproxEq::approx_eq(&out, &m) { if !ApproxEq::approx_eq(&out, &m) {
return Err("Cholesky: Input matrix is not symmetric"); 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 /// 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 /// * Second return value `h` - Matrix m in Hessenberg form
pub fn hessenberg<N, V, M>(m: &M) -> (M, M) pub fn hessenberg<N, V, M>(m: &M) -> (M, M)
where N: BaseFloat, 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> + M: Copy + Eye + ColumnSlice<V> + Transpose + Indexable<(usize, usize), N> +
Mul<M, Output = M> { Mul<M, Output = M> {
let mut h = m.clone(); let mut h = *m;
let (rows, cols) = h.shape(); let (rows, cols) = h.shape();
let mut q : M = Eye::new_identity(cols); 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 num::{Zero, One};
use structs::dvector::{DVector, DVector1, DVector2, DVector3, DVector4, DVector5, DVector6}; use structs::dvector::{DVector, DVector1, DVector2, DVector3, DVector4, DVector5, DVector6};
use traits::operations::{ApproxEq, Inverse, Transpose, Mean, Covariance}; 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")] #[cfg(feature="arbitrary")]
use quickcheck::{Arbitrary, Gen}; use quickcheck::{Arbitrary, Gen};
@ -109,7 +110,7 @@ impl<N: Clone + Copy> DMatrix<N> {
impl<N> DMatrix<N> { impl<N> DMatrix<N> {
/// Builds a matrix filled with the results of a function applied to each of its component coordinates. /// 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> { pub fn from_fn<F: FnMut(usize, usize) -> N>(nrows: usize, ncols: usize, mut f: F) -> DMatrix<N> {
DMatrix { DMatrix {
nrows: nrows, nrows: nrows,
@ -133,7 +134,7 @@ dmat_impl!(DMatrix, DVector);
pub struct DMatrix1<N> { pub struct DMatrix1<N> {
nrows: usize, nrows: usize,
ncols: usize, ncols: usize,
mij: [N; 1 * 1], mij: [N; 1],
} }
small_dmat_impl!(DMatrix1, DVector1, 1, 0); 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); let mut res = $dmatrix::new_zeros(dimension, dimension);
for i in 0 .. dimension { for i in 0 .. dimension {
let _1: N = ::one(); res[(i, i)] = ::one::<N>();
res[(i, i)] = _1;
} }
res res
@ -94,7 +93,7 @@ macro_rules! dmat_impl(
} }
impl<N> $dmatrix<N> { impl<N> $dmatrix<N> {
#[inline(always)] #[inline]
fn offset(&self, i: usize, j: usize) -> usize { fn offset(&self, i: usize, j: usize) -> usize {
i + j * self.nrows i + j * self.nrows
} }
@ -774,9 +773,8 @@ macro_rules! dmat_impl(
// We can init from slice thanks to the matrix being column-major. // We can init from slice thanks to the matrix being column-major.
let start = self.offset(row_start, column_id); let start = self.offset(row_start, column_id);
let stop = self.offset(row_end, 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 { let mut slice : $dvector<N> = unsafe {
$dvector::new_uninitialized(column_end - column_start) $dvector::new_uninitialized(column_end - column_start)
}; };
let mut slice_idx = 0;
for column_id in column_start .. column_end { for column_id in column_start .. column_end {
unsafe { unsafe {
let slice_idx = column_id - column_start;
slice.unsafe_set(slice_idx, self.unsafe_at((row_id, column_id))); slice.unsafe_set(slice_idx, self.unsafe_at((row_id, column_id)));
} }
slice_idx += 1;
} }
slice 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] #[inline]
fn set_diagonal(&mut self, diagonal: &$dvector<N>) { fn set_diagonal(&mut self, diagonal: &$dvector<N>) {
let smallest_dim = cmp::min(self.nrows, self.ncols); 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. /// 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> { pub fn from_fn<F: FnMut(usize, usize) -> N>(nrows: usize, ncols: usize, mut f: F) -> $dmatrix<N> {
assert!(nrows <= $dimension); assert!(nrows <= $dimension);
assert!(ncols <= $dimension); assert!(ncols <= $dimension);

View File

@ -56,9 +56,9 @@ impl<N: Clone> DVector<N> {
impl<N> DVector<N> { impl<N> DVector<N> {
/// Builds a vector filled with the results of a function applied to each of its component coordinates. /// Builds a vector filled with the results of a function applied to each of its component coordinates.
#[inline(always)] #[inline]
pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, mut f: F) -> DVector<N> { pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, f: F) -> DVector<N> {
DVector { at: (0 .. dimension).map(|i| f(i)).collect() } DVector { at: (0 .. dimension).map(f).collect() }
} }
/// The vector length. /// The vector length.

View File

@ -191,7 +191,7 @@ macro_rules! small_dvec_from_impl (
impl<N: Zero> $dvector<N> { impl<N: Zero> $dvector<N> {
/// Builds a vector filled with the result of a function. /// 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> { pub fn from_fn<F: FnMut(usize) -> N>(dimension: usize, mut f: F) -> $dvector<N> {
assert!(dimension <= $dimension); assert!(dimension <= $dimension);

View File

@ -44,7 +44,7 @@ pub struct Isometry3<N> {
pub translation: Vector3<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 /// Creates an isometry that corresponds to the local frame of an observer standing at the
/// point `eye` and looking toward `target`. /// point `eye` and looking toward `target`.
/// ///
@ -59,7 +59,7 @@ impl<N: Clone + BaseFloat> Isometry3<N> {
#[inline] #[inline]
pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Isometry3<N> { 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); 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. /// 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 rotation = Rotation3::look_at_rh(&(*target - *eye), up);
let trans = rotation * (-*eye); 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. /// 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 rotation = Rotation3::look_at_lh(&(*target - *eye), up);
let trans = rotation * (-*eye); 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); isometry_impl!(Isometry2, Rotation2, Vector2, Vector1, Point2, Matrix3);
rotation_matrix_impl!(Isometry2, Rotation2, Vector2, Vector1);
rotation_impl!(Isometry2, Rotation2, Vector1);
dim_impl!(Isometry2, 2); 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); isometry_impl!(Isometry3, Rotation3, Vector3, Vector3, Point3, Matrix4);
rotation_matrix_impl!(Isometry3, Rotation3, Vector3, Vector3);
rotation_impl!(Isometry3, Rotation3, Vector3);
dim_impl!(Isometry3, 3); 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_use]
macro_rules! isometry_impl( 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> { impl<N: BaseFloat> $t<N> {
/// Creates a new isometry from an axis-angle rotation, and a vector. /// Creates a new isometry from an axis-angle rotation, and a vector.
#[inline] #[inline]
pub fn new(translation: $subvector<N>, rotation: $subrotvector<N>) -> $t<N> { pub fn new(translation: $vector<N>, rotation: $rotvector<N>) -> $t<N> {
$t { $t {
rotation: $submatrix::new(rotation), rotation: $rotmatrix::new(rotation),
translation: translation translation: translation
} }
} }
/// Creates a new isometry from a rotation matrix and a vector. /// Creates a new isometry from a rotation matrix and a vector.
#[inline] #[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 { $t {
rotation: rotation, rotation: rotation,
translation: translation translation: translation
} }
} }
} }
)
);
macro_rules! rotation_matrix_impl(
($t: ident, $trotation: ident, $tlv: ident, $tav: ident) => ( /*
*
* RotationMatrix
*
*/
impl<N: Cast<f64> + BaseFloat> impl<N: Cast<f64> + BaseFloat>
RotationMatrix<N, $tlv<N>, $tav<N>> for $t<N> { RotationMatrix<N, $vector<N>, $rotvector<N>> for $t<N> {
type Output = $trotation<N>; type Output = $rotmatrix<N>;
#[inline] #[inline]
fn to_rotation_matrix(&self) -> $trotation<N> { fn to_rotation_matrix(&self) -> $rotmatrix<N> {
self.rotation self.rotation
} }
} }
)
);
macro_rules! dim_impl( /*
($t: ident, $dimension: expr) => ( *
impl<N> Dimension for $t<N> { * One
#[inline] *
fn dimension(_: Option<$t<N>>) -> usize { */
$dimension
}
}
)
);
macro_rules! one_impl(
($t: ident) => (
impl<N: BaseFloat> One for $t<N> { impl<N: BaseFloat> One for $t<N> {
#[inline] #[inline]
fn one() -> $t<N> { 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> { impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
type Output = $t<N>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $t<N> { fn mul(self, right: $t<N>) -> $t<N> {
$t::new_with_rotation_matrix( $t::from_rotation_matrix(
self.translation + self.rotation * right.translation, self.translation + self.rotation * right.translation,
self.rotation * right.rotation) self.rotation * right.rotation)
} }
@ -81,192 +76,208 @@ macro_rules! isometry_mul_isometry_impl(
self.rotation *= right.rotation; 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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $rotation<N>) -> $t<N> { fn mul(self, right: $rotmatrix<N>) -> $t<N> {
$t::new_with_rotation_matrix(self.translation, self.rotation * right) $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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $t<N> { fn mul(self, right: $t<N>) -> $t<N> {
$t::new_with_rotation_matrix( $t::from_rotation_matrix(
self * right.translation, self * right.translation,
self * right.rotation) self * right.rotation)
} }
} }
impl<N: BaseFloat> MulAssign<$rotation<N>> for $t<N> { impl<N: BaseFloat> MulAssign<$rotmatrix<N>> for $t<N> {
#[inline] #[inline]
fn mul_assign(&mut self, right: $rotation<N>) { fn mul_assign(&mut self, right: $rotmatrix<N>) {
self.rotation *= right 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] #[inline]
fn mul(self, right: $tv<N>) -> $tv<N> { fn mul(self, right: $point<N>) -> $point<N> {
self.rotation * right + self.translation 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] #[inline]
fn mul(self, right: $tv<N>) -> $tv<N> { fn mul(self, right: $vector<N>) -> $vector<N> {
self.rotation * right 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] #[inline]
fn translation(&self) -> $tv<N> { fn translation(&self) -> $vector<N> {
self.translation self.translation
} }
#[inline] #[inline]
fn inverse_translation(&self) -> $tv<N> { fn inverse_translation(&self) -> $vector<N> {
-self.translation -self.translation
} }
#[inline] #[inline]
fn append_translation_mut(&mut self, t: &$tv<N>) { fn append_translation_mut(&mut self, t: &$vector<N>) {
self.translation = *t + self.translation self.translation = *t + self.translation
} }
#[inline] #[inline]
fn append_translation(&self, t: &$tv<N>) -> $t<N> { fn append_translation(&self, t: &$vector<N>) -> $t<N> {
$t::new_with_rotation_matrix(*t + self.translation, self.rotation) $t::from_rotation_matrix(*t + self.translation, self.rotation)
} }
#[inline] #[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 self.translation = self.translation + self.rotation * *t
} }
#[inline] #[inline]
fn prepend_translation(&self, t: &$tv<N>) -> $t<N> { fn prepend_translation(&self, t: &$vector<N>) -> $t<N> {
$t::new_with_rotation_matrix(self.translation + self.rotation * *t, self.rotation) $t::from_rotation_matrix(self.translation + self.rotation * *t, self.rotation)
} }
#[inline] #[inline]
fn set_translation(&mut self, t: $tv<N>) { fn set_translation(&mut self, t: $vector<N>) {
self.translation = t 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] #[inline]
fn translate(&self, v: &$tv<N>) -> $tv<N> { fn translate(&self, v: &$point<N>) -> $point<N> {
*v + self.translation *v + self.translation
} }
#[inline] #[inline]
fn inverse_translate(&self, v: &$tv<N>) -> $tv<N> { fn inverse_translate(&self, v: &$point<N>) -> $point<N> {
*v - self.translation *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] #[inline]
fn rotation(&self) -> $tav<N> { fn rotation(&self) -> $rotvector<N> {
self.rotation.rotation() self.rotation.rotation()
} }
#[inline] #[inline]
fn inverse_rotation(&self) -> $tav<N> { fn inverse_rotation(&self) -> $rotvector<N> {
self.rotation.inverse_rotation() self.rotation.inverse_rotation()
} }
#[inline] #[inline]
fn append_rotation_mut(&mut self, rotation: &$tav<N>) { fn append_rotation_mut(&mut self, rotation: &$rotvector<N>) {
let delta = $trotation::new(*rotation); let delta = $rotmatrix::new(*rotation);
self.rotation = delta * self.rotation; self.rotation = delta * self.rotation;
self.translation = delta * self.translation; self.translation = delta * self.translation;
} }
#[inline] #[inline]
fn append_rotation(&self, rotation: &$tav<N>) -> $t<N> { fn append_rotation(&self, rotation: &$rotvector<N>) -> $t<N> {
let delta = $trotation::new(*rotation); 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] #[inline]
fn prepend_rotation_mut(&mut self, rotation: &$tav<N>) { fn prepend_rotation_mut(&mut self, rotation: &$rotvector<N>) {
let delta = $trotation::new(*rotation); let delta = $rotmatrix::new(*rotation);
self.rotation = self.rotation * delta; self.rotation = self.rotation * delta;
} }
#[inline] #[inline]
fn prepend_rotation(&self, rotation: &$tav<N>) -> $t<N> { fn prepend_rotation(&self, rotation: &$rotvector<N>) -> $t<N> {
let delta = $trotation::new(*rotation); 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] #[inline]
fn set_rotation(&mut self, rotation: $tav<N>) { fn set_rotation(&mut self, rotation: $rotvector<N>) {
// FIXME: should the translation be changed too? // FIXME: should the translation be changed too?
self.rotation.set_rotation(rotation) 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] #[inline]
fn rotate(&self, v: &$tv<N>) -> $tv<N> { fn rotate(&self, v: &$vector<N>) -> $vector<N> {
self.rotation.rotate(v) self.rotation.rotate(v)
} }
#[inline] #[inline]
fn inverse_rotate(&self, v: &$tv<N>) -> $tv<N> { fn inverse_rotate(&self, v: &$vector<N>) -> $vector<N> {
self.rotation.inverse_rotate(v) self.rotation.inverse_rotate(v)
} }
} }
)
);
macro_rules! transformation_impl(
($t: ident) => ( /*
*
* Transformation
*
*/
impl<N: BaseFloat> Transformation<$t<N>> for $t<N> { impl<N: BaseFloat> Transformation<$t<N>> for $t<N> {
fn transformation(&self) -> $t<N> { fn transformation(&self) -> $t<N> {
*self *self
@ -297,27 +308,31 @@ macro_rules! transformation_impl(
*self = t *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] #[inline]
fn transform(&self, p: &$tp<N>) -> $tp<N> { fn transform(&self, p: &$point<N>) -> $point<N> {
self.rotation.transform(p) + self.translation self.rotation.transform(p) + self.translation
} }
#[inline] #[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)) self.rotation.inverse_transform(&(*p - self.translation))
} }
} }
)
);
macro_rules! inverse_impl(
($t: ident) => ( /*
*
* Inverse
*
*/
impl<N: BaseNum + Neg<Output = N>> Inverse for $t<N> { impl<N: BaseNum + Neg<Output = N>> Inverse for $t<N> {
#[inline] #[inline]
fn inverse_mut(&mut self) -> bool { fn inverse_mut(&mut self) -> bool {
@ -335,28 +350,32 @@ macro_rules! inverse_impl(
Some(res) 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(); let mut res = self.rotation.to_homogeneous();
// copy the translation // 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.set_column(dimension - 1, self.translation.as_point().to_homogeneous().to_vector());
res res
} }
} }
)
);
macro_rules! approx_eq_impl(
($t: ident) => ( /*
*
* ApproxEq
*
*/
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> { impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline] #[inline]
fn approx_epsilon(_: Option<$t<N>>) -> N { 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) ApproxEq::approx_eq_ulps(&self.translation, &other.translation, ulps)
} }
} }
)
);
macro_rules! rand_impl(
($t: ident) => ( /*
*
* Rand
*
*/
impl<N: Rand + BaseFloat> Rand for $t<N> { impl<N: Rand + BaseFloat> Rand for $t<N> {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> $t<N> { fn rand<R: Rng>(rng: &mut R) -> $t<N> {
$t::new(rng.gen(), rng.gen()) $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] #[inline]
fn absolute_rotate(&self, v: &$tv<N>) -> $tv<N> { fn absolute_rotate(&self, v: &$vector<N>) -> $vector<N> {
self.rotation.absolute_rotate(v) self.rotation.absolute_rotate(v)
} }
} }
)
);
macro_rules! arbitrary_isometry_impl(
($t: ident) => ( /*
*
* Arbitrary
*
*/
#[cfg(feature="arbitrary")] #[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> { impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
fn arbitrary<G: Gen>(g: &mut G) -> $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),
Arbitrary::arbitrary(g) Arbitrary::arbitrary(g)
) )
} }
} }
)
);
macro_rules! isometry_display_impl(
($t: ident) => ( /*
*
* Display
*
*/
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> { impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "Isometry {{")); 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 structs::dvector::{DVector1, DVector2, DVector3, DVector4, DVector5, DVector6};
use traits::structure::{Cast, Row, Column, Iterable, IterableMut, Dimension, Indexable, Eye, ColumnSlice, 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::operations::{Absolute, Transpose, Inverse, Outer, EigenQR, Mean};
use traits::geometry::{ToHomogeneous, FromHomogeneous, Origin}; use traits::geometry::{ToHomogeneous, FromHomogeneous, Origin};
use linalg; use linalg;
@ -50,45 +50,20 @@ pub struct Matrix1<N> {
eye_impl!(Matrix1, 1, m11); eye_impl!(Matrix1, 1, m11);
mat_impl!(Matrix1, m11); matrix_impl!(Matrix1, 1, Vector1, DVector1, 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);
one_impl!(Matrix1, ::one); one_impl!(Matrix1, ::one);
iterable_impl!(Matrix1, 1);
iterable_mut_impl!(Matrix1, 1);
at_fast_impl!(Matrix1, 1);
dim_impl!(Matrix1, 1); dim_impl!(Matrix1, 1);
indexable_impl!(Matrix1, 1);
index_impl!(Matrix1, 1);
mat_mul_mat_impl!(Matrix1, 1); mat_mul_mat_impl!(Matrix1, 1);
mat_mul_vec_impl!(Matrix1, Vector1, 1, ::zero); mat_mul_vec_impl!(Matrix1, Vector1, 1, ::zero);
vec_mul_mat_impl!(Matrix1, Vector1, 1, ::zero); vec_mul_mat_impl!(Matrix1, Vector1, 1, ::zero);
mat_mul_point_impl!(Matrix1, Point1, 1, Origin::origin); mat_mul_point_impl!(Matrix1, Point1, 1, Origin::origin);
point_mul_mat_impl!(Matrix1, Point1, 1, Origin::origin); point_mul_mat_impl!(Matrix1, Point1, 1, Origin::origin);
// (specialized); inverse_impl!(Matrix1, 1); // (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); to_homogeneous_impl!(Matrix1, Matrix2, 1, 2);
from_homogeneous_impl!(Matrix1, Matrix2, 1, 2); from_homogeneous_impl!(Matrix1, Matrix2, 1, 2);
outer_impl!(Vector1, Matrix1);
eigen_qr_impl!(Matrix1, Vector1); eigen_qr_impl!(Matrix1, Vector1);
arbitrary_impl!(Matrix1, m11); componentwise_arbitrary!(Matrix1, m11);
rand_impl!(Matrix1, m11); componentwise_rand!(Matrix1, m11);
mean_impl!(Matrix1, Vector1, 1);
mat_display_impl!(Matrix1, 1); mat_display_impl!(Matrix1, 1);
/// Square matrix of dimension 2. /// Square matrix of dimension 2.
@ -101,49 +76,20 @@ pub struct Matrix2<N> {
eye_impl!(Matrix2, 2, m11, m22); eye_impl!(Matrix2, 2, m11, m22);
mat_impl!(Matrix2, m11, m12, matrix_impl!(Matrix2, 2, Vector2, DVector2, m11, m12,
m21, m22);
repeat_impl!(Matrix2, m11, m12,
m21, m22);
conversion_impl!(Matrix2, 2);
mat_cast_impl!(Matrix2, m11, m12,
m21, m22);
add_impl!(Matrix2, m11, m12, m21, m22);
sub_impl!(Matrix2, m11, m12, m21, m22);
scalar_add_impl!(Matrix2, m11, m12, m21, m22);
scalar_sub_impl!(Matrix2, m11, m12, m21, m22);
scalar_mul_impl!(Matrix2, m11, m12, m21, m22);
scalar_div_impl!(Matrix2, m11, m12, m21, m22);
absolute_impl!(Matrix2, m11, m12,
m21, m22);
zero_impl!(Matrix2, m11, m12,
m21, m22); m21, m22);
one_impl!(Matrix2, ::one, ::zero, one_impl!(Matrix2, ::one, ::zero,
::zero, ::one); ::zero, ::one);
iterable_impl!(Matrix2, 2);
iterable_mut_impl!(Matrix2, 2);
dim_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); mul_impl!(Matrix2, 2);
// (specialized); rmul_impl!(Matrix2, Vector2, 2); // (specialized); rmul_impl!(Matrix2, Vector2, 2);
// (specialized); lmul_impl!(Matrix2, Vector2, 2); // (specialized); lmul_impl!(Matrix2, Vector2, 2);
// (specialized); inverse_impl!(Matrix2, 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); to_homogeneous_impl!(Matrix2, Matrix3, 2, 3);
from_homogeneous_impl!(Matrix2, Matrix3, 2, 3); from_homogeneous_impl!(Matrix2, Matrix3, 2, 3);
outer_impl!(Vector2, Matrix2);
eigen_qr_impl!(Matrix2, Vector2); eigen_qr_impl!(Matrix2, Vector2);
arbitrary_impl!(Matrix2, m11, m12, m21, m22); componentwise_arbitrary!(Matrix2, m11, m12, m21, m22);
rand_impl!(Matrix2, m11, m12, m21, m22); componentwise_rand!(Matrix2, m11, m12, m21, m22);
mean_impl!(Matrix2, Vector2, 2);
mat_display_impl!(Matrix2, 2); mat_display_impl!(Matrix2, 2);
/// Square matrix of dimension 3. /// Square matrix of dimension 3.
@ -157,91 +103,30 @@ pub struct Matrix3<N> {
eye_impl!(Matrix3, 3, m11, m22, m33); 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, m21, m22, m23,
m31, m32, m33); 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, one_impl!(Matrix3, ::one , ::zero, ::zero,
::zero, ::one , ::zero, ::zero, ::one , ::zero,
::zero, ::zero, ::one); ::zero, ::zero, ::one);
iterable_impl!(Matrix3, 3);
iterable_mut_impl!(Matrix3, 3);
dim_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); mul_impl!(Matrix3, 3);
// (specialized); rmul_impl!(Matrix3, Vector3, 3); // (specialized); rmul_impl!(Matrix3, Vector3, 3);
// (specialized); lmul_impl!(Matrix3, Vector3, 3); // (specialized); lmul_impl!(Matrix3, Vector3, 3);
// (specialized); inverse_impl!(Matrix3, 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); to_homogeneous_impl!(Matrix3, Matrix4, 3, 4);
from_homogeneous_impl!(Matrix3, Matrix4, 3, 4); from_homogeneous_impl!(Matrix3, Matrix4, 3, 4);
outer_impl!(Vector3, Matrix3);
eigen_qr_impl!(Matrix3, Vector3); eigen_qr_impl!(Matrix3, Vector3);
arbitrary_impl!(Matrix3, componentwise_arbitrary!(Matrix3,
m11, m12, m13, m11, m12, m13,
m21, m22, m23, m21, m22, m23,
m31, m32, m33 m31, m32, m33
); );
rand_impl!(Matrix3, componentwise_rand!(Matrix3,
m11, m12, m13, m11, m12, m13,
m21, m22, m23, m21, m22, m23,
m31, m32, m33 m31, m32, m33
); );
mean_impl!(Matrix3, Vector3, 3);
mat_display_impl!(Matrix3, 3); mat_display_impl!(Matrix3, 3);
/// Square matrix of dimension 4. /// Square matrix of dimension 4.
@ -256,68 +141,7 @@ pub struct Matrix4<N> {
eye_impl!(Matrix4, 4, m11, m22, m33, m44); eye_impl!(Matrix4, 4, m11, m22, m33, m44);
mat_impl!(Matrix4, matrix_impl!(Matrix4, 4, Vector4, DVector4,
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,
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
@ -327,42 +151,28 @@ one_impl!(Matrix4, ::one , ::zero, ::zero, ::zero,
::zero, ::one , ::zero, ::zero, ::zero, ::one , ::zero, ::zero,
::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::one , ::zero,
::zero, ::zero, ::zero, ::one); ::zero, ::zero, ::zero, ::one);
iterable_impl!(Matrix4, 4);
iterable_mut_impl!(Matrix4, 4);
dim_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_mat_impl!(Matrix4, 4);
mat_mul_vec_impl!(Matrix4, Vector4, 4, ::zero); mat_mul_vec_impl!(Matrix4, Vector4, 4, ::zero);
vec_mul_mat_impl!(Matrix4, Vector4, 4, ::zero); vec_mul_mat_impl!(Matrix4, Vector4, 4, ::zero);
mat_mul_point_impl!(Matrix4, Point4, 4, Origin::origin); mat_mul_point_impl!(Matrix4, Point4, 4, Origin::origin);
point_mul_mat_impl!(Matrix4, Point4, 4, Origin::origin); point_mul_mat_impl!(Matrix4, Point4, 4, Origin::origin);
inverse_impl!(Matrix4, 4); 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); to_homogeneous_impl!(Matrix4, Matrix5, 4, 5);
from_homogeneous_impl!(Matrix4, Matrix5, 4, 5); from_homogeneous_impl!(Matrix4, Matrix5, 4, 5);
outer_impl!(Vector4, Matrix4);
eigen_qr_impl!(Matrix4, Vector4); eigen_qr_impl!(Matrix4, Vector4);
arbitrary_impl!(Matrix4, componentwise_arbitrary!(Matrix4,
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
m41, m42, m43, m44 m41, m42, m43, m44
); );
rand_impl!(Matrix4, componentwise_rand!(Matrix4,
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
m41, m42, m43, m44 m41, m42, m43, m44
); );
mean_impl!(Matrix4, Vector4, 4);
mat_display_impl!(Matrix4, 4); mat_display_impl!(Matrix4, 4);
/// Square matrix of dimension 5. /// Square matrix of dimension 5.
@ -378,36 +188,7 @@ pub struct Matrix5<N> {
eye_impl!(Matrix5, 5, m11, m22, m33, m44, m55); eye_impl!(Matrix5, 5, m11, m22, m33, m44, m55);
mat_impl!(Matrix5, matrix_impl!(Matrix5, 5, Vector5, DVector5,
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,
m11, m12, m13, m14, m15, m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25, m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35, m31, m32, m33, m34, m35,
@ -421,86 +202,30 @@ one_impl!(Matrix5,
::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::one , ::zero,
::zero, ::zero, ::zero, ::zero, ::one ::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); 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_mat_impl!(Matrix5, 5);
mat_mul_vec_impl!(Matrix5, Vector5, 5, ::zero); mat_mul_vec_impl!(Matrix5, Vector5, 5, ::zero);
vec_mul_mat_impl!(Matrix5, Vector5, 5, ::zero); vec_mul_mat_impl!(Matrix5, Vector5, 5, ::zero);
mat_mul_point_impl!(Matrix5, Point5, 5, Origin::origin); mat_mul_point_impl!(Matrix5, Point5, 5, Origin::origin);
point_mul_mat_impl!(Matrix5, Point5, 5, Origin::origin); point_mul_mat_impl!(Matrix5, Point5, 5, Origin::origin);
inverse_impl!(Matrix5, 5); 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); to_homogeneous_impl!(Matrix5, Matrix6, 5, 6);
from_homogeneous_impl!(Matrix5, Matrix6, 5, 6); from_homogeneous_impl!(Matrix5, Matrix6, 5, 6);
outer_impl!(Vector5, Matrix5);
eigen_qr_impl!(Matrix5, Vector5); eigen_qr_impl!(Matrix5, Vector5);
arbitrary_impl!(Matrix5, componentwise_arbitrary!(Matrix5,
m11, m12, m13, m14, m15, m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25, m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35, m31, m32, m33, m34, m35,
m41, m42, m43, m44, m45, m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55 m51, m52, m53, m54, m55
); );
rand_impl!(Matrix5, componentwise_rand!(Matrix5,
m11, m12, m13, m14, m15, m11, m12, m13, m14, m15,
m21, m22, m23, m24, m25, m21, m22, m23, m24, m25,
m31, m32, m33, m34, m35, m31, m32, m33, m34, m35,
m41, m42, m43, m44, m45, m41, m42, m43, m44, m45,
m51, m52, m53, m54, m55 m51, m52, m53, m54, m55
); );
mean_impl!(Matrix5, Vector5, 5);
mat_display_impl!(Matrix5, 5); mat_display_impl!(Matrix5, 5);
/// Square matrix of dimension 6. /// Square matrix of dimension 6.
@ -517,7 +242,7 @@ pub struct Matrix6<N> {
eye_impl!(Matrix6, 6, m11, m22, m33, m44, m55, m66); 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, m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26, m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36, m31, m32, m33, m34, m35, m36,
@ -525,78 +250,6 @@ mat_impl!(Matrix6,
m51, m52, m53, m54, m55, m56, m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66 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_impl!(Matrix6,
::one , ::zero, ::zero, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::zero,
@ -606,28 +259,15 @@ one_impl!(Matrix6,
::zero, ::zero, ::zero, ::zero, ::one , ::zero, ::zero, ::zero, ::zero, ::zero, ::one , ::zero,
::zero, ::zero, ::zero, ::zero, ::zero, ::one ::zero, ::zero, ::zero, ::zero, ::zero, ::one
); );
iterable_impl!(Matrix6, 6);
iterable_mut_impl!(Matrix6, 6);
dim_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_mat_impl!(Matrix6, 6);
mat_mul_vec_impl!(Matrix6, Vector6, 6, ::zero); mat_mul_vec_impl!(Matrix6, Vector6, 6, ::zero);
vec_mul_mat_impl!(Matrix6, Vector6, 6, ::zero); vec_mul_mat_impl!(Matrix6, Vector6, 6, ::zero);
mat_mul_point_impl!(Matrix6, Point6, 6, Origin::origin); mat_mul_point_impl!(Matrix6, Point6, 6, Origin::origin);
point_mul_mat_impl!(Matrix6, Point6, 6, Origin::origin); point_mul_mat_impl!(Matrix6, Point6, 6, Origin::origin);
inverse_impl!(Matrix6, 6); 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); eigen_qr_impl!(Matrix6, Vector6);
arbitrary_impl!(Matrix6, componentwise_arbitrary!(Matrix6,
m11, m12, m13, m14, m15, m16, m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26, m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36, m31, m32, m33, m34, m35, m36,
@ -635,7 +275,7 @@ arbitrary_impl!(Matrix6,
m51, m52, m53, m54, m55, m56, m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66 m61, m62, m63, m64, m65, m66
); );
rand_impl!(Matrix6, componentwise_rand!(Matrix6,
m11, m12, m13, m14, m15, m16, m11, m12, m13, m14, m15, m16,
m21, m22, m23, m24, m25, m26, m21, m22, m23, m24, m25, m26,
m31, m32, m33, m34, m35, m36, m31, m32, m33, m34, m35, m36,
@ -643,5 +283,4 @@ rand_impl!(Matrix6,
m51, m52, m53, m54, m55, m56, m51, m52, m53, m54, m55, m56,
m61, m62, m63, m64, m65, m66 m61, m62, m63, m64, m65, m66
); );
mean_impl!(Matrix6, Vector6, 6);
mat_display_impl!(Matrix6, 6); mat_display_impl!(Matrix6, 6);

View File

@ -1,7 +1,7 @@
#![macro_use] #![macro_use]
macro_rules! mat_impl( macro_rules! matrix_impl(
($t: ident, $($compN: ident),+) => ( ($t: ident, $dimension: expr, $vector: ident, $dvector: ident, $($compN: ident),+) => (
impl<N> $t<N> { impl<N> $t<N> {
#[inline] #[inline]
pub fn new($($compN: N ),+) -> $t<N> { 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> { impl<N> AsRef<[[N; $dimension]; $dimension]> for $t<N> {
#[inline] #[inline]
fn as_ref(&self) -> &[[N; $dimension]; $dimension] { fn as_ref(&self) -> &[[N; $dimension]; $dimension] {
@ -58,11 +60,13 @@ macro_rules! conversion_impl(
tref.clone() tref.clone()
} }
} }
)
);
macro_rules! at_fast_impl(
($t: ident, $dimension: expr) => ( /*
*
* Unsafe indexing.
*
*/
impl<N: Copy> $t<N> { impl<N: Copy> $t<N> {
#[inline] #[inline]
pub unsafe fn at_fast(&self, (i, j): (usize, usize)) -> N { 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 .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> { impl<Nin: Copy, Nout: Copy + Cast<Nin>> Cast<$t<Nin>> for $t<Nout> {
#[inline] #[inline]
fn from(v: $t<Nin>) -> $t<Nout> { fn from(v: $t<Nin>) -> $t<Nout> {
$t::new($(Cast::from(v.$compN)),+) $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>) { * Iterable
$( 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) => (
impl<N> Iterable<N> for $t<N> { impl<N> Iterable<N> for $t<N> {
#[inline] #[inline]
fn iter<'l>(&'l self) -> Iter<'l, N> { fn iter(&self) -> Iter<N> {
unsafe { 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> { impl<N> IterableMut<N> for $t<N> {
#[inline] #[inline]
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> { fn iter_mut(& mut self) -> IterMut<N> {
unsafe { 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> { * Shape/Indexable/Index
#[inline] *
fn dimension(_: Option<$t<N>>) -> usize { */
$dimension
}
}
)
);
macro_rules! indexable_impl(
($t: ident, $dimension: expr) => (
impl<N> Shape<(usize, usize)> for $t<N> { impl<N> Shape<(usize, usize)> for $t<N> {
#[inline] #[inline]
fn shape(&self) -> (usize, usize) { 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 (*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> { impl<N> Index<(usize, usize)> for $t<N> {
type Output = 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]) /*
} *
} * Row/Column
) *
); */
impl<N: Copy + Zero> Column<$vector<N>> for $t<N> {
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> {
#[inline] #[inline]
fn ncols(&self) -> usize { fn ncols(&self) -> usize {
Dimension::dimension(None::<$t<N>>) Dimension::dimension(None::<$t<N>>)
} }
#[inline] #[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() { for (i, e) in v.iter().enumerate() {
self[(i, column)] = *e; self[(i, column)] = *e;
} }
} }
#[inline] #[inline]
fn column(&self, column: usize) -> $tv<N> { fn column(&self, column: usize) -> $vector<N> {
let mut res: $tv<N> = ::zero(); let mut res: $vector<N> = ::zero();
for (i, e) in res.iter_mut().enumerate() { for (i, e) in res.iter_mut().enumerate() {
*e = self[(i, column)]; *e = self[(i, column)];
@ -500,14 +199,136 @@ macro_rules! column_impl(
res res
} }
} }
)
);
macro_rules! diag_impl( impl<N: Clone + Copy + Zero> ColumnSlice<$dvector<N>> for $t<N> {
($t: ident, $tv: ident, $dimension: expr) => ( fn column_slice(&self, cid: usize, rstart: usize, rend: usize) -> $dvector<N> {
impl<N: Copy + Zero> Diagonal<$tv<N>> for $t<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] #[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(); let mut res: $t<N> = ::zero();
res.set_diagonal(diagonal); res.set_diagonal(diagonal);
@ -516,8 +337,8 @@ macro_rules! diag_impl(
} }
#[inline] #[inline]
fn diagonal(&self) -> $tv<N> { fn diagonal(&self) -> $vector<N> {
let mut diagonal: $tv<N> = ::zero(); let mut diagonal: $vector<N> = ::zero();
for i in 0 .. $dimension { for i in 0 .. $dimension {
unsafe { diagonal.unsafe_set(i, self.unsafe_at((i, i))) } 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] #[inline]
fn set_diagonal(&mut self, diagonal: &$tv<N>) { fn set_diagonal(&mut self, diagonal: &$vector<N>) {
for i in 0 .. $dimension { for i in 0 .. $dimension {
unsafe { self.unsafe_set((i, i), diagonal.unsafe_at(i)) } 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( macro_rules! mat_mul_mat_impl(
($t: ident, $dimension: expr) => ( ($t: ident, $dimension: expr) => (
impl<N: Copy + BaseNum> Mul<$t<N>> for $t<N> { 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( macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident, $dimension: expr, $dim2: expr) => ( ($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( macro_rules! eigen_qr_impl(
($t: ident, $v: ident) => ( ($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( macro_rules! mat_display_impl(
($t: ident, $dimension: expr) => ( ($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::perspective::{Perspective3, PerspectiveMatrix3};
pub use self::orthographic::{Orthographic3, OrthographicMatrix3}; pub use self::orthographic::{Orthographic3, OrthographicMatrix3};
pub use self::quaternion::{Quaternion, UnitQuaternion}; pub use self::quaternion::{Quaternion, UnitQuaternion};
pub use self::unit::Unit;
#[cfg(feature="generic_sizes")] #[cfg(feature="generic_sizes")]
pub use self::vectorn::VectorN; pub use self::vectorn::VectorN;
mod common_macros;
mod dmatrix_macros; mod dmatrix_macros;
mod dmatrix; mod dmatrix;
mod vectorn_macros; mod vectorn_macros;
@ -37,6 +39,7 @@ mod similarity_macros;
mod similarity; mod similarity;
mod perspective; mod perspective;
mod orthographic; mod orthographic;
mod unit;
// Specialization for some 1d, 2d and 3d operations. // Specialization for some 1d, 2d and 3d operations.
#[doc(hidden)] #[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. /// The smallest x-coordinate of the view cuboid.
#[inline] #[inline]
pub fn left(&self) -> N { pub fn left(&self) -> N {
self.left.clone() self.left
} }
/// The largest x-coordinate of the view cuboid. /// The largest x-coordinate of the view cuboid.
#[inline] #[inline]
pub fn right(&self) -> N { pub fn right(&self) -> N {
self.right.clone() self.right
} }
/// The smallest y-coordinate of the view cuboid. /// The smallest y-coordinate of the view cuboid.
#[inline] #[inline]
pub fn bottom(&self) -> N { pub fn bottom(&self) -> N {
self.bottom.clone() self.bottom
} }
/// The largest y-coordinate of the view cuboid. /// The largest y-coordinate of the view cuboid.
#[inline] #[inline]
pub fn top(&self) -> N { pub fn top(&self) -> N {
self.top.clone() self.top
} }
/// The near plane offset of the view cuboid. /// The near plane offset of the view cuboid.
#[inline] #[inline]
pub fn znear(&self) -> N { pub fn znear(&self) -> N {
self.znear.clone() self.znear
} }
/// The far plane offset of the view cuboid. /// The far plane offset of the view cuboid.
#[inline] #[inline]
pub fn zfar(&self) -> N { pub fn zfar(&self) -> N {
self.zfar.clone() self.zfar
} }
/// Sets the smallest x-coordinate of the view cuboid. /// 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. /// 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!(znear < zfar, "The far plane must be farther than the near plane.");
assert!(!::is_zero(&aspect)); assert!(!::is_zero(&aspect));
let _1: N = ::one(); let half: N = ::cast(0.5);
let _2 = _1 + _1; let width = zfar * (vfov * half).tan();
let width = zfar * (vfov / _2).tan();
let height = width / aspect; 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. /// 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] #[inline]
pub unsafe fn new_with_matrix(matrix: Matrix4<N>) -> OrthographicMatrix3<N> { pub fn from_matrix_unchecked(matrix: Matrix4<N>) -> OrthographicMatrix3<N> {
OrthographicMatrix3 { OrthographicMatrix3 {
matrix: matrix matrix: matrix
} }
@ -207,7 +204,7 @@ impl<N: BaseFloat> OrthographicMatrix3<N> {
/// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection. /// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection.
#[inline] #[inline]
pub fn as_matrix<'a>(&'a self) -> &'a Matrix4<N> { pub fn as_matrix(&self) -> &Matrix4<N> {
&self.matrix &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. /// Returns the 4D matrix (using homogeneous coordinates) of this projection.
#[inline] #[inline]
pub fn to_matrix<'a>(&'a self) -> Matrix4<N> { pub fn to_matrix(&self) -> Matrix4<N> {
self.matrix.clone() 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")] #[cfg(feature="arbitrary")]
#[inline] #[inline]
pub fn reject<G: Gen, F: FnMut(&T) -> bool, T: Arbitrary>(g: &mut G, f: F) -> T { 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. /// Gets the `width / height` aspect ratio.
#[inline] #[inline]
pub fn aspect(&self) -> N { pub fn aspect(&self) -> N {
self.aspect.clone() self.aspect
} }
/// Gets the y field of view of the view frustrum. /// Gets the y field of view of the view frustrum.
#[inline] #[inline]
pub fn fovy(&self) -> N { pub fn fovy(&self) -> N {
self.fovy.clone() self.fovy
} }
/// Gets the near plane offset of the view frustrum. /// Gets the near plane offset of the view frustrum.
#[inline] #[inline]
pub fn znear(&self) -> N { pub fn znear(&self) -> N {
self.znear.clone() self.znear
} }
/// Gets the far plane offset of the view frustrum. /// Gets the far plane offset of the view frustrum.
#[inline] #[inline]
pub fn zfar(&self) -> N { pub fn zfar(&self) -> N {
self.zfar.clone() self.zfar
} }
/// Sets the `width / height` aspect ratio of the view frustrum. /// 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. /// 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] #[inline]
pub unsafe fn new_with_matrix(matrix: Matrix4<N>) -> PerspectiveMatrix3<N> { pub fn from_matrix_unchecked(matrix: Matrix4<N>) -> PerspectiveMatrix3<N> {
PerspectiveMatrix3 { PerspectiveMatrix3 {
matrix: matrix matrix: matrix
} }
@ -165,7 +163,7 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
/// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection. /// Returns a reference to the 4D matrix (using homogeneous coordinates) of this projection.
#[inline] #[inline]
pub fn as_matrix<'a>(&'a self) -> &'a Matrix4<N> { pub fn as_matrix(&self) -> &Matrix4<N> {
&self.matrix &self.matrix
} }
@ -178,30 +176,23 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
/// Gets the y field of view of the view frustrum. /// Gets the y field of view of the view frustrum.
#[inline] #[inline]
pub fn fovy(&self) -> N { pub fn fovy(&self) -> N {
let _1: N = ::one(); (::one::<N>() / self.matrix.m22).atan() * ::cast(2.0)
let _2 = _1 + _1;
(_1 / self.matrix.m22).atan() * _2
} }
/// Gets the near plane offset of the view frustrum. /// Gets the near plane offset of the view frustrum.
#[inline] #[inline]
pub fn znear(&self) -> N { pub fn znear(&self) -> N {
let _1: N = ::one(); let ratio = (-self.matrix.m33 + ::one::<N>()) / (-self.matrix.m33 - ::one::<N>());
let _2 = _1 + _1;
let ratio = (-self.matrix.m33 + _1) / (-self.matrix.m33 - _1);
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. /// Gets the far plane offset of the view frustrum.
#[inline] #[inline]
pub fn zfar(&self) -> N { pub fn zfar(&self) -> N {
let _1: N = ::one(); let ratio = (-self.matrix.m33 + ::one()) / (-self.matrix.m33 - ::one());
let _2 = _1 + _1;
let ratio = (-self.matrix.m33 + _1) / (-self.matrix.m33 - _1);
(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? // 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. /// Updates this projection with a new y field of view of the view frustrum.
#[inline] #[inline]
pub fn set_fovy(&mut self, fovy: N) { pub fn set_fovy(&mut self, fovy: N) {
let _1: N = ::one(); let old_m22 = self.matrix.m22;
let _2 = _1 + _1; self.matrix.m22 = ::one::<N>() / (fovy / ::cast(2.0)).tan();
let old_m22 = self.matrix.m22.clone();
self.matrix.m22 = _1 / (fovy / _2).tan();
self.matrix.m11 = self.matrix.m11 * (self.matrix.m22 / old_m22); 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. /// Updates this projection matrix with new near and far plane offsets of the view frustrum.
#[inline] #[inline]
pub fn set_znear_and_zfar(&mut self, znear: N, zfar: N) { 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.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. /// Projects a point.
#[inline] #[inline]
pub fn project_point(&self, p: &Point3<N>) -> Point3<N> { pub fn project_point(&self, p: &Point3<N>) -> Point3<N> {
let _1: N = ::one(); let inverse_denom = -::one::<N>() / p.z;
let inverse_denom = -_1 / p.z;
Point3::new( Point3::new(
self.matrix.m11 * p.x * inverse_denom, self.matrix.m11 * p.x * inverse_denom,
self.matrix.m22 * p.y * inverse_denom, self.matrix.m22 * p.y * inverse_denom,
@ -264,8 +249,8 @@ impl<N: BaseFloat> PerspectiveMatrix3<N> {
/// Projects a vector. /// Projects a vector.
#[inline] #[inline]
pub fn project_vector(&self, p: &Vector3<N>) -> Vector3<N> { pub fn project_vector(&self, p: &Vector3<N>) -> Vector3<N> {
let _1: N = ::one(); let inverse_denom = -::one::<N>() / p.z;
let inverse_denom = -_1 / p.z;
Vector3::new( Vector3::new(
self.matrix.m11 * p.x * inverse_denom, self.matrix.m11 * p.x * inverse_denom,
self.matrix.m22 * p.y * 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. /// Returns the 4D matrix (using homogeneous coordinates) of this projection.
#[inline] #[inline]
pub fn to_matrix<'a>(&'a self) -> Matrix4<N> { pub fn to_matrix(&self) -> Matrix4<N> {
self.matrix.clone() self.matrix
} }
} }

View File

@ -27,38 +27,9 @@ pub struct Point1<N> {
pub x: N pub x: N
} }
new_impl!(Point1, x); point_impl!(Point1, Vector1, Point2, y | x);
origin_impl!(Point1, x); vectorlike_impl!(Point1, 1, 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);
from_iterator_impl!(Point1, iterator); 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. /// Point of dimension 2.
/// ///
@ -73,38 +44,9 @@ pub struct Point2<N> {
pub y: N pub y: N
} }
new_impl!(Point2, x, y); point_impl!(Point2, Vector2, Point3, z | x, y);
origin_impl!(Point2, x, y); vectorlike_impl!(Point2, 2, 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);
from_iterator_impl!(Point2, iterator, iterator); 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. /// Point of dimension 3.
/// ///
@ -121,38 +63,9 @@ pub struct Point3<N> {
pub z: N pub z: N
} }
new_impl!(Point3, x, y, z); point_impl!(Point3, Vector3, Point4, w | x, y, z);
origin_impl!(Point3, x, y, z); vectorlike_impl!(Point3, 3, 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);
from_iterator_impl!(Point3, iterator, iterator, iterator); 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. /// Point of dimension 4.
/// ///
@ -171,38 +84,9 @@ pub struct Point4<N> {
pub w: N pub w: N
} }
new_impl!(Point4, x, y, z, w); point_impl!(Point4, Vector4, Point5, a | x, y, z, w);
origin_impl!(Point4, x, y, z, w); vectorlike_impl!(Point4, 4, 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);
from_iterator_impl!(Point4, iterator, iterator, iterator, iterator); 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. /// Point of dimension 5.
/// ///
@ -223,38 +107,9 @@ pub struct Point5<N> {
pub a: N pub a: N
} }
new_impl!(Point5, x, y, z, w, a); point_impl!(Point5, Vector5, Point6, b | x, y, z, w, a);
origin_impl!(Point5, x, y, z, w, a); vectorlike_impl!(Point5, 5, 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);
from_iterator_impl!(Point5, iterator, iterator, iterator, iterator, iterator); 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. /// Point of dimension 6.
/// ///
@ -277,33 +132,6 @@ pub struct Point6<N> {
pub b: N pub b: N
} }
new_impl!(Point6, x, y, z, w, a, b); point_impl!(Point6, Vector6 | x, y, z, w, a, b);
origin_impl!(Point6, x, y, z, w, a, b); vectorlike_impl!(Point6, 6, 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);
from_iterator_impl!(Point6, iterator, iterator, iterator, iterator, iterator, iterator); 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_use]
macro_rules! origin_impl( macro_rules! point_impl(
($t: ident, $($compN: ident),+) => ( ($t: ident, $tv: ident | $($compN: ident),+) => (
/*
*
* Origin.
*
*/
impl<N: Zero> Origin for $t<N> { impl<N: Zero> Origin for $t<N> {
#[inline] #[inline]
fn origin() -> $t<N> { fn origin() -> $t<N> {
@ -15,11 +21,13 @@ macro_rules! origin_impl(
$(self.$compN.is_zero() )&&+ $(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> { impl<N: Copy + Sub<N, Output = N>> Sub<$t<N>> for $t<N> {
type Output = $tv<N>; type Output = $tv<N>;
@ -28,11 +36,13 @@ macro_rules! point_sub_impl(
*self.as_vector() - *right.as_vector() *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> { impl<N: Copy + Add<N, Output = N>> Add<$tv<N>> for $t<N> {
type Output = $t<N>; type Output = $t<N>;
@ -48,11 +58,13 @@ macro_rules! point_add_vec_impl(
$( self.$compN += right.$compN; )+ $( 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> { impl<N: Copy + Sub<N, Output = N>> Sub<$tv<N>> for $t<N> {
type Output = $t<N>; type Output = $t<N>;
@ -68,11 +80,14 @@ macro_rules! point_sub_vec_impl(
$( self.$compN -= right.$compN; )+ $( self.$compN -= right.$compN; )+
} }
} }
)
);
macro_rules! point_as_vec_impl(
($t: ident, $tv: ident, $($compN: ident),+) => (
/*
*
* Point as vector.
*
*/
impl<N> $t<N> { impl<N> $t<N> {
/// Converts this point to its associated vector. /// Converts this point to its associated vector.
#[inline] #[inline]
@ -84,7 +99,7 @@ macro_rules! point_as_vec_impl(
/// Converts a reference to this point to a reference to its associated vector. /// Converts a reference to this point to a reference to its associated vector.
#[inline] #[inline]
pub fn as_vector<'a>(&'a self) -> &'a $tv<N> { pub fn as_vector(&self) -> &$tv<N> {
unsafe { unsafe {
mem::transmute(self) mem::transmute(self)
} }
@ -105,7 +120,7 @@ macro_rules! point_as_vec_impl(
} }
#[inline] #[inline]
fn as_vector<'a>(&'a self) -> &'a $tv<N> { fn as_vector(&self) -> &$tv<N> {
self.as_vector() self.as_vector()
} }
@ -114,40 +129,14 @@ macro_rules! point_as_vec_impl(
self.set_coords(v) 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 /*
} *
} * NumPoint / FloatPoint
) *
); */
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) => (
impl<N> NumPoint<N> for $t<N> impl<N> NumPoint<N> for $t<N>
where N: BaseNum { where N: BaseNum {
} }
@ -155,25 +144,13 @@ macro_rules! num_float_point_impl(
impl<N> FloatPoint<N> for $t<N> impl<N> FloatPoint<N> for $t<N>
where N: BaseFloat + ApproxEq<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> { impl<N: fmt::Display> fmt::Display for $t<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// FIXME: differenciate them from vectors ? // FIXME: differenciate them from vectors ?
@ -190,5 +167,34 @@ macro_rules! point_display_impl(
write!(f, ")") 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 std::iter::{FromIterator, IntoIterator};
use rand::{Rand, Rng}; use rand::{Rand, Rng};
use num::{Zero, One}; 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::operations::{ApproxEq, Inverse, PartialOrder, PartialOrdering, Axpy};
use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dimension, Shape, BaseFloat, BaseNum, use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dimension, Shape, BaseFloat, BaseNum,
Bounded, Repeat}; Bounded, Repeat};
@ -31,35 +31,21 @@ pub struct Quaternion<N> {
pub k: N pub k: N
} }
impl<N> Quaternion<N> { impl<N: Copy> 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
}
}
/// The vector part `(i, j, k)` of this quaternion. /// The vector part `(i, j, k)` of this quaternion.
#[inline] #[inline]
pub fn vector<'a>(&'a self) -> &'a Vector3<N> { pub fn vector(&self) -> &Vector3<N> {
// FIXME: do this require a `repr(C)` ? unsafe { mem::transmute(&self.i) }
unsafe {
mem::transmute(&self.i)
}
} }
/// The scalar part `w` of this quaternion. /// The scalar part `w` of this quaternion.
#[inline] #[inline]
pub fn scalar<'a>(&'a self) -> &'a N { pub fn scalar(&self) -> N {
&self.w self.w
} }
} }
impl<N: Neg<Output = N> + Copy> Quaternion<N> { impl<N: BaseNum + Neg<Output = N>> Quaternion<N> {
/// Compute the conjugate of this quaternion. /// Compute the conjugate of this quaternion.
#[inline] #[inline]
pub fn conjugate(&self) -> Quaternion<N> { 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] #[inline]
fn inverse(&self) -> Option<Quaternion<N>> { fn inverse(&self) -> Option<Quaternion<N>> {
let mut res = *self; let mut res = *self;
@ -97,17 +122,16 @@ impl<N: BaseFloat + ApproxEq<N>> Inverse for Quaternion<N> {
} }
else { else {
self.conjugate_mut(); self.conjugate_mut();
self.w = self.w / norm_squared; *self /= norm_squared;
self.i = self.i / norm_squared;
self.j = self.j / norm_squared;
self.k = self.k / norm_squared;
true true
} }
} }
} }
impl<N: BaseFloat> Norm<N> for Quaternion<N> { impl<N: BaseFloat> Norm for Quaternion<N> {
type NormType = N;
#[inline] #[inline]
fn norm_squared(&self) -> N { fn norm_squared(&self) -> N {
self.w * self.w + self.i * self.i + self.j * self.j + self.k * self.k 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] #[inline]
fn normalize(&self) -> Quaternion<N> { fn normalize(&self) -> Quaternion<N> {
let n = self.norm(); let n = ::norm(self);
Quaternion::new(self.w / n, self.i / n, self.j / n, self.k / n) *self / n
} }
#[inline] #[inline]
fn normalize_mut(&mut self) -> N { fn normalize_mut(&mut self) -> N {
let n = Norm::norm(self); let n = ::norm(self);
*self /= n;
self.w = self.w / n;
self.i = self.i / n;
self.j = self.j / n;
self.k = self.k / n;
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> 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>; type Output = Quaternion<N>;
#[inline] #[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] #[inline]
fn div_assign(&mut self, right: Quaternion<N>) { fn div_assign(&mut self, right: Quaternion<N>) {
*self *= right.inverse().expect("Unable to invert the denominator.") *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> { impl<N: fmt::Display> fmt::Display for Quaternion<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Quaternion {} ({}, {}, {})", self.w, self.i, self.j, self.k) 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>>;
impl<N> UnitQuaternion<N> {
/// A unit quaternion that can represent a 3D rotation. /// The underlying quaternion.
#[repr(C)] ///
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)] /// Same as `self.as_ref()`.
pub struct UnitQuaternion<N> { #[inline]
q: Quaternion<N> pub fn quaternion(&self) -> &Quaternion<N> {
self.as_ref()
}
} }
impl<N: BaseFloat> UnitQuaternion<N> { 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] #[inline]
pub fn new(axisangle: Vector3<N>) -> UnitQuaternion<N> { pub fn from_axisangle(axis: Unit<Vector3<N>>, angle: N) -> UnitQuaternion<N> {
let sqang = Norm::norm_squared(&axisangle); let (sang, cang) = (angle / ::cast(2.0)).sin_cos();
if ::is_zero(&sqang) { let q = Quaternion::from_parts(cang, axis.unwrap() * sang);
::one() 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; /// Same as `::from_axisangle` with the axis multiplied with the angle.
#[inline]
unsafe { pub fn from_scaled_axis(axis: Vector3<N>) -> UnitQuaternion<N> {
UnitQuaternion::new_with_unit_quaternion( let two: N = ::cast(2.0);
Quaternion::new( let q = Quaternion::from_parts(::zero(), axis / two).exp();
c, UnitQuaternion::from_unit_value_unchecked(q)
axisangle.x * s_ang,
axisangle.y * s_ang,
axisangle.z * s_ang)
)
}
}
} }
/// Creates a new unit quaternion from a quaternion. /// Creates a new unit quaternion from a quaternion.
/// ///
/// The input quaternion will be normalized. /// The input quaternion will be normalized.
#[inline] #[inline]
pub fn new_with_quaternion(q: Quaternion<N>) -> UnitQuaternion<N> { pub fn from_quaternion(q: &Quaternion<N>) -> UnitQuaternion<N> {
UnitQuaternion { q: q.normalize() } Unit::new(&q)
} }
/// Creates a new unit quaternion from Euler angles. /// Creates a new unit quaternion from Euler angles.
/// ///
/// The primitive rotations are applied in order: 1 roll 2 pitch 3 yaw. /// The primitive rotations are applied in order: 1 roll 2 pitch 3 yaw.
#[inline] #[inline]
pub fn new_with_euler_angles(roll: N, pitch: N, yaw: N) -> UnitQuaternion<N> { pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> UnitQuaternion<N> {
let _0_5: N = Cast::from(0.5); let (sr, cr) = (roll * ::cast(0.5)).sin_cos();
let (sr, cr) = (roll * _0_5).sin_cos(); let (sp, cp) = (pitch * ::cast(0.5)).sin_cos();
let (sp, cp) = (pitch * _0_5).sin_cos(); let (sy, cy) = (yaw * ::cast(0.5)).sin_cos();
let (sy, cy) = (yaw * _0_5).sin_cos();
unsafe { let q = Quaternion::new(
UnitQuaternion::new_with_unit_quaternion(
Quaternion::new(
cr * cp * cy + sr * sp * sy, cr * cp * cy + sr * sp * sy,
sr * cp * cy - cr * sp * sy, sr * cp * cy - cr * sp * sy,
cr * sp * cy + sr * cp * 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. /// Builds a rotation matrix from this quaternion.
pub fn to_rotation_matrix(&self) -> Rotation3<N> { pub fn to_rotation_matrix(&self) -> Rotation3<N> {
let _2: N = Cast::from(2.0); let ww = self.as_ref().w * self.as_ref().w;
let ww = self.q.w * self.q.w; let ii = self.as_ref().i * self.as_ref().i;
let ii = self.q.i * self.q.i; let jj = self.as_ref().j * self.as_ref().j;
let jj = self.q.j * self.q.j; let kk = self.as_ref().k * self.as_ref().k;
let kk = self.q.k * self.q.k; let ij = self.as_ref().i * self.as_ref().j * ::cast(2.0);
let ij = _2 * self.q.i * self.q.j; let wk = self.as_ref().w * self.as_ref().k * ::cast(2.0);
let wk = _2 * self.q.w * self.q.k; let wj = self.as_ref().w * self.as_ref().j * ::cast(2.0);
let wj = _2 * self.q.w * self.q.j; let ik = self.as_ref().i * self.as_ref().k * ::cast(2.0);
let ik = _2 * self.q.i * self.q.k; let jk = self.as_ref().j * self.as_ref().k * ::cast(2.0);
let jk = _2 * self.q.j * self.q.k; let wi = self.as_ref().w * self.as_ref().i * ::cast(2.0);
let wi = _2 * self.q.w * self.q.i;
unsafe { Rotation3::from_matrix_unchecked(
Rotation3::new_with_matrix(
Matrix3::new( Matrix3::new(
ww + ii - jj - kk, ij - wk, wj + ik, ww + ii - jj - kk, ij - wk, wj + ik,
wk + ij, ww - ii + jj - kk, jk - wi, 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> { impl<N: BaseNum> One for UnitQuaternion<N> {
#[inline] #[inline]
fn one() -> UnitQuaternion<N> { fn one() -> UnitQuaternion<N> {
unsafe { let one = Quaternion::new(::one(), ::zero(), ::zero(), ::zero());
UnitQuaternion::new_with_unit_quaternion(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] #[inline]
fn inverse(&self) -> Option<UnitQuaternion<N>> { fn inverse(&self) -> Option<UnitQuaternion<N>> {
let mut cpy = *self; let mut cpy = *self;
@ -307,7 +374,7 @@ impl<N: Copy + Neg<Output = N>> Inverse for UnitQuaternion<N> {
#[inline] #[inline]
fn inverse_mut(&mut self) -> bool { fn inverse_mut(&mut self) -> bool {
self.q.conjugate_mut(); *self = Unit::from_unit_value_unchecked(self.as_ref().conjugate());
true true
} }
@ -316,7 +383,7 @@ impl<N: Copy + Neg<Output = N>> Inverse for UnitQuaternion<N> {
impl<N: Rand + BaseFloat> Rand for UnitQuaternion<N> { impl<N: Rand + BaseFloat> Rand for UnitQuaternion<N> {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> UnitQuaternion<N> { 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] #[inline]
fn approx_eq_eps(&self, other: &UnitQuaternion<N>, eps: &N) -> bool { 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] #[inline]
fn approx_eq_ulps(&self, other: &UnitQuaternion<N>, ulps: u32) -> bool { 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>; type Output = UnitQuaternion<N>;
#[inline] #[inline]
fn div(self, other: UnitQuaternion<N>) -> UnitQuaternion<N> { 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] #[inline]
fn div_assign(&mut self, other: UnitQuaternion<N>) { 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] #[inline]
fn mul(self, right: UnitQuaternion<N>) -> UnitQuaternion<N> { 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> { impl<N: BaseNum> MulAssign<UnitQuaternion<N>> for UnitQuaternion<N> {
#[inline] #[inline]
fn mul_assign(&mut self, right: UnitQuaternion<N>) { 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] #[inline]
fn mul(self, right: Vector3<N>) -> Vector3<N> { fn mul(self, right: Vector3<N>) -> Vector3<N> {
let _2: N = ::one::<N>() + ::one(); let two: N = ::one::<N>() + ::one();
let mut t = ::cross(self.q.vector(), &right); let t = ::cross(self.as_ref().vector(), &right) * two;
t.x = t.x * _2;
t.y = t.y * _2;
t.z = t.z * _2;
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> { impl<N: BaseFloat> Rotation<Vector3<N>> for UnitQuaternion<N> {
#[inline] #[inline]
fn rotation(&self) -> Vector3<N> { fn rotation(&self) -> Vector3<N> {
let _2 = ::one::<N>() + ::one(); if let Some(v) = self.axis() {
let mut v = *self.q.vector(); v.unwrap() * self.angle()
let ang = _2 * v.normalize_mut().atan2(self.q.w);
if ::is_zero(&ang) {
::zero()
} }
else { 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] #[inline]
fn append_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> { fn append_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> {
*self * UnitQuaternion::new(*amount) *self * UnitQuaternion::from_scaled_axis(*amount)
} }
#[inline] #[inline]
@ -471,12 +531,12 @@ impl<N: BaseFloat> Rotation<Vector3<N>> for UnitQuaternion<N> {
#[inline] #[inline]
fn prepend_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> { fn prepend_rotation(&self, amount: &Vector3<N>) -> UnitQuaternion<N> {
UnitQuaternion::new(*amount) * *self UnitQuaternion::from_scaled_axis(*amount) * *self
} }
#[inline] #[inline]
fn set_rotation(&mut self, v: Vector3<N>) { 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 AngleType = N;
type DeltaRotationType = UnitQuaternion<N>; type DeltaRotationType = UnitQuaternion<N>;
#[inline] #[inline]
fn angle_to(&self, other: &Self) -> N { fn angle_to(&self, other: &Self) -> N {
let delta = self.rotation_to(other); 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] #[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> { impl<N: fmt::Display> fmt::Display for UnitQuaternion<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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")] #[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuaternion<N> { impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuaternion<N> {
fn arbitrary<G: Gen>(g: &mut G) -> 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); /// Compute the natural logarithm of a quaternion.
vec_axis_impl!(Quaternion, w, i, j, k); ///
vec_cast_impl!(Quaternion, w, i, j, k); /// Note that this function yields a `Quaternion<N>` because it looses the unit property. The
conversion_impl!(Quaternion, 4); /// vector part of the return value corresponds to the axis-angle representation (divided by
index_impl!(Quaternion); /// 2.0) of this unit quaternion.
indexable_impl!(Quaternion, 4); pub fn ln(&self) -> Quaternion<N> {
at_fast_impl!(Quaternion, 4); if let Some(v) = self.axis() {
repeat_impl!(Quaternion, val, w, i, j, k); Quaternion::from_parts(::zero(), v.unwrap() * self.angle())
dim_impl!(Quaternion, 3); }
container_impl!(Quaternion); else {
add_impl!(Quaternion, w, i, j, k); ::zero()
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); /// Raise this unit quaternion to a given floating power.
scalar_div_impl!(Quaternion, w, i, j, k); ///
neg_impl!(Quaternion, w, i, j, k); /// If this unit quaternion represents a rotation by `theta`, then the resulting quaternion
zero_one_impl!(Quaternion, w, i, j, k); /// rotates by `n * theta`.
approx_eq_impl!(Quaternion, w, i, j, k); 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); from_iterator_impl!(Quaternion, iterator, iterator, iterator, iterator);
bounded_impl!(Quaternion, w, i, j, k); vectorlike_impl!(Quaternion, 4, 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);

View File

@ -1,7 +1,7 @@
//! Rotations matrices. //! Rotations matrices.
use std::fmt; use std::fmt;
use std::ops::{Mul, Neg, MulAssign, Index}; use std::ops::{Mul, MulAssign, Index};
use rand::{Rand, Rng}; use rand::{Rand, Rng};
use num::{Zero, One}; use num::{Zero, One};
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, RotationTo, Transform, use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, RotationTo, Transform,
@ -22,21 +22,21 @@ pub struct Rotation2<N> {
submatrix: Matrix2<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. /// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn new(angle: Vector1<N>) -> Rotation2<N> { pub fn new(angle: Vector1<N>) -> Rotation2<N> {
let (sia, coa) = angle.x.sin_cos(); let (sia, coa) = angle.x.sin_cos();
Rotation2 { 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] #[inline]
fn rotation(&self) -> Vector1<N> { 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] #[inline]
@ -51,7 +51,7 @@ impl<N: BaseFloat + Clone> Rotation<Vector1<N>> for Rotation2<N> {
#[inline] #[inline]
fn append_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> { fn append_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> {
Rotation2::new(rotation.clone()) * *self Rotation2::new(*rotation) * *self
} }
#[inline] #[inline]
@ -61,7 +61,7 @@ impl<N: BaseFloat + Clone> Rotation<Vector1<N>> for Rotation2<N> {
#[inline] #[inline]
fn prepend_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> { fn prepend_rotation(&self, rotation: &Vector1<N>) -> Rotation2<N> {
*self * Rotation2::new(rotation.clone()) *self * Rotation2::new(*rotation)
} }
#[inline] #[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 * 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. /// Builds a 3 dimensional rotation matrix from an axis and an angle.
/// ///
/// # Arguments /// # Arguments
@ -137,37 +130,34 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
else { else {
let mut axis = axisangle; let mut axis = axisangle;
let angle = axis.normalize_mut(); let angle = axis.normalize_mut();
let _1: N = ::one(); let ux = axis.x;
let ux = axis.x.clone(); let uy = axis.y;
let uy = axis.y.clone(); let uz = axis.z;
let uz = axis.z.clone();
let sqx = ux * ux; let sqx = ux * ux;
let sqy = uy * uy; let sqy = uy * uy;
let sqz = uz * uz; let sqz = uz * uz;
let (sin, cos) = angle.sin_cos(); let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos; let one_m_cos = ::one::<N>() - cos;
Rotation3 { Rotation3 {
submatrix: Matrix3::new( submatrix: Matrix3::new(
(sqx + (_1 - sqx) * cos), (sqx + (::one::<N>() - sqx) * cos),
(ux * uy * one_m_cos - uz * sin), (ux * uy * one_m_cos - uz * sin),
(ux * uz * one_m_cos + uy * sin), (ux * uz * one_m_cos + uy * sin),
(ux * uy * one_m_cos + uz * sin), (ux * uy * one_m_cos + uz * sin),
(sqy + (_1 - sqy) * cos), (sqy + (::one::<N>() - sqy) * cos),
(uy * uz * one_m_cos - ux * sin), (uy * uz * one_m_cos - ux * sin),
(ux * uz * one_m_cos - uy * sin), (ux * uz * one_m_cos - uy * sin),
(uy * uz * one_m_cos + ux * 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. /// Builds a rotation matrix from an orthogonal matrix.
/// pub fn from_matrix_unchecked(matrix: Matrix3<N>) -> Rotation3<N> {
/// This is unsafe because the orthogonality of `matrix` is not checked.
pub unsafe fn new_with_matrix(matrix: Matrix3<N>) -> Rotation3<N> {
Rotation3 { Rotation3 {
submatrix: matrix submatrix: matrix
} }
@ -176,13 +166,12 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
/// Creates a new rotation from Euler angles. /// Creates a new rotation from Euler angles.
/// ///
/// The primitive rotations are applied in order: 1 roll 2 pitch 3 yaw. /// 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 (sr, cr) = roll.sin_cos();
let (sp, cp) = pitch.sin_cos(); let (sp, cp) = pitch.sin_cos();
let (sy, cy) = yaw.sin_cos(); let (sy, cy) = yaw.sin_cos();
unsafe { Rotation3::from_matrix_unchecked(
Rotation3::new_with_matrix(
Matrix3::new( Matrix3::new(
cy * cp, cy * sp * sr - sy * cr, cy * sp * cr + sy * sr, cy * cp, cy * sp * sr - sy * cr, cy * sp * cr + sy * sr,
sy * cp, sy * sp * sr + cy * cr, sy * sp * cr - cy * 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 /// Creates a rotation that corresponds to the local frame of an observer standing at the
/// origin and looking toward `dir`. /// origin and looking toward `dir`.
/// ///
@ -210,13 +198,11 @@ impl<N: Clone + BaseFloat> Rotation3<N> {
let xaxis = Norm::normalize(&Cross::cross(up, &zaxis)); let xaxis = Norm::normalize(&Cross::cross(up, &zaxis));
let yaxis = Norm::normalize(&Cross::cross(&zaxis, &xaxis)); let yaxis = Norm::normalize(&Cross::cross(&zaxis, &xaxis));
unsafe { Rotation3::from_matrix_unchecked(Matrix3::new(
Rotation3::new_with_matrix(Matrix3::new( xaxis.x, yaxis.x, zaxis.x,
xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(), xaxis.y, yaxis.y, zaxis.y,
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z, yaxis.z, zaxis.z)) xaxis.z, yaxis.z, zaxis.z))
} }
}
/// Builds a right-handed look-at view matrix without translation. /// 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>> impl<N: BaseFloat> Rotation<Vector3<N>> for Rotation3<N> {
Rotation<Vector3<N>> for Rotation3<N> {
#[inline] #[inline]
fn rotation(&self) -> Vector3<N> { fn rotation(&self) -> Vector3<N> {
let angle = ((self.submatrix.m11 + self.submatrix.m22 + self.submatrix.m33 - ::one()) / Cast::from(2.0)).acos(); let angle = ((self.submatrix.m11 + self.submatrix.m22 + self.submatrix.m33 - ::one()) / Cast::from(2.0)).acos();
if angle != angle { if !angle.is_finite() || ::is_zero(&angle) {
// FIXME: handle that correctly // FIXME: handle the non-finite case robustly.
::zero()
}
else if ::is_zero(&angle) {
::zero() ::zero()
} }
else { else {
@ -296,7 +278,7 @@ Rotation<Vector3<N>> for Rotation3<N> {
#[inline] #[inline]
fn append_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> { fn append_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> {
Rotation3::new(axisangle.clone()) * *self Rotation3::new(*axisangle) * *self
} }
#[inline] #[inline]
@ -306,7 +288,7 @@ Rotation<Vector3<N>> for Rotation3<N> {
#[inline] #[inline]
fn prepend_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> { fn prepend_rotation(&self, axisangle: &Vector3<N>) -> Rotation3<N> {
*self * Rotation3::new(axisangle.clone()) *self * Rotation3::new(*axisangle)
} }
#[inline] #[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] #[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotation3<N> { fn rand<R: Rng>(rng: &mut R) -> Rotation3<N> {
Rotation3::new(rng.gen()) 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. * Common implementations.
*/ */
submat_impl!(Rotation2, Matrix2); rotation_impl!(Rotation2, Matrix2, Vector2, Vector1, Point2, Matrix3);
rotate_impl!(Rotation2, Vector2, Point2);
transform_impl!(Rotation2, Vector2, Point2);
dim_impl!(Rotation2, 2); 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); rotation_impl!(Rotation3, Matrix3, Vector3, Vector3, Point3, Matrix4);
rotate_impl!(Rotation3, Vector3, Point3);
transform_impl!(Rotation3, Vector3, Point3);
dim_impl!(Rotation3, 3); 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_use]
macro_rules! submat_impl( macro_rules! rotation_impl(
($t: ident, $submatrix: ident) => ( ($t: ident, $submatrix: ident, $vector: ident, $rotvector: ident, $point: ident, $homogeneous: ident) => (
impl<N> $t<N> { impl<N> $t<N> {
/// This rotation's underlying matrix. /// This rotation's underlying matrix.
#[inline] #[inline]
pub fn submatrix<'r>(&'r self) -> &'r $submatrix<N> { pub fn submatrix(&self) -> &$submatrix<N> {
&self.submatrix &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] #[inline]
fn rotate(&self, v: &$tv<N>) -> $tv<N> { fn rotate(&self, v: &$vector<N>) -> $vector<N> {
*self * *v *self * *v
} }
#[inline] #[inline]
fn inverse_rotate(&self, v: &$tv<N>) -> $tv<N> { fn inverse_rotate(&self, v: &$vector<N>) -> $vector<N> {
*v * *self *v * *self
} }
} }
impl<N: BaseNum> Rotate<$tp<N>> for $t<N> { impl<N: BaseNum> Rotate<$point<N>> for $t<N> {
#[inline] #[inline]
fn rotate(&self, p: &$tp<N>) -> $tp<N> { fn rotate(&self, p: &$point<N>) -> $point<N> {
*self * *p *self * *p
} }
#[inline] #[inline]
fn inverse_rotate(&self, p: &$tp<N>) -> $tp<N> { fn inverse_rotate(&self, p: &$point<N>) -> $point<N> {
*p * *self *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] #[inline]
fn transform(&self, v: &$tv<N>) -> $tv<N> { fn transform(&self, v: &$vector<N>) -> $vector<N> {
self.rotate(v) self.rotate(v)
} }
#[inline] #[inline]
fn inverse_transform(&self, v: &$tv<N>) -> $tv<N> { fn inverse_transform(&self, v: &$vector<N>) -> $vector<N> {
self.inverse_rotate(v) self.inverse_rotate(v)
} }
} }
impl<N: BaseNum> Transform<$tp<N>> for $t<N> { impl<N: BaseNum> Transform<$point<N>> for $t<N> {
#[inline] #[inline]
fn transform(&self, p: &$tp<N>) -> $tp<N> { fn transform(&self, p: &$point<N>) -> $point<N> {
self.rotate(p) self.rotate(p)
} }
#[inline] #[inline]
fn inverse_transform(&self, p: &$tp<N>) -> $tp<N> { fn inverse_transform(&self, p: &$point<N>) -> $point<N> {
self.inverse_rotate(p) 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>; type Output = $t<N>;
#[inline] #[inline]
@ -89,22 +85,26 @@ macro_rules! rotation_matrix_impl(
self.clone() self.clone()
} }
} }
)
);
macro_rules! one_impl(
($t: ident) => ( /*
*
* One
*
*/
impl<N: BaseNum> One for $t<N> { impl<N: BaseNum> One for $t<N> {
#[inline] #[inline]
fn one() -> $t<N> { fn one() -> $t<N> {
$t { submatrix: ::one() } $t { submatrix: ::one() }
} }
} }
)
);
macro_rules! eye_impl(
($t: ident) => ( /*
*
* Eye
*
*/
impl<N: BaseNum> Eye for $t<N> { impl<N: BaseNum> Eye for $t<N> {
#[inline] #[inline]
fn new_identity(dimension: usize) -> $t<N> { 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] #[inline]
fn from_diagonal(diagonal: &$tv<N>) -> $t<N> { fn from_diagonal(diagonal: &$vector<N>) -> $t<N> {
$t { submatrix: Diagonal::from_diagonal(diagonal) } $t { submatrix: Diagonal::from_diagonal(diagonal) }
} }
#[inline] #[inline]
fn diagonal(&self) -> $tv<N> { fn diagonal(&self) -> $vector<N> {
self.submatrix.diagonal() self.submatrix.diagonal()
} }
} }
)
);
macro_rules! rotation_mul_rotation_impl(
($t: ident) => ( /*
*
* Rotation * Rotation
*
*/
impl<N: BaseNum> Mul<$t<N>> for $t<N> { impl<N: BaseNum> Mul<$t<N>> for $t<N> {
type Output = $t<N>; type Output = $t<N>;
@ -152,56 +156,75 @@ macro_rules! rotation_mul_rotation_impl(
self.submatrix *= right.submatrix 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] #[inline]
fn mul(self, right: $tv<N>) -> $tv<N> { fn mul(self, right: $vector<N>) -> $vector<N> {
self.submatrix * right self.submatrix * right
} }
} }
)
);
macro_rules! rotation_mul_point_impl( impl<N: BaseNum> Mul<$t<N>> for $vector<N> {
($t: ident, $tv: ident) => ( type Output = $vector<N>;
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>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $tv<N> { fn mul(self, right: $t<N>) -> $vector<N> {
self * right.submatrix self * right.submatrix
} }
} }
impl<N: Copy + BaseNum> MulAssign<$t<N>> for $tv<N> { impl<N: Copy + BaseNum> MulAssign<$t<N>> for $vector<N> {
#[inline] #[inline]
fn mul_assign(&mut self, right: $t<N>) { fn mul_assign(&mut self, right: $t<N>) {
*self *= right.submatrix *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> { impl<N: Copy> Inverse for $t<N> {
#[inline] #[inline]
fn inverse_mut(&mut self) -> bool { fn inverse_mut(&mut self) -> bool {
@ -217,11 +240,13 @@ macro_rules! inverse_impl(
Some(self.transpose()) Some(self.transpose())
} }
} }
)
);
macro_rules! transpose_impl(
($t: ident) => ( /*
*
* Transpose
*
*/
impl<N: Copy> Transpose for $t<N> { impl<N: Copy> Transpose for $t<N> {
#[inline] #[inline]
fn transpose(&self) -> $t<N> { fn transpose(&self) -> $t<N> {
@ -233,51 +258,57 @@ macro_rules! transpose_impl(
self.submatrix.transpose_mut() 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] #[inline]
fn nrows(&self) -> usize { fn nrows(&self) -> usize {
self.submatrix.nrows() self.submatrix.nrows()
} }
#[inline] #[inline]
fn row(&self, i: usize) -> $tv<N> { fn row(&self, i: usize) -> $vector<N> {
self.submatrix.row(i) self.submatrix.row(i)
} }
#[inline] #[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); 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] #[inline]
fn ncols(&self) -> usize { fn ncols(&self) -> usize {
self.submatrix.ncols() self.submatrix.ncols()
} }
#[inline] #[inline]
fn column(&self, i: usize) -> $tv<N> { fn column(&self, i: usize) -> $vector<N> {
self.submatrix.column(i) self.submatrix.column(i)
} }
#[inline] #[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); self.submatrix.set_column(i, column);
} }
} }
)
);
macro_rules! index_impl(
($t: ident) => ( /*
*
* Index
*
*/
impl<N> Index<(usize, usize)> for $t<N> { impl<N> Index<(usize, usize)> for $t<N> {
type Output = N; type Output = N;
@ -285,22 +316,26 @@ macro_rules! index_impl(
&self.submatrix[i] &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] #[inline]
fn to_homogeneous(&self) -> $tm<N> { fn to_homogeneous(&self) -> $homogeneous<N> {
self.submatrix.to_homogeneous() self.submatrix.to_homogeneous()
} }
} }
)
);
macro_rules! approx_eq_impl(
($t: ident) => ( /*
*
* ApproxEq
*
*/
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> { impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline] #[inline]
fn approx_epsilon(_: Option<$t<N>>) -> N { 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) 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] #[inline]
fn abs(m: &$t<N>) -> $tm<N> { fn abs(m: &$t<N>) -> $submatrix<N> {
Absolute::abs(&m.submatrix) Absolute::abs(&m.submatrix)
} }
} }
)
);
macro_rules! rotation_display_impl(
($t: ident) => (
/*
*
* Display
*
*/
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> { impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let precision = f.precision().unwrap_or(3); let precision = f.precision().unwrap_or(3);
@ -352,5 +392,29 @@ macro_rules! rotation_display_impl(
writeln!(f, "}}") 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 structs::matrix::{Matrix3, Matrix4};
use traits::structure::{Dimension, Column, BaseFloat, BaseNum}; use traits::structure::{Dimension, Column, BaseFloat, BaseNum};
use traits::operations::{Inverse, ApproxEq}; 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::vector::{Vector1, Vector2, Vector3};
use structs::point::{Point2, Point3}; use structs::point::{Point2, Point3};
@ -49,38 +49,9 @@ pub struct Similarity3<N> {
pub isometry: Isometry3<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); 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_use]
macro_rules! sim_impl( macro_rules! similarity_impl(
($t: ident, $isometry: ident, $rotation_matrix: ident, $subvector: ident, $subrotvector: ident) => ( ($t: ident,
$isometry: ident, $rotation_matrix: ident,
$vector: ident, $rotvector: ident,
$point: ident,
$homogeneous_matrix: ident) => (
impl<N: BaseFloat> $t<N> { impl<N: BaseFloat> $t<N> {
/*
*
* Constructors.
*
*/
/// Creates a new similarity transformation from a vector, an axis-angle rotation, and a scale factor. /// 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. /// The scale factor may be negative but not zero.
#[inline] #[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."); assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
$t { $t {
@ -20,12 +29,12 @@ macro_rules! sim_impl(
/// ///
/// The scale factor may be negative but not zero. /// The scale factor may be negative but not zero.
#[inline] #[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."); assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
$t { $t {
scale: scale, 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. /// The scale factor may be negative but not zero.
#[inline] #[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."); assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
$t { $t {
@ -41,13 +50,12 @@ macro_rules! sim_impl(
isometry: isometry 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. /// The scale factor of this similarity transformation.
#[inline] #[inline]
pub fn scale(&self) -> N { pub fn scale(&self) -> N {
@ -72,7 +80,7 @@ macro_rules! sim_scale_impl(
#[inline] #[inline]
pub fn append_scale(&self, s: &N) -> $t<N> { pub fn append_scale(&self, s: &N) -> $t<N> {
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation."); 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. /// Prepends in-place a scale to this similarity transformation.
@ -86,7 +94,7 @@ macro_rules! sim_scale_impl(
#[inline] #[inline]
pub fn prepend_scale(&self, s: &N) -> $t<N> { pub fn prepend_scale(&self, s: &N) -> $t<N> {
assert!(!s.is_zero(), "A similarity transformation scale must not be zero."); 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. /// Sets the scale of this similarity transformation.
@ -96,28 +104,67 @@ macro_rules! sim_scale_impl(
self.scale = s self.scale = s
} }
} }
)
);
macro_rules! sim_one_impl( /*
($t: ident) => ( *
* One Impl.
*
*/
impl<N: BaseFloat> One for $t<N> { impl<N: BaseFloat> One for $t<N> {
#[inline] #[inline]
fn one() -> $t<N> { 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> { impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
type Output = $t<N>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $t<N> { 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.translation + self.isometry.rotation * (right.isometry.translation * self.scale),
self.isometry.rotation * right.isometry.rotation, self.isometry.rotation * right.isometry.rotation,
self.scale * right.scale) self.scale * right.scale)
@ -132,115 +179,130 @@ macro_rules! sim_mul_sim_impl(
self.scale *= right.scale; 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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $ti<N>) -> $t<N> { fn mul(self, right: $isometry<N>) -> $t<N> {
$t::new_with_rotation_matrix( $t::from_rotation_matrix(
self.isometry.translation + self.isometry.rotation * (right.translation * self.scale), self.isometry.translation + self.isometry.rotation * (right.translation * self.scale),
self.isometry.rotation * right.rotation, self.isometry.rotation * right.rotation,
self.scale) self.scale)
} }
} }
impl<N: BaseFloat> MulAssign<$ti<N>> for $t<N> { impl<N: BaseFloat> MulAssign<$isometry<N>> for $t<N> {
#[inline] #[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.translation += self.isometry.rotation * (right.translation * self.scale);
self.isometry.rotation *= right.rotation; 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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $t<N> { 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.translation + self.rotation * right.isometry.translation,
self.rotation * right.isometry.rotation, self.rotation * right.isometry.rotation,
right.scale) 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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $tr<N>) -> $t<N> { fn mul(self, right: $rotation_matrix<N>) -> $t<N> {
$t::new_with_rotation_matrix( $t::from_rotation_matrix(
self.isometry.translation, self.isometry.translation,
self.isometry.rotation * right, self.isometry.rotation * right,
self.scale) self.scale)
} }
} }
impl<N: BaseFloat> MulAssign<$tr<N>> for $t<N> { impl<N: BaseFloat> MulAssign<$rotation_matrix<N>> for $t<N> {
#[inline] #[inline]
fn mul_assign(&mut self, right: $tr<N>) { fn mul_assign(&mut self, right: $rotation_matrix<N>) {
self.isometry.rotation *= right; 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>; type Output = $t<N>;
#[inline] #[inline]
fn mul(self, right: $t<N>) -> $t<N> { fn mul(self, right: $t<N>) -> $t<N> {
$t::new_with_rotation_matrix( $t::from_rotation_matrix(
self * right.isometry.translation, self * right.isometry.translation,
self * right.isometry.rotation, self * right.isometry.rotation,
right.scale) right.scale)
} }
} }
)
);
macro_rules! sim_mul_point_vec_impl( /*
($t: ident, $tv: ident) => ( *
impl<N: BaseNum> Mul<$tv<N>> for $t<N> { * Similarity × { Point, Vector }
type Output = $tv<N>; *
*/
impl<N: BaseNum> Mul<$vector<N>> for $t<N> {
type Output = $vector<N>;
#[inline] #[inline]
fn mul(self, right: $tv<N>) -> $tv<N> { fn mul(self, right: $vector<N>) -> $vector<N> {
self.isometry * (right * self.scale) 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 // NOTE: there is no viable pre-multiplication definition because of the translation
// component. // 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] #[inline]
fn transform(&self, p: &$tp<N>) -> $tp<N> { fn transform(&self, p: &$point<N>) -> $point<N> {
self.isometry.transform(&(*p * self.scale)) self.isometry.transform(&(*p * self.scale))
} }
#[inline] #[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 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> { impl<N: BaseNum + Neg<Output = N>> Inverse for $t<N> {
#[inline] #[inline]
fn inverse_mut(&mut self) -> bool { fn inverse_mut(&mut self) -> bool {
@ -263,28 +325,32 @@ macro_rules! sim_inverse_impl(
Some(res) 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(); let mut res = (*self.isometry.rotation.submatrix() * self.scale).to_homogeneous();
// copy the translation // 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.set_column(dimension - 1, self.isometry.translation.as_point().to_homogeneous().to_vector());
res res
} }
} }
)
);
macro_rules! sim_approx_eq_impl(
($t: ident) => ( /*
*
* ApproxEq
*
*/
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> { impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
#[inline] #[inline]
fn approx_epsilon(_: Option<$t<N>>) -> N { 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) 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> { impl<N: Rand + BaseFloat> Rand for $t<N> {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> $t<N> { fn rand<R: Rng>(rng: &mut R) -> $t<N> {
@ -321,28 +389,32 @@ macro_rules! sim_rand_impl(
scale = rng.gen(); 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")] #[cfg(feature="arbitrary")]
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> { impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> { fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
$t::new_with_isometry( $t::from_isometry(
Arbitrary::arbitrary(g), Arbitrary::arbitrary(g),
Arbitrary::arbitrary(g) Arbitrary::arbitrary(g)
) )
} }
} }
)
);
macro_rules! sim_display_impl(
($t: ident) => ( /*
*
* Display
*
*/
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> { impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "Similarity transformation {{")); try!(writeln!(f, "Similarity transformation {{"));

View File

@ -3,7 +3,7 @@ use structs::vector::{Vector2, Vector3};
use structs::point::{Point2, Point3}; use structs::point::{Point2, Point3};
use structs::matrix::{Matrix1, Matrix2, Matrix3}; use structs::matrix::{Matrix1, Matrix2, Matrix3};
use traits::operations::{Inverse, Determinant, ApproxEq}; use traits::operations::{Inverse, Determinant, ApproxEq};
use traits::structure::{Row, Column, BaseNum}; use traits::structure::BaseNum;
// some specializations: // some specializations:
impl<N: BaseNum + ApproxEq<N>> Inverse for Matrix1<N> { impl<N: BaseNum + ApproxEq<N>> Inverse for Matrix1<N> {
@ -24,9 +24,8 @@ impl<N: BaseNum + ApproxEq<N>> Inverse for Matrix1<N> {
false false
} }
else { else {
let _1: N = ::one(); self.m11 = ::one::<N>() / Determinant::determinant(self);
self.m11 = _1 / Determinant::determinant(self);
true 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Matrix3<N> {
type Output = 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Matrix2<N> {
type Output = Matrix2<N>; type Output = Matrix2<N>;
#[inline(always)] #[inline]
fn mul(self, right: Matrix2<N>) -> Matrix2<N> { fn mul(self, right: Matrix2<N>) -> Matrix2<N> {
Matrix2::new( Matrix2::new(
self.m11 * right.m11 + self.m12 * right.m21, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector3<N>> for Matrix3<N> {
type Output = Vector3<N>; type Output = Vector3<N>;
#[inline(always)] #[inline]
fn mul(self, right: Vector3<N>) -> Vector3<N> { fn mul(self, right: Vector3<N>) -> Vector3<N> {
Vector3::new( Vector3::new(
self.m11 * right.x + self.m12 * right.y + self.m13 * right.z, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Vector3<N> {
type Output = Vector3<N>; type Output = Vector3<N>;
#[inline(always)] #[inline]
fn mul(self, right: Matrix3<N>) -> Vector3<N> { fn mul(self, right: Matrix3<N>) -> Vector3<N> {
Vector3::new( Vector3::new(
self.x * right.m11 + self.y * right.m21 + self.z * right.m31, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Vector2<N> {
type Output = Vector2<N>; type Output = Vector2<N>;
#[inline(always)] #[inline]
fn mul(self, right: Matrix2<N>) -> Vector2<N> { fn mul(self, right: Matrix2<N>) -> Vector2<N> {
Vector2::new( Vector2::new(
self.x * right.m11 + self.y * right.m21, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Vector2<N>> for Matrix2<N> {
type Output = Vector2<N>; type Output = Vector2<N>;
#[inline(always)] #[inline]
fn mul(self, right: Vector2<N>) -> Vector2<N> { fn mul(self, right: Vector2<N>) -> Vector2<N> {
Vector2::new( Vector2::new(
self.m11 * right.x + self.m12 * right.y, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point3<N>> for Matrix3<N> {
type Output = Point3<N>; type Output = Point3<N>;
#[inline(always)] #[inline]
fn mul(self, right: Point3<N>) -> Point3<N> { fn mul(self, right: Point3<N>) -> Point3<N> {
Point3::new( Point3::new(
self.m11 * right.x + self.m12 * right.y + self.m13 * right.z, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix3<N>> for Point3<N> {
type Output = Point3<N>; type Output = Point3<N>;
#[inline(always)] #[inline]
fn mul(self, right: Matrix3<N>) -> Point3<N> { fn mul(self, right: Matrix3<N>) -> Point3<N> {
Point3::new( Point3::new(
self.x * right.m11 + self.y * right.m21 + self.z * right.m31, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Matrix2<N>> for Point2<N> {
type Output = Point2<N>; type Output = Point2<N>;
#[inline(always)] #[inline]
fn mul(self, right: Matrix2<N>) -> Point2<N> { fn mul(self, right: Matrix2<N>) -> Point2<N> {
Point2::new( Point2::new(
self.x * right.m11 + self.y * right.m21, 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> { impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> Mul<Point2<N>> for Matrix2<N> {
type Output = Point2<N>; type Output = Point2<N>;
#[inline(always)] #[inline]
fn mul(self, right: Point2<N>) -> Point2<N> { fn mul(self, right: Point2<N>) -> Point2<N> {
Point2::new( Point2::new(
self.m11 * right.x + self.m12 * right.y, 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( macro_rules! impl_mul_assign_from_mul(
($tleft: ident, $tright: ident) => ( ($tleft: ident, $tright: ident) => (
impl<N: Copy + Mul<N, Output = N> + Add<N, Output = N>> MulAssign<$tright<N>> for $tleft<N> { 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>) { fn mul_assign(&mut self, right: $tright<N>) {
// NOTE: there is probably no interesting optimization compared to the not-inplace // NOTE: there is probably no interesting optimization compared to the not-inplace
// operation. // operation.

View File

@ -5,7 +5,7 @@ use traits::structure::Cast;
macro_rules! primitive_cast_impl( macro_rules! primitive_cast_impl(
($from: ty, $to: ty) => ( ($from: ty, $to: ty) => (
impl Cast<$from> for $to { impl Cast<$from> for $to {
#[inline(always)] #[inline]
fn from(t: $from) -> $to { fn from(t: $from) -> $to {
t as $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> { impl<N: One> Basis for Vector1<N> {
#[inline(always)] #[inline]
fn canonical_basis<F: FnMut(Vector1<N>) -> bool>(mut f: F) { fn canonical_basis<F: FnMut(Vector1<N>) -> bool>(mut f: F) {
f(Vector1::new(::one())); f(Vector1::new(::one()));
} }
#[inline(always)] #[inline]
fn orthonormal_subspace_basis<F: FnMut(Vector1<N>) -> bool>(_: &Vector1<N>, _: F) { } fn orthonormal_subspace_basis<F: FnMut(Vector1<N>) -> bool>(_: &Vector1<N>, _: F) { }
#[inline] #[inline]
@ -135,7 +135,7 @@ impl<N: One> Basis for Vector1<N> {
} }
impl<N: Copy + One + Zero + Neg<Output = N>> Basis for Vector2<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) { fn canonical_basis<F: FnMut(Vector2<N>) -> bool>(mut f: F) {
if !f(Vector2::new(::one(), ::zero())) { return }; if !f(Vector2::new(::one(), ::zero())) { return };
f(Vector2::new(::zero(), ::one())); 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> { impl<N: BaseFloat> Basis for Vector3<N> {
#[inline(always)] #[inline]
fn canonical_basis<F: FnMut(Vector3<N>) -> bool>(mut f: F) { fn canonical_basis<F: FnMut(Vector3<N>) -> bool>(mut f: F) {
if !f(Vector3::new(::one(), ::zero(), ::zero())) { return }; if !f(Vector3::new(::one(), ::zero(), ::zero())) { return };
if !f(Vector3::new(::zero(), ::one(), ::zero())) { return }; if !f(Vector3::new(::zero(), ::one(), ::zero())) { return };
f(Vector3::new(::zero(), ::zero(), ::one())); f(Vector3::new(::zero(), ::zero(), ::one()));
} }
#[inline(always)] #[inline]
fn orthonormal_subspace_basis<F: FnMut(Vector3<N>) -> bool>(n: &Vector3<N>, mut f: F) { fn orthonormal_subspace_basis<F: FnMut(Vector3<N>) -> bool>(n: &Vector3<N>, mut f: F) {
let a = let a =
if n.x.abs() > n.y.abs() { 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 { 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 }; if !f(Cross::cross(&a, n)) { return };
@ -272,14 +272,14 @@ static SAMPLES_3_F64: [Vector3<f64>; 42] = [
impl<N> UniformSphereSample for Vector1<N> impl<N> UniformSphereSample for Vector1<N>
where Vector1<N>: One { where Vector1<N>: One {
#[inline(always)] #[inline]
fn sample<F: FnMut(Vector1<N>)>(mut f: F) { fn sample<F: FnMut(Vector1<N>)>(mut f: F) {
f(::one()) f(::one())
} }
} }
impl<N: Cast<f64> + Copy> UniformSphereSample for Vector2<N> { impl<N: Cast<f64> + Copy> UniformSphereSample for Vector2<N> {
#[inline(always)] #[inline]
fn sample<F: FnMut(Vector2<N>)>(mut f: F) { fn sample<F: FnMut(Vector2<N>)>(mut f: F) {
for sample in SAMPLES_2_F64.iter() { for sample in SAMPLES_2_F64.iter() {
f(Cast::from(*sample)) 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> { impl<N: Cast<f64> + Copy> UniformSphereSample for Vector3<N> {
#[inline(always)] #[inline]
fn sample<F: FnMut(Vector3<N>)>(mut f: F) { fn sample<F: FnMut(Vector3<N>)>(mut f: F) {
for sample in SAMPLES_3_F64.iter() { for sample in SAMPLES_3_F64.iter() {
f(Cast::from(*sample)) 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> { impl<N: Cast<f64> + Copy> UniformSphereSample for Vector4<N> {
#[inline(always)] #[inline]
fn sample<F: FnMut(Vector4<N>)>(_: F) { fn sample<F: FnMut(Vector4<N>)>(_: F) {
panic!("UniformSphereSample::<Vector4<N>>::sample : Not yet implemented.") panic!("UniformSphereSample::<Vector4<N>>::sample : Not yet implemented.")
// for sample in SAMPLES_3_F32.iter() { // 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 pub x: N
} }
new_impl!(Vector1, x); vector_impl!(Vector1, Point1, x);
pord_impl!(Vector1, x,); vectorlike_impl!(Vector1, 1, 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);
from_iterator_impl!(Vector1, iterator); from_iterator_impl!(Vector1, iterator);
bounded_impl!(Vector1, x); // (specialized); basis_impl!(Vector1, 1);
axpy_impl!(Vector1, x);
iterable_impl!(Vector1, 1);
iterable_mut_impl!(Vector1, 1);
vec_to_homogeneous_impl!(Vector1, Vector2, y, x); vec_to_homogeneous_impl!(Vector1, Vector2, y, x);
vec_from_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. /// Vector of dimension 2.
/// ///
@ -87,50 +51,14 @@ pub struct Vector2<N> {
pub y: N pub y: N
} }
new_impl!(Vector2, x, y); vector_impl!(Vector2, Point2, x, y);
pord_impl!(Vector2, x, y); vectorlike_impl!(Vector2, 2, 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);
from_iterator_impl!(Vector2, iterator, iterator); from_iterator_impl!(Vector2, iterator, iterator);
bounded_impl!(Vector2, x, y); // (specialized); basis_impl!(Vector2, 1);
axpy_impl!(Vector2, x, y);
iterable_impl!(Vector2, 2);
iterable_mut_impl!(Vector2, 2);
vec_to_homogeneous_impl!(Vector2, Vector3, z, x, y); vec_to_homogeneous_impl!(Vector2, Vector3, z, x, y);
vec_from_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. /// Vector of dimension 3.
/// ///
@ -147,50 +75,12 @@ pub struct Vector3<N> {
pub z: N pub z: N
} }
new_impl!(Vector3, x, y, z); vector_impl!(Vector3, Point3, x, y, z);
pord_impl!(Vector3, x, y, z); vectorlike_impl!(Vector3, 3, 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);
from_iterator_impl!(Vector3, iterator, iterator, iterator); from_iterator_impl!(Vector3, iterator, iterator, iterator);
bounded_impl!(Vector3, x, y, z); // (specialized); basis_impl!(Vector3, 1);
axpy_impl!(Vector3, x, y, z);
iterable_impl!(Vector3, 3);
iterable_mut_impl!(Vector3, 3);
vec_to_homogeneous_impl!(Vector3, Vector4, w, x, y, z); vec_to_homogeneous_impl!(Vector3, Vector4, w, x, y, z);
vec_from_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. /// Vector of dimension 4.
@ -210,50 +100,14 @@ pub struct Vector4<N> {
pub w: N pub w: N
} }
new_impl!(Vector4, x, y, z, w); vector_impl!(Vector4, Point4, x, y, z, w);
pord_impl!(Vector4, x, y, z, w); vectorlike_impl!(Vector4, 4, 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);
from_iterator_impl!(Vector4, iterator, iterator, iterator, iterator); from_iterator_impl!(Vector4, iterator, iterator, iterator, iterator);
bounded_impl!(Vector4, x, y, z, w); basis_impl!(Vector4, 4);
axpy_impl!(Vector4, x, y, z, w);
iterable_impl!(Vector4, 4);
iterable_mut_impl!(Vector4, 4);
vec_to_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w); vec_to_homogeneous_impl!(Vector4, Vector5, a, x, y, z, w);
vec_from_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. /// Vector of dimension 5.
/// ///
@ -274,50 +128,13 @@ pub struct Vector5<N> {
pub a: N pub a: N
} }
new_impl!(Vector5, x, y, z, w, a); vector_impl!(Vector5, Point5, x, y, z, w, a);
pord_impl!(Vector5, x, y, z, w, a); vectorlike_impl!(Vector5, 5, 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);
from_iterator_impl!(Vector5, iterator, iterator, iterator, iterator, iterator); from_iterator_impl!(Vector5, iterator, iterator, iterator, iterator, iterator);
bounded_impl!(Vector5, x, y, z, w, a); basis_impl!(Vector5, 5);
axpy_impl!(Vector5, x, y, z, w, a);
iterable_impl!(Vector5, 5);
iterable_mut_impl!(Vector5, 5);
vec_to_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a); vec_to_homogeneous_impl!(Vector5, Vector6, b, x, y, z, w, a);
vec_from_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. /// Vector of dimension 6.
/// ///
@ -340,45 +157,8 @@ pub struct Vector6<N> {
pub b: N pub b: N
} }
new_impl!(Vector6, x, y, z, w, a, b); vector_impl!(Vector6, Point6, x, y, z, w, a, b);
pord_impl!(Vector6, x, y, z, w, a, b); vectorlike_impl!(Vector6, 6, 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);
from_iterator_impl!(Vector6, iterator, iterator, iterator, iterator, iterator, iterator); 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); basis_impl!(Vector6, 6);
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);

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)*> { impl<N $(, $param : ArrayLength<N>)*> Iterable<N> for $vecn<N $(, $param)*> {
#[inline] #[inline]
fn iter<'l>(&'l self) -> Iter<'l, N> { fn iter(&self) -> Iter<N> {
self.as_ref().iter() self.as_ref().iter()
} }
} }
impl<N $(, $param : ArrayLength<N>)*> IterableMut<N> for $vecn<N $(, $param)*> { impl<N $(, $param : ArrayLength<N>)*> IterableMut<N> for $vecn<N $(, $param)*> {
#[inline] #[inline]
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> { fn iter_mut(&mut self) -> IterMut<N> {
self.as_mut().iter_mut() 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)*> impl<N $(, $param: ArrayLength<N>)*> DivAssign<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*>
where N: Copy + DivAssign<N> + Zero $(, $param : ArrayLength<N>)* { where N: Copy + DivAssign<N> + Zero $(, $param : ArrayLength<N>)* {
#[inline] #[inline]
@ -495,10 +513,12 @@ macro_rules! vecn_dvec_common_impl(
* Norm. * 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] #[inline]
fn norm_squared(&self) -> N { fn norm_squared(&self) -> N {
Dot::dot(self, self) ::dot(self, self)
} }
#[inline] #[inline]
@ -510,13 +530,35 @@ macro_rules! vecn_dvec_common_impl(
#[inline] #[inline]
fn normalize_mut(&mut self) -> N { 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 = *n / l;
} }
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. //! Traits of operations having a well-known or explicit geometric meaning.
use std::ops::{Neg, Mul}; use std::ops::{Neg, Mul};
use num::Float;
use traits::structure::{BaseFloat, SquareMatrix}; use traits::structure::{BaseFloat, SquareMatrix};
/// Trait of object which represent a translation, and to wich new translation /// 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. /// 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`. /// Computes the norm of `self`.
#[inline] #[inline]
fn norm(&self) -> N { fn norm(&self) -> Self::NormType {
self.norm_squared().sqrt() self.norm_squared().sqrt()
} }
/// Computes the squared norm of `self`. /// Computes the squared norm of `self`.
/// ///
/// This is usually faster than computing the norm itself. /// 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`. /// 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; fn normalize(&self) -> Self;
/// Normalizes `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, pub use traits::structure::{FloatVector, FloatPoint, Basis, Cast, Column, Dimension, Indexable, Iterable,
IterableMut, Matrix, SquareMatrix, Row, NumVector, NumPoint, PointAsVector, ColumnSlice, 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}; Bounded};
pub use traits::operations::{Absolute, ApproxEq, Axpy, Covariance, Determinant, Inverse, Mean, Outer, PartialOrder, Transpose, 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. //! 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::ops::Mul;
use std::cmp::Ordering; use std::cmp::Ordering;
use traits::structure::SquareMatrix; use traits::structure::SquareMatrix;
@ -136,8 +137,7 @@ pub trait PartialOrder {
if v_min.is_not_comparable() || v_max.is_not_comparable() { if v_min.is_not_comparable() || v_max.is_not_comparable() {
None None
} }
else { else if v_min.is_lt() {
if v_min.is_lt() {
Some(min) Some(min)
} }
else if v_max.is_gt() { else if v_max.is_gt() {
@ -148,7 +148,6 @@ pub trait PartialOrder {
} }
} }
} }
}
/// Trait for testing approximate equality /// Trait for testing approximate equality
pub trait ApproxEq<Eps>: Sized { 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 // IEEE754 floats are in the same order as 2s complement isizes
// so this trick (subtracting the isizes) works. // so this trick (subtracting the isizes) works.
let iself: i32 = unsafe { ::std::mem::transmute(*self) }; let iself: i32 = unsafe { mem::transmute(*self) };
let iother: i32 = unsafe { ::std::mem::transmute(*other) }; let iother: i32 = unsafe { mem::transmute(*other) };
(iself - iother).abs() < ulps as i32 (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 // Otherwise, differing signs should be not-equal, even if within ulps
if self.signum() != other.signum() { return false; } if self.signum() != other.signum() { return false; }
let iself: i64 = unsafe { ::std::mem::transmute(*self) }; let iself: i64 = unsafe { mem::transmute(*self) };
let iother: i64 = unsafe { ::std::mem::transmute(*other) }; let iother: i64 = unsafe { mem::transmute(*other) };
(iself - iother).abs() < ulps as i64 (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, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign,
Index, IndexMut, Neg}; Index, IndexMut, Neg};
use num::{Float, Zero, One}; 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}; use traits::geometry::{Dot, Norm, Origin};
/// Basic integral numeric trait. /// Basic integral numeric trait.
@ -21,7 +21,7 @@ pub trait BaseNum: Copy + Zero + One +
} }
/// Basic floating-point number numeric trait. /// 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. /// Archimedes' constant.
fn pi() -> Self; fn pi() -> Self;
/// 2.0 * pi. /// 2.0 * pi.
@ -176,7 +176,7 @@ pub trait Diagonal<V> {
} }
/// Trait to set the diagonal of square matrices. /// 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. /// Sets the diagonal of this matrix.
fn set_diagonal(&mut self, diagonal: &V); 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. /// Traits of objects which can be iterated through like a vector.
pub trait Iterable<N> { pub trait Iterable<N> {
/// Gets a vector-like read-only iterator. /// 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. /// 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. /// Traits of mutable objects which can be iterated through like a vector.
pub trait IterableMut<N> { pub trait IterableMut<N> {
/// Gets a vector-like read-write iterator. /// 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. /// 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; fn to_vector(self) -> Self::Vector;
/// Converts a reference to this point to a reference to its associated 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 // NOTE: this is used in some places to overcome some limitations untill the trait reform is
// done on rustc. // done on rustc.
@ -289,7 +289,7 @@ pub trait NumPoint<N>:
/// Trait of points with components implementing the `BaseFloat` trait. /// Trait of points with components implementing the `BaseFloat` trait.
pub trait FloatPoint<N: BaseFloat>: NumPoint<N> + Sized 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. /// Computes the square distance between two points.
#[inline] #[inline]
fn distance_squared(&self, other: &Self) -> N { fn distance_squared(&self, other: &Self) -> N {

View File

@ -1,7 +1,7 @@
extern crate nalgebra as na; extern crate nalgebra as na;
extern crate rand; extern crate rand;
use na::{Point3, Vector3, Rotation3, UnitQuaternion, Rotation}; use na::{Point3, Quaternion, Vector3, Rotation3, UnitQuaternion, Rotation, one};
use rand::random; use rand::random;
#[test] #[test]
@ -9,7 +9,7 @@ fn test_quaternion_as_matrix() {
for _ in 0usize .. 10000 { for _ in 0usize .. 10000 {
let axis_angle: Vector3<f64> = random(); 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 point: Point3<f64> = random();
let matrix = Rotation3::new(axis_angle); 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 * vector), &(quaternion * vector)));
assert!(na::approx_eq(&(matrix * point), &(quaternion * point))); assert!(na::approx_eq(&(matrix * point), &(quaternion * point)));
@ -39,8 +39,8 @@ fn test_quaternion_div_quaternion() {
let r1 = Rotation3::new(axis_angle1); let r1 = Rotation3::new(axis_angle1);
let r2 = na::inverse(&Rotation3::new(axis_angle2)).unwrap(); let r2 = na::inverse(&Rotation3::new(axis_angle2)).unwrap();
let q1 = UnitQuaternion::new(axis_angle1); let q1 = UnitQuaternion::from_scaled_axis(axis_angle1);
let q2 = UnitQuaternion::new(axis_angle2); let q2 = UnitQuaternion::from_scaled_axis(axis_angle2);
assert!(na::approx_eq(&(q1 / q2).to_rotation_matrix(), &(r1 * r2))) 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 { for _ in 0usize .. 10000 {
let axis_angle: Vector3<f64> = random(); 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); println!("{:?} {:?}", q.rotation(), axis_angle);
assert!(na::approx_eq(&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 { for _ in 0usize .. 10000 {
let angles: Vector3<f64> = random(); let angles: Vector3<f64> = random();
let q = UnitQuaternion::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::new_with_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)) 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)) 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))
}
}