Indentation fixes.
This commit is contained in:
parent
53a5dbb6e3
commit
a810bf6008
|
@ -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) }
|
||||
}
|
||||
|
|
|
@ -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()) }
|
||||
}
|
||||
|
|
404
src/dmat.rs
404
src/dmat.rs
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
358
src/dvec.rs
358
src/dvec.rs
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
42
src/mat.rs
42
src/mat.rs
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
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)) != _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
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
85
src/vec.rs
85
src/vec.rs
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
pub fn canonical_basis(f: &fn($t<N>))
|
||||
{
|
||||
for i in range(0u, $dim)
|
||||
{
|
||||
let mut basis_element : $t<N> = Zero::zero();
|
||||
|
||||
basis_element.set(i, One::one());
|
||||
basis_element.set(i, One::one());
|
||||
|
||||
f(basis_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)*) }
|
||||
($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;)*
|
||||
}
|
||||
}
|
||||
)
|
||||
#[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)*) }
|
||||
($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;)*
|
||||
}
|
||||
}
|
||||
)
|
||||
#[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)*) }
|
||||
($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;)*
|
||||
}
|
||||
}
|
||||
)
|
||||
#[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)*) }
|
||||
($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;)*
|
||||
}
|
||||
}
|
||||
)
|
||||
#[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 inv_translation(&self) -> $t<N>
|
||||
{ -self }
|
||||
|
||||
#[inline]
|
||||
fn translate_by(&mut self, t: &$t<N>)
|
||||
{ *self = *self + *t; }
|
||||
}
|
||||
)
|
||||
#[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) }
|
||||
($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 norm(&self) -> N
|
||||
{ self.sqnorm().sqrt() }
|
||||
|
||||
#[inline]
|
||||
fn normalized(&self) -> $t<N>
|
||||
{
|
||||
let mut res : $t<N> = self.clone();
|
||||
#[inline]
|
||||
fn normalized(&self) -> $t<N>
|
||||
{
|
||||
let mut res : $t<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();
|
||||
|
||||
self.scalar_div_inplace(&l);
|
||||
self.scalar_div_inplace(&l);
|
||||
|
||||
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>() }
|
||||
($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(&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))* }
|
||||
}
|
||||
)
|
||||
#[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()) }
|
||||
($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()) }
|
||||
}
|
||||
)
|
||||
#[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
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
235
src/vec_spec.rs
235
src/vec_spec.rs
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue