Add sphere sempling trait + Copy becomes Clone

This commit is contained in:
Sébastien Crozet 2013-07-04 14:23:08 +00:00
parent 51fd2bc744
commit 6f081b70b8
13 changed files with 268 additions and 137 deletions

View File

@ -19,22 +19,21 @@ use vec::Vec3;
pub struct Rotmat<M> pub struct Rotmat<M>
{ priv submat: M } { priv submat: M }
impl<M: Copy> Rotmat<M> impl<M: Clone> Rotmat<M>
{ {
pub fn submat(&self) -> M pub fn submat(&self) -> M
{ copy self.submat } { self.submat.clone() }
} }
pub fn rotmat2<N: Copy + Trigonometric + Neg<N>>(angle: N) -> Rotmat<Mat2<N>> pub fn rotmat2<N: Clone + Trigonometric + Neg<N>>(angle: N) -> Rotmat<Mat2<N>>
{ {
let coa = angle.cos(); let (sia, coa) = angle.sin_cos();
let sia = angle.sin();
Rotmat Rotmat
{ submat: Mat2::new( [ copy coa, -sia, copy sia, copy coa ] ) } { submat: Mat2::new( [ coa.clone(), -sia, sia.clone(), coa ] ) }
} }
pub fn rotmat3<N: Copy + Trigonometric + DivisionRing + Algebraic> pub fn rotmat3<N: Clone + Copy + Trigonometric + DivisionRing + Algebraic>
(axisangle: Vec3<N>) -> Rotmat<Mat3<N>> (axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
{ {
if axisangle.sqnorm().is_zero() if axisangle.sqnorm().is_zero()
@ -44,15 +43,14 @@ pub fn rotmat3<N: Copy + Trigonometric + DivisionRing + Algebraic>
let mut axis = axisangle; let mut axis = axisangle;
let angle = axis.normalize(); let angle = axis.normalize();
let _1 = One::one::<N>(); let _1 = One::one::<N>();
let ux = copy axis.at[0]; let ux = axis.at[0].clone();
let uy = copy axis.at[1]; let uy = axis.at[1].clone();
let uz = copy axis.at[2]; let uz = axis.at[2].clone();
let sqx = ux * ux; let sqx = ux * ux;
let sqy = uy * uy; let sqy = uy * uy;
let sqz = uz * uz; let sqz = uz * uz;
let cos = angle.cos(); let (sin, cos) = angle.sin_cos();
let one_m_cos = _1 - cos; let one_m_cos = _1 - cos;
let sin = angle.sin();
Rotmat { Rotmat {
submat: Mat3::new( [ submat: Mat3::new( [
@ -71,12 +69,12 @@ pub fn rotmat3<N: Copy + Trigonometric + DivisionRing + Algebraic>
} }
} }
impl<N: Trigonometric + DivisionRing + Copy> impl<N: Trigonometric + DivisionRing + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>> Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{ {
#[inline] #[inline]
fn rotation(&self) -> Vec1<N> fn rotation(&self) -> Vec1<N>
{ Vec1::new([ -(self.submat.at((0, 1)) / self.submat.at((0, 0))).atan() ]) } { Vec1::new([ (-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))) ]) }
#[inline] #[inline]
fn inv_rotation(&self) -> Vec1<N> fn inv_rotation(&self) -> Vec1<N>
@ -87,15 +85,15 @@ Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
impl<N: Trigonometric + DivisionRing + Copy> impl<N: Trigonometric + DivisionRing + Clone>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{ {
#[inline] #[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>> fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
{ rotmat2(copy rot.at[0]) * *self } { rotmat2(rot.at[0].clone()) * *self }
} }
impl<N: Copy + Trigonometric + DivisionRing + Algebraic> impl<N: Clone + Copy + Trigonometric + DivisionRing + Algebraic>
Rotation<Vec3<N>> for Rotmat<Mat3<N>> Rotation<Vec3<N>> for Rotmat<Mat3<N>>
{ {
#[inline] #[inline]
@ -112,15 +110,15 @@ Rotation<Vec3<N>> for Rotmat<Mat3<N>>
{ *self = self.rotated(rot) } { *self = self.rotated(rot) }
} }
impl<N: Copy + Trigonometric + DivisionRing + Algebraic> impl<N: Clone + Copy + Trigonometric + DivisionRing + Algebraic>
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
{ {
#[inline] #[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>> fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
{ rotmat3(copy *axisangle) * *self } { rotmat3(axisangle.clone()) * *self }
} }
impl<N: Copy + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>> impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{ {
#[inline] #[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>> fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
@ -149,7 +147,7 @@ impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
{ self.inv_rotate(v) } { self.inv_rotate(v) }
} }
impl<N: Copy + Rand + Trigonometric + DivisionRing + Algebraic> impl<N: Clone + Copy + Rand + Trigonometric + DivisionRing + Algebraic>
Rand for Rotmat<Mat3<N>> Rand for Rotmat<Mat3<N>>
{ {
#[inline] #[inline]
@ -195,12 +193,16 @@ impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
impl<M: Transpose> Inv for Rotmat<M> impl<M: Transpose> Inv for Rotmat<M>
{ {
#[inline] #[inline]
fn invert(&mut self) fn invert(&mut self) -> bool
{ self.transpose() } {
self.transpose();
true
}
#[inline] #[inline]
fn inverse(&self) -> Rotmat<M> fn inverse(&self) -> Option<Rotmat<M>>
{ self.transposed() } { Some(self.transposed()) }
} }
impl<M: Transpose> impl<M: Transpose>

View File

@ -179,7 +179,14 @@ Transformation<Transform<M, V>> for Transform<M, V>
{ copy *self } { copy *self }
fn inv_transformation(&self) -> Transform<M, V> fn inv_transformation(&self) -> Transform<M, V>
{ self.inverse() } {
// 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>) fn transform_by(&mut self, other: &Transform<M, V>)
{ *self = other * *self; } { *self = other * *self; }
@ -211,20 +218,26 @@ impl<M: Copy + Inv + RMul<V>, V: Copy + Neg<V>>
Inv for Transform<M, V> Inv for Transform<M, V>
{ {
#[inline] #[inline]
fn invert(&mut self) fn invert(&mut self) -> bool
{
if !self.submat.invert()
{ false }
else
{ {
self.submat.invert();
self.subtrans = self.submat.rmul(&-self.subtrans); self.subtrans = self.submat.rmul(&-self.subtrans);
true
}
} }
#[inline] #[inline]
fn inverse(&self) -> Transform<M, V> fn inverse(&self) -> Option<Transform<M, V>>
{ {
let mut res = copy *self; let mut res = copy *self;
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
} }

View File

@ -137,16 +137,17 @@ impl<N: Copy + Eq + DivisionRing>
Inv for DMat<N> Inv for DMat<N>
{ {
#[inline] #[inline]
fn inverse(&self) -> DMat<N> fn inverse(&self) -> Option<DMat<N>>
{ {
let mut res : DMat<N> = copy *self; let mut res : DMat<N> = copy *self;
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
fn invert(&mut self) fn invert(&mut self) -> bool
{ {
let dim = self.dim; let dim = self.dim;
let mut res = one_mat_with_dim::<N>(dim); let mut res = one_mat_with_dim::<N>(dim);
@ -169,7 +170,8 @@ Inv for DMat<N>
n0 = n0 + 1; n0 = n0 + 1;
} }
assert!(n0 != dim); // non inversible matrix if n0 == dim
{ return false }
// swap pivot line // swap pivot line
if n0 != k if n0 != k
@ -220,6 +222,8 @@ Inv for DMat<N>
} }
*self = res; *self = res;
true
} }
} }

View File

@ -22,6 +22,7 @@ mod mat_impl;
pub struct Mat1<N> pub struct Mat1<N>
{ mij: [N, ..1 * 1] } { mij: [N, ..1 * 1] }
clone_impl!(Mat1)
mat_impl!(Mat1, 1) mat_impl!(Mat1, 1)
one_impl!(Mat1, [ _1 ]) one_impl!(Mat1, [ _1 ])
zero_impl!(Mat1, [ _0 ]) zero_impl!(Mat1, [ _0 ])
@ -43,6 +44,7 @@ column_impl!(Mat1, 1)
pub struct Mat2<N> pub struct Mat2<N>
{ mij: [N, ..2 * 2] } { mij: [N, ..2 * 2] }
clone_impl!(Mat2)
mat_impl!(Mat2, 2) mat_impl!(Mat2, 2)
one_impl!(Mat2, [ _1 | _0 | one_impl!(Mat2, [ _1 | _0 |
_0 | _1 ]) _0 | _1 ])
@ -67,6 +69,7 @@ column_impl!(Mat2, 2)
pub struct Mat3<N> pub struct Mat3<N>
{ mij: [N, ..3 * 3] } { mij: [N, ..3 * 3] }
clone_impl!(Mat3)
mat_impl!(Mat3, 3) mat_impl!(Mat3, 3)
one_impl!(Mat3, [ _1 | _0 | _0 | one_impl!(Mat3, [ _1 | _0 | _0 |
_0 | _1 | _0 | _0 | _1 | _0 |
@ -94,6 +97,7 @@ column_impl!(Mat3, 3)
pub struct Mat4<N> pub struct Mat4<N>
{ mij: [N, ..4 * 4] } { mij: [N, ..4 * 4] }
clone_impl!(Mat4)
mat_impl!(Mat4, 4) mat_impl!(Mat4, 4)
one_impl!(Mat4, [ one_impl!(Mat4, [
_1 | _0 | _0 | _0 | _1 | _0 | _0 | _0 |
@ -130,6 +134,7 @@ column_impl!(Mat4, 4)
pub struct Mat5<N> pub struct Mat5<N>
{ mij: [N, ..5 * 5] } { mij: [N, ..5 * 5] }
clone_impl!(Mat5)
mat_impl!(Mat5, 5) mat_impl!(Mat5, 5)
one_impl!(Mat5, [ one_impl!(Mat5, [
_1 | _0 | _0 | _0 | _0 | _1 | _0 | _0 | _0 | _0 |
@ -169,6 +174,7 @@ column_impl!(Mat5, 5)
pub struct Mat6<N> pub struct Mat6<N>
{ mij: [N, ..6 * 6] } { mij: [N, ..6 * 6] }
clone_impl!(Mat6)
mat_impl!(Mat6, 6) mat_impl!(Mat6, 6)
one_impl!(Mat6, [ one_impl!(Mat6, [
_1 | _0 | _0 | _0 | _0 | _0 | _1 | _0 | _0 | _0 | _0 | _0 |

View File

@ -1,5 +1,22 @@
#[macro_escape]; #[macro_escape];
macro_rules! clone_impl(
// FIXME: use 'Clone' alone. For the moment, we need 'Copy' because the automatic
// implementation of Clone for [t, ..n] is badly typed.
($t: ident) => (
impl<N: Clone + Copy> Clone for $t<N>
{
#[inline]
fn clone(&self) -> $t<N>
{
$t {
mij: copy self.mij
}
}
}
)
)
macro_rules! mat_impl( macro_rules! mat_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N> $t<N> impl<N> $t<N>
@ -17,13 +34,13 @@ macro_rules! mat_impl(
macro_rules! one_impl( macro_rules! one_impl(
($t: ident, [ $($value: ident)|+ ] ) => ( ($t: ident, [ $($value: ident)|+ ] ) => (
impl<N: Copy + One + Zero> One for $t<N> impl<N: Clone + One + Zero> One for $t<N>
{ {
#[inline] #[inline]
fn one() -> $t<N> fn one() -> $t<N>
{ {
let (_0, _1) = (Zero::zero::<N>(), One::one::<N>()); let (_0, _1) = (Zero::zero::<N>(), One::one::<N>());
return $t::new( [ $( copy $value, )+ ] ) return $t::new( [ $( $value.clone(), )+ ] )
} }
} }
) )
@ -31,13 +48,13 @@ macro_rules! one_impl(
macro_rules! zero_impl( macro_rules! zero_impl(
($t: ident, [ $($value: ident)|+ ] ) => ( ($t: ident, [ $($value: ident)|+ ] ) => (
impl<N: Copy + Zero> Zero for $t<N> impl<N: Clone + Zero> Zero for $t<N>
{ {
#[inline] #[inline]
fn zero() -> $t<N> fn zero() -> $t<N>
{ {
let _0 = Zero::zero(); let _0 = Zero::zero::<N>();
return $t::new( [ $( copy $value, )+ ] ) return $t::new( [ $( $value.clone(), )+ ] )
} }
#[inline] #[inline]
@ -60,11 +77,11 @@ macro_rules! dim_impl(
macro_rules! mat_indexable_impl( macro_rules! mat_indexable_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy> Indexable<(uint, uint), N> for $t<N> impl<N: Clone> Indexable<(uint, uint), N> for $t<N>
{ {
#[inline] #[inline]
pub fn at(&self, (i, j): (uint, uint)) -> N pub fn at(&self, (i, j): (uint, uint)) -> N
{ copy self.mij[self.offset(i, j)] } { self.mij[self.offset(i, j)].clone() }
#[inline] #[inline]
pub fn set(&mut self, (i, j): (uint, uint), t: N) pub fn set(&mut self, (i, j): (uint, uint), t: N)
@ -75,7 +92,7 @@ macro_rules! mat_indexable_impl(
macro_rules! column_impl( macro_rules! column_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy, V: Zero + Iterable<N> + IterableMut<N>> Column<V> for $t<N> impl<N: Clone, V: Zero + Iterable<N> + IterableMut<N>> Column<V> for $t<N>
{ {
fn set_column(&mut self, col: uint, v: V) fn set_column(&mut self, col: uint, v: V)
{ {
@ -84,7 +101,7 @@ macro_rules! column_impl(
if i == Dim::dim::<$t<N>>() if i == Dim::dim::<$t<N>>()
{ break } { break }
self.set((i, col), copy *e); self.set((i, col), e.clone());
} }
} }
@ -108,7 +125,7 @@ macro_rules! column_impl(
macro_rules! mul_impl( macro_rules! mul_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy + Ring> impl<N: Clone + Ring>
Mul<$t<N>, $t<N>> for $t<N> Mul<$t<N>, $t<N>> for $t<N>
{ {
fn mul(&self, other: &$t<N>) -> $t<N> fn mul(&self, other: &$t<N>) -> $t<N>
@ -136,7 +153,7 @@ macro_rules! mul_impl(
macro_rules! rmul_impl( macro_rules! rmul_impl(
($t: ident, $v: ident, $dim: expr) => ( ($t: ident, $v: ident, $dim: expr) => (
impl<N: Copy + Ring> impl<N: Clone + Ring>
RMul<$v<N>> for $t<N> RMul<$v<N>> for $t<N>
{ {
fn rmul(&self, other: &$v<N>) -> $v<N> fn rmul(&self, other: &$v<N>) -> $v<N>
@ -157,7 +174,7 @@ macro_rules! rmul_impl(
macro_rules! lmul_impl( macro_rules! lmul_impl(
($t: ident, $v: ident, $dim: expr) => ( ($t: ident, $v: ident, $dim: expr) => (
impl<N: Copy + Ring> impl<N: Clone + Ring>
LMul<$v<N>> for $t<N> LMul<$v<N>> for $t<N>
{ {
fn lmul(&self, other: &$v<N>) -> $v<N> fn lmul(&self, other: &$v<N>) -> $v<N>
@ -179,7 +196,7 @@ macro_rules! lmul_impl(
macro_rules! transform_impl( macro_rules! transform_impl(
($t: ident, $v: ident) => ( ($t: ident, $v: ident) => (
impl<N: Copy + DivisionRing + Eq> impl<N: Clone + Copy + DivisionRing + Eq>
Transform<$v<N>> for $t<N> Transform<$v<N>> for $t<N>
{ {
#[inline] #[inline]
@ -188,27 +205,34 @@ macro_rules! transform_impl(
#[inline] #[inline]
fn inv_transform(&self, v: &$v<N>) -> $v<N> fn inv_transform(&self, v: &$v<N>) -> $v<N>
{ self.inverse().transform_vec(v) } {
match self.inverse()
{
Some(t) => t.transform_vec(v),
None => fail!("Cannot use inv_transform on a non-inversible matrix.")
}
}
} }
) )
) )
macro_rules! inv_impl( macro_rules! inv_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy + Eq + DivisionRing> impl<N: Clone + Copy + Eq + DivisionRing>
Inv for $t<N> Inv for $t<N>
{ {
#[inline] #[inline]
fn inverse(&self) -> $t<N> fn inverse(&self) -> Option<$t<N>>
{ {
let mut res : $t<N> = copy *self; let mut res : $t<N> = self.clone();
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
fn invert(&mut self) fn invert(&mut self) -> bool
{ {
let mut res: $t<N> = One::one(); let mut res: $t<N> = One::one();
let _0N: N = Zero::zero(); let _0N: N = Zero::zero();
@ -230,6 +254,9 @@ macro_rules! inv_impl(
n0 = n0 + 1; n0 = n0 + 1;
} }
if n0 == $dim
{ return false }
// swap pivot line // swap pivot line
if n0 != k if n0 != k
{ {
@ -279,6 +306,8 @@ macro_rules! inv_impl(
} }
*self = res; *self = res;
true
} }
} }
) )
@ -286,12 +315,12 @@ macro_rules! inv_impl(
macro_rules! transpose_impl( macro_rules! transpose_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy> Transpose for $t<N> impl<N: Clone + Copy> Transpose for $t<N>
{ {
#[inline] #[inline]
fn transposed(&self) -> $t<N> fn transposed(&self) -> $t<N>
{ {
let mut res = copy *self; let mut res = self.clone();
res.transpose(); res.transpose();
@ -355,7 +384,7 @@ macro_rules! rand_impl(
macro_rules! to_homogeneous_impl( macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident, $dim: expr) => ( ($t: ident, $t2: ident, $dim: expr) => (
impl<N: One + Zero + Copy> ToHomogeneous<$t2<N>> for $t<N> impl<N: One + Zero + Clone> ToHomogeneous<$t2<N>> for $t<N>
{ {
fn to_homogeneous(&self) -> $t2<N> fn to_homogeneous(&self) -> $t2<N>
{ {
@ -375,7 +404,7 @@ macro_rules! to_homogeneous_impl(
macro_rules! from_homogeneous_impl( macro_rules! from_homogeneous_impl(
($t: ident, $t2: ident, $dim2: expr) => ( ($t: ident, $t2: ident, $dim2: expr) => (
impl<N: One + Zero + Copy> FromHomogeneous<$t2<N>> for $t<N> impl<N: One + Zero + Clone> FromHomogeneous<$t2<N>> for $t<N>
{ {
fn from_homogeneous(m: &$t2<N>) -> $t<N> fn from_homogeneous(m: &$t2<N>) -> $t<N>
{ {

View File

@ -8,21 +8,26 @@ impl<N: Copy + DivisionRing>
Inv for Mat1<N> Inv for Mat1<N>
{ {
#[inline] #[inline]
fn inverse(&self) -> Mat1<N> fn inverse(&self) -> Option<Mat1<N>>
{ {
let mut res : Mat1<N> = copy *self; let mut res : Mat1<N> = copy *self;
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
#[inline] #[inline]
fn invert(&mut self) fn invert(&mut self) -> bool
{ {
assert!(!self.mij[0].is_zero()); if self.mij[0].is_zero()
{ false }
self.mij[0] = One::one::<N>() / self.mij[0] else
{
self.mij[0] = One::one::<N>() / self.mij[0];
true
}
} }
} }
@ -30,24 +35,30 @@ impl<N: Copy + DivisionRing>
Inv for Mat2<N> Inv for Mat2<N>
{ {
#[inline] #[inline]
fn inverse(&self) -> Mat2<N> fn inverse(&self) -> Option<Mat2<N>>
{ {
let mut res : Mat2<N> = copy *self; let mut res : Mat2<N> = copy *self;
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
#[inline] #[inline]
fn invert(&mut self) fn invert(&mut self) -> bool
{ {
let det = self.mij[0 * 2 + 0] * self.mij[1 * 2 + 1] - self.mij[1 * 2 + 0] * self.mij[0 * 2 + 1]; let det = self.mij[0 * 2 + 0] * self.mij[1 * 2 + 1] - self.mij[1 * 2 + 0] * self.mij[0 * 2 + 1];
assert!(!det.is_zero()); if det.is_zero()
{ false }
else
{
*self = Mat2::new([self.mij[1 * 2 + 1] / det , -self.mij[0 * 2 + 1] / det, *self = Mat2::new([self.mij[1 * 2 + 1] / det , -self.mij[0 * 2 + 1] / det,
-self.mij[1 * 2 + 0] / det, self.mij[0 * 2 + 0] / det]) -self.mij[1 * 2 + 0] / det, self.mij[0 * 2 + 0] / det]);
true
}
} }
} }
@ -55,17 +66,18 @@ impl<N: Copy + DivisionRing>
Inv for Mat3<N> Inv for Mat3<N>
{ {
#[inline] #[inline]
fn inverse(&self) -> Mat3<N> fn inverse(&self) -> Option<Mat3<N>>
{ {
let mut res = copy *self; let mut res = copy *self;
res.invert(); if res.invert()
{ Some(res) }
res else
{ None }
} }
#[inline] #[inline]
fn invert(&mut self) fn invert(&mut self) -> bool
{ {
let minor_m12_m23 = self.mij[1 * 3 + 1] * self.mij[2 * 3 + 2] - self.mij[2 * 3 + 1] * self.mij[1 * 3 + 2]; let minor_m12_m23 = self.mij[1 * 3 + 1] * self.mij[2 * 3 + 2] - self.mij[2 * 3 + 1] * self.mij[1 * 3 + 2];
let minor_m11_m23 = self.mij[1 * 3 + 0] * self.mij[2 * 3 + 2] - self.mij[2 * 3 + 0] * self.mij[1 * 3 + 2]; let minor_m11_m23 = self.mij[1 * 3 + 0] * self.mij[2 * 3 + 2] - self.mij[2 * 3 + 0] * self.mij[1 * 3 + 2];
@ -75,8 +87,10 @@ Inv for Mat3<N>
- self.mij[0 * 3 + 1] * minor_m11_m23 - self.mij[0 * 3 + 1] * minor_m11_m23
+ self.mij[0 * 3 + 2] * minor_m11_m22; + self.mij[0 * 3 + 2] * minor_m11_m22;
assert!(!det.is_zero()); if det.is_zero()
{ false }
else
{
*self = Mat3::new( [ *self = Mat3::new( [
(minor_m12_m23 / det), (minor_m12_m23 / det),
((self.mij[0 * 3 + 2] * self.mij[2 * 3 + 1] - self.mij[2 * 3 + 2] * self.mij[0 * 3 + 1]) / det), ((self.mij[0 * 3 + 2] * self.mij[2 * 3 + 1] - self.mij[2 * 3 + 2] * self.mij[0 * 3 + 1]) / det),
@ -89,6 +103,9 @@ Inv for Mat3<N>
(minor_m11_m22 / det), (minor_m11_m22 / det),
((self.mij[0 * 3 + 1] * self.mij[2 * 3 + 0] - self.mij[2 * 3 + 1] * self.mij[0 * 3 + 0]) / det), ((self.mij[0 * 3 + 1] * self.mij[2 * 3 + 0] - self.mij[2 * 3 + 1] * self.mij[0 * 3 + 0]) / det),
((self.mij[0 * 3 + 0] * self.mij[1 * 3 + 1] - self.mij[1 * 3 + 0] * self.mij[0 * 3 + 1]) / det) ((self.mij[0 * 3 + 0] * self.mij[1 * 3 + 1] - self.mij[1 * 3 + 0] * self.mij[0 * 3 + 1]) / det)
] ) ] );
true
}
} }
} }

View File

@ -34,6 +34,7 @@ pub mod adaptors
/// Useful linear-algebra related traits. /// Useful linear-algebra related traits.
pub mod traits pub mod traits
{ {
pub mod sample;
pub mod indexable; pub mod indexable;
pub mod column; pub mod column;
pub mod iterable; pub mod iterable;

View File

@ -25,7 +25,7 @@ macro_rules! test_inv_mat_impl(
{ {
let randmat : $t = random(); let randmat : $t = random();
assert!((randmat.inverse() * randmat).approx_eq(&One::one())); assert!((randmat.inverse().unwrap() * randmat).approx_eq(&One::one()));
} }
); );
) )

View File

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

4
src/traits/sample.rs Normal file
View File

@ -0,0 +1,4 @@
pub trait UniformSphereSample
{
pub fn sample(&fn(&'static Self));
}

View File

@ -24,6 +24,7 @@ mod vec_impl;
pub struct Vec1<N> pub struct Vec1<N>
{ at: [N, ..1] } { at: [N, ..1] }
clone_impl!(Vec1)
new_impl!(Vec1, 1) new_impl!(Vec1, 1)
new_repeat_impl!(Vec1, elem, [elem]) new_repeat_impl!(Vec1, elem, [elem])
indexable_impl!(Vec1) indexable_impl!(Vec1)
@ -58,6 +59,7 @@ from_homogeneous_impl!(Vec2, Vec1, 2)
pub struct Vec2<N> pub struct Vec2<N>
{ at: [N, ..2] } { at: [N, ..2] }
clone_impl!(Vec2)
new_impl!(Vec2, 2) new_impl!(Vec2, 2)
new_repeat_impl!(Vec2, elem, [elem | elem]) new_repeat_impl!(Vec2, elem, [elem | elem])
indexable_impl!(Vec2) indexable_impl!(Vec2)
@ -92,6 +94,7 @@ from_homogeneous_impl!(Vec3, Vec2, 3)
pub struct Vec3<N> pub struct Vec3<N>
{ at: [N, ..3] } { at: [N, ..3] }
clone_impl!(Vec3)
new_impl!(Vec3, 3) new_impl!(Vec3, 3)
new_repeat_impl!(Vec3, elem, [elem | elem | elem]) new_repeat_impl!(Vec3, elem, [elem | elem | elem])
indexable_impl!(Vec3) indexable_impl!(Vec3)
@ -126,6 +129,7 @@ from_homogeneous_impl!(Vec4, Vec3, 4)
pub struct Vec4<N> pub struct Vec4<N>
{ at: [N, ..4] } { at: [N, ..4] }
clone_impl!(Vec4)
new_impl!(Vec4, 4) new_impl!(Vec4, 4)
new_repeat_impl!(Vec4, elem, [elem | elem | elem | elem]) new_repeat_impl!(Vec4, elem, [elem | elem | elem | elem])
indexable_impl!(Vec4) indexable_impl!(Vec4)
@ -160,6 +164,7 @@ from_homogeneous_impl!(Vec5, Vec4, 5)
pub struct Vec5<N> pub struct Vec5<N>
{ at: [N, ..5] } { at: [N, ..5] }
clone_impl!(Vec5)
new_impl!(Vec5, 5) new_impl!(Vec5, 5)
new_repeat_impl!(Vec5, elem, [elem | elem | elem | elem | elem]) new_repeat_impl!(Vec5, elem, [elem | elem | elem | elem | elem])
indexable_impl!(Vec5) indexable_impl!(Vec5)
@ -194,6 +199,7 @@ from_homogeneous_impl!(Vec6, Vec5, 6)
pub struct Vec6<N> pub struct Vec6<N>
{ at: [N, ..6] } { at: [N, ..6] }
clone_impl!(Vec6)
new_impl!(Vec6, 6) new_impl!(Vec6, 6)
new_repeat_impl!(Vec6, elem, [elem | elem | elem | elem | elem | elem]) new_repeat_impl!(Vec6, elem, [elem | elem | elem | elem | elem | elem])
indexable_impl!(Vec6) indexable_impl!(Vec6)

View File

@ -1,5 +1,19 @@
#[macro_escape]; #[macro_escape];
macro_rules! clone_impl(
($t:ident) => (
// FIXME: use 'Clone' alone. For the moment, we need 'Copy' because the automatic
// implementation of Clone for [t, ..n] is badly typed.
impl<N: Clone + Copy> Clone for $t<N>
{
fn clone(&self) -> $t<N>
{
$t { at: copy self.at }
}
}
)
)
macro_rules! new_impl( macro_rules! new_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N> $t<N> impl<N> $t<N>
@ -13,11 +27,11 @@ macro_rules! new_impl(
macro_rules! indexable_impl( macro_rules! indexable_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy> Indexable<uint, N> for $t<N> impl<N: Clone> Indexable<uint, N> for $t<N>
{ {
#[inline] #[inline]
pub fn at(&self, i: uint) -> N pub fn at(&self, i: uint) -> N
{ copy self.at[i] } { self.at[i].clone() }
#[inline] #[inline]
pub fn set(&mut self, i: uint, val: N) pub fn set(&mut self, i: uint, val: N)
@ -28,11 +42,11 @@ macro_rules! indexable_impl(
macro_rules! new_repeat_impl( macro_rules! new_repeat_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => ( ($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N: Copy> $t<N> impl<N: Clone> $t<N>
{ {
#[inline] #[inline]
pub fn new_repeat($param: N) -> $t<N> pub fn new_repeat($param: N) -> $t<N>
{ $t{ at: [ $( copy $elem, )+ ] } } { $t{ at: [ $( $elem.clone(), )+ ] } }
} }
) )
) )
@ -86,7 +100,7 @@ macro_rules! dim_impl(
// FIXME: add the possibility to specialize that // FIXME: add the possibility to specialize that
macro_rules! basis_impl( macro_rules! basis_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N> impl<N: Clone + Copy + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N>
{ {
pub fn canonical_basis(f: &fn($t<N>)) pub fn canonical_basis(f: &fn($t<N>))
{ {
@ -115,7 +129,7 @@ macro_rules! basis_impl(
if basis.len() == $dim - 1 if basis.len() == $dim - 1
{ break; } { break; }
let mut elt = copy basis_element; let mut elt = basis_element.clone();
elt = elt - self.scalar_mul(&basis_element.dot(self)); elt = elt - self.scalar_mul(&basis_element.dot(self));
@ -126,7 +140,7 @@ macro_rules! basis_impl(
{ {
let new_element = elt.normalized(); let new_element = elt.normalized();
f(copy new_element); f(new_element.clone());
basis.push(new_element); basis.push(new_element);
} }
@ -138,7 +152,7 @@ macro_rules! basis_impl(
macro_rules! add_impl( macro_rules! add_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy + Add<N,N>> Add<$t<N>, $t<N>> for $t<N> impl<N: Clone + Add<N,N>> Add<$t<N>, $t<N>> for $t<N>
{ {
#[inline] #[inline]
fn add(&self, other: &$t<N>) -> $t<N> fn add(&self, other: &$t<N>) -> $t<N>
@ -154,7 +168,7 @@ macro_rules! add_impl(
macro_rules! sub_impl( macro_rules! sub_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy + Sub<N,N>> Sub<$t<N>, $t<N>> for $t<N> impl<N: Clone + Sub<N,N>> Sub<$t<N>, $t<N>> for $t<N>
{ {
#[inline] #[inline]
fn sub(&self, other: &$t<N>) -> $t<N> fn sub(&self, other: &$t<N>) -> $t<N>
@ -290,11 +304,11 @@ macro_rules! scalar_sub_impl(
macro_rules! translation_impl( macro_rules! translation_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N> impl<N: Clone + Copy + Add<N, N> + Neg<N>> Translation<$t<N>> for $t<N>
{ {
#[inline] #[inline]
fn translation(&self) -> $t<N> fn translation(&self) -> $t<N>
{ copy *self } { self.clone() }
#[inline] #[inline]
fn inv_translation(&self) -> $t<N> fn inv_translation(&self) -> $t<N>
@ -309,7 +323,7 @@ macro_rules! translation_impl(
macro_rules! translatable_impl( macro_rules! translatable_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Add<N, N> + Neg<N> + Copy> Translatable<$t<N>, $t<N>> for $t<N> impl<N: Add<N, N> + Neg<N> + Clone> Translatable<$t<N>, $t<N>> for $t<N>
{ {
#[inline] #[inline]
fn translated(&self, t: &$t<N>) -> $t<N> fn translated(&self, t: &$t<N>) -> $t<N>
@ -320,7 +334,7 @@ macro_rules! translatable_impl(
macro_rules! norm_impl( macro_rules! norm_impl(
($t: ident, $dim: expr) => ( ($t: ident, $dim: expr) => (
impl<N: Copy + DivisionRing + Algebraic> Norm<N> for $t<N> impl<N: Clone + Copy + DivisionRing + Algebraic> Norm<N> for $t<N>
{ {
#[inline] #[inline]
fn sqnorm(&self) -> N fn sqnorm(&self) -> N
@ -333,7 +347,7 @@ macro_rules! norm_impl(
#[inline] #[inline]
fn normalized(&self) -> $t<N> fn normalized(&self) -> $t<N>
{ {
let mut res : $t<N> = copy *self; let mut res : $t<N> = self.clone();
res.normalize(); res.normalize();
@ -383,7 +397,7 @@ macro_rules! approx_eq_impl(
macro_rules! zero_impl( macro_rules! zero_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy + Zero> Zero for $t<N> impl<N: Clone + Zero> Zero for $t<N>
{ {
#[inline] #[inline]
fn zero() -> $t<N> fn zero() -> $t<N>
@ -398,7 +412,7 @@ macro_rules! zero_impl(
macro_rules! one_impl( macro_rules! one_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Copy + One> One for $t<N> impl<N: Clone + One> One for $t<N>
{ {
#[inline] #[inline]
fn one() -> $t<N> fn one() -> $t<N>
@ -420,13 +434,13 @@ macro_rules! rand_impl(
macro_rules! from_any_iterator_impl( macro_rules! from_any_iterator_impl(
($t: ident, $param: ident, [ $($elem: ident)|+ ]) => ( ($t: ident, $param: ident, [ $($elem: ident)|+ ]) => (
impl<N: Copy> FromAnyIterator<N> for $t<N> impl<N: Clone> FromAnyIterator<N> for $t<N>
{ {
fn from_iterator<'l>($param: &mut VecIterator<'l, N>) -> $t<N> fn from_iterator<'l>($param: &mut VecIterator<'l, N>) -> $t<N>
{ $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } } { $t { at: [ $( $elem.next().unwrap().clone(), )+ ] } }
fn from_mut_iterator<'l>($param: &mut VecMutIterator<'l, N>) -> $t<N> fn from_mut_iterator<'l>($param: &mut VecMutIterator<'l, N>) -> $t<N>
{ $t { at: [ $( copy *$elem.next().unwrap(), )+ ] } } { $t { at: [ $( $elem.next().unwrap().clone(), )+ ] } }
} }
) )
) )
@ -443,7 +457,7 @@ macro_rules! from_iterator_impl(
macro_rules! bounded_impl( macro_rules! bounded_impl(
($t: ident) => ( ($t: ident) => (
impl<N: Bounded + Copy> Bounded for $t<N> impl<N: Bounded + Clone> Bounded for $t<N>
{ {
#[inline] #[inline]
fn max_value() -> $t<N> fn max_value() -> $t<N>
@ -459,14 +473,14 @@ macro_rules! bounded_impl(
macro_rules! to_homogeneous_impl( macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident) => ($t: ident, $t2: ident) =>
{ {
impl<N: Copy + One> ToHomogeneous<$t2<N>> for $t<N> impl<N: Clone + One> ToHomogeneous<$t2<N>> for $t<N>
{ {
fn to_homogeneous(&self) -> $t2<N> fn to_homogeneous(&self) -> $t2<N>
{ {
let mut res: $t2<N> = One::one(); let mut res: $t2<N> = One::one();
for self.iter().zip(res.mut_iter()).advance |(in, out)| for self.iter().zip(res.mut_iter()).advance |(in, out)|
{ *out = copy *in } { *out = in.clone() }
res res
} }
@ -477,14 +491,14 @@ macro_rules! to_homogeneous_impl(
macro_rules! from_homogeneous_impl( macro_rules! from_homogeneous_impl(
($t: ident, $t2: ident, $dim2: expr) => ($t: ident, $t2: ident, $dim2: expr) =>
{ {
impl<N: Copy + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N> impl<N: Clone + Div<N, N> + One + Zero> FromHomogeneous<$t2<N>> for $t<N>
{ {
fn from_homogeneous(v: &$t2<N>) -> $t<N> fn from_homogeneous(v: &$t2<N>) -> $t<N>
{ {
let mut res: $t<N> = Zero::zero(); let mut res: $t<N> = Zero::zero();
for v.iter().zip(res.mut_iter()).advance |(in, out)| for v.iter().zip(res.mut_iter()).advance |(in, out)|
{ *out = copy *in } { *out = in.clone() }
res.scalar_div(&v.at[$dim2 - 1]); res.scalar_div(&v.at[$dim2 - 1]);

View File

@ -3,6 +3,7 @@ use traits::basis::Basis;
use traits::cross::Cross; use traits::cross::Cross;
use traits::division_ring::DivisionRing; use traits::division_ring::DivisionRing;
use traits::norm::Norm; use traits::norm::Norm;
use traits::sample::UniformSphereSample;
use vec::{Vec1, Vec2, Vec3}; use vec::{Vec1, Vec2, Vec3};
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N>
@ -36,7 +37,7 @@ impl<N: One> Basis for Vec1<N>
{ } { }
} }
impl<N: Copy + One + Zero + Neg<N>> Basis for Vec2<N> impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N>
{ {
#[inline] #[inline]
fn canonical_basis(f: &fn(Vec2<N>)) fn canonical_basis(f: &fn(Vec2<N>))
@ -47,10 +48,10 @@ impl<N: Copy + One + Zero + Neg<N>> Basis for Vec2<N>
#[inline] #[inline]
fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>)) fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>))
{ f(Vec2::new([-self.at[1], copy self.at[0]])) } { f(Vec2::new([-self.at[1], self.at[0].clone()])) }
} }
impl<N: Copy + DivisionRing + Ord + Algebraic> impl<N: Clone + Copy + DivisionRing + Ord + Algebraic>
Basis for Vec3<N> Basis for Vec3<N>
{ {
#[inline(always)] #[inline(always)]
@ -65,12 +66,46 @@ Basis for Vec3<N>
fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>)) fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>))
{ {
let a = let a =
if abs(copy self.at[0]) > abs(copy self.at[1]) if abs(self.at[0].clone()) > abs(self.at[1].clone())
{ Vec3::new([copy self.at[2], Zero::zero(), -copy self.at[0]]).normalized() } { Vec3::new([self.at[2].clone(), Zero::zero(), -self.at[0]]).normalized() }
else else
{ Vec3::new([Zero::zero(), -self.at[2], copy self.at[1]]).normalized() }; { Vec3::new([Zero::zero(), -self.at[2], self.at[1].clone()]).normalized() };
f(a.cross(self)); f(a.cross(self));
f(a); f(a);
} }
} }
// FIXME: this bad: this fixes definitly the number of samples…
static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
Vec2 { at: [1.0, 0.0] },
Vec2 { at: [0.95557281, 0.29475517] },
Vec2 { at: [0.82623877, 0.56332006] },
Vec2 { at: [0.6234898, 0.78183148] },
Vec2 { at: [0.36534102, 0.93087375] },
Vec2 { at: [0.07473009, 0.9972038] },
Vec2 { at: [-0.22252093, 0.97492791] },
Vec2 { at: [-0.5, 0.8660254] },
Vec2 { at: [-0.73305187, 0.68017274] },
Vec2 { at: [-0.90096887, 0.43388374] },
Vec2 { at: [-0.98883083, 0.14904227] },
Vec2 { at: [-0.98883083, -0.14904227] },
Vec2 { at: [-0.90096887, -0.43388374] },
Vec2 { at: [-0.73305187, -0.68017274] },
Vec2 { at: [-0.5, -0.8660254] },
Vec2 { at: [-0.22252093, -0.97492791] },
Vec2 { at: [0.07473009, -0.9972038] },
Vec2 { at: [0.36534102, -0.93087375] },
Vec2 { at: [0.6234898, -0.78183148] },
Vec2 { at: [0.82623877, -0.56332006] },
Vec2 { at: [0.95557281, -0.29475517] },
];
impl UniformSphereSample for Vec2<f64>
{
pub fn sample(f: &fn(&'static Vec2<f64>))
{
for SAMPLES_2_F64.iter().advance |sample|
{ f(sample) }
}
}