Remove dimensional HOFs

This commit is contained in:
Brendan Zabarauskas 2013-07-07 16:00:35 +10:00
parent c91b0747b3
commit 288afe0898
6 changed files with 998 additions and 404 deletions

View file

@ -43,150 +43,6 @@ macro_rules! impl_dimensional(
) )
) )
macro_rules! impl_dimensional_fns(
($Self:ident, $T:ty, 2) => (
impl<T> $Self<T> {
#[inline]
pub fn from_slice<'a>(slice: [$T,..2]) -> $Self<T> {
use std::cast::transmute;
unsafe { transmute(slice) }
}
#[inline(always)]
pub fn map<U>(&self, f: &fn(&$T) -> U) -> [U,..2] {
[f(self.index(0)),
f(self.index(1))]
}
#[inline(always)]
pub fn map_mut(&mut self, f: &fn(&mut $T)) {
f(self.index_mut(0));
f(self.index_mut(1));
}
#[inline(always)]
pub fn zip<U, SU: Dimensional<U,[U,..2]>, V>(&self, other: &SU, f: &fn(&$T, &U) -> V) -> [V,..2] {
[f(self.index(0), other.index(0)),
f(self.index(1), other.index(1))]
}
#[inline(always)]
pub fn zip_mut<U, SU: Dimensional<U,[U,..2]>>(&mut self, other: &SU, f: &fn(&mut $T, &U)) {
f(self.index_mut(0), other.index(0));
f(self.index_mut(1), other.index(1));
}
#[inline(always)]
pub fn foldl<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(0), &f(self.index(1), init))
}
#[inline(always)]
pub fn foldr<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(1), &f(self.index(0), init))
}
}
);
($Self:ident, $T:ty, 3) => (
impl<T> $Self<T> {
#[inline]
pub fn from_slice<'a>(slice: [$T,..3]) -> $Self<T> {
use std::cast::transmute;
unsafe { transmute(slice) }
}
#[inline(always)]
pub fn map<U>(&self, f: &fn(&$T) -> U) -> [U,..3] {
[f(self.index(0)),
f(self.index(1)),
f(self.index(2))]
}
#[inline(always)]
pub fn map_mut(&mut self, f: &fn(&mut $T)) {
f(self.index_mut(0));
f(self.index_mut(1));
f(self.index_mut(2));
}
#[inline(always)]
pub fn zip<U, SU: Dimensional<U,[U,..3]>, V>(&self, other: &SU, f: &fn(&$T, &U) -> V) -> [V,..3] {
[f(self.index(0), other.index(0)),
f(self.index(1), other.index(1)),
f(self.index(2), other.index(2))]
}
#[inline(always)]
pub fn zip_mut<U, SU: Dimensional<U,[U,..3]>>(&mut self, other: &SU, f: &fn(&mut $T, &U)) {
f(self.index_mut(0), other.index(0));
f(self.index_mut(1), other.index(1));
f(self.index_mut(2), other.index(2));
}
#[inline(always)]
pub fn foldl<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(0), &f(self.index(1), &f(self.index(2), init)))
}
#[inline(always)]
pub fn foldr<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(2), &f(self.index(1), &f(self.index(0), init)))
}
}
);
($Self:ident, $T:ty, 4) => (
impl<T> $Self<T> {
#[inline]
pub fn from_slice<'a>(slice: [$T,..4]) -> $Self<T> {
use std::cast::transmute;
unsafe { transmute(slice) }
}
#[inline(always)]
pub fn map<U>(&self, f: &fn(&$T) -> U) -> [U,..4] {
[f(self.index(0)),
f(self.index(1)),
f(self.index(2)),
f(self.index(3))]
}
#[inline(always)]
pub fn map_mut(&mut self, f: &fn(&mut $T)) {
f(self.index_mut(0));
f(self.index_mut(1));
f(self.index_mut(2));
f(self.index_mut(3));
}
#[inline(always)]
pub fn zip<U, SU: Dimensional<U,[U,..4]>, V>(&self, other: &SU, f: &fn(&$T, &U) -> V) -> [V,..4] {
[f(self.index(0), other.index(0)),
f(self.index(1), other.index(1)),
f(self.index(2), other.index(2)),
f(self.index(3), other.index(3))]
}
#[inline(always)]
pub fn zip_mut<U, SU: Dimensional<U,[U,..4]>>(&mut self, other: &SU, f: &fn(&mut $T, &U)) {
f(self.index_mut(0), other.index(0));
f(self.index_mut(1), other.index(1));
f(self.index_mut(2), other.index(2));
f(self.index_mut(3), other.index(3));
}
#[inline(always)]
pub fn foldl<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(0), &f(self.index(1), &f(self.index(2), &f(self.index(3), init))))
}
#[inline(always)]
pub fn foldr<U>(&self, init: &U, f: &fn(&$T, &U) -> U) -> U {
f(self.index(3), &f(self.index(2), &f(self.index(1), &f(self.index(0), init))))
}
}
)
)
macro_rules! impl_swap( macro_rules! impl_swap(
($Self:ident) => ( ($Self:ident) => (
impl<T:Clone> $Self<T> { impl<T:Clone> $Self<T> {
@ -201,7 +57,7 @@ macro_rules! impl_swap(
) )
macro_rules! impl_approx( macro_rules! impl_approx(
($Self:ident) => ( ($Self:ident, 2) => (
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $Self<T> { impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $Self<T> {
#[inline] #[inline]
pub fn approx_epsilon() -> T { pub fn approx_epsilon() -> T {
@ -215,8 +71,49 @@ macro_rules! impl_approx(
#[inline] #[inline]
pub fn approx_eq_eps(&self, other: &$Self<T>, epsilon: &T) -> bool { pub fn approx_eq_eps(&self, other: &$Self<T>, epsilon: &T) -> bool {
let tmp = self.zip(other, |a, b| a.approx_eq_eps(b, epsilon)); self.index(0).approx_eq_eps(other.index(0), epsilon) &&
tmp.iter().all(|&x| x) self.index(1).approx_eq_eps(other.index(1), epsilon)
}
}
);
($Self:ident, 3) => (
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $Self<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &$Self<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &$Self<T>, epsilon: &T) -> bool {
self.index(0).approx_eq_eps(other.index(0), epsilon) &&
self.index(1).approx_eq_eps(other.index(1), epsilon) &&
self.index(2).approx_eq_eps(other.index(2), epsilon)
}
}
);
($Self:ident, 4) => (
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for $Self<T> {
#[inline]
pub fn approx_epsilon() -> T {
ApproxEq::approx_epsilon::<T,T>()
}
#[inline]
pub fn approx_eq(&self, other: &$Self<T>) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
}
#[inline]
pub fn approx_eq_eps(&self, other: &$Self<T>, epsilon: &T) -> bool {
self.index(0).approx_eq_eps(other.index(0), epsilon) &&
self.index(1).approx_eq_eps(other.index(1), epsilon) &&
self.index(2).approx_eq_eps(other.index(2), epsilon) &&
self.index(3).approx_eq_eps(other.index(3), epsilon)
} }
} }
) )

View file

@ -47,14 +47,9 @@ macro_rules! impl_mat(
) )
) )
macro_rules! impl_mat_clonable( macro_rules! impl_mat_swap(
($Mat:ident, $Vec:ident) => ( ($Mat:ident, $Vec:ident) => (
impl<T:Clone> $Mat<T> { impl<T:Clone> $Mat<T> {
#[inline]
pub fn row(&self, i: uint) -> $Vec<T> {
$Vec::from_slice(self.map(|c| c.index(i).clone()))
}
#[inline] #[inline]
pub fn swap_cols(&mut self, a: uint, b: uint) { pub fn swap_cols(&mut self, a: uint, b: uint) {
let tmp = self.col(a).clone(); let tmp = self.col(a).clone();
@ -62,11 +57,6 @@ macro_rules! impl_mat_clonable(
*self.col_mut(b) = tmp; *self.col_mut(b) = tmp;
} }
#[inline]
pub fn swap_rows(&mut self, a: uint, b: uint) {
self.map_mut(|x| x.swap(a, b))
}
#[inline] #[inline]
pub fn swap_elem(&mut self, (col_a, row_a): (uint, uint), (col_b, row_b): (uint, uint)) { pub fn swap_elem(&mut self, (col_a, row_a): (uint, uint), (col_b, row_b): (uint, uint)) {
let tmp = self.elem(col_a, row_a).clone(); let tmp = self.elem(col_a, row_a).clone();
@ -136,11 +126,10 @@ pub type Mat2f32 = Mat2<f32>;
pub type Mat2f64 = Mat2<f64>; pub type Mat2f64 = Mat2<f64>;
impl_dimensional!(Mat2, Vec2<T>, 2) impl_dimensional!(Mat2, Vec2<T>, 2)
impl_dimensional_fns!(Mat2, Vec2<T>, 2) impl_approx!(Mat2, 2)
impl_approx!(Mat2)
impl_mat!(Mat2, Vec2) impl_mat!(Mat2, Vec2)
impl_mat_clonable!(Mat2, Vec2) impl_mat_swap!(Mat2, Vec2)
pub trait ToMat2<T> { pub trait ToMat2<T> {
pub fn to_mat2(&self) -> Mat2<T>; pub fn to_mat2(&self) -> Mat2<T>;
@ -161,6 +150,20 @@ impl<T> Mat2<T> {
} }
} }
impl<T:Clone> Mat2<T> {
#[inline]
pub fn row(&self, i: uint) -> Vec2<T> {
Vec2::new(self.col(0).index(i).clone(),
self.col(1).index(i).clone())
}
#[inline]
pub fn swap_rows(&mut self, a: uint, b: uint) {
self.col_mut(0).swap(a, b);
self.col_mut(1).swap(a, b);
}
}
impl<T:Clone + Num> ToMat3<T> for Mat2<T> { impl<T:Clone + Num> ToMat3<T> for Mat2<T> {
#[inline] #[inline]
pub fn to_mat3(&self) -> Mat3<T> { pub fn to_mat3(&self) -> Mat3<T> {
@ -195,7 +198,8 @@ impl<T:Clone + Num> Mat2<T> {
#[inline] #[inline]
pub fn mul_t(&self, value: T) -> Mat2<T> { pub fn mul_t(&self, value: T) -> Mat2<T> {
Mat2::from_slice(self.map(|&c| c.mul_t(value.clone()))) Mat2::from_cols(self.col(0).mul_t(value.clone()),
self.col(1).mul_t(value.clone()))
} }
#[inline] #[inline]
@ -204,6 +208,18 @@ impl<T:Clone + Num> Mat2<T> {
self.row(1).dot(vec)) self.row(1).dot(vec))
} }
#[inline]
pub fn add_m(&self, other: &Mat2<T>) -> Mat2<T> {
Mat2::from_cols(self.col(0).add_v(other.col(0)),
self.col(1).add_v(other.col(1)))
}
#[inline]
pub fn sub_m(&self, other: &Mat2<T>) -> Mat2<T> {
Mat2::from_cols(self.col(0).sub_v(other.col(0)),
self.col(1).sub_v(other.col(1)))
}
#[inline] #[inline]
pub fn mul_m(&self, other: &Mat2<T>) -> Mat2<T> { pub fn mul_m(&self, other: &Mat2<T>) -> Mat2<T> {
Mat2::new(self.row(0).dot(other.col(0)), Mat2::new(self.row(0).dot(other.col(0)),
@ -213,29 +229,22 @@ impl<T:Clone + Num> Mat2<T> {
self.row(1).dot(other.col(1))) self.row(1).dot(other.col(1)))
} }
#[inline]
pub fn add_m(&self, other: &Mat2<T>) -> Mat2<T> {
Mat2::from_slice(self.zip(other, |a, b| a.add_v(b)))
}
#[inline]
pub fn sub_m(&self, other: &Mat2<T>) -> Mat2<T> {
Mat2::from_slice(self.zip(other, |a, b| a.sub_v(b)))
}
#[inline] #[inline]
pub fn mul_self_t(&mut self, value: T) { pub fn mul_self_t(&mut self, value: T) {
self.map_mut(|x| x.mul_self_t(value.clone())) self.col_mut(0).mul_self_t(value.clone());
self.col_mut(1).mul_self_t(value.clone());
} }
#[inline] #[inline]
pub fn add_self_m(&mut self, other: &Mat2<T>) { pub fn add_self_m(&mut self, other: &Mat2<T>) {
self.zip_mut(other, |a, b| a.add_self_v(b)) self.col_mut(0).add_self_v(other.col(0));
self.col_mut(1).add_self_v(other.col(1));
} }
#[inline] #[inline]
pub fn sub_self_m(&mut self, other: &Mat2<T>) { pub fn sub_self_m(&mut self, other: &Mat2<T>) {
self.zip_mut(other, |a, b| a.sub_self_v(b)) self.col_mut(0).sub_self_v(other.col(0));
self.col_mut(1).sub_self_v(other.col(1));
} }
pub fn dot(&self, other: &Mat2<T>) -> T { pub fn dot(&self, other: &Mat2<T>) -> T {
@ -264,7 +273,8 @@ impl<T:Clone + Num> Mat2<T> {
impl<T:Clone + Num> Neg<Mat2<T>> for Mat2<T> { impl<T:Clone + Num> Neg<Mat2<T>> for Mat2<T> {
#[inline] #[inline]
pub fn neg(&self) -> Mat2<T> { pub fn neg(&self) -> Mat2<T> {
Mat2::from_slice(self.map(|&x| -x)) Mat2::from_cols(-*self.col(0),
-*self.col(1))
} }
} }
@ -529,11 +539,10 @@ pub type Mat3f32 = Mat3<f32>;
pub type Mat3f64 = Mat3<f64>; pub type Mat3f64 = Mat3<f64>;
impl_dimensional!(Mat3, Vec3<T>, 3) impl_dimensional!(Mat3, Vec3<T>, 3)
impl_dimensional_fns!(Mat3, Vec3<T>, 3) impl_approx!(Mat3, 3)
impl_approx!(Mat3)
impl_mat!(Mat3, Vec3) impl_mat!(Mat3, Vec3)
impl_mat_clonable!(Mat3, Vec3) impl_mat_swap!(Mat3, Vec3)
pub trait ToMat3<T> { pub trait ToMat3<T> {
pub fn to_mat3(&self) -> Mat3<T>; pub fn to_mat3(&self) -> Mat3<T>;
@ -557,6 +566,22 @@ impl<T> Mat3<T> {
} }
} }
impl<T:Clone> Mat3<T> {
#[inline]
pub fn row(&self, i: uint) -> Vec3<T> {
Vec3::new(self.col(0).index(i).clone(),
self.col(1).index(i).clone(),
self.col(2).index(i).clone())
}
#[inline]
pub fn swap_rows(&mut self, a: uint, b: uint) {
self.col_mut(0).swap(a, b);
self.col_mut(1).swap(a, b);
self.col_mut(2).swap(a, b);
}
}
impl<T:Clone + Num> ToMat4<T> for Mat3<T> { impl<T:Clone + Num> ToMat4<T> for Mat3<T> {
#[inline] #[inline]
pub fn to_mat4(&self) -> Mat4<T> { pub fn to_mat4(&self) -> Mat4<T> {
@ -583,7 +608,9 @@ impl<T:Clone + Num> Mat3<T> {
#[inline] #[inline]
pub fn mul_t(&self, value: T) -> Mat3<T> { pub fn mul_t(&self, value: T) -> Mat3<T> {
Mat3::from_slice(self.map(|&c| c.mul_t(value.clone()))) Mat3::from_cols(self.col(0).mul_t(value.clone()),
self.col(1).mul_t(value.clone()),
self.col(2).mul_t(value.clone()))
} }
#[inline] #[inline]
@ -593,6 +620,20 @@ impl<T:Clone + Num> Mat3<T> {
self.row(2).dot(vec)) self.row(2).dot(vec))
} }
#[inline]
pub fn add_m(&self, other: &Mat3<T>) -> Mat3<T> {
Mat3::from_cols(self.col(0).add_v(other.col(0)),
self.col(1).add_v(other.col(1)),
self.col(2).add_v(other.col(2)))
}
#[inline]
pub fn sub_m(&self, other: &Mat3<T>) -> Mat3<T> {
Mat3::from_cols(self.col(0).sub_v(other.col(0)),
self.col(1).sub_v(other.col(1)),
self.col(2).sub_v(other.col(2)))
}
#[inline] #[inline]
pub fn mul_m(&self, other: &Mat3<T>) -> Mat3<T> { pub fn mul_m(&self, other: &Mat3<T>) -> Mat3<T> {
Mat3::new(self.row(0).dot(other.col(0)), Mat3::new(self.row(0).dot(other.col(0)),
@ -608,29 +649,25 @@ impl<T:Clone + Num> Mat3<T> {
self.row(2).dot(other.col(2))) self.row(2).dot(other.col(2)))
} }
#[inline]
pub fn add_m(&self, other: &Mat3<T>) -> Mat3<T> {
Mat3::from_slice(self.zip(other, |a, b| a.add_v(b)))
}
#[inline]
pub fn sub_m(&self, other: &Mat3<T>) -> Mat3<T> {
Mat3::from_slice(self.zip(other, |a, b| a.sub_v(b)))
}
#[inline] #[inline]
pub fn mul_self_t(&mut self, value: T) { pub fn mul_self_t(&mut self, value: T) {
self.map_mut(|x| x.mul_self_t(value.clone())) self.col_mut(0).mul_self_t(value.clone());
self.col_mut(1).mul_self_t(value.clone());
self.col_mut(2).mul_self_t(value.clone());
} }
#[inline] #[inline]
pub fn add_self_m(&mut self, other: &Mat3<T>) { pub fn add_self_m(&mut self, other: &Mat3<T>) {
self.zip_mut(other, |a, b| a.add_self_v(b)) self.col_mut(0).add_self_v(other.col(0));
self.col_mut(1).add_self_v(other.col(1));
self.col_mut(2).add_self_v(other.col(2));
} }
#[inline] #[inline]
pub fn sub_self_m(&mut self, other: &Mat3<T>) { pub fn sub_self_m(&mut self, other: &Mat3<T>) {
self.zip_mut(other, |a, b| a.sub_self_v(b)) self.col_mut(0).sub_self_v(other.col(0));
self.col_mut(1).sub_self_v(other.col(1));
self.col_mut(2).sub_self_v(other.col(2));
} }
pub fn dot(&self, other: &Mat3<T>) -> T { pub fn dot(&self, other: &Mat3<T>) -> T {
@ -661,7 +698,9 @@ impl<T:Clone + Num> Mat3<T> {
impl<T:Clone + Num> Neg<Mat3<T>> for Mat3<T> { impl<T:Clone + Num> Neg<Mat3<T>> for Mat3<T> {
#[inline] #[inline]
pub fn neg(&self) -> Mat3<T> { pub fn neg(&self) -> Mat3<T> {
Mat3::from_slice(self.map(|&x| -x)) Mat3::from_cols(-*self.col(0),
-*self.col(1),
-*self.col(2))
} }
} }
@ -1089,11 +1128,10 @@ pub type Mat4f32 = Mat4<f32>;
pub type Mat4f64 = Mat4<f64>; pub type Mat4f64 = Mat4<f64>;
impl_dimensional!(Mat4, Vec4<T>, 4) impl_dimensional!(Mat4, Vec4<T>, 4)
impl_dimensional_fns!(Mat4, Vec4<T>, 4) impl_approx!(Mat4, 4)
impl_approx!(Mat4)
impl_mat!(Mat4, Vec4) impl_mat!(Mat4, Vec4)
impl_mat_clonable!(Mat4, Vec4) impl_mat_swap!(Mat4, Vec4)
pub trait ToMat4<T> { pub trait ToMat4<T> {
pub fn to_mat4(&self) -> Mat4<T>; pub fn to_mat4(&self) -> Mat4<T>;
@ -1120,6 +1158,24 @@ impl<T> Mat4<T> {
} }
} }
impl<T:Clone> Mat4<T> {
#[inline]
pub fn row(&self, i: uint) -> Vec4<T> {
Vec4::new(self.col(0).index(i).clone(),
self.col(1).index(i).clone(),
self.col(2).index(i).clone(),
self.col(3).index(i).clone())
}
#[inline]
pub fn swap_rows(&mut self, a: uint, b: uint) {
self.col_mut(0).swap(a, b);
self.col_mut(1).swap(a, b);
self.col_mut(2).swap(a, b);
self.col_mut(3).swap(a, b);
}
}
impl<T:Clone + Num> Mat4<T> { impl<T:Clone + Num> Mat4<T> {
#[inline] #[inline]
pub fn from_value(value: T) -> Mat4<T> { pub fn from_value(value: T) -> Mat4<T> {
@ -1137,7 +1193,10 @@ impl<T:Clone + Num> Mat4<T> {
#[inline] #[inline]
pub fn mul_t(&self, value: T) -> Mat4<T> { pub fn mul_t(&self, value: T) -> Mat4<T> {
Mat4::from_slice(self.map(|&c| c.mul_t(value.clone()))) Mat4::from_cols(self.col(0).mul_t(value.clone()),
self.col(1).mul_t(value.clone()),
self.col(2).mul_t(value.clone()),
self.col(3).mul_t(value.clone()))
} }
#[inline] #[inline]
@ -1148,6 +1207,22 @@ impl<T:Clone + Num> Mat4<T> {
self.row(3).dot(vec)) self.row(3).dot(vec))
} }
#[inline]
pub fn add_m(&self, other: &Mat4<T>) -> Mat4<T> {
Mat4::from_cols(self.col(0).add_v(other.col(0)),
self.col(1).add_v(other.col(1)),
self.col(2).add_v(other.col(2)),
self.col(3).add_v(other.col(3)))
}
#[inline]
pub fn sub_m(&self, other: &Mat4<T>) -> Mat4<T> {
Mat4::from_cols(self.col(0).sub_v(other.col(0)),
self.col(1).sub_v(other.col(1)),
self.col(2).sub_v(other.col(2)),
self.col(3).sub_v(other.col(3)))
}
#[inline] #[inline]
pub fn mul_m(&self, other: &Mat4<T>) -> Mat4<T> { pub fn mul_m(&self, other: &Mat4<T>) -> Mat4<T> {
Mat4::new(self.row(0).dot(other.col(0)), Mat4::new(self.row(0).dot(other.col(0)),
@ -1171,29 +1246,28 @@ impl<T:Clone + Num> Mat4<T> {
self.row(3).dot(other.col(3))) self.row(3).dot(other.col(3)))
} }
#[inline]
pub fn add_m(&self, other: &Mat4<T>) -> Mat4<T> {
Mat4::from_slice(self.zip(other, |a, b| a.add_v(b)))
}
#[inline]
pub fn sub_m(&self, other: &Mat4<T>) -> Mat4<T> {
Mat4::from_slice(self.zip(other, |a, b| a.sub_v(b)))
}
#[inline] #[inline]
pub fn mul_self_t(&mut self, value: T) { pub fn mul_self_t(&mut self, value: T) {
self.map_mut(|x| x.mul_self_t(value.clone())) self.col_mut(0).mul_self_t(value.clone());
self.col_mut(1).mul_self_t(value.clone());
self.col_mut(2).mul_self_t(value.clone());
self.col_mut(3).mul_self_t(value.clone());
} }
#[inline] #[inline]
pub fn add_self_m(&mut self, other: &Mat4<T>) { pub fn add_self_m(&mut self, other: &Mat4<T>) {
self.zip_mut(other, |a, b| a.add_self_v(b)) self.col_mut(0).add_self_v(other.col(0));
self.col_mut(1).add_self_v(other.col(1));
self.col_mut(2).add_self_v(other.col(2));
self.col_mut(3).add_self_v(other.col(3));
} }
#[inline] #[inline]
pub fn sub_self_m(&mut self, other: &Mat4<T>) { pub fn sub_self_m(&mut self, other: &Mat4<T>) {
self.zip_mut(other, |a, b| a.sub_self_v(b)) self.col_mut(0).sub_self_v(other.col(0));
self.col_mut(1).sub_self_v(other.col(1));
self.col_mut(2).sub_self_v(other.col(2));
self.col_mut(3).sub_self_v(other.col(3));
} }
pub fn dot(&self, other: &Mat4<T>) -> T { pub fn dot(&self, other: &Mat4<T>) -> T {
@ -1238,7 +1312,10 @@ impl<T:Clone + Num> Mat4<T> {
impl<T:Clone + Num> Neg<Mat4<T>> for Mat4<T> { impl<T:Clone + Num> Neg<Mat4<T>> for Mat4<T> {
#[inline] #[inline]
pub fn neg(&self) -> Mat4<T> { pub fn neg(&self) -> Mat4<T> {
Mat4::from_slice(self.map(|&x| -x)) Mat4::from_cols(-*self.col(0),
-*self.col(1),
-*self.col(2),
-*self.col(3))
} }
} }

View file

@ -38,9 +38,8 @@ pub struct Plane<T> {
} }
impl_dimensional!(Plane, T, 4) impl_dimensional!(Plane, T, 4)
impl_dimensional_fns!(Plane, T, 4) impl_approx!(Plane, 4)
impl_swap!(Plane) impl_swap!(Plane)
impl_approx!(Plane)
impl<T:Clone + Real> Plane<T> { impl<T:Clone + Real> Plane<T> {
/// # Arguments /// # Arguments

View file

@ -29,8 +29,7 @@ pub trait Point<T,V>: Eq + ApproxEq<T> + ToStr {
pub struct Point2<T>(Vec2<T>); pub struct Point2<T>(Vec2<T>);
impl_dimensional!(Point2, T, 2) impl_dimensional!(Point2, T, 2)
impl_dimensional_fns!(Point2, T, 2) impl_approx!(Point2, 2)
impl_approx!(Point2)
impl<T> Point2<T> { impl<T> Point2<T> {
pub fn new(x: T, y: T) -> Point2<T> { pub fn new(x: T, y: T) -> Point2<T> {
@ -59,8 +58,7 @@ impl<T> ToStr for Point2<T> {
pub struct Point3<T>(Vec3<T>); pub struct Point3<T>(Vec3<T>);
impl_dimensional!(Point3, T, 3) impl_dimensional!(Point3, T, 3)
impl_dimensional_fns!(Point3, T, 3) impl_approx!(Point3, 3)
impl_approx!(Point3)
impl<T> Point3<T> { impl<T> Point3<T> {
pub fn new(x: T, y: T, z: T) -> Point3<T> { pub fn new(x: T, y: T, z: T) -> Point3<T> {

View file

@ -37,9 +37,8 @@ pub type Quatf64 = Quat<f64>;
pub struct Quat<T> { s: T, v: Vec3<T> } pub struct Quat<T> { s: T, v: Vec3<T> }
impl_dimensional!(Quat, T, 4) impl_dimensional!(Quat, T, 4)
impl_dimensional_fns!(Quat, T, 4) impl_approx!(Quat, 4)
impl_swap!(Quat) impl_swap!(Quat)
impl_approx!(Quat)
pub trait ToQuat<T> { pub trait ToQuat<T> {
pub fn to_quat(&self) -> Quat<T>; pub fn to_quat(&self) -> Quat<T>;
@ -124,13 +123,13 @@ impl<T:Clone + Real> Quat<T> {
/// The result of multiplying the quaternion a scalar /// The result of multiplying the quaternion a scalar
#[inline] #[inline]
pub fn mul_t(&self, value: T) -> Quat<T> { pub fn mul_t(&self, value: T) -> Quat<T> {
Quat::from_slice(self.map(|&x| x * value)) Quat::from_sv(self.s * value, self.v.mul_t(value))
} }
/// The result of dividing the quaternion a scalar /// The result of dividing the quaternion a scalar
#[inline] #[inline]
pub fn div_t(&self, value: T) -> Quat<T> { pub fn div_t(&self, value: T) -> Quat<T> {
Quat::from_slice(self.map(|&x| x / value)) Quat::from_sv(self.s / value, self.v.div_t(value))
} }
/// The result of multiplying the quaternion by a vector /// The result of multiplying the quaternion by a vector
@ -250,7 +249,7 @@ impl<T:Clone + Num> ToMat3<T> for Quat<T> {
impl<T:Clone + Float> Neg<Quat<T>> for Quat<T> { impl<T:Clone + Float> Neg<Quat<T>> for Quat<T> {
#[inline] #[inline]
pub fn neg(&self) -> Quat<T> { pub fn neg(&self) -> Quat<T> {
Quat::from_slice(self.map(|&x| -x)) Quat::from_sv(-self.s, -self.v)
} }
} }
@ -316,42 +315,21 @@ mod tests {
use vec::*; use vec::*;
#[test] #[test]
fn test_quat() { fn test_from_angle_axis() {
let a = Quat { s: 1.0, v: Vec3 { x: 2.0, y: 3.0, z: 4.0 } }; let v = Vec3::new(1f, 0f, 0f);
assert_eq!(a, Quat::from_sv::<float>(1.0, Vec3::new::<float>(2.0, 3.0, 4.0))); let q = Quat::from_angle_axis((-45f).to_radians(), &Vec3::new(0f, 0f, -1f));
assert_eq!(a, Quat::new::<float>(1.0, 2.0, 3.0, 4.0));
assert_eq!(Quat::zero::<float>(), Quat::new::<float>(0.0, 0.0, 0.0, 0.0));
assert_eq!(Quat::identity::<float>(), Quat::new::<float>(1.0, 0.0, 0.0, 0.0));
assert_eq!(a.s, 1.0);
assert_eq!(a.v.x, 2.0);
assert_eq!(a.v.y, 3.0);
assert_eq!(a.v.z, 4.0);
assert_eq!(*a.index(0), 1.0);
assert_eq!(*a.index(1), 2.0);
assert_eq!(*a.index(2), 3.0);
assert_eq!(*a.index(3), 4.0);
// TODO
}
#[test]
fn test_quat_2() {
let v = Vec3::new(1f32, 0f32, 0f32);
let q = Quat::from_angle_axis((-45f32).to_radians(), &Vec3::new(0f32, 0f32, -1f32));
// http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees // http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees
assert_approx_eq!(q.mul_v(&v), Vec3::new(1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32)); assert_approx_eq!(q.mul_v(&v), Vec3::new(1f/2f.sqrt(), 1f/2f.sqrt(), 0f));
assert_eq!(q.mul_v(&v).length(), v.length()); assert_eq!(q.mul_v(&v).length(), v.length());
assert_approx_eq!(q.to_mat3(), Mat3::new( 1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32, assert_approx_eq!(q.to_mat3(), Mat3::new( 1f/2f.sqrt(), 1f/2f.sqrt(), 0f,
-1f32/2f32.sqrt(), 1f32/2f32.sqrt(), 0f32, -1f/2f.sqrt(), 1f/2f.sqrt(), 0f,
0f32, 0f32, 1f32)); 0f, 0f, 1f));
} }
#[test] #[test]
fn test_quat_approx_eq() { fn test_approx_eq() {
assert!(!Quat::new::<float>(0.000001, 0.000001, 0.000001, 0.000001) assert!(!Quat::new::<float>(0.000001, 0.000001, 0.000001, 0.000001)
.approx_eq(&Quat::new::<float>(0.0, 0.0, 0.0, 0.0))); .approx_eq(&Quat::new::<float>(0.0, 0.0, 0.0, 0.0)));
assert!(Quat::new::<float>(0.0000001, 0.0000001, 0.0000001, 0.0000001) assert!(Quat::new::<float>(0.0000001, 0.0000001, 0.0000001, 0.0000001)

File diff suppressed because it is too large Load diff