Indentation fixes.

This commit is contained in:
Sébastien Crozet 2013-08-05 09:44:56 +02:00
parent 53a5dbb6e3
commit a810bf6008
29 changed files with 1726 additions and 1792 deletions

View File

@ -25,272 +25,272 @@ pub struct Rotmat<M>
impl<M: Clone> Rotmat<M>
{
/// Gets a copy of the internal representation of the rotation.
pub fn submat(&self) -> M
{ self.submat.clone() }
/// Gets a copy of the internal representation of the rotation.
pub fn submat(&self) -> M
{ self.submat.clone() }
}
impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>>
{
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn from_angle(angle: N) -> Rotmat<Mat2<N>>
{
let (sia, coa) = angle.sin_cos();
/// Builds a 2 dimensional rotation matrix from an angle in radian.
pub fn from_angle(angle: N) -> Rotmat<Mat2<N>>
{
let (sia, coa) = angle.sin_cos();
Rotmat { submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) }
}
Rotmat { submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) }
}
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # Arguments
/// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
/// in radian. Its direction is the axis of rotation.
pub fn from_axis_angle(axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
{
if axisangle.sqnorm().is_zero()
{ One::one() }
else
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # Arguments
/// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
/// in radian. Its direction is the axis of rotation.
pub fn from_axis_angle(axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
{
let mut axis = axisangle;
let angle = axis.normalize();
let _1 = One::one::<N>();
let ux = axis.x.clone();
let uy = axis.y.clone();
let uz = axis.z.clone();
let sqx = ux * ux;
let sqy = uy * uy;
let sqz = uz * uz;
let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos;
if axisangle.sqnorm().is_zero()
{ One::one() }
else
{
let mut axis = axisangle;
let angle = axis.normalize();
let _1 = One::one::<N>();
let ux = axis.x.clone();
let uy = axis.y.clone();
let uz = axis.z.clone();
let sqx = ux * ux;
let sqy = uy * uy;
let sqz = uz * uz;
let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos;
Rotmat {
submat: Mat3::new(
(sqx + (_1 - sqx) * cos),
(ux * uy * one_m_cos - uz * sin),
(ux * uz * one_m_cos + uy * sin),
Rotmat {
submat: Mat3::new(
(sqx + (_1 - sqx) * cos),
(ux * uy * one_m_cos - uz * sin),
(ux * uz * one_m_cos + uy * sin),
(ux * uy * one_m_cos + uz * sin),
(sqy + (_1 - sqy) * cos),
(uy * uz * one_m_cos - ux * sin),
(ux * uy * one_m_cos + uz * sin),
(sqy + (_1 - sqy) * cos),
(uy * uz * one_m_cos - ux * sin),
(ux * uz * one_m_cos - uy * sin),
(uy * uz * one_m_cos + ux * sin),
(sqz + (_1 - sqz) * cos))
}
(ux * uz * one_m_cos - uy * sin),
(uy * uz * one_m_cos + ux * sin),
(sqz + (_1 - sqz) * cos))
}
}
}
}
}
impl<N: Clone + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
/// with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>)
{
let xaxis = at.normalized();
let zaxis = up.cross(&xaxis).normalized();
let yaxis = zaxis.cross(&xaxis);
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
/// with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>)
{
let xaxis = at.normalized();
let zaxis = up.cross(&xaxis).normalized();
let yaxis = zaxis.cross(&xaxis);
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z , yaxis.z , zaxis.z)
}
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z , yaxis.z , zaxis.z)
}
/// Reorient this matrix such that its local `z` axis points to a given point.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
/// with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>)
{
let zaxis = at.normalized();
let xaxis = up.cross(&zaxis).normalized();
let yaxis = zaxis.cross(&xaxis);
/// Reorient this matrix such that its local `z` axis points to a given point.
///
/// # Arguments
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
/// with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>)
{
let zaxis = at.normalized();
let xaxis = up.cross(&zaxis).normalized();
let yaxis = zaxis.cross(&xaxis);
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z , yaxis.z , zaxis.z)
}
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
xaxis.z , yaxis.z , zaxis.z)
}
}
impl<N: Trigonometric + DivisionRing + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{
#[inline]
fn rotation(&self) -> Vec1<N>
{ Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0)))) }
#[inline]
fn rotation(&self) -> Vec1<N>
{ Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0)))) }
#[inline]
fn inv_rotation(&self) -> Vec1<N>
{ -self.rotation() }
#[inline]
fn inv_rotation(&self) -> Vec1<N>
{ -self.rotation() }
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>)
{ *self = self.rotated(rot) }
#[inline]
fn rotate_by(&mut self, rot: &Vec1<N>)
{ *self = self.rotated(rot) }
}
impl<N: Trigonometric + DivisionRing + Clone>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ Rotmat::from_angle(rot.x.clone()) * *self }
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ Rotmat::from_angle(rot.x.clone()) * *self }
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotation<Vec3<N>> for Rotmat<Mat3<N>>
{
#[inline]
fn rotation(&self) -> Vec3<N>
{ fail!("Not yet implemented.") }
#[inline]
#[inline]
fn rotation(&self) -> Vec3<N>
{ fail!("Not yet implemented.") }
#[inline]
fn inv_rotation(&self) -> Vec3<N>
{ fail!("Not yet implemented.") }
fn inv_rotation(&self) -> Vec3<N>
{ fail!("Not yet implemented.") }
#[inline]
fn rotate_by(&mut self, rot: &Vec3<N>)
{ *self = self.rotated(rot) }
#[inline]
fn rotate_by(&mut self, rot: &Vec3<N>)
{ *self = self.rotated(rot) }
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
{
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
{ Rotmat::from_axis_angle(axisangle.clone()) * *self }
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
{ Rotmat::from_axis_angle(axisangle.clone()) * *self }
}
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
{ Rotmat::from_angle(rng.gen()) }
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
{ Rotmat::from_angle(rng.gen()) }
}
impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M>
{
#[inline]
fn rotate(&self, v: &V) -> V
{ self.rmul(v) }
#[inline]
fn rotate(&self, v: &V) -> V
{ self.rmul(v) }
#[inline]
fn inv_rotate(&self, v: &V) -> V
{ self.lmul(v) }
#[inline]
fn inv_rotate(&self, v: &V) -> V
{ self.lmul(v) }
}
impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
{
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.rotate(v) }
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.rotate(v) }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.inv_rotate(v) }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.inv_rotate(v) }
}
impl<N: Clone + Rand + Trigonometric + DivisionRing + Algebraic>
Rand for Rotmat<Mat3<N>>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>>
{ Rotmat::from_axis_angle(rng.gen()) }
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>>
{ Rotmat::from_axis_angle(rng.gen()) }
}
impl<M: Dim> Dim for Rotmat<M>
{
#[inline]
fn dim() -> uint
{ Dim::dim::<M>() }
#[inline]
fn dim() -> uint
{ Dim::dim::<M>() }
}
impl<M: One + Zero> One for Rotmat<M>
{
#[inline]
fn one() -> Rotmat<M>
{ Rotmat { submat: One::one() } }
#[inline]
fn one() -> Rotmat<M>
{ Rotmat { submat: One::one() } }
}
impl<M: Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M>
{
#[inline]
fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
{ Rotmat { submat: self.submat.mul(&other.submat) } }
#[inline]
fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
{ Rotmat { submat: self.submat.mul(&other.submat) } }
}
impl<V, M: RMul<V>> RMul<V> for Rotmat<M>
{
#[inline]
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) }
#[inline]
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) }
}
impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
{
#[inline]
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) }
#[inline]
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) }
}
impl<M: Transpose> Inv for Rotmat<M>
{
#[inline]
fn inplace_inverse(&mut self) -> bool
{
self.transpose();
#[inline]
fn inplace_inverse(&mut self) -> bool
{
self.transpose();
true
}
true
}
#[inline]
fn inverse(&self) -> Option<Rotmat<M>>
{ Some(self.transposed()) }
#[inline]
fn inverse(&self) -> Option<Rotmat<M>>
{ Some(self.transposed()) }
}
impl<M: Transpose>
Transpose for Rotmat<M>
{
#[inline]
fn transposed(&self) -> Rotmat<M>
{ Rotmat { submat: self.submat.transposed() } }
#[inline]
fn transposed(&self) -> Rotmat<M>
{ Rotmat { submat: self.submat.transposed() } }
#[inline]
fn transpose(&mut self)
{ self.submat.transpose() }
#[inline]
fn transpose(&mut self)
{ self.submat.transpose() }
}
// we loose the info that we are a rotation matrix
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M>
{
fn to_homogeneous(&self) -> M2
{ self.submat.to_homogeneous() }
fn to_homogeneous(&self) -> M2
{ self.submat.to_homogeneous() }
}
impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &Rotmat<M>) -> bool
{ self.submat.approx_eq(&other.submat) }
#[inline]
fn approx_eq(&self, other: &Rotmat<M>) -> bool
{ self.submat.approx_eq(&other.submat) }
#[inline]
fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool
{ self.submat.approx_eq_eps(&other.submat, epsilon) }
#[inline]
fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool
{ self.submat.approx_eq_eps(&other.submat, epsilon) }
}

View File

@ -25,231 +25,226 @@ use mat::Mat3;
#[deriving(Eq, ToStr, Clone)]
pub struct Transform<M, V>
{
priv submat : M,
priv subtrans : V
priv submat : M,
priv subtrans : V
}
impl<M, V> Transform<M, V>
{
/// Builds a new transform from a matrix and a vector.
#[inline]
pub fn new(mat: M, trans: V) -> Transform<M, V>
{ Transform { submat: mat, subtrans: trans } }
/// Builds a new transform from a matrix and a vector.
#[inline]
pub fn new(mat: M, trans: V) -> Transform<M, V>
{ Transform { submat: mat, subtrans: trans } }
}
impl<M: Clone, V: Clone> Transform<M, V>
{
/// Gets a copy of the internal matrix.
#[inline]
pub fn submat(&self) -> M
{ self.submat.clone() }
/// Gets a copy of the internal matrix.
#[inline]
pub fn submat(&self) -> M
{ self.submat.clone() }
/// Gets a copy of the internal translation.
#[inline]
pub fn subtrans(&self) -> V
{ self.subtrans.clone() }
/// Gets a copy of the internal translation.
#[inline]
pub fn subtrans(&self) -> V
{ self.subtrans.clone() }
}
impl<N: Clone + DivisionRing + Algebraic> Transform<Rotmat<Mat3<N>>, Vec3<N>>
{
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>)
{
self.submat.look_at(&(*at - *eye), up);
self.subtrans = eye.clone();
}
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>)
{
self.submat.look_at(&(*at - *eye), up);
self.subtrans = eye.clone();
}
/// Reorient and translate this transformation such that its local `z` axis points to a given
/// direction.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at_z(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>)
{
self.submat.look_at_z(&(*at - *eye), up);
self.subtrans = eye.clone();
}
/// Reorient and translate this transformation such that its local `z` axis points to a given
/// direction.
///
/// # Arguments
/// * eye - The new translation of the transformation.
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
/// aligned with
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
/// with `at`. Non-colinearity is not checked.
pub fn look_at_z(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>)
{
self.submat.look_at_z(&(*at - *eye), up);
self.subtrans = eye.clone();
}
}
impl<M: Dim, V> Dim for Transform<M, V>
{
#[inline]
fn dim() -> uint
{ Dim::dim::<M>() }
#[inline]
fn dim() -> uint
{ Dim::dim::<M>() }
}
impl<M: One, V: Zero> One for Transform<M, V>
{
#[inline]
fn one() -> Transform<M, V>
{ Transform { submat: One::one(), subtrans: Zero::zero() } }
#[inline]
fn one() -> Transform<M, V>
{ Transform { submat: One::one(), subtrans: Zero::zero() } }
}
impl<M: Zero, V: Zero> Zero for Transform<M, V>
{
#[inline]
fn zero() -> Transform<M, V>
{ Transform { submat: Zero::zero(), subtrans: Zero::zero() } }
#[inline]
fn zero() -> Transform<M, V>
{ Transform { submat: Zero::zero(), subtrans: Zero::zero() } }
#[inline]
fn is_zero(&self) -> bool
{ self.submat.is_zero() && self.subtrans.is_zero() }
#[inline]
fn is_zero(&self) -> bool
{ self.submat.is_zero() && self.subtrans.is_zero() }
}
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>>
Mul<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
#[inline]
fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
{
Transform { submat: self.submat * other.submat,
subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
}
#[inline]
fn mul(&self, other: &Transform<M, V>) -> Transform<M, V>
{
Transform { submat: self.submat * other.submat,
subtrans: self.subtrans + self.submat.rmul(&other.subtrans) }
}
}
impl<M: RMul<V>, V: Add<V, V>> RMul<V> for Transform<M, V>
{
#[inline]
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) + self.subtrans }
#[inline]
fn rmul(&self, other: &V) -> V
{ self.submat.rmul(other) + self.subtrans }
}
impl<M: LMul<V>, V: Add<V, V>> LMul<V> for Transform<M, V>
{
#[inline]
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) + self.subtrans }
#[inline]
fn lmul(&self, other: &V) -> V
{ self.submat.lmul(other) + self.subtrans }
}
impl<M, V: Translation<V>> Translation<V> for Transform<M, V>
{
#[inline]
fn translation(&self) -> V
{ self.subtrans.translation() }
#[inline]
fn translation(&self) -> V
{ self.subtrans.translation() }
#[inline]
fn inv_translation(&self) -> V
{ self.subtrans.inv_translation() }
#[inline]
fn inv_translation(&self) -> V
{ self.subtrans.inv_translation() }
#[inline]
fn translate_by(&mut self, t: &V)
{ self.subtrans.translate_by(t) }
#[inline]
fn translate_by(&mut self, t: &V)
{ self.subtrans.translate_by(t) }
}
impl<M: Translate<V>, V, _0> Translate<V> for Transform<M, _0>
{
#[inline]
fn translate(&self, v: &V) -> V
{ self.submat.translate(v) }
#[inline]
fn translate(&self, v: &V) -> V
{ self.submat.translate(v) }
#[inline]
fn inv_translate(&self, v: &V) -> V
{ self.submat.inv_translate(v) }
#[inline]
fn inv_translate(&self, v: &V) -> V
{ self.submat.inv_translate(v) }
}
impl<M: Clone, V: Translatable<V, V> + Translation<V>>
Translatable<V, Transform<M, V>> for Transform<M, V>
{
#[inline]
fn translated(&self, t: &V) -> Transform<M, V>
{ Transform::new(self.submat.clone(), self.subtrans.translated(t)) }
#[inline]
fn translated(&self, t: &V) -> Transform<M, V>
{ Transform::new(self.submat.clone(), self.subtrans.translated(t)) }
}
impl<M: Rotation<AV> + RMul<V> + One,
V,
AV>
impl<M: Rotation<AV> + RMul<V> + One, V, AV>
Rotation<AV> for Transform<M, V>
{
#[inline]
fn rotation(&self) -> AV
{ self.submat.rotation() }
#[inline]
fn rotation(&self) -> AV
{ self.submat.rotation() }
#[inline]
fn inv_rotation(&self) -> AV
{ self.submat.inv_rotation() }
#[inline]
fn inv_rotation(&self) -> AV
{ self.submat.inv_rotation() }
#[inline]
fn rotate_by(&mut self, rot: &AV)
{
// FIXME: this does not seem opitmal
let mut delta = One::one::<M>();
delta.rotate_by(rot);
self.submat.rotate_by(rot);
self.subtrans = delta.rmul(&self.subtrans);
}
#[inline]
fn rotate_by(&mut self, rot: &AV)
{
// FIXME: this does not seem opitmal
let mut delta = One::one::<M>();
delta.rotate_by(rot);
self.submat.rotate_by(rot);
self.subtrans = delta.rmul(&self.subtrans);
}
}
impl<M: Rotate<V>, V, _0> Rotate<V> for Transform<M, _0>
{
#[inline]
fn rotate(&self, v: &V) -> V
{ self.submat.rotate(v) }
#[inline]
fn rotate(&self, v: &V) -> V
{ self.submat.rotate(v) }
#[inline]
fn inv_rotate(&self, v: &V) -> V
{ self.submat.inv_rotate(v) }
#[inline]
fn inv_rotate(&self, v: &V) -> V
{ self.submat.inv_rotate(v) }
}
impl<M: Rotatable<AV, Res> + One,
Res: Rotation<AV> + RMul<V> + One,
V,
AV>
impl<M: Rotatable<AV, Res> + One, Res: Rotation<AV> + RMul<V> + One, V, AV>
Rotatable<AV, Transform<Res, V>> for Transform<M, V>
{
#[inline]
fn rotated(&self, rot: &AV) -> Transform<Res, V>
{
// FIXME: this does not seem opitmal
let delta = One::one::<M>().rotated(rot);
#[inline]
fn rotated(&self, rot: &AV) -> Transform<Res, V>
{
// FIXME: this does not seem opitmal
let delta = One::one::<M>().rotated(rot);
Transform::new(self.submat.rotated(rot), delta.rmul(&self.subtrans))
}
Transform::new(self.submat.rotated(rot), delta.rmul(&self.subtrans))
}
}
impl<M: Inv + RMul<V> + Mul<M, M> + Clone, V: Add<V, V> + Neg<V> + Clone>
Transformation<Transform<M, V>> for Transform<M, V>
{
fn transformation(&self) -> Transform<M, V>
{ self.clone() }
fn transformation(&self) -> Transform<M, V>
{ self.clone() }
fn inv_transformation(&self) -> Transform<M, V>
{
// FIXME: fail or return a Some<Transform<M, V>> ?
match self.inverse()
fn inv_transformation(&self) -> Transform<M, V>
{
Some(t) => t,
None => fail!("This transformation was not inversible.")
// FIXME: fail or return a Some<Transform<M, V>> ?
match self.inverse()
{
Some(t) => t,
None => fail!("This transformation was not inversible.")
}
}
}
fn transform_by(&mut self, other: &Transform<M, V>)
{ *self = other * *self; }
fn transform_by(&mut self, other: &Transform<M, V>)
{ *self = other * *self; }
}
impl<M: Ts<V>, V: Add<V, V> + Sub<V, V>>
Ts<V> for Transform<M, V>
{
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.submat.transform_vec(v) + self.subtrans }
#[inline]
fn transform_vec(&self, v: &V) -> V
{ self.submat.transform_vec(v) + self.subtrans }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.submat.inv_transform(&(v - self.subtrans)) }
#[inline]
fn inv_transform(&self, v: &V) -> V
{ self.submat.inv_transform(&(v - self.subtrans)) }
}
@ -258,87 +253,87 @@ Ts<V> for Transform<M, V>
impl<M: RMul<V> + Mul<M, M> + Inv + Clone, V: Add<V, V> + Neg<V> + Clone>
Transformable<Transform<M, V>, Transform<M, V>> for Transform<M, V>
{
fn transformed(&self, t: &Transform<M, V>) -> Transform<M, V>
{ t * *self }
fn transformed(&self, t: &Transform<M, V>) -> Transform<M, V>
{ t * *self }
}
impl<M: Inv + RMul<V> + Clone, V: Neg<V> + Clone>
Inv for Transform<M, V>
{
#[inline]
fn inplace_inverse(&mut self) -> bool
{
if !self.submat.inplace_inverse()
{ false }
else
#[inline]
fn inplace_inverse(&mut self) -> bool
{
self.subtrans = self.submat.rmul(&-self.subtrans);
true
if !self.submat.inplace_inverse()
{ false }
else
{
self.subtrans = self.submat.rmul(&-self.subtrans);
true
}
}
}
#[inline]
fn inverse(&self) -> Option<Transform<M, V>>
{
let mut res = self.clone();
#[inline]
fn inverse(&self) -> Option<Transform<M, V>>
{
let mut res = self.clone();
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
}
impl<M: ToHomogeneous<M2>, M2: Dim + Column<V>, V: Clone>
ToHomogeneous<M2> for Transform<M, V>
{
fn to_homogeneous(&self) -> M2
{
let mut res = self.submat.to_homogeneous();
fn to_homogeneous(&self) -> M2
{
let mut res = self.submat.to_homogeneous();
// copy the translation
let dim = Dim::dim::<M2>();
// copy the translation
let dim = Dim::dim::<M2>();
res.set_column(dim - 1, self.subtrans.clone());
res.set_column(dim - 1, self.subtrans.clone());
res
}
res
}
}
impl<M: Column<V> + Dim, M2: FromHomogeneous<M>, V>
FromHomogeneous<M> for Transform<M2, V>
{
fn from(m: &M) -> Transform<M2, V>
{
Transform::new(FromHomogeneous::from(m), m.column(Dim::dim::<M>() - 1))
}
fn from(m: &M) -> Transform<M2, V>
{
Transform::new(FromHomogeneous::from(m), m.column(Dim::dim::<M>() - 1))
}
}
impl<N: ApproxEq<N>, M:ApproxEq<N>, V:ApproxEq<N>>
ApproxEq<N> for Transform<M, V>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &Transform<M, V>) -> bool
{
self.submat.approx_eq(&other.submat) &&
self.subtrans.approx_eq(&other.subtrans)
}
#[inline]
fn approx_eq(&self, other: &Transform<M, V>) -> bool
{
self.submat.approx_eq(&other.submat) &&
self.subtrans.approx_eq(&other.subtrans)
}
#[inline]
fn approx_eq_eps(&self, other: &Transform<M, V>, epsilon: &N) -> bool
{
self.submat.approx_eq_eps(&other.submat, epsilon) &&
self.subtrans.approx_eq_eps(&other.subtrans, epsilon)
}
#[inline]
fn approx_eq_eps(&self, other: &Transform<M, V>, epsilon: &N) -> bool
{
self.submat.approx_eq_eps(&other.submat, epsilon) &&
self.subtrans.approx_eq_eps(&other.subtrans, epsilon)
}
}
impl<M: Rand, V: Rand> Rand for Transform<M, V>
{
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Transform<M, V>
{ Transform::new(rng.gen(), rng.gen()) }
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Transform<M, V>
{ Transform::new(rng.gen(), rng.gen()) }
}

View File

@ -12,8 +12,8 @@ use dvec::{DVec, zero_vec_with_dim};
#[deriving(Eq, ToStr, Clone)]
pub struct DMat<N>
{
priv dim: uint, // FIXME: handle more than just square matrices
priv mij: ~[N]
priv dim: uint, // FIXME: handle more than just square matrices
priv mij: ~[N]
}
/// Builds a matrix filled with zeros.
@ -38,264 +38,264 @@ pub fn is_zero_mat<N: Zero>(mat: &DMat<N>) -> bool
#[inline]
pub fn one_mat_with_dim<N: Clone + One + Zero>(dim: uint) -> DMat<N>
{
let mut res = zero_mat_with_dim(dim);
let _1 = One::one::<N>();
let mut res = zero_mat_with_dim(dim);
let _1 = One::one::<N>();
for i in range(0u, dim)
{ res.set(i, i, &_1); }
for i in range(0u, dim)
{ res.set(i, i, &_1); }
res
res
}
impl<N: Clone> DMat<N>
{
#[inline]
fn offset(&self, i: uint, j: uint) -> uint
{ i * self.dim + j }
#[inline]
fn offset(&self, i: uint, j: uint) -> uint
{ i * self.dim + j }
/// Changes the value of a component of the matrix.
///
/// # Arguments
/// * `i` - 0-based index of the line to be changed
/// * `j` - 0-based index of the column to be changed
#[inline]
pub fn set(&mut self, i: uint, j: uint, t: &N)
{
assert!(i < self.dim);
assert!(j < self.dim);
self.mij[self.offset(i, j)] = t.clone()
}
/// Changes the value of a component of the matrix.
///
/// # Arguments
/// * `i` - 0-based index of the line to be changed
/// * `j` - 0-based index of the column to be changed
#[inline]
pub fn set(&mut self, i: uint, j: uint, t: &N)
{
assert!(i < self.dim);
assert!(j < self.dim);
self.mij[self.offset(i, j)] = t.clone()
}
/// Reads the value of a component of the matrix.
///
/// # Arguments
/// * `i` - 0-based index of the line to be read
/// * `j` - 0-based index of the column to be read
#[inline]
pub fn at(&self, i: uint, j: uint) -> N
{
assert!(i < self.dim);
assert!(j < self.dim);
self.mij[self.offset(i, j)].clone()
}
/// Reads the value of a component of the matrix.
///
/// # Arguments
/// * `i` - 0-based index of the line to be read
/// * `j` - 0-based index of the column to be read
#[inline]
pub fn at(&self, i: uint, j: uint) -> N
{
assert!(i < self.dim);
assert!(j < self.dim);
self.mij[self.offset(i, j)].clone()
}
}
impl<N: Clone> Index<(uint, uint), N> for DMat<N>
{
#[inline]
fn index(&self, &(i, j): &(uint, uint)) -> N
{ self.at(i, j) }
#[inline]
fn index(&self, &(i, j): &(uint, uint)) -> N
{ self.at(i, j) }
}
impl<N: Clone + Mul<N, N> + Add<N, N> + Zero>
Mul<DMat<N>, DMat<N>> for DMat<N>
{
fn mul(&self, other: &DMat<N>) -> DMat<N>
{
assert!(self.dim == other.dim);
let dim = self.dim;
let mut res = zero_mat_with_dim(dim);
for i in range(0u, dim)
fn mul(&self, other: &DMat<N>) -> DMat<N>
{
for j in range(0u, dim)
{
let mut acc = Zero::zero::<N>();
assert!(self.dim == other.dim);
for k in range(0u, dim)
{ acc = acc + self.at(i, k) * other.at(k, j); }
let dim = self.dim;
let mut res = zero_mat_with_dim(dim);
res.set(i, j, &acc);
}
for i in range(0u, dim)
{
for j in range(0u, dim)
{
let mut acc = Zero::zero::<N>();
for k in range(0u, dim)
{ acc = acc + self.at(i, k) * other.at(k, j); }
res.set(i, j, &acc);
}
}
res
}
res
}
}
impl<N: Clone + Add<N, N> + Mul<N, N> + Zero>
RMul<DVec<N>> for DMat<N>
{
fn rmul(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.dim == other.at.len());
let dim = self.dim;
let mut res : DVec<N> = zero_vec_with_dim(dim);
for i in range(0u, dim)
fn rmul(&self, other: &DVec<N>) -> DVec<N>
{
for j in range(0u, dim)
{ res.at[i] = res.at[i] + other.at[j] * self.at(i, j); }
}
assert!(self.dim == other.at.len());
res
}
let dim = self.dim;
let mut res : DVec<N> = zero_vec_with_dim(dim);
for i in range(0u, dim)
{
for j in range(0u, dim)
{ res.at[i] = res.at[i] + other.at[j] * self.at(i, j); }
}
res
}
}
impl<N: Clone + Add<N, N> + Mul<N, N> + Zero>
LMul<DVec<N>> for DMat<N>
{
fn lmul(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.dim == other.at.len());
let dim = self.dim;
let mut res : DVec<N> = zero_vec_with_dim(dim);
for i in range(0u, dim)
fn lmul(&self, other: &DVec<N>) -> DVec<N>
{
for j in range(0u, dim)
{ res.at[i] = res.at[i] + other.at[j] * self.at(j, i); }
}
assert!(self.dim == other.at.len());
res
}
let dim = self.dim;
let mut res : DVec<N> = zero_vec_with_dim(dim);
for i in range(0u, dim)
{
for j in range(0u, dim)
{ res.at[i] = res.at[i] + other.at[j] * self.at(j, i); }
}
res
}
}
impl<N: Clone + Eq + DivisionRing>
Inv for DMat<N>
{
#[inline]
fn inverse(&self) -> Option<DMat<N>>
{
let mut res : DMat<N> = self.clone();
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
fn inplace_inverse(&mut self) -> bool
{
let dim = self.dim;
let mut res = one_mat_with_dim::<N>(dim);
let _0T = Zero::zero::<N>();
// inversion using Gauss-Jordan elimination
for k in range(0u, dim)
#[inline]
fn inverse(&self) -> Option<DMat<N>>
{
// search a non-zero value on the k-th column
// FIXME: would it be worth it to spend some more time searching for the
// max instead?
let mut res : DMat<N> = self.clone();
let mut n0 = k; // index of a non-zero entry
while (n0 != dim)
{
if self.at(n0, k) != _0T
{ break; }
n0 = n0 + 1;
}
if n0 == dim
{ return false }
// swap pivot line
if n0 != k
{
for j in range(0u, dim)
{
let off_n0_j = self.offset(n0, j);
let off_k_j = self.offset(k, j);
self.mij.swap(off_n0_j, off_k_j);
res.mij.swap(off_n0_j, off_k_j);
}
}
let pivot = self.at(k, k);
for j in range(k, dim)
{
let selfval = &(self.at(k, j) / pivot);
self.set(k, j, selfval);
}
for j in range(0u, dim)
{
let resval = &(res.at(k, j) / pivot);
res.set(k, j, resval);
}
for l in range(0u, dim)
{
if l != k
{
let normalizer = self.at(l, k);
for j in range(k, dim)
{
let selfval = &(self.at(l, j) - self.at(k, j) * normalizer);
self.set(l, j, selfval);
}
for j in range(0u, dim)
{
let resval = &(res.at(l, j) - res.at(k, j) * normalizer);
res.set(l, j, resval);
}
}
}
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
*self = res;
fn inplace_inverse(&mut self) -> bool
{
let dim = self.dim;
let mut res = one_mat_with_dim::<N>(dim);
let _0T = Zero::zero::<N>();
true
}
// inversion using Gauss-Jordan elimination
for k in range(0u, dim)
{
// search a non-zero value on the k-th column
// FIXME: would it be worth it to spend some more time searching for the
// max instead?
let mut n0 = k; // index of a non-zero entry
while (n0 != dim)
{
if self.at(n0, k) != _0T
{ break; }
n0 = n0 + 1;
}
if n0 == dim
{ return false }
// swap pivot line
if n0 != k
{
for j in range(0u, dim)
{
let off_n0_j = self.offset(n0, j);
let off_k_j = self.offset(k, j);
self.mij.swap(off_n0_j, off_k_j);
res.mij.swap(off_n0_j, off_k_j);
}
}
let pivot = self.at(k, k);
for j in range(k, dim)
{
let selfval = &(self.at(k, j) / pivot);
self.set(k, j, selfval);
}
for j in range(0u, dim)
{
let resval = &(res.at(k, j) / pivot);
res.set(k, j, resval);
}
for l in range(0u, dim)
{
if l != k
{
let normalizer = self.at(l, k);
for j in range(k, dim)
{
let selfval = &(self.at(l, j) - self.at(k, j) * normalizer);
self.set(l, j, selfval);
}
for j in range(0u, dim)
{
let resval = &(res.at(l, j) - res.at(k, j) * normalizer);
res.set(l, j, resval);
}
}
}
}
*self = res;
true
}
}
impl<N: Clone> Transpose for DMat<N>
{
#[inline]
fn transposed(&self) -> DMat<N>
{
let mut res = self.clone();
res.transpose();
res
}
fn transpose(&mut self)
{
let dim = self.dim;
for i in range(1u, dim)
#[inline]
fn transposed(&self) -> DMat<N>
{
for j in range(0u, dim - 1)
{
let off_i_j = self.offset(i, j);
let off_j_i = self.offset(j, i);
let mut res = self.clone();
self.mij.swap(off_i_j, off_j_i);
}
res.transpose();
res
}
fn transpose(&mut self)
{
let dim = self.dim;
for i in range(1u, dim)
{
for j in range(0u, dim - 1)
{
let off_i_j = self.offset(i, j);
let off_j_i = self.offset(j, i);
self.mij.swap(off_i_j, off_j_i);
}
}
}
}
}
impl<N: ApproxEq<N>> ApproxEq<N> for DMat<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &DMat<N>) -> bool
{
let mut zip = self.mij.iter().zip(other.mij.iter());
#[inline]
fn approx_eq(&self, other: &DMat<N>) -> bool
{
let mut zip = self.mij.iter().zip(other.mij.iter());
do zip.all |(a, b)| { a.approx_eq(b) }
}
do zip.all |(a, b)| { a.approx_eq(b) }
}
#[inline]
fn approx_eq_eps(&self, other: &DMat<N>, epsilon: &N) -> bool
{
let mut zip = self.mij.iter().zip(other.mij.iter());
#[inline]
fn approx_eq_eps(&self, other: &DMat<N>, epsilon: &N) -> bool
{
let mut zip = self.mij.iter().zip(other.mij.iter());
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
}

View File

@ -16,8 +16,8 @@ use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, Ord, ToStr, Clone)]
pub struct DVec<N>
{
/// Components of the vector. Contains as much elements as the vector dimension.
at: ~[N]
/// Components of the vector. Contains as much elements as the vector dimension.
at: ~[N]
}
/// Builds a vector filled with zeros.
@ -35,282 +35,276 @@ pub fn is_zero_vec<N: Zero>(vec: &DVec<N>) -> bool
impl<N> Iterable<N> for DVec<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ self.at.iter() }
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ self.at.iter() }
}
impl<N> IterableMut<N> for DVec<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ self.at.mut_iter() }
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ self.at.mut_iter() }
}
impl<N, Iter: Iterator<N>> FromIterator<N, Iter> for DVec<N>
{
fn from_iterator(mut param: &mut Iter) -> DVec<N>
{
let mut res = DVec { at: ~[] };
fn from_iterator(mut param: &mut Iter) -> DVec<N>
{
let mut res = DVec { at: ~[] };
for e in param
{ res.at.push(e) }
for e in param
{ res.at.push(e) }
res
}
res
}
}
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> DVec<N>
{
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
/// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal to
/// 1.0.
pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec<N>]
{
let mut res : ~[DVec<N>] = ~[];
for i in range(0u, dim)
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
/// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal
/// to 1.0.
pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec<N>]
{
let mut basis_element : DVec<N> = zero_vec_with_dim(dim);
let mut res : ~[DVec<N>] = ~[];
basis_element.at[i] = One::one();
for i in range(0u, dim)
{
let mut basis_element : DVec<N> = zero_vec_with_dim(dim);
res.push(basis_element);
basis_element.at[i] = One::one();
res.push(basis_element);
}
res
}
res
}
/// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
/// `n`, this will return `n - 1` vectors.
pub fn orthogonal_subspace_basis(&self) -> ~[DVec<N>]
{
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let dim = self.at.len();
let mut res : ~[DVec<N>] = ~[];
for i in range(0u, dim)
/// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
/// `n`, this will return `n - 1` vectors.
pub fn orthogonal_subspace_basis(&self) -> ~[DVec<N>]
{
let mut basis_element : DVec<N> = zero_vec_with_dim(self.at.len());
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let dim = self.at.len();
let mut res : ~[DVec<N>] = ~[];
basis_element.at[i] = One::one();
for i in range(0u, dim)
{
let mut basis_element : DVec<N> = zero_vec_with_dim(self.at.len());
if res.len() == dim - 1
{ break; }
basis_element.at[i] = One::one();
let mut elt = basis_element.clone();
if res.len() == dim - 1
{ break; }
elt = elt - self.scalar_mul(&basis_element.dot(self));
let mut elt = basis_element.clone();
for v in res.iter()
{ elt = elt - v.scalar_mul(&elt.dot(v)) };
elt = elt - self.scalar_mul(&basis_element.dot(self));
if !elt.sqnorm().approx_eq(&Zero::zero())
{ res.push(elt.normalized()); }
for v in res.iter()
{ elt = elt - v.scalar_mul(&elt.dot(v)) };
if !elt.sqnorm().approx_eq(&Zero::zero())
{ res.push(elt.normalized()); }
}
assert!(res.len() == dim - 1);
res
}
assert!(res.len() == dim - 1);
res
}
}
impl<N: Add<N,N>> Add<DVec<N>, DVec<N>> for DVec<N>
{
#[inline]
fn add(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.at.len() == other.at.len());
DVec {
at: self.at.iter().zip(other.at.iter()).transform(|(a, b)| *a + *b).collect()
#[inline]
fn add(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.at.len() == other.at.len());
DVec {
at: self.at.iter().zip(other.at.iter()).transform(|(a, b)| *a + *b).collect()
}
}
}
}
impl<N: Sub<N,N>> Sub<DVec<N>, DVec<N>> for DVec<N>
{
#[inline]
fn sub(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.at.len() == other.at.len());
DVec {
at: self.at.iter().zip(other.at.iter()).transform(|(a, b)| *a - *b).collect()
#[inline]
fn sub(&self, other: &DVec<N>) -> DVec<N>
{
assert!(self.at.len() == other.at.len());
DVec {
at: self.at.iter().zip(other.at.iter()).transform(|(a, b)| *a - *b).collect()
}
}
}
}
impl<N: Neg<N>> Neg<DVec<N>> for DVec<N>
{
#[inline]
fn neg(&self) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| -a).collect() } }
#[inline]
fn neg(&self) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| -a).collect() } }
}
impl<N: Ring>
Dot<N> for DVec<N>
impl<N: Ring> Dot<N> for DVec<N>
{
#[inline]
fn dot(&self, other: &DVec<N>) -> N
{
assert!(self.at.len() == other.at.len());
#[inline]
fn dot(&self, other: &DVec<N>) -> N
{
assert!(self.at.len() == other.at.len());
let mut res = Zero::zero::<N>();
let mut res = Zero::zero::<N>();
for i in range(0u, self.at.len())
{ res = res + self.at[i] * other.at[i]; }
for i in range(0u, self.at.len())
{ res = res + self.at[i] * other.at[i]; }
res
}
res
}
}
impl<N: Ring> SubDot<N> for DVec<N>
{
#[inline]
fn sub_dot(&self, a: &DVec<N>, b: &DVec<N>) -> N
{
let mut res = Zero::zero::<N>();
#[inline]
fn sub_dot(&self, a: &DVec<N>, b: &DVec<N>) -> N
{
let mut res = Zero::zero::<N>();
for i in range(0u, self.at.len())
{ res = res + (self.at[i] - a.at[i]) * b.at[i]; }
for i in range(0u, self.at.len())
{ res = res + (self.at[i] - a.at[i]) * b.at[i]; }
res
}
res
}
}
impl<N: Mul<N, N>>
ScalarMul<N> for DVec<N>
impl<N: Mul<N, N>> ScalarMul<N> for DVec<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a * *s).collect() } }
#[inline]
fn scalar_mul(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a * *s).collect() } }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] * *s; }
}
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] * *s; }
}
}
impl<N: Div<N, N>>
ScalarDiv<N> for DVec<N>
impl<N: Div<N, N>> ScalarDiv<N> for DVec<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a / *s).collect() } }
#[inline]
fn scalar_div(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a / *s).collect() } }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] / *s; }
}
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] / *s; }
}
}
impl<N: Add<N, N>>
ScalarAdd<N> for DVec<N>
impl<N: Add<N, N>> ScalarAdd<N> for DVec<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a + *s).collect() } }
#[inline]
fn scalar_add(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a + *s).collect() } }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] + *s; }
}
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] + *s; }
}
}
impl<N: Sub<N, N>>
ScalarSub<N> for DVec<N>
impl<N: Sub<N, N>> ScalarSub<N> for DVec<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a - *s).collect() } }
#[inline]
fn scalar_sub(&self, s: &N) -> DVec<N>
{ DVec { at: self.at.iter().transform(|a| a - *s).collect() } }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] - *s; }
}
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] - *s; }
}
}
impl<N: Add<N, N> + Neg<N> + Clone> Translation<DVec<N>> for DVec<N>
{
#[inline]
fn translation(&self) -> DVec<N>
{ self.clone() }
#[inline]
fn translation(&self) -> DVec<N>
{ self.clone() }
#[inline]
fn inv_translation(&self) -> DVec<N>
{ -self }
#[inline]
fn inv_translation(&self) -> DVec<N>
{ -self }
#[inline]
fn translate_by(&mut self, t: &DVec<N>)
{ *self = *self + *t; }
#[inline]
fn translate_by(&mut self, t: &DVec<N>)
{ *self = *self + *t; }
}
impl<N: Add<N, N> + Neg<N> + Clone> Translatable<DVec<N>, DVec<N>> for DVec<N>
{
#[inline]
fn translated(&self, t: &DVec<N>) -> DVec<N>
{ self + *t }
#[inline]
fn translated(&self, t: &DVec<N>) -> DVec<N>
{ self + *t }
}
impl<N: DivisionRing + Algebraic + Clone>
Norm<N> for DVec<N>
impl<N: DivisionRing + Algebraic + Clone> Norm<N> for DVec<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> DVec<N>
{
let mut res : DVec<N> = self.clone();
#[inline]
fn normalized(&self) -> DVec<N>
{
let mut res : DVec<N> = self.clone();
res.normalize();
res.normalize();
res
}
res
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] / l; }
for i in range(0u, self.at.len())
{ self.at[i] = self.at[i] / l; }
l
}
l
}
}
impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &DVec<N>) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
#[inline]
fn approx_eq(&self, other: &DVec<N>) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
do zip.all |(a, b)| { a.approx_eq(b) }
}
do zip.all |(a, b)| { a.approx_eq(b) }
}
#[inline]
fn approx_eq_eps(&self, other: &DVec<N>, epsilon: &N) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
#[inline]
fn approx_eq_eps(&self, other: &DVec<N>, epsilon: &N) -> bool
{
let mut zip = self.at.iter().zip(other.at.iter());
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
}

View File

@ -33,7 +33,7 @@ mod mat_macros;
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat1<N>
{
m11: N
m11: N
}
mat_impl!(Mat1, m11)
@ -58,8 +58,8 @@ from_homogeneous_impl!(Mat1, Mat2, 1, 2)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat2<N>
{
m11: N, m12: N,
m21: N, m22: N
m11: N, m12: N,
m21: N, m22: N
}
mat_impl!(Mat2, m11, m12,
@ -87,9 +87,9 @@ from_homogeneous_impl!(Mat2, Mat3, 2, 3)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat3<N>
{
m11: N, m12: N, m13: N,
m21: N, m22: N, m23: N,
m31: N, m32: N, m33: N
m11: N, m12: N, m13: N,
m21: N, m22: N, m23: N,
m31: N, m32: N, m33: N
}
mat_impl!(Mat3, m11, m12, m13,
@ -120,10 +120,10 @@ from_homogeneous_impl!(Mat3, Mat4, 3, 4)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat4<N>
{
m11: N, m12: N, m13: N, m14: N,
m21: N, m22: N, m23: N, m24: N,
m31: N, m32: N, m33: N, m34: N,
m41: N, m42: N, m43: N, m44: N
m11: N, m12: N, m13: N, m14: N,
m21: N, m22: N, m23: N, m24: N,
m31: N, m32: N, m33: N, m34: N,
m41: N, m42: N, m43: N, m44: N
}
mat_impl!(Mat4,
@ -161,11 +161,11 @@ from_homogeneous_impl!(Mat4, Mat5, 4, 5)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat5<N>
{
m11: N, m12: N, m13: N, m14: N, m15: N,
m21: N, m22: N, m23: N, m24: N, m25: N,
m31: N, m32: N, m33: N, m34: N, m35: N,
m41: N, m42: N, m43: N, m44: N, m45: N,
m51: N, m52: N, m53: N, m54: N, m55: N
m11: N, m12: N, m13: N, m14: N, m15: N,
m21: N, m22: N, m23: N, m24: N, m25: N,
m31: N, m32: N, m33: N, m34: N, m35: N,
m41: N, m42: N, m43: N, m44: N, m45: N,
m51: N, m52: N, m53: N, m54: N, m55: N
}
mat_impl!(Mat5,
@ -208,12 +208,12 @@ from_homogeneous_impl!(Mat5, Mat6, 5, 6)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Mat6<N>
{
m11: N, m12: N, m13: N, m14: N, m15: N, m16: N,
m21: N, m22: N, m23: N, m24: N, m25: N, m26: N,
m31: N, m32: N, m33: N, m34: N, m35: N, m36: N,
m41: N, m42: N, m43: N, m44: N, m45: N, m46: N,
m51: N, m52: N, m53: N, m54: N, m55: N, m56: N,
m61: N, m62: N, m63: N, m64: N, m65: N, m66: N
m11: N, m12: N, m13: N, m14: N, m15: N, m16: N,
m21: N, m22: N, m23: N, m24: N, m25: N, m26: N,
m31: N, m32: N, m33: N, m34: N, m35: N, m36: N,
m41: N, m42: N, m43: N, m44: N, m45: N, m46: N,
m51: N, m52: N, m53: N, m54: N, m55: N, m56: N,
m61: N, m62: N, m63: N, m64: N, m65: N, m66: N
}
mat_impl!(Mat6,

View File

@ -4,14 +4,14 @@ macro_rules! mat_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N> $t<N>
{
#[inline]
pub fn new($comp0: N $(, $compN: N )*) -> $t<N>
{
$t {
$comp0: $comp0
$(, $compN: $compN )*
#[inline]
pub fn new($comp0: N $(, $compN: N )*) -> $t<N>
{
$t {
$comp0: $comp0
$(, $compN: $compN )*
}
}
}
}
)
)
@ -20,9 +20,9 @@ macro_rules! mat_cast_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: NumCast + Clone, Nout: NumCast> MatCast<$t<Nout>> for $t<Nin>
{
#[inline]
pub fn from(m: $t<Nin>) -> $t<Nout>
{ $t::new(NumCast::from(m.$comp0.clone()) $(, NumCast::from(m.$compN.clone()) )*) }
#[inline]
pub fn from(m: $t<Nin>) -> $t<Nout>
{ $t::new(NumCast::from(m.$comp0.clone()) $(, NumCast::from(m.$compN.clone()) )*) }
}
)
)
@ -31,8 +31,8 @@ macro_rules! iterable_impl(
($t: ident, $dim: expr) => (
impl<N> Iterable<N> for $t<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ unsafe { cast::transmute::<&'l $t<N>, &'l [N, ..$dim * $dim]>(self).iter() } }
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ unsafe { cast::transmute::<&'l $t<N>, &'l [N, ..$dim * $dim]>(self).iter() } }
}
)
)
@ -41,8 +41,8 @@ macro_rules! iterable_mut_impl(
($t: ident, $dim: expr) => (
impl<N> IterableMut<N> for $t<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ unsafe { cast::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim * $dim]>(self).mut_iter() } }
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ unsafe { cast::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim * $dim]>(self).mut_iter() } }
}
)
)
@ -51,12 +51,12 @@ macro_rules! one_impl(
($t: ident, $value0: ident $(, $valueN: ident)* ) => (
impl<N: Clone + One + Zero> One for $t<N>
{
#[inline]
fn one() -> $t<N>
{
let (_0, _1) = (Zero::zero::<N>(), One::one::<N>());
return $t::new($value0.clone() $(, $valueN.clone() )*)
}
#[inline]
fn one() -> $t<N>
{
let (_0, _1) = (Zero::zero::<N>(), One::one::<N>());
return $t::new($value0.clone() $(, $valueN.clone() )*)
}
}
)
)
@ -65,9 +65,9 @@ macro_rules! dim_impl(
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N>
{
#[inline]
fn dim() -> uint
{ $dim }
#[inline]
fn dim() -> uint
{ $dim }
}
)
)
@ -76,22 +76,22 @@ macro_rules! indexable_impl(
($t: ident, $dim: expr) => (
impl<N: Clone> Indexable<(uint, uint), N> for $t<N>
{
#[inline]
pub fn at(&self, (i, j): (uint, uint)) -> N
{ unsafe { cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)[i * $dim + j].clone() } }
#[inline]
pub fn at(&self, (i, j): (uint, uint)) -> N
{ unsafe { cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)[i * $dim + j].clone() } }
#[inline]
pub fn set(&mut self, (i, j): (uint, uint), val: N)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)[i * $dim + j] = val } }
#[inline]
pub fn set(&mut self, (i, j): (uint, uint), val: N)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)[i * $dim + j] = val } }
#[inline]
pub fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint))
{
unsafe {
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
.swap(i1 * $dim + j1, i2 * $dim + j2)
#[inline]
pub fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint))
{
unsafe {
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
.swap(i1 * $dim + j1, i2 * $dim + j2)
}
}
}
}
)
)
@ -100,108 +100,104 @@ macro_rules! column_impl(
($t: ident, $dim: expr) => (
impl<N: Clone, V: Zero + Iterable<N> + IterableMut<N>> Column<V> for $t<N>
{
fn set_column(&mut self, col: uint, v: V)
{
for (i, e) in v.iter().enumerate()
fn set_column(&mut self, col: uint, v: V)
{
if i == Dim::dim::<$t<N>>()
{ break }
for (i, e) in v.iter().enumerate()
{
if i == Dim::dim::<$t<N>>()
{ break }
self.set((i, col), e.clone());
}
}
fn column(&self, col: uint) -> V
{
let mut res = Zero::zero::<V>();
for (i, e) in res.mut_iter().enumerate()
{
if i >= Dim::dim::<$t<N>>()
{ break }
*e = self.at((i, col));
self.set((i, col), e.clone());
}
}
res
}
fn column(&self, col: uint) -> V
{
let mut res = Zero::zero::<V>();
for (i, e) in res.mut_iter().enumerate()
{
if i >= Dim::dim::<$t<N>>()
{ break }
*e = self.at((i, col));
}
res
}
}
)
)
macro_rules! mul_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + Ring>
Mul<$t<N>, $t<N>> for $t<N>
impl<N: Clone + Ring> Mul<$t<N>, $t<N>> for $t<N>
{
fn mul(&self, other: &$t<N>) -> $t<N>
{
let mut res: $t<N> = Zero::zero();
for i in range(0u, $dim)
fn mul(&self, other: &$t<N>) -> $t<N>
{
for j in range(0u, $dim)
{
let mut acc = Zero::zero::<N>();
let mut res: $t<N> = Zero::zero();
for k in range(0u, $dim)
{ acc = acc + self.at((i, k)) * other.at((k, j)); }
for i in range(0u, $dim)
{
for j in range(0u, $dim)
{
let mut acc = Zero::zero::<N>();
res.set((i, j), acc);
}
for k in range(0u, $dim)
{ acc = acc + self.at((i, k)) * other.at((k, j)); }
res.set((i, j), acc);
}
}
res
}
res
}
}
)
)
macro_rules! rmul_impl(
($t: ident, $v: ident, $dim: expr) => (
impl<N: Clone + Ring>
RMul<$v<N>> for $t<N>
impl<N: Clone + Ring> RMul<$v<N>> for $t<N>
{
fn rmul(&self, other: &$v<N>) -> $v<N>
{
let mut res : $v<N> = Zero::zero();
for i in range(0u, $dim)
fn rmul(&self, other: &$v<N>) -> $v<N>
{
for j in range(0u, $dim)
{
let val = res.at(i) + other.at(j) * self.at((i, j));
res.set(i, val)
}
}
let mut res : $v<N> = Zero::zero();
res
}
for i in range(0u, $dim)
{
for j in range(0u, $dim)
{
let val = res.at(i) + other.at(j) * self.at((i, j));
res.set(i, val)
}
}
res
}
}
)
)
macro_rules! lmul_impl(
($t: ident, $v: ident, $dim: expr) => (
impl<N: Clone + Ring>
LMul<$v<N>> for $t<N>
impl<N: Clone + Ring> LMul<$v<N>> for $t<N>
{
fn lmul(&self, other: &$v<N>) -> $v<N>
{
let mut res : $v<N> = Zero::zero();
for i in range(0u, $dim)
fn lmul(&self, other: &$v<N>) -> $v<N>
{
for j in range(0u, $dim)
{
let val = res.at(i) + other.at(j) * self.at((j, i));
res.set(i, val)
}
}
let mut res : $v<N> = Zero::zero();
res
}
for i in range(0u, $dim)
{
for j in range(0u, $dim)
{
let val = res.at(i) + other.at(j) * self.at((j, i));
res.set(i, val)
}
}
res
}
}
)
)
@ -211,19 +207,19 @@ macro_rules! transform_impl(
impl<N: Clone + DivisionRing + Eq>
Transform<$v<N>> for $t<N>
{
#[inline]
fn transform_vec(&self, v: &$v<N>) -> $v<N>
{ self.rmul(v) }
#[inline]
fn transform_vec(&self, v: &$v<N>) -> $v<N>
{ self.rmul(v) }
#[inline]
fn inv_transform(&self, v: &$v<N>) -> $v<N>
{
match self.inverse()
#[inline]
fn inv_transform(&self, v: &$v<N>) -> $v<N>
{
Some(t) => t.transform_vec(v),
None => fail!("Cannot use inv_transform on a non-inversible matrix.")
match self.inverse()
{
Some(t) => t.transform_vec(v),
None => fail!("Cannot use inv_transform on a non-inversible matrix.")
}
}
}
}
)
)
@ -233,91 +229,91 @@ macro_rules! inv_impl(
impl<N: Clone + Eq + DivisionRing>
Inv for $t<N>
{
#[inline]
fn inverse(&self) -> Option<$t<N>>
{
let mut res : $t<N> = self.clone();
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
fn inplace_inverse(&mut self) -> bool
{
let mut res: $t<N> = One::one();
let _0N: N = Zero::zero();
// inversion using Gauss-Jordan elimination
for k in range(0u, $dim)
#[inline]
fn inverse(&self) -> Option<$t<N>>
{
// search a non-zero value on the k-th column
// FIXME: would it be worth it to spend some more time searching for the
// max instead?
let mut res : $t<N> = self.clone();
let mut n0 = k; // index of a non-zero entry
while (n0 != $dim)
{
if self.at((n0, k)) != _0N
{ break; }
n0 = n0 + 1;
}
if n0 == $dim
{ return false }
// swap pivot line
if n0 != k
{
for j in range(0u, $dim)
{
self.swap((n0, j), (k, j));
res.swap((n0, j), (k, j));
}
}
let pivot = self.at((k, k));
for j in range(k, $dim)
{
let selfval = self.at((k, j)) / pivot;
self.set((k, j), selfval);
}
for j in range(0u, $dim)
{
let resval = res.at((k, j)) / pivot;
res.set((k, j), resval);
}
for l in range(0u, $dim)
{
if l != k
{
let normalizer = self.at((l, k));
for j in range(k, $dim)
{
let selfval = self.at((l, j)) - self.at((k, j)) * normalizer;
self.set((l, j), selfval);
}
for j in range(0u, $dim)
{
let resval = res.at((l, j)) - res.at((k, j)) * normalizer;
res.set((l, j), resval);
}
}
}
if res.inplace_inverse()
{ Some(res) }
else
{ None }
}
*self = res;
fn inplace_inverse(&mut self) -> bool
{
let mut res: $t<N> = One::one();
let _0N: N = Zero::zero();
// inversion using Gauss-Jordan elimination
for k in range(0u, $dim)
{
// search a non-zero value on the k-th column
// FIXME: would it be worth it to spend some more time searching for the
// max instead?
true
}
let mut n0 = k; // index of a non-zero entry
while (n0 != $dim)
{
if self.at((n0, k)) != _0N
{ break; }
n0 = n0 + 1;
}
if n0 == $dim
{ return false }
// swap pivot line
if n0 != k
{
for j in range(0u, $dim)
{
self.swap((n0, j), (k, j));
res.swap((n0, j), (k, j));
}
}
let pivot = self.at((k, k));
for j in range(k, $dim)
{
let selfval = self.at((k, j)) / pivot;
self.set((k, j), selfval);
}
for j in range(0u, $dim)
{
let resval = res.at((k, j)) / pivot;
res.set((k, j), resval);
}
for l in range(0u, $dim)
{
if l != k
{
let normalizer = self.at((l, k));
for j in range(k, $dim)
{
let selfval = self.at((l, j)) - self.at((k, j)) * normalizer;
self.set((l, j), selfval);
}
for j in range(0u, $dim)
{
let resval = res.at((l, j)) - res.at((k, j)) * normalizer;
res.set((l, j), resval);
}
}
}
}
*self = res;
true
}
}
)
)
@ -326,24 +322,24 @@ macro_rules! transpose_impl(
($t: ident, $dim: expr) => (
impl<N: Clone> Transpose for $t<N>
{
#[inline]
fn transposed(&self) -> $t<N>
{
let mut res = self.clone();
res.transpose();
res
}
fn transpose(&mut self)
{
for i in range(1u, $dim)
#[inline]
fn transposed(&self) -> $t<N>
{
for j in range(0u, i)
{ self.swap((i, j), (j, i)) }
let mut res = self.clone();
res.transpose();
res
}
fn transpose(&mut self)
{
for i in range(1u, $dim)
{
for j in range(0u, i)
{ self.swap((i, j), (j, i)) }
}
}
}
}
)
)
@ -352,25 +348,25 @@ macro_rules! approx_eq_impl(
($t: ident) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool
{
let mut zip = self.iter().zip(other.iter());
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool
{
let mut zip = self.iter().zip(other.iter());
do zip.all |(a, b)| { a.approx_eq(b) }
}
do zip.all |(a, b)| { a.approx_eq(b) }
}
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool
{
let mut zip = self.iter().zip(other.iter());
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool
{
let mut zip = self.iter().zip(other.iter());
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
do zip.all |(a, b)| { a.approx_eq_eps(b, epsilon) }
}
}
)
)
@ -379,18 +375,18 @@ macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident, $dim: expr, $dim2: expr) => (
impl<N: One + Zero + Clone> ToHomogeneous<$t2<N>> for $t<N>
{
fn to_homogeneous(&self) -> $t2<N>
{
let mut res: $t2<N> = One::one();
for i in range(0u, $dim)
fn to_homogeneous(&self) -> $t2<N>
{
for j in range(0u, $dim)
{ res.set((i, j), self.at((i, j))) }
}
let mut res: $t2<N> = One::one();
res
}
for i in range(0u, $dim)
{
for j in range(0u, $dim)
{ res.set((i, j), self.at((i, j))) }
}
res
}
}
)
)
@ -399,21 +395,21 @@ macro_rules! from_homogeneous_impl(
($t: ident, $t2: ident, $dim: expr, $dim2: expr) => (
impl<N: One + Zero + Clone> FromHomogeneous<$t2<N>> for $t<N>
{
fn from(m: &$t2<N>) -> $t<N>
{
let mut res: $t<N> = One::one();
for i in range(0u, $dim2)
fn from(m: &$t2<N>) -> $t<N>
{
for j in range(0u, $dim2)
{ res.set((i, j), m.at((i, j))) }
let mut res: $t<N> = One::one();
for i in range(0u, $dim2)
{
for j in range(0u, $dim2)
{ res.set((i, j), m.at((i, j))) }
}
// FIXME: do we have to deal the lost components
// (like if the 1 is not a 1… do we have to divide?)
res
}
// FIXME: do we have to deal the lost components
// (like if the 1 is not a 1… do we have to divide?)
res
}
}
)
)

View File

@ -1,31 +1,31 @@
/// Traits of objecs which can form a basis.
pub trait Basis
{
/// Iterate through the canonical basis of the space in which this object lives.
fn canonical_basis(&fn(Self));
/// Iterate through the canonical basis of the space in which this object lives.
fn canonical_basis(&fn(Self));
/// Iterate through a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis(&self, &fn(Self));
/// Iterate through a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis(&self, &fn(Self));
/// Creates the canonical basis of the space in which this object lives.
fn canonical_basis_list() -> ~[Self]
{
let mut res = ~[];
/// Creates the canonical basis of the space in which this object lives.
fn canonical_basis_list() -> ~[Self]
{
let mut res = ~[];
do Basis::canonical_basis::<Self> |elem|
{ res.push(elem) }
do Basis::canonical_basis::<Self> |elem|
{ res.push(elem) }
res
}
res
}
/// Creates a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis_list(&self) -> ~[Self]
{
let mut res = ~[];
/// Creates a basis of the subspace orthogonal to `self`.
fn orthonormal_subspace_basis_list(&self) -> ~[Self]
{
let mut res = ~[];
do self.orthonormal_subspace_basis |elem|
{ res.push(elem) }
do self.orthonormal_subspace_basis |elem|
{ res.push(elem) }
res
}
res
}
}

View File

@ -1,8 +1,8 @@
/// Traits to access columns of a matrix.
pub trait Column<C>
{
/// Reads the `i`-th column of `self`.
fn column(&self, i: uint) -> C;
/// Writes the `i`-th column of `self`.
fn set_column(&mut self, i: uint, C);
/// Reads the `i`-th column of `self`.
fn column(&self, i: uint) -> C;
/// Writes the `i`-th column of `self`.
fn set_column(&mut self, i: uint, C);
}

View File

@ -3,6 +3,6 @@
*/
pub trait Cross<Result>
{
/// Computes the cross product between two elements (usually vectors).
fn cross(&self, other : &Self) -> Result;
/// Computes the cross product between two elements (usually vectors).
fn cross(&self, other : &Self) -> Result;
}

View File

@ -2,65 +2,6 @@
* Trait of objects having a spacial dimension.
*/
pub trait Dim {
/// The dimension of the object.
fn dim() -> uint;
/// The dimension of the object.
fn dim() -> uint;
}
// Some dimension token. Useful to restrict the dimension of n-dimensional
// object at the type-level.
/// Dimensional token for 0-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D0;
/// Dimensional token for 1-dimension. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D1;
/// Dimensional token for 2-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D2;
/// Dimensional token for 3-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D3;
/// Dimensional token for 4-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D4;
/// Dimensional token for 5-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D5;
/// Dimensional token for 6-dimensions. Dimensional tokens are the preferred
/// way to specify at the type level the dimension of n-dimensional objects.
#[deriving(Eq, Ord, ToStr)]
pub struct D6;
impl Dim for D0
{ fn dim() -> uint { 0 } }
impl Dim for D1
{ fn dim() -> uint { 1 } }
impl Dim for D2
{ fn dim() -> uint { 2 } }
impl Dim for D3
{ fn dim() -> uint { 3 } }
impl Dim for D4
{ fn dim() -> uint { 4 } }
impl Dim for D5
{ fn dim() -> uint { 5 } }
impl Dim for D6
{ fn dim() -> uint { 6 } }

View File

@ -3,6 +3,6 @@
*/
pub trait Dot<N>
{
/// Computes the dot (inner) product of two objects.
fn dot(&self, &Self) -> N;
/// Computes the dot (inner) product of two objects.
fn dot(&self, &Self) -> N;
}

View File

@ -1,15 +1,15 @@
/// Traits of objects which can be put in homogeneous coordinates.
pub trait ToHomogeneous<U>
{
/// Gets the homogeneous coordinates version of this object.
fn to_homogeneous(&self) -> U;
/// Gets the homogeneous coordinates version of this object.
fn to_homogeneous(&self) -> U;
}
/// Traits of objects which can be build from an homogeneous coordinate representation.
pub trait FromHomogeneous<U>
{
/// Builds an object with its homogeneous coordinate version. Note this it is not required for
/// `from` to be the iverse of `to_homogeneous`. Typically, `from` will remove some informations
/// unrecoverable by `to_homogeneous`.
fn from(&U) -> Self;
/// Builds an object with its homogeneous coordinate version. Note this it is not required for
/// `from` to be the iverse of `to_homogeneous`. Typically, `from` will remove some informations
/// unrecoverable by `to_homogeneous`.
fn from(&U) -> Self;
}

View File

@ -9,10 +9,10 @@
/// to write to a specific index.
pub trait Indexable<Index, Res>
{
/// Reads the `i`-th element of `self`.
fn at(&self, i: Index) -> Res;
/// Writes to the `i`-th element of `self`.
fn set(&mut self, i: Index, Res);
/// Swaps the `i`-th element of `self` with its `j`-th element.
fn swap(&mut self, i: Index, j: Index);
/// Reads the `i`-th element of `self`.
fn at(&self, i: Index) -> Res;
/// Writes to the `i`-th element of `self`.
fn set(&mut self, i: Index, Res);
/// Swaps the `i`-th element of `self` with its `j`-th element.
fn swap(&mut self, i: Index, j: Index);
}

View File

@ -3,8 +3,8 @@
*/
pub trait Inv
{
/// Returns the inverse of an element.
fn inverse(&self) -> Option<Self>;
/// Inplace version of `inverse`.
fn inplace_inverse(&mut self) -> bool;
/// Returns the inverse of an element.
fn inverse(&self) -> Option<Self>;
/// Inplace version of `inverse`.
fn inplace_inverse(&mut self) -> bool;
}

View File

@ -3,30 +3,30 @@ use std::vec;
/// Traits of objects which can be iterated through like a vector.
pub trait Iterable<N>
{
/// Gets a vector-like read-only iterator.
fn iter<'l>(&'l self) -> vec::VecIterator<'l, N>;
/// Gets a vector-like read-only iterator.
fn iter<'l>(&'l self) -> vec::VecIterator<'l, N>;
}
/// Traits of mutable objects which can be iterated through like a vector.
pub trait IterableMut<N>
{
/// Gets a vector-like read-write iterator.
fn mut_iter<'l>(&'l mut self) -> vec::VecMutIterator<'l, N>;
/// Gets a vector-like read-write iterator.
fn mut_iter<'l>(&'l mut self) -> vec::VecMutIterator<'l, N>;
}
/*
* FIXME: the prevous traits are only workarounds.
* It should be something like:
pub trait Iterable<'self, N, I: Iterator<N>>
{
fn iter(&'self self) -> I;
}
pub trait Iterable<'self, N, I: Iterator<N>>
{
fn iter(&'self self) -> I;
}
pub trait IterableMut<'self, N, I: Iterator<N>>
{
fn mut_iter(&'self self) -> I;
}
pub trait IterableMut<'self, N, I: Iterator<N>>
{
fn mut_iter(&'self self) -> I;
}
* but this gives an ICE =(
* For now, we oblige the iterator to be one specific type which works with

View File

@ -2,6 +2,6 @@
/// components.
pub trait MatCast<M>
{
/// Converts `m` to have the type `M`.
fn from(m: Self) -> M;
/// Converts `m` to have the type `M`.
fn from(m: Self) -> M;
}

View File

@ -3,18 +3,18 @@
*/
pub trait Norm<N>
{
/// Computes the norm a an object.
fn norm(&self) -> N;
/// Computes the norm a an object.
fn norm(&self) -> N;
/**
* Computes the squared norm of an object. Usually faster than computing the
* norm itself.
*/
fn sqnorm(&self) -> N;
/**
* Computes the squared norm of an object. Usually faster than computing the
* norm itself.
*/
fn sqnorm(&self) -> N;
/// Gets the normalized version of the argument.
fn normalized(&self) -> Self;
/// Gets the normalized version of the argument.
fn normalized(&self) -> Self;
/// In-place version of `normalized`.
fn normalize(&mut self) -> N;
/// In-place version of `normalized`.
fn normalize(&mut self) -> N;
}

View File

@ -3,8 +3,8 @@
*/
pub trait RMul<V>
{
/// Computes self * v
fn rmul(&self, v : &V) -> V;
/// Computes self * v
fn rmul(&self, v : &V) -> V;
}
/**
@ -12,6 +12,6 @@ pub trait RMul<V>
*/
pub trait LMul<V>
{
/// Computes v * self
fn lmul(&self, &V) -> V;
/// Computes v * self
fn lmul(&self, &V) -> V;
}

View File

@ -5,14 +5,14 @@ use traits::translation::{Translation, Translatable};
/// and without reflexion.
pub trait Rotation<V>
{
/// Gets the rotation associated with this object.
fn rotation(&self) -> V;
/// Gets the rotation associated with this object.
fn rotation(&self) -> V;
/// Gets the inverse rotation associated with this object.
fn inv_rotation(&self) -> V;
/// Gets the inverse rotation associated with this object.
fn inv_rotation(&self) -> V;
/// In-place version of `rotated` (see the `Rotatable` trait).
fn rotate_by(&mut self, &V);
/// In-place version of `rotated` (see the `Rotatable` trait).
fn rotate_by(&mut self, &V);
}
/// Trait of objects which can be put on an alternate form which represent a rotation. This is
@ -20,19 +20,19 @@ pub trait Rotation<V>
/// represent a rotation.
pub trait Rotatable<V, Res: Rotation<V>>
{
/// Appends a rotation from an alternative representation. Such
/// representation has the same format as the one returned by `rotation`.
fn rotated(&self, &V) -> Res;
/// Appends a rotation from an alternative representation. Such
/// representation has the same format as the one returned by `rotation`.
fn rotated(&self, &V) -> Res;
}
/// Trait of objects able to rotate other objects. This is typically implemented by matrices which
/// rotate vectors.
pub trait Rotate<V>
{
/// Apply a rotation to an object.
fn rotate(&self, &V) -> V;
/// Apply an inverse rotation to an object.
fn inv_rotate(&self, &V) -> V;
/// Apply a rotation to an object.
fn rotate(&self, &V) -> V;
/// Apply an inverse rotation to an object.
fn inv_rotate(&self, &V) -> V;
}
/**
@ -46,15 +46,18 @@ pub trait Rotate<V>
pub fn rotated_wrt_point<M: Translatable<LV, M2>,
M2: Rotation<AV> + Translation<LV>,
LV: Neg<LV>,
AV>
(m: &M, ammount: &AV, center: &LV) -> M2
AV>(
m: &M,
ammount: &AV,
center: &LV)
-> M2
{
let mut res = m.translated(&-center);
let mut res = m.translated(&-center);
res.rotate_by(ammount);
res.translate_by(center);
res.rotate_by(ammount);
res.translate_by(center);
res
res
}
/// Rotates an object using a specific center of rotation.
@ -66,12 +69,14 @@ pub fn rotated_wrt_point<M: Translatable<LV, M2>,
#[inline]
pub fn rotate_wrt_point<M: Rotation<AV> + Translation<LV>,
LV: Neg<LV>,
AV>
(m: &mut M, ammount: &AV, center: &LV)
AV>(
m: &mut M,
ammount: &AV,
center: &LV)
{
m.translate_by(&-center);
m.rotate_by(ammount);
m.translate_by(center);
m.translate_by(&-center);
m.rotate_by(ammount);
m.translate_by(center);
}
/**
@ -85,8 +90,10 @@ pub fn rotate_wrt_point<M: Rotation<AV> + Translation<LV>,
pub fn rotated_wrt_center<M: Translatable<LV, M2> + Translation<LV>,
M2: Rotation<AV> + Translation<LV>,
LV: Neg<LV>,
AV>
(m: &M, ammount: &AV) -> M2
AV>(
m: &M,
ammount: &AV)
-> M2
{ rotated_wrt_point(m, ammount, &m.translation()) }
/**
@ -99,10 +106,11 @@ pub fn rotated_wrt_center<M: Translatable<LV, M2> + Translation<LV>,
#[inline]
pub fn rotate_wrt_center<M: Translatable<LV, M> + Translation<LV> + Rotation<AV>,
LV: Neg<LV>,
AV>
(m: &mut M, ammount: &AV)
AV>(
m: &mut M,
ammount: &AV)
{
let t = m.translation();
let t = m.translation();
rotate_wrt_point(m, ammount, &t)
rotate_wrt_point(m, ammount, &t)
}

View File

@ -2,17 +2,17 @@
/// approximate a sphere using support mapping functions.
pub trait UniformSphereSample
{
/// Iterate throught the samples.
pub fn sample(&fn(&'static Self));
/// Iterate throught the samples.
pub fn sample(&fn(&'static Self));
/// Gets the list of all samples.
pub fn sample_list() -> ~[&'static Self]
{
let mut res = ~[];
/// Gets the list of all samples.
pub fn sample_list() -> ~[&'static Self]
{
let mut res = ~[];
do UniformSphereSample::sample::<Self> |s|
{ res.push(s) }
do UniformSphereSample::sample::<Self> |s|
{ res.push(s) }
res
}
res
}
}

View File

@ -3,11 +3,11 @@
*/
pub trait ScalarMul<N>
{
/// Gets the result of a multiplication by a scalar.
fn scalar_mul(&self, &N) -> Self;
/// Gets the result of a multiplication by a scalar.
fn scalar_mul(&self, &N) -> Self;
/// In-place version of `scalar_mul`.
fn scalar_mul_inplace(&mut self, &N);
/// In-place version of `scalar_mul`.
fn scalar_mul_inplace(&mut self, &N);
}
/**
@ -15,11 +15,11 @@ pub trait ScalarMul<N>
*/
pub trait ScalarDiv<N>
{
/// Gets the result of a division by a scalar.
fn scalar_div(&self, &N) -> Self;
/// Gets the result of a division by a scalar.
fn scalar_div(&self, &N) -> Self;
/// In-place version of `scalar_div`.
fn scalar_div_inplace(&mut self, &N);
/// In-place version of `scalar_div`.
fn scalar_div_inplace(&mut self, &N);
}
/**
@ -27,11 +27,11 @@ pub trait ScalarDiv<N>
*/
pub trait ScalarAdd<N>
{
/// Gets the result of an addition by a scalar.
fn scalar_add(&self, &N) -> Self;
/// Gets the result of an addition by a scalar.
fn scalar_add(&self, &N) -> Self;
/// In-place version of `scalar_add`.
fn scalar_add_inplace(&mut self, &N);
/// In-place version of `scalar_add`.
fn scalar_add_inplace(&mut self, &N);
}
/**
@ -39,9 +39,9 @@ pub trait ScalarAdd<N>
*/
pub trait ScalarSub<N>
{
/// Gets the result of a subtraction by a scalar.
fn scalar_sub(&self, &N) -> Self;
/// Gets the result of a subtraction by a scalar.
fn scalar_sub(&self, &N) -> Self;
/// In-place version of `scalar_sub`.
fn scalar_sub_inplace(&mut self, &N);
/// In-place version of `scalar_sub`.
fn scalar_sub_inplace(&mut self, &N);
}

View File

@ -3,13 +3,13 @@ use traits::dot::Dot;
/// Traits of objects with a subtract and a dot product. Exists only for optimization purpose.
pub trait SubDot<N> : Sub<Self, Self> + Dot<N>
{
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* This must be equivalent to:
*
* (a - b).dot(c)
*
*/
fn sub_dot(&self, b: &Self, c: &Self) -> N;
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* This must be equivalent to:
*
* (a - b).dot(c)
*
*/
fn sub_dot(&self, b: &Self, c: &Self) -> N;
}

View File

@ -3,26 +3,26 @@
/// and without reflexion.
pub trait Transformation<M>
{
/// Gets the transformation associated with this object.
fn transformation(&self) -> M;
/// Gets the transformation associated with this object.
fn transformation(&self) -> M;
/// Gets the inverse transformation associated with this object.
fn inv_transformation(&self) -> M;
/// Gets the inverse transformation associated with this object.
fn inv_transformation(&self) -> M;
/// In-place version of `transformed` (see the `Transformable` trait).
fn transform_by(&mut self, &M);
/// In-place version of `transformed` (see the `Transformable` trait).
fn transform_by(&mut self, &M);
}
/// Trait of objects able to transform other objects. This is typically implemented by matrices which
/// transform vectors.
pub trait Transform<V>
{
// XXX: sadly we cannot call this `transform` as it conflicts with the
// iterators' `transform` function (which seems always exist).
/// Apply a transformation to an object.
fn transform_vec(&self, &V) -> V;
/// Apply an inverse transformation to an object.
fn inv_transform(&self, &V) -> V;
// XXX: sadly we cannot call this `transform` as it conflicts with the
// iterators' `transform` function (which seems always exist).
/// Apply a transformation to an object.
fn transform_vec(&self, &V) -> V;
/// Apply an inverse transformation to an object.
fn inv_transform(&self, &V) -> V;
}
/// Trait of objects which can be put on an alternate form which represent a transformation. This is
@ -30,7 +30,7 @@ pub trait Transform<V>
/// represent a transformation.
pub trait Transformable<M, Res: Transformation<M>>
{
/// Appends a transformation from an alternative representation. Such
/// representation has the same format as the one returned by `transformation`.
fn transformed(&self, &M) -> Res;
/// Appends a transformation from an alternative representation. Such
/// representation has the same format as the one returned by `transformation`.
fn transformed(&self, &M) -> Res;
}

View File

@ -2,25 +2,25 @@
/// can be appended.
pub trait Translation<V>
{
// FIXME: add a "from translation: translantion(V) -> Self ?
/// Gets the translation associated with this object.
fn translation(&self) -> V;
// FIXME: add a "from translation: translantion(V) -> Self ?
/// Gets the translation associated with this object.
fn translation(&self) -> V;
/// Gets the inverse translation associated with this object.
fn inv_translation(&self) -> V;
/// Gets the inverse translation associated with this object.
fn inv_translation(&self) -> V;
/// In-place version of `translated` (see the `Translatable` trait).
fn translate_by(&mut self, &V);
/// In-place version of `translated` (see the `Translatable` trait).
fn translate_by(&mut self, &V);
}
/// Trait of objects able to rotate other objects. This is typically implemented by matrices which
/// rotate vectors.
pub trait Translate<V>
{
/// Apply a translation to an object.
fn translate(&self, &V) -> V;
/// Apply an inverse translation to an object.
fn inv_translate(&self, &V) -> V;
/// Apply a translation to an object.
fn translate(&self, &V) -> V;
/// Apply an inverse translation to an object.
fn inv_translate(&self, &V) -> V;
}
/// Trait of objects which can be put on an alternate form which represent a translation. This is
@ -28,7 +28,7 @@ pub trait Translate<V>
/// represent a translation.
pub trait Translatable<V, Res: Translation<V>>
{
/// Appends a translation from an alternative representation. Such
/// representation has the same format as the one returned by `translation`.
fn translated(&self, &V) -> Res;
/// Appends a translation from an alternative representation. Such
/// representation has the same format as the one returned by `translation`.
fn translated(&self, &V) -> Res;
}

View File

@ -4,9 +4,9 @@
/// is not stable by transposition).
pub trait Transpose
{
/// Computes the transpose of a matrix.
fn transposed(&self) -> Self;
/// Computes the transpose of a matrix.
fn transposed(&self) -> Self;
/// In-place version of `transposed`.
fn transpose(&mut self);
/// In-place version of `transposed`.
fn transpose(&mut self);
}

View File

@ -2,6 +2,6 @@
/// components.
pub trait VecCast<V>
{
/// Converts `v` to have the type `V`.
fn from(v: Self) -> V;
/// Converts `v` to have the type `V`.
fn from(v: Self) -> V;
}

View File

@ -34,8 +34,8 @@ pub struct Vec0<N>;
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec1<N>
{
/// First component of the vector.
x: N
/// First component of the vector.
x: N
}
new_impl!(Vec1, x)
@ -72,10 +72,10 @@ from_homogeneous_impl!(Vec1, Vec2, y, x)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec2<N>
{
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N
}
new_impl!(Vec2, x, y)
@ -111,14 +111,13 @@ from_homogeneous_impl!(Vec2, Vec3, z, x, y)
/// Vector of dimension 3.
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec3<N>
{
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N
}
new_impl!(Vec3, x, y, z)
@ -155,14 +154,14 @@ from_homogeneous_impl!(Vec3, Vec4, w, x, y, z)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec4<N>
{
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N
}
new_impl!(Vec4, x, y, z, w)
@ -199,16 +198,16 @@ from_homogeneous_impl!(Vec4, Vec5, a, x, y, z, w)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec5<N>
{
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N,
/// Fifth of the vector.
a: N
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N,
/// Fifth of the vector.
a: N
}
new_impl!(Vec5, x, y, z, w, a)
@ -245,18 +244,18 @@ from_homogeneous_impl!(Vec5, Vec6, b, x, y, z, w, a)
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, IterBytes, Rand, Zero, ToStr)]
pub struct Vec6<N>
{
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N,
/// Fifth of the vector.
a: N,
/// Sixth component of the vector.
b: N
/// First component of the vector.
x: N,
/// Second component of the vector.
y: N,
/// Third component of the vector.
z: N,
/// Fourth component of the vector.
w: N,
/// Fifth of the vector.
a: N,
/// Sixth component of the vector.
b: N
}
new_impl!(Vec6, x, y, z, w, a, b)

View File

@ -1,507 +1,507 @@
#[macro_escape];
macro_rules! new_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N> $t<N>
{
/// Creates a new vector.
#[inline]
pub fn new($comp0: N $( , $compN: N )*) -> $t<N>
{
$t {
$comp0: $comp0
$(, $compN: $compN )*
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N> $t<N>
{
/// Creates a new vector.
#[inline]
pub fn new($comp0: N $( , $compN: N )*) -> $t<N>
{
$t {
$comp0: $comp0
$(, $compN: $compN )*
}
}
}
}
}
)
)
)
macro_rules! ord_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ord> Ord for $t<N>
{
#[inline]
fn lt(&self, other: &$t<N>) -> bool
{ self.$comp0 < other.$comp0 $(&& self.$compN < other.$compN)* }
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ord> Ord for $t<N>
{
#[inline]
fn lt(&self, other: &$t<N>) -> bool
{ self.$comp0 < other.$comp0 $(&& self.$compN < other.$compN)* }
#[inline]
fn le(&self, other: &$t<N>) -> bool
{ self.$comp0 <= other.$comp0 $(&& self.$compN <= other.$compN)* }
#[inline]
fn le(&self, other: &$t<N>) -> bool
{ self.$comp0 <= other.$comp0 $(&& self.$compN <= other.$compN)* }
#[inline]
fn gt(&self, other: &$t<N>) -> bool
{ self.$comp0 > other.$comp0 $(&& self.$compN > other.$compN)* }
#[inline]
fn gt(&self, other: &$t<N>) -> bool
{ self.$comp0 > other.$comp0 $(&& self.$compN > other.$compN)* }
#[inline]
fn ge(&self, other: &$t<N>) -> bool
{ self.$comp0 >= other.$comp0 $(&& self.$compN >= other.$compN)* }
}
)
#[inline]
fn ge(&self, other: &$t<N>) -> bool
{ self.$comp0 >= other.$comp0 $(&& self.$compN >= other.$compN)* }
}
)
)
macro_rules! orderable_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Orderable> Orderable for $t<N>
{
#[inline]
fn max(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0.max(&other.$comp0) $(, self.$compN.max(&other.$compN))*) }
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Orderable> Orderable for $t<N>
{
#[inline]
fn max(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0.max(&other.$comp0) $(, self.$compN.max(&other.$compN))*) }
#[inline]
fn min(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0.min(&other.$comp0) $(, self.$compN.min(&other.$compN))*) }
#[inline]
fn min(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0.min(&other.$comp0) $(, self.$compN.min(&other.$compN))*) }
#[inline]
fn clamp(&self, min: &$t<N>, max: &$t<N>) -> $t<N>
{
$t::new(self.$comp0.clamp(&min.$comp0, &max.$comp0)
$(, self.$compN.clamp(&min.$comp0, &max.$comp0))*)
}
}
)
#[inline]
fn clamp(&self, min: &$t<N>, max: &$t<N>) -> $t<N>
{
$t::new(self.$comp0.clamp(&min.$comp0, &max.$comp0)
$(, self.$compN.clamp(&min.$comp0, &max.$comp0))*)
}
}
)
)
macro_rules! vec_axis_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Zero + One> $t<N>
{
/// Create a unit vector with its `$comp0` component equal to 1.0.
#[inline]
pub fn $comp0() -> $t<N>
{
let mut res: $t<N> = Zero::zero();
res.$comp0 = One::one();
res
}
$(
/// Create a unit vector with its `$compN` component equal to 1.0.
#[inline]
pub fn $compN() -> $t<N>
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Zero + One> $t<N>
{
let mut res: $t<N> = Zero::zero();
/// Create a unit vector with its `$comp0` component equal to 1.0.
#[inline]
pub fn $comp0() -> $t<N>
{
let mut res: $t<N> = Zero::zero();
res.$compN = One::one();
res.$comp0 = One::one();
res
res
}
$(
/// Create a unit vector with its `$compN` component equal to 1.0.
#[inline]
pub fn $compN() -> $t<N>
{
let mut res: $t<N> = Zero::zero();
res.$compN = One::one();
res
}
)*
}
)*
}
)
)
)
macro_rules! vec_cast_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: NumCast + Clone, Nout: NumCast> VecCast<$t<Nout>> for $t<Nin>
{
#[inline]
pub fn from(v: $t<Nin>) -> $t<Nout>
{ $t::new(NumCast::from(v.$comp0.clone()) $(, NumCast::from(v.$compN.clone()))*) }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: NumCast + Clone, Nout: NumCast> VecCast<$t<Nout>> for $t<Nin>
{
#[inline]
pub fn from(v: $t<Nin>) -> $t<Nout>
{ $t::new(NumCast::from(v.$comp0.clone()) $(, NumCast::from(v.$compN.clone()))*) }
}
)
)
macro_rules! indexable_impl(
($t: ident, $dim: expr) => (
impl<N: Clone> Indexable<uint, N> for $t<N>
{
#[inline]
pub fn at(&self, i: uint) -> N
{ unsafe { cast::transmute::<&$t<N>, &[N, ..$dim]>(self)[i].clone() } }
($t: ident, $dim: expr) => (
impl<N: Clone> Indexable<uint, N> for $t<N>
{
#[inline]
pub fn at(&self, i: uint) -> N
{ unsafe { cast::transmute::<&$t<N>, &[N, ..$dim]>(self)[i].clone() } }
#[inline]
pub fn set(&mut self, i: uint, val: N)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self)[i] = val } }
#[inline]
pub fn set(&mut self, i: uint, val: N)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self)[i] = val } }
#[inline]
pub fn swap(&mut self, i1: uint, i2: uint)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self).swap(i1, i2) } }
}
)
#[inline]
pub fn swap(&mut self, i1: uint, i2: uint)
{ unsafe { cast::transmute::<&mut $t<N>, &mut [N, ..$dim]>(self).swap(i1, i2) } }
}
)
)
macro_rules! new_repeat_impl(
($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone> $t<N>
{
/// Creates a new vector with all its components equal to a given value.
#[inline]
pub fn new_repeat($param: N) -> $t<N>
{
$t{
$comp0: $param.clone()
$(, $compN: $param.clone() )*
($t: ident, $param: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone> $t<N>
{
/// Creates a new vector with all its components equal to a given value.
#[inline]
pub fn new_repeat($param: N) -> $t<N>
{
$t{
$comp0: $param.clone()
$(, $compN: $param.clone() )*
}
}
}
}
}
)
)
)
macro_rules! iterable_impl(
($t: ident, $dim: expr) => (
impl<N> Iterable<N> for $t<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ unsafe { cast::transmute::<&'l $t<N>, &'l [N, ..$dim]>(self).iter() } }
}
)
($t: ident, $dim: expr) => (
impl<N> Iterable<N> for $t<N>
{
fn iter<'l>(&'l self) -> VecIterator<'l, N>
{ unsafe { cast::transmute::<&'l $t<N>, &'l [N, ..$dim]>(self).iter() } }
}
)
)
macro_rules! iterable_mut_impl(
($t: ident, $dim: expr) => (
impl<N> IterableMut<N> for $t<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ unsafe { cast::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim]>(self).mut_iter() } }
}
)
($t: ident, $dim: expr) => (
impl<N> IterableMut<N> for $t<N>
{
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N>
{ unsafe { cast::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim]>(self).mut_iter() } }
}
)
)
macro_rules! dim_impl(
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N>
{
#[inline]
fn dim() -> uint
{ $dim }
}
)
($t: ident, $dim: expr) => (
impl<N> Dim for $t<N>
{
#[inline]
fn dim() -> uint
{ $dim }
}
)
)
macro_rules! basis_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N>
{
pub fn canonical_basis(f: &fn($t<N>))
{
for i in range(0u, $dim)
($t: ident, $dim: expr) => (
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N>
{
let mut basis_element : $t<N> = Zero::zero();
basis_element.set(i, One::one());
f(basis_element);
}
}
pub fn orthonormal_subspace_basis(&self, f: &fn($t<N>))
{
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let mut basis: ~[$t<N>] = ~[];
for i in range(0u, $dim)
{
let mut basis_element : $t<N> = Zero::zero();
basis_element.set(i, One::one());
if basis.len() == $dim - 1
{ break; }
let mut elt = basis_element.clone();
elt = elt - self.scalar_mul(&basis_element.dot(self));
for v in basis.iter()
{ elt = elt - v.scalar_mul(&elt.dot(v)) };
if !elt.sqnorm().approx_eq(&Zero::zero())
{
let new_element = elt.normalized();
pub fn canonical_basis(f: &fn($t<N>))
{
for i in range(0u, $dim)
{
let mut basis_element : $t<N> = Zero::zero();
f(new_element.clone());
basis_element.set(i, One::one());
basis.push(new_element);
}
f(basis_element);
}
}
pub fn orthonormal_subspace_basis(&self, f: &fn($t<N>))
{
// compute the basis of the orthogonal subspace using Gram-Schmidt
// orthogonalization algorithm
let mut basis: ~[$t<N>] = ~[];
for i in range(0u, $dim)
{
let mut basis_element : $t<N> = Zero::zero();
basis_element.set(i, One::one());
if basis.len() == $dim - 1
{ break; }
let mut elt = basis_element.clone();
elt = elt - self.scalar_mul(&basis_element.dot(self));
for v in basis.iter()
{ elt = elt - v.scalar_mul(&elt.dot(v)) };
if !elt.sqnorm().approx_eq(&Zero::zero())
{
let new_element = elt.normalized();
f(new_element.clone());
basis.push(new_element);
}
}
}
}
}
}
)
)
)
macro_rules! add_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Add<N, N>> Add<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn add(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Add<N, N>> Add<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn add(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) }
}
)
)
macro_rules! sub_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Sub<N, N>> Sub<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn sub(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0 - other.$comp0 $(, self.$compN - other.$compN)*) }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Sub<N, N>> Sub<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn sub(&self, other: &$t<N>) -> $t<N>
{ $t::new(self.$comp0 - other.$comp0 $(, self.$compN - other.$compN)*) }
}
)
)
macro_rules! neg_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Neg<N>> Neg<$t<N>> for $t<N>
{
#[inline]
fn neg(&self) -> $t<N>
{ $t::new(-self.$comp0 $(, -self.$compN )*) }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Neg<N>> Neg<$t<N>> for $t<N>
{
#[inline]
fn neg(&self) -> $t<N>
{ $t::new(-self.$comp0 $(, -self.$compN )*) }
}
)
)
macro_rules! dot_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ring> Dot<N> for $t<N>
{
#[inline]
fn dot(&self, other: &$t<N>) -> N
{ self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ring> Dot<N> for $t<N>
{
#[inline]
fn dot(&self, other: &$t<N>) -> N
{ self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )* }
}
)
)
macro_rules! sub_dot_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Ring> SubDot<N> for $t<N>
{
#[inline]
fn sub_dot(&self, a: &$t<N>, b: &$t<N>) -> N
{ (self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )* }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Ring> SubDot<N> for $t<N>
{
#[inline]
fn sub_dot(&self, a: &$t<N>, b: &$t<N>) -> N
{ (self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )* }
}
)
)
macro_rules! scalar_mul_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Mul<N, N>> ScalarMul<N> for $t<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 * *s $(, self.$compN * *s)*) }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 * *s;
$(self.$compN = self.$compN * *s;)*
}
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Mul<N, N>> ScalarMul<N> for $t<N>
{
#[inline]
fn scalar_mul(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 * *s $(, self.$compN * *s)*) }
#[inline]
fn scalar_mul_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 * *s;
$(self.$compN = self.$compN * *s;)*
}
}
)
)
macro_rules! scalar_div_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Div<N, N>> ScalarDiv<N> for $t<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 / *s $(, self.$compN / *s)*) }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 / *s;
$(self.$compN = self.$compN / *s;)*
}
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Div<N, N>> ScalarDiv<N> for $t<N>
{
#[inline]
fn scalar_div(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 / *s $(, self.$compN / *s)*) }
#[inline]
fn scalar_div_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 / *s;
$(self.$compN = self.$compN / *s;)*
}
}
)
)
macro_rules! scalar_add_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Add<N, N>> ScalarAdd<N> for $t<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 + *s $(, self.$compN + *s)*) }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 + *s;
$(self.$compN = self.$compN + *s;)*
}
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Add<N, N>> ScalarAdd<N> for $t<N>
{
#[inline]
fn scalar_add(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 + *s $(, self.$compN + *s)*) }
#[inline]
fn scalar_add_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 + *s;
$(self.$compN = self.$compN + *s;)*
}
}
)
)
macro_rules! scalar_sub_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Sub<N, N>> ScalarSub<N> for $t<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 - *s $(, self.$compN - *s)*) }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 - *s;
$(self.$compN = self.$compN - *s;)*
}
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Sub<N, N>> ScalarSub<N> for $t<N>
{
#[inline]
fn scalar_sub(&self, s: &N) -> $t<N>
{ $t::new(self.$comp0 - *s $(, self.$compN - *s)*) }
#[inline]
fn scalar_sub_inplace(&mut self, s: &N)
{
self.$comp0 = self.$comp0 - *s;
$(self.$compN = self.$compN - *s;)*
}
}
)
)
macro_rules! translation_impl(
($t: ident) => (
impl<N: Clone + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N>
{
#[inline]
fn translation(&self) -> $t<N>
{ self.clone() }
($t: ident) => (
impl<N: Clone + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N>
{
#[inline]
fn translation(&self) -> $t<N>
{ self.clone() }
#[inline]
fn inv_translation(&self) -> $t<N>
{ -self }
#[inline]
fn translate_by(&mut self, t: &$t<N>)
{ *self = *self + *t; }
}
)
#[inline]
fn inv_translation(&self) -> $t<N>
{ -self }
#[inline]
fn translate_by(&mut self, t: &$t<N>)
{ *self = *self + *t; }
}
)
)
macro_rules! translatable_impl(
($t: ident) => (
impl<N: Add<N, N> + Neg<N> + Clone> Translatable<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn translated(&self, t: &$t<N>) -> $t<N>
{ self + *t }
}
)
($t: ident) => (
impl<N: Add<N, N> + Neg<N> + Clone> Translatable<$t<N>, $t<N>> for $t<N>
{
#[inline]
fn translated(&self, t: &$t<N>) -> $t<N>
{ self + *t }
}
)
)
macro_rules! norm_impl(
($t: ident) => (
impl<N: Clone + DivisionRing + Algebraic> Norm<N> for $t<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> $t<N>
{
let mut res : $t<N> = self.clone();
res.normalize();
res
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
self.scalar_div_inplace(&l);
l
}
}
)
($t: ident) => (
impl<N: Clone + DivisionRing + Algebraic> Norm<N> for $t<N>
{
#[inline]
fn sqnorm(&self) -> N
{ self.dot(self) }
#[inline]
fn norm(&self) -> N
{ self.sqnorm().sqrt() }
#[inline]
fn normalized(&self) -> $t<N>
{
let mut res : $t<N> = self.clone();
res.normalize();
res
}
#[inline]
fn normalize(&mut self) -> N
{
let l = self.norm();
self.scalar_div_inplace(&l);
l
}
}
)
)
macro_rules! approx_eq_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool
{ self.$comp0.approx_eq(&other.$comp0) $(&& self.$compN.approx_eq(&other.$compN))* }
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, eps: &N) -> bool
{ self.$comp0.approx_eq_eps(&other.$comp0, eps) $(&& self.$compN.approx_eq_eps(&other.$compN, eps))* }
}
)
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N>
{
#[inline]
fn approx_epsilon() -> N
{ ApproxEq::approx_epsilon::<N, N>() }
#[inline]
fn approx_eq(&self, other: &$t<N>) -> bool
{ self.$comp0.approx_eq(&other.$comp0) $(&& self.$compN.approx_eq(&other.$compN))* }
#[inline]
fn approx_eq_eps(&self, other: &$t<N>, eps: &N) -> bool
{ self.$comp0.approx_eq_eps(&other.$comp0, eps) $(&& self.$compN.approx_eq_eps(&other.$compN, eps))* }
}
)
)
macro_rules! one_impl(
($t: ident) => (
impl<N: Clone + One> One for $t<N>
{
#[inline]
fn one() -> $t<N>
{ $t::new_repeat(One::one()) }
}
)
($t: ident) => (
impl<N: Clone + One> One for $t<N>
{
#[inline]
fn one() -> $t<N>
{ $t::new_repeat(One::one()) }
}
)
)
macro_rules! from_iterator_impl(
($t: ident, $param0: ident $(, $paramN: ident)*) => (
impl<N, Iter: Iterator<N>> FromIterator<N, Iter> for $t<N>
{
fn from_iterator($param0: &mut Iter) -> $t<N>
{ $t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*) }
}
)
($t: ident, $param0: ident $(, $paramN: ident)*) => (
impl<N, Iter: Iterator<N>> FromIterator<N, Iter> for $t<N>
{
fn from_iterator($param0: &mut Iter) -> $t<N>
{ $t::new($param0.next().unwrap() $(, $paramN.next().unwrap())*) }
}
)
)
macro_rules! bounded_impl(
($t: ident) => (
impl<N: Bounded + Clone> Bounded for $t<N>
{
#[inline]
fn max_value() -> $t<N>
{ $t::new_repeat(Bounded::max_value()) }
#[inline]
fn min_value() -> $t<N>
{ $t::new_repeat(Bounded::min_value()) }
}
)
($t: ident) => (
impl<N: Bounded + Clone> Bounded for $t<N>
{
#[inline]
fn max_value() -> $t<N>
{ $t::new_repeat(Bounded::max_value()) }
#[inline]
fn min_value() -> $t<N>
{ $t::new_repeat(Bounded::min_value()) }
}
)
)
macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + One + Zero> ToHomogeneous<$t2<N>> for $t<N>
{
fn to_homogeneous(&self) -> $t2<N>
{
let mut res: $t2<N> = One::one();
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + One + Zero> ToHomogeneous<$t2<N>> for $t<N>
{
fn to_homogeneous(&self) -> $t2<N>
{
let mut res: $t2<N> = One::one();
res.$comp0 = self.$comp0.clone();
$( res.$compN = self.$compN.clone(); )*
res.$comp0 = self.$comp0.clone();
$( res.$compN = self.$compN.clone(); )*
res
}
}
)
res
}
}
)
)
macro_rules! from_homogeneous_impl(
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N>
{
fn from(v: &$t2<N>) -> $t<N>
{
let mut res: $t<N> = Zero::zero();
($t: ident, $t2: ident, $extra: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N>
{
fn from(v: &$t2<N>) -> $t<N>
{
let mut res: $t<N> = Zero::zero();
res.$comp0 = v.$comp0.clone();
$( res.$compN = v.$compN.clone(); )*
res.$comp0 = v.$comp0.clone();
$( res.$compN = v.$compN.clone(); )*
res.scalar_div(&v.$extra);
res.scalar_div(&v.$extra);
res
}
}
)
res
}
}
)
)

View File

@ -8,158 +8,159 @@ use vec::{Vec1, Vec2, Vec3};
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N>
{
#[inline]
fn cross(&self, other : &Vec2<N>) -> Vec1<N>
{ Vec1::new(self.x * other.y - self.y * other.x) }
#[inline]
fn cross(&self, other : &Vec2<N>) -> Vec1<N>
{ Vec1::new(self.x * other.y - self.y * other.x) }
}
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N>
{
#[inline]
fn cross(&self, other : &Vec3<N>) -> Vec3<N>
{
Vec3::new(self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x
)
}
#[inline]
fn cross(&self, other : &Vec3<N>) -> Vec3<N>
{
Vec3::new(
self.y * other.z - self.z * other.y,
self.z * other.x - self.x * other.z,
self.x * other.y - self.y * other.x
)
}
}
impl<N: One> Basis for Vec1<N>
{
#[inline(always)]
fn canonical_basis(f: &fn(Vec1<N>))
{ f(Vec1::new(One::one())) }
#[inline(always)]
fn canonical_basis(f: &fn(Vec1<N>))
{ f(Vec1::new(One::one())) }
#[inline(always)]
fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>))
{ }
#[inline(always)]
fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>))
{ }
}
impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N>
{
#[inline]
fn canonical_basis(f: &fn(Vec2<N>))
{
f(Vec2::new(One::one(), Zero::zero()));
f(Vec2::new(Zero::zero(), One::one()));
}
#[inline]
fn canonical_basis(f: &fn(Vec2<N>))
{
f(Vec2::new(One::one(), Zero::zero()));
f(Vec2::new(Zero::zero(), One::one()));
}
#[inline]
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>))
{ f(Vec2::new(-self.y, self.x.clone())) }
#[inline]
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>))
{ f(Vec2::new(-self.y, self.x.clone())) }
}
impl<N: Clone + DivisionRing + Ord + Algebraic + Signed>
Basis for Vec3<N>
{
#[inline(always)]
fn canonical_basis(f: &fn(Vec3<N>))
{
f(Vec3::new(One::one(), Zero::zero(), Zero::zero()));
f(Vec3::new(Zero::zero(), One::one(), Zero::zero()));
f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
}
#[inline(always)]
fn canonical_basis(f: &fn(Vec3<N>))
{
f(Vec3::new(One::one(), Zero::zero(), Zero::zero()));
f(Vec3::new(Zero::zero(), One::one(), Zero::zero()));
f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
}
#[inline(always)]
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>))
{
let a =
if self.x.clone().abs() > self.y.clone().abs()
{ Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized() }
else
{ Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized() };
#[inline(always)]
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>))
{
let a =
if self.x.clone().abs() > self.y.clone().abs()
{ Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized() }
else
{ Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized() };
f(a.cross(self));
f(a);
}
f(a.cross(self));
f(a);
}
}
// FIXME: this bad: this fixes definitly the number of samples…
static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
Vec2 { x: 1.0, y: 0.0 },
Vec2 { x: 0.95557281, y: 0.29475517 },
Vec2 { x: 0.82623877, y: 0.56332006 },
Vec2 { x: 0.6234898, y: 0.78183148 },
Vec2 { x: 0.36534102, y: 0.93087375 },
Vec2 { x: 0.07473009, y: 0.9972038 },
Vec2 { x: -0.22252093, y: 0.97492791 },
Vec2 { x: -0.5, y: 0.8660254 },
Vec2 { x: -0.73305187, y: 0.68017274 },
Vec2 { x: -0.90096887, y: 0.43388374 },
Vec2 { x: -0.98883083, y: 0.14904227 },
Vec2 { x: -0.98883083, y: -0.14904227 },
Vec2 { x: -0.90096887, y: -0.43388374 },
Vec2 { x: -0.73305187, y: -0.68017274 },
Vec2 { x: -0.5, y: -0.8660254 },
Vec2 { x: -0.22252093, y: -0.97492791 },
Vec2 { x: 0.07473009, y: -0.9972038 },
Vec2 { x: 0.36534102, y: -0.93087375 },
Vec2 { x: 0.6234898, y: -0.78183148 },
Vec2 { x: 0.82623877, y: -0.56332006 },
Vec2 { x: 0.95557281, y: -0.29475517 },
Vec2 { x: 1.0, y: 0.0 },
Vec2 { x: 0.95557281, y: 0.29475517 },
Vec2 { x: 0.82623877, y: 0.56332006 },
Vec2 { x: 0.6234898, y: 0.78183148 },
Vec2 { x: 0.36534102, y: 0.93087375 },
Vec2 { x: 0.07473009, y: 0.9972038 },
Vec2 { x: -0.22252093, y: 0.97492791 },
Vec2 { x: -0.5, y: 0.8660254 },
Vec2 { x: -0.73305187, y: 0.68017274 },
Vec2 { x: -0.90096887, y: 0.43388374 },
Vec2 { x: -0.98883083, y: 0.14904227 },
Vec2 { x: -0.98883083, y: -0.14904227 },
Vec2 { x: -0.90096887, y: -0.43388374 },
Vec2 { x: -0.73305187, y: -0.68017274 },
Vec2 { x: -0.5, y: -0.8660254 },
Vec2 { x: -0.22252093, y: -0.97492791 },
Vec2 { x: 0.07473009, y: -0.9972038 },
Vec2 { x: 0.36534102, y: -0.93087375 },
Vec2 { x: 0.6234898, y: -0.78183148 },
Vec2 { x: 0.82623877, y: -0.56332006 },
Vec2 { x: 0.95557281, y: -0.29475517 },
];
// Those vectors come from bullet 3d
static SAMPLES_3_F64: [Vec3<f64>, ..42] = [
Vec3 { x: 0.000000 , y: -0.000000, z: -1.000000 },
Vec3 { x: 0.723608 , y: -0.525725, z: -0.447219 },
Vec3 { x: -0.276388, y: -0.850649, z: -0.447219 },
Vec3 { x: -0.894426, y: -0.000000, z: -0.447216 },
Vec3 { x: -0.276388, y: 0.850649 , z: -0.447220 },
Vec3 { x: 0.723608 , y: 0.525725 , z: -0.447219 },
Vec3 { x: 0.276388 , y: -0.850649, z: 0.447220 },
Vec3 { x: -0.723608, y: -0.525725, z: 0.447219 },
Vec3 { x: -0.723608, y: 0.525725 , z: 0.447219 },
Vec3 { x: 0.276388 , y: 0.850649 , z: 0.447219 },
Vec3 { x: 0.894426 , y: 0.000000 , z: 0.447216 },
Vec3 { x: -0.000000, y: 0.000000 , z: 1.000000 },
Vec3 { x: 0.425323 , y: -0.309011, z: -0.850654 },
Vec3 { x: -0.162456, y: -0.499995, z: -0.850654 },
Vec3 { x: 0.262869 , y: -0.809012, z: -0.525738 },
Vec3 { x: 0.425323 , y: 0.309011 , z: -0.850654 },
Vec3 { x: 0.850648 , y: -0.000000, z: -0.525736 },
Vec3 { x: -0.525730, y: -0.000000, z: -0.850652 },
Vec3 { x: -0.688190, y: -0.499997, z: -0.525736 },
Vec3 { x: -0.162456, y: 0.499995 , z: -0.850654 },
Vec3 { x: -0.688190, y: 0.499997 , z: -0.525736 },
Vec3 { x: 0.262869 , y: 0.809012 , z: -0.525738 },
Vec3 { x: 0.951058 , y: 0.309013 , z: 0.000000 },
Vec3 { x: 0.951058 , y: -0.309013, z: 0.000000 },
Vec3 { x: 0.587786 , y: -0.809017, z: 0.000000 },
Vec3 { x: 0.000000 , y: -1.000000, z: 0.000000 },
Vec3 { x: -0.587786, y: -0.809017, z: 0.000000 },
Vec3 { x: -0.951058, y: -0.309013, z: -0.000000 },
Vec3 { x: -0.951058, y: 0.309013 , z: -0.000000 },
Vec3 { x: -0.587786, y: 0.809017 , z: -0.000000 },
Vec3 { x: -0.000000, y: 1.000000 , z: -0.000000 },
Vec3 { x: 0.587786 , y: 0.809017 , z: -0.000000 },
Vec3 { x: 0.688190 , y: -0.499997, z: 0.525736 },
Vec3 { x: -0.262869, y: -0.809012, z: 0.525738 },
Vec3 { x: -0.850648, y: 0.000000 , z: 0.525736 },
Vec3 { x: -0.262869, y: 0.809012 , z: 0.525738 },
Vec3 { x: 0.688190 , y: 0.499997 , z: 0.525736 },
Vec3 { x: 0.525730 , y: 0.000000 , z: 0.850652 },
Vec3 { x: 0.162456 , y: -0.499995, z: 0.850654 },
Vec3 { x: -0.425323, y: -0.309011, z: 0.850654 },
Vec3 { x: -0.425323, y: 0.309011 , z: 0.850654 },
Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 }
Vec3 { x: 0.000000 , y: -0.000000, z: -1.000000 },
Vec3 { x: 0.723608 , y: -0.525725, z: -0.447219 },
Vec3 { x: -0.276388, y: -0.850649, z: -0.447219 },
Vec3 { x: -0.894426, y: -0.000000, z: -0.447216 },
Vec3 { x: -0.276388, y: 0.850649 , z: -0.447220 },
Vec3 { x: 0.723608 , y: 0.525725 , z: -0.447219 },
Vec3 { x: 0.276388 , y: -0.850649, z: 0.447220 },
Vec3 { x: -0.723608, y: -0.525725, z: 0.447219 },
Vec3 { x: -0.723608, y: 0.525725 , z: 0.447219 },
Vec3 { x: 0.276388 , y: 0.850649 , z: 0.447219 },
Vec3 { x: 0.894426 , y: 0.000000 , z: 0.447216 },
Vec3 { x: -0.000000, y: 0.000000 , z: 1.000000 },
Vec3 { x: 0.425323 , y: -0.309011, z: -0.850654 },
Vec3 { x: -0.162456, y: -0.499995, z: -0.850654 },
Vec3 { x: 0.262869 , y: -0.809012, z: -0.525738 },
Vec3 { x: 0.425323 , y: 0.309011 , z: -0.850654 },
Vec3 { x: 0.850648 , y: -0.000000, z: -0.525736 },
Vec3 { x: -0.525730, y: -0.000000, z: -0.850652 },
Vec3 { x: -0.688190, y: -0.499997, z: -0.525736 },
Vec3 { x: -0.162456, y: 0.499995 , z: -0.850654 },
Vec3 { x: -0.688190, y: 0.499997 , z: -0.525736 },
Vec3 { x: 0.262869 , y: 0.809012 , z: -0.525738 },
Vec3 { x: 0.951058 , y: 0.309013 , z: 0.000000 },
Vec3 { x: 0.951058 , y: -0.309013, z: 0.000000 },
Vec3 { x: 0.587786 , y: -0.809017, z: 0.000000 },
Vec3 { x: 0.000000 , y: -1.000000, z: 0.000000 },
Vec3 { x: -0.587786, y: -0.809017, z: 0.000000 },
Vec3 { x: -0.951058, y: -0.309013, z: -0.000000 },
Vec3 { x: -0.951058, y: 0.309013 , z: -0.000000 },
Vec3 { x: -0.587786, y: 0.809017 , z: -0.000000 },
Vec3 { x: -0.000000, y: 1.000000 , z: -0.000000 },
Vec3 { x: 0.587786 , y: 0.809017 , z: -0.000000 },
Vec3 { x: 0.688190 , y: -0.499997, z: 0.525736 },
Vec3 { x: -0.262869, y: -0.809012, z: 0.525738 },
Vec3 { x: -0.850648, y: 0.000000 , z: 0.525736 },
Vec3 { x: -0.262869, y: 0.809012 , z: 0.525738 },
Vec3 { x: 0.688190 , y: 0.499997 , z: 0.525736 },
Vec3 { x: 0.525730 , y: 0.000000 , z: 0.850652 },
Vec3 { x: 0.162456 , y: -0.499995, z: 0.850654 },
Vec3 { x: -0.425323, y: -0.309011, z: 0.850654 },
Vec3 { x: -0.425323, y: 0.309011 , z: 0.850654 },
Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 }
];
impl UniformSphereSample for Vec2<f64>
{
pub fn sample(f: &fn(&'static Vec2<f64>))
{
for sample in SAMPLES_2_F64.iter()
{ f(sample) }
}
pub fn sample(f: &fn(&'static Vec2<f64>))
{
for sample in SAMPLES_2_F64.iter()
{ f(sample) }
}
}
impl UniformSphereSample for Vec3<f64>
{
pub fn sample(f: &fn(&'static Vec3<f64>))
{
for sample in SAMPLES_3_F64.iter()
{ f(sample) }
}
pub fn sample(f: &fn(&'static Vec3<f64>))
{
for sample in SAMPLES_3_F64.iter()
{ f(sample) }
}
}