Remove algebraic traits to simplify library
Pragmatically, according to advice from zeuxcg, I have decided to remove the algebraic traits. This has simplified the library a great deal by reducing indirection and removing redundant code.cx
This commit is contained in:
parent
c404092879
commit
68bd70f78f
23 changed files with 374 additions and 1028 deletions
|
@ -17,7 +17,12 @@
|
|||
|
||||
use std::vec::{VecIterator, VecMutIterator};
|
||||
|
||||
pub trait Array<T, Slice> {
|
||||
pub trait Array
|
||||
<
|
||||
T: Clone,
|
||||
Slice
|
||||
>
|
||||
{
|
||||
fn i<'a>(&'a self, i: uint) -> &'a T;
|
||||
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T;
|
||||
fn as_slice<'a>(&'a self) -> &'a Slice;
|
||||
|
@ -27,21 +32,29 @@ pub trait Array<T, Slice> {
|
|||
fn iter<'a>(&'a self) -> VecIterator<'a, T>;
|
||||
fn mut_iter<'a>(&'a mut self) -> VecMutIterator<'a, T>;
|
||||
|
||||
/// Swap two elements of the type in place.
|
||||
#[inline]
|
||||
fn map<U, SliceU, UU: Array<U, SliceU>>(&self, f: &fn(&T) -> U) -> UU {
|
||||
fn swap(&mut self, a: uint, b: uint) {
|
||||
let tmp = self.i(a).clone();
|
||||
*self.mut_i(a) = self.i(b).clone();
|
||||
*self.mut_i(b) = tmp;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn map<U: Clone, SliceU, UU: Array<U, SliceU>>(&self, f: &fn(&T) -> U) -> UU {
|
||||
Array::build(|i| f(self.i(i)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bimap<U, SliceU, UU: Array<U, SliceU>,
|
||||
V, SliceV, VV: Array<V, SliceV>>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV {
|
||||
fn bimap<U: Clone, SliceU, UU: Array<U, SliceU>,
|
||||
V: Clone, SliceV, VV: Array<V, SliceV>>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV {
|
||||
Array::build(|i| f(self.i(i), other.i(i)))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array(
|
||||
(impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr]) => (
|
||||
impl<$S> Array<$T, [$T,..$n]> for $Self {
|
||||
impl<$S: Clone> Array<$T, [$T,..$n]> for $Self {
|
||||
#[inline]
|
||||
fn i<'a>(&'a self, i: uint) -> &'a $T {
|
||||
&'a self.as_slice()[i]
|
||||
|
@ -114,14 +127,3 @@ macro_rules! array_op(
|
|||
(impl<$S:ident> $Self:ty / $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Div, div) for ($Self, $Other) -> $Result));
|
||||
(impl<$S:ident> $Self:ty % $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Rem, rem) for ($Self, $Other) -> $Result));
|
||||
)
|
||||
|
||||
/// An `Array` whose elements can be cloned
|
||||
pub trait ClonableArray<T: Clone, Slice>: Array<T, Slice> {
|
||||
/// Swap two elements of the type in place.
|
||||
#[inline]
|
||||
fn swap(&mut self, a: uint, b: uint) {
|
||||
let tmp = self.i(a).clone();
|
||||
*self.mut_i(a) = self.i(b).clone();
|
||||
*self.mut_i(b) = tmp;
|
||||
}
|
||||
}
|
|
@ -22,5 +22,8 @@
|
|||
#[license = "ASL2"];
|
||||
#[crate_type = "lib"];
|
||||
|
||||
pub mod traits;
|
||||
pub mod types;
|
||||
pub mod array;
|
||||
pub mod matrix;
|
||||
pub mod point;
|
||||
pub mod quaternion;
|
||||
pub mod vector;
|
||||
|
|
|
@ -13,18 +13,18 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::{One, one, zero};
|
||||
use std::num::{one, zero};
|
||||
|
||||
use traits::alg::*;
|
||||
use types::vector::*;
|
||||
use array::*;
|
||||
use vector::*;
|
||||
|
||||
#[deriving(Clone, Eq, Zero)] pub struct Mat2<S> { x: Vec2<S>, y: Vec2<S> }
|
||||
#[deriving(Clone, Eq, Zero)] pub struct Mat3<S> { x: Vec3<S>, y: Vec3<S>, z: Vec3<S> }
|
||||
#[deriving(Clone, Eq, Zero)] pub struct Mat4<S> { x: Vec4<S>, y: Vec4<S>, z: Vec4<S>, w: Vec4<S> }
|
||||
#[deriving(Clone, Eq)] pub struct Mat2<S> { x: Vec2<S>, y: Vec2<S> }
|
||||
#[deriving(Clone, Eq)] pub struct Mat3<S> { x: Vec3<S>, y: Vec3<S>, z: Vec3<S> }
|
||||
#[deriving(Clone, Eq)] pub struct Mat4<S> { x: Vec4<S>, y: Vec4<S>, z: Vec4<S>, w: Vec4<S> }
|
||||
|
||||
// Constructors
|
||||
|
||||
impl<S: Clone + Field> Mat2<S> {
|
||||
impl<S: Clone + Num> Mat2<S> {
|
||||
#[inline]
|
||||
pub fn new(c0r0: S, c0r1: S,
|
||||
c1r0: S, c1r1: S) -> Mat2<S> {
|
||||
|
@ -54,7 +54,7 @@ impl<S: Clone + Field> Mat2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field> Mat3<S> {
|
||||
impl<S: Clone + Num> Mat3<S> {
|
||||
#[inline]
|
||||
pub fn new(c0r0:S, c0r1:S, c0r2:S,
|
||||
c1r0:S, c1r1:S, c1r2:S,
|
||||
|
@ -87,7 +87,7 @@ impl<S: Clone + Field> Mat3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field> Mat4<S> {
|
||||
impl<S: Clone + Num> Mat4<S> {
|
||||
#[inline]
|
||||
pub fn new(c0r0: S, c0r1: S, c0r2: S, c0r3: S,
|
||||
c1r0: S, c1r1: S, c1r2: S, c1r3: S,
|
||||
|
@ -129,62 +129,80 @@ array!(impl<S> Mat2<S> -> [Vec2<S>, ..2])
|
|||
array!(impl<S> Mat3<S> -> [Vec3<S>, ..3])
|
||||
array!(impl<S> Mat4<S> -> [Vec4<S>, ..4])
|
||||
|
||||
impl<S: Clone + Field> ClonableArray<Vec2<S>, [Vec2<S>, ..2]> for Mat2<S>;
|
||||
impl<S: Clone + Field> ClonableArray<Vec3<S>, [Vec3<S>, ..3]> for Mat3<S>;
|
||||
impl<S: Clone + Field> ClonableArray<Vec4<S>, [Vec4<S>, ..4]> for Mat4<S>;
|
||||
|
||||
scalar_op!(impl Mat2<S> * S -> Mat2<S>)
|
||||
scalar_op!(impl Mat3<S> * S -> Mat3<S>)
|
||||
scalar_op!(impl Mat4<S> * S -> Mat4<S>)
|
||||
scalar_op!(impl Mat2<S> / S -> Mat2<S>)
|
||||
scalar_op!(impl Mat3<S> / S -> Mat3<S>)
|
||||
scalar_op!(impl Mat4<S> / S -> Mat4<S>)
|
||||
scalar_op!(impl Mat2<S> % S -> Mat2<S>)
|
||||
scalar_op!(impl Mat3<S> % S -> Mat3<S>)
|
||||
scalar_op!(impl Mat4<S> % S -> Mat4<S>)
|
||||
|
||||
impl<S: Field> ScalarMul<S> for Mat2<S>;
|
||||
impl<S: Field> ScalarMul<S> for Mat3<S>;
|
||||
impl<S: Field> ScalarMul<S> for Mat4<S>;
|
||||
|
||||
array_op!(impl<S> Mat2<S> + Mat2<S> -> Mat2<S>)
|
||||
array_op!(impl<S> Mat3<S> + Mat3<S> -> Mat3<S>)
|
||||
array_op!(impl<S> Mat4<S> + Mat4<S> -> Mat4<S>)
|
||||
array_op!(impl<S> Mat2<S> - Mat2<S> -> Mat2<S>)
|
||||
array_op!(impl<S> Mat3<S> - Mat3<S> -> Mat3<S>)
|
||||
array_op!(impl<S> Mat4<S> - Mat4<S> -> Mat4<S>)
|
||||
array_op!(impl<S> -Mat2<S> -> Mat2<S>)
|
||||
array_op!(impl<S> -Mat3<S> -> Mat3<S>)
|
||||
array_op!(impl<S> -Mat4<S> -> Mat4<S>)
|
||||
|
||||
impl<S: Field> Module<S> for Mat2<S>;
|
||||
impl<S: Field> Module<S> for Mat3<S>;
|
||||
impl<S: Field> Module<S> for Mat4<S>;
|
||||
|
||||
impl<S: Clone + Field> One for Mat2<S> {
|
||||
#[inline] fn one() -> Mat2<S> { Mat2::ident() }
|
||||
}
|
||||
|
||||
impl<S: Clone + Field> One for Mat3<S> {
|
||||
#[inline] fn one() -> Mat3<S> { Mat3::ident() }
|
||||
}
|
||||
|
||||
impl<S: Clone + Field> One for Mat4<S> {
|
||||
#[inline] fn one() -> Mat4<S> { Mat4::ident() }
|
||||
}
|
||||
|
||||
impl<S: Clone + Field> Ring<S> for Mat2<S>;
|
||||
impl<S: Clone + Field> Ring<S> for Mat3<S>;
|
||||
impl<S: Clone + Field> Ring<S> for Mat4<S>;
|
||||
|
||||
impl<S: Clone + Field + ApproxEq<S>>
|
||||
Matrix
|
||||
pub trait Matrix
|
||||
<
|
||||
S,
|
||||
Vec2<S>, [S, ..2], [Vec2<S>, ..2],
|
||||
Vec2<S>, [S, ..2], [Vec2<S>, ..2],
|
||||
Mat2<S>
|
||||
S: Num + Clone + ApproxEq<S>, Slice,
|
||||
V: Clone + Vector<S, VSlice> + Array<S, VSlice>, VSlice
|
||||
>
|
||||
: Array<V, Slice>
|
||||
{
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a V { self.i(c) }
|
||||
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut V { self.mut_i(c) }
|
||||
|
||||
#[inline]
|
||||
fn swap_c(&mut self, a: uint, b: uint) {
|
||||
let tmp = self.c(a).clone();
|
||||
*self.mut_c(a) = self.c(b).clone();
|
||||
*self.mut_c(b) = tmp;
|
||||
}
|
||||
|
||||
fn r(&self, r: uint) -> V;
|
||||
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
for c in self.mut_iter() { c.swap(a, b) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cr<'a>(&'a self, c: uint, r: uint) -> &'a S { self.i(c).i(r) }
|
||||
|
||||
#[inline]
|
||||
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut S {
|
||||
self.mut_i(c).mut_i(r)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
|
||||
let (ca, ra) = a;
|
||||
let (cb, rb) = b;
|
||||
let tmp = self.cr(ca, ra).clone();
|
||||
*self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
|
||||
*self.mut_cr(cb, rb) = tmp;
|
||||
}
|
||||
|
||||
// fn swap_cr(&mut self, (ca, ra): (uint, uint), (cb, rb): (uint, uint)) {
|
||||
// let tmp = self.cr(ca, ra).clone();
|
||||
// *self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
|
||||
// *self.mut_cr(cb, rb) = tmp;
|
||||
// }
|
||||
|
||||
fn transpose(&self) -> Self;
|
||||
fn transpose_self(&mut self);
|
||||
fn trace(&self) -> S;
|
||||
fn determinant(&self) -> S;
|
||||
fn invert(&self) -> Option<Self>;
|
||||
|
||||
#[inline]
|
||||
fn invert_self(&mut self) {
|
||||
*self = self.invert().expect("Attempted to invert a matrix with zero determinant.");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_invertible(&self) -> bool {
|
||||
!self.determinant().approx_eq(&zero::<S>())
|
||||
}
|
||||
|
||||
// pub fn is_identity(&self) -> bool;
|
||||
// pub fn is_diagonal(&self) -> bool;
|
||||
// pub fn is_rotated(&self) -> bool;
|
||||
// pub fn is_symmetric(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<S: Clone + Num + ApproxEq<S>>
|
||||
Matrix<S, [Vec2<S>, ..2], Vec2<S>, [S, ..2]>
|
||||
for Mat2<S>
|
||||
{
|
||||
#[inline]
|
||||
|
@ -197,62 +215,7 @@ for Mat2<S>
|
|||
Mat2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field + ApproxEq<S>>
|
||||
Matrix
|
||||
<
|
||||
S,
|
||||
Vec3<S>, [S, ..3], [Vec3<S>, ..3],
|
||||
Vec3<S>, [S, ..3], [Vec3<S>, ..3],
|
||||
Mat3<S>
|
||||
>
|
||||
for Mat3<S>
|
||||
{
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vec3<S> {
|
||||
Vec3::new(self.i(0).i(r).clone(),
|
||||
self.i(1).i(r).clone(),
|
||||
self.i(2).i(r).clone())
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Mat3<S> {
|
||||
Mat3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(),
|
||||
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field + ApproxEq<S>>
|
||||
Matrix
|
||||
<
|
||||
S,
|
||||
Vec4<S>, [S, ..4], [Vec4<S>, ..4],
|
||||
Vec4<S>, [S, ..4], [Vec4<S>, ..4],
|
||||
Mat4<S>
|
||||
>
|
||||
for Mat4<S>
|
||||
{
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vec4<S> {
|
||||
Vec4::new(self.i(0).i(r).clone(),
|
||||
self.i(1).i(r).clone(),
|
||||
self.i(2).i(r).clone(),
|
||||
self.i(2).i(r).clone())
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Mat4<S> {
|
||||
Mat4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(),
|
||||
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(),
|
||||
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field + ApproxEq<S>>
|
||||
SquareMatrix<S, Vec2<S>, [S, ..2], [Vec2<S>, ..2]>
|
||||
for Mat2<S>
|
||||
{
|
||||
#[inline]
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_cr((0, 1), (1, 0));
|
||||
|
@ -279,10 +242,23 @@ for Mat2<S>
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Field + ApproxEq<S>>
|
||||
SquareMatrix<S, Vec3<S>, [S, ..3], [Vec3<S>, ..3]>
|
||||
impl<S: Clone + Num + ApproxEq<S>>
|
||||
Matrix<S, [Vec3<S>, ..3], Vec3<S>, [S, ..3]>
|
||||
for Mat3<S>
|
||||
{
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vec3<S> {
|
||||
Vec3::new(self.i(0).i(r).clone(),
|
||||
self.i(1).i(r).clone(),
|
||||
self.i(2).i(r).clone())
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Mat3<S> {
|
||||
Mat3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(),
|
||||
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_cr((0, 1), (1, 0));
|
||||
|
@ -306,17 +282,32 @@ for Mat3<S>
|
|||
if det.approx_eq(&zero()) {
|
||||
None
|
||||
} else {
|
||||
Some(Mat3::from_cols(self.c(1).cross(self.c(2)) / det,
|
||||
self.c(2).cross(self.c(0)) / det,
|
||||
self.c(0).cross(self.c(1)) / det).transpose())
|
||||
Some(Mat3::from_cols(self.c(1).cross(self.c(2)).div_s(det.clone()),
|
||||
self.c(2).cross(self.c(0)).div_s(det.clone()),
|
||||
self.c(0).cross(self.c(1)).div_s(det.clone())).transpose())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Real + Field + ApproxEq<S>>
|
||||
SquareMatrix<S, Vec4<S>, [S, ..4], [Vec4<S>, ..4]>
|
||||
impl<S: Clone + Real + Num + ApproxEq<S>>
|
||||
Matrix<S, [Vec4<S>, ..4], Vec4<S>, [S, ..4]>
|
||||
for Mat4<S>
|
||||
{
|
||||
#[inline]
|
||||
fn r(&self, r: uint) -> Vec4<S> {
|
||||
Vec4::new(self.i(0).i(r).clone(),
|
||||
self.i(1).i(r).clone(),
|
||||
self.i(2).i(r).clone(),
|
||||
self.i(2).i(r).clone())
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Mat4<S> {
|
||||
Mat4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(),
|
||||
self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(),
|
||||
self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(),
|
||||
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose_self(&mut self) {
|
||||
self.swap_cr((0, 1), (1, 0));
|
||||
|
@ -359,7 +350,7 @@ for Mat4<S>
|
|||
// and essentially reduce [A|I]
|
||||
|
||||
let mut A = self.clone();
|
||||
let mut I = one::<Mat4<S>>();
|
||||
let mut I = Mat4::ident();
|
||||
|
||||
for j in range(0u, 4u) {
|
||||
// Find largest element in col j
|
||||
|
@ -376,17 +367,17 @@ for Mat4<S>
|
|||
I.swap_c(i1, j);
|
||||
|
||||
// Scale col j to have a unit diagonal
|
||||
*I.mut_c(j) = I.c(j) / *A.cr(j, j);
|
||||
*A.mut_c(j) = A.c(j) / *A.cr(j, j);
|
||||
*I.mut_c(j) = I.c(j).div_s(A.cr(j, j).clone());
|
||||
*A.mut_c(j) = A.c(j).div_s(A.cr(j, j).clone());
|
||||
|
||||
// Eliminate off-diagonal elems in col j of A,
|
||||
// doing identical ops to I
|
||||
for i in range(0u, 4u) {
|
||||
if i != j {
|
||||
let ij_mul_aij = I.c(j) * *A.cr(i, j);
|
||||
let aj_mul_aij = A.c(j) * *A.cr(i, j);
|
||||
*I.mut_c(i) = I.c(i) - ij_mul_aij;
|
||||
*A.mut_c(i) = A.c(i) - aj_mul_aij;
|
||||
let ij_mul_aij = I.c(j).mul_s(A.cr(i, j).clone());
|
||||
let aj_mul_aij = A.c(j).mul_s(A.cr(i, j).clone());
|
||||
*I.mut_c(i) = I.c(i).sub_v(&ij_mul_aij);
|
||||
*A.mut_c(i) = A.c(i).sub_v(&aj_mul_aij);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,4 +387,3 @@ for Mat4<S>
|
|||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,10 @@
|
|||
//! disinguishes them from vectors, which have a length and direction, but do
|
||||
//! not have a fixed position.
|
||||
|
||||
use traits::alg::*;
|
||||
use types::vector::{Vec2, Vec3};
|
||||
use std::num::zero;
|
||||
|
||||
use array::*;
|
||||
use vector::*;
|
||||
|
||||
#[deriving(Eq, Zero, Clone)]
|
||||
struct Point2<S> { x: S, y: S }
|
||||
|
@ -26,40 +28,50 @@ struct Point2<S> { x: S, y: S }
|
|||
#[deriving(Eq, Zero, Clone)]
|
||||
struct Point3<S> { x: S, y: S, z: S }
|
||||
|
||||
impl<S: Field> Point2<S> {
|
||||
impl<S: Num> Point2<S> {
|
||||
#[inline]
|
||||
pub fn new(x: S, y: S) -> Point2<S> {
|
||||
Point2 { x: x, y: y }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn origin() -> Point2<S> { zero() }
|
||||
}
|
||||
|
||||
impl<S: Field> Point3<S> {
|
||||
impl<S: Num> Point3<S> {
|
||||
#[inline]
|
||||
pub fn new(x: S, y: S, z: S) -> Point3<S> {
|
||||
Point3 { x: x, y: y, z: z }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn origin() -> Point3<S> { zero() }
|
||||
}
|
||||
|
||||
pub trait Point
|
||||
<
|
||||
S: Clone + Num,
|
||||
V: Vector<S, Slice>,
|
||||
Slice
|
||||
>
|
||||
: Array<S, Slice>
|
||||
{
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { self.map(|x| x.mul(&s)) }
|
||||
#[inline] fn div_s(&self, s: S) -> Self { self.map(|x| x.div(&s)) }
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { self.map(|x| x.rem(&s)) }
|
||||
|
||||
#[inline] fn add_v(&self, other: &V) -> Self { self.bimap(other, |a, b| a.add(b) ) }
|
||||
#[inline] fn sub_p(&self, other: &Self) -> V { self.bimap(other, |a, b| a.sub(b) ) }
|
||||
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.mul(&s) } }
|
||||
#[inline] fn div_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.div(&s) } }
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.rem(&s) } }
|
||||
|
||||
#[inline] fn add_self_v(&mut self, other: &V) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.add(b) } }
|
||||
}
|
||||
|
||||
array!(impl<S> Point2<S> -> [S, ..2])
|
||||
array!(impl<S> Point3<S> -> [S, ..3])
|
||||
|
||||
impl<S: Clone + Field> ClonableArray<S, [S, ..2]> for Point2<S>;
|
||||
impl<S: Clone + Field> ClonableArray<S, [S, ..3]> for Point3<S>;
|
||||
|
||||
scalar_op!(impl Point2<S> * S -> Point2<S>)
|
||||
scalar_op!(impl Point3<S> * S -> Point3<S>)
|
||||
scalar_op!(impl Point2<S> / S -> Point2<S>)
|
||||
scalar_op!(impl Point3<S> / S -> Point3<S>)
|
||||
scalar_op!(impl Point2<S> % S -> Point2<S>)
|
||||
scalar_op!(impl Point3<S> % S -> Point3<S>)
|
||||
|
||||
impl<S: Field> ScalarMul<S> for Point2<S>;
|
||||
impl<S: Field> ScalarMul<S> for Point3<S>;
|
||||
|
||||
array_op!(impl<S> Point2<S> + Vec2<S> -> Point2<S>)
|
||||
array_op!(impl<S> Point3<S> + Vec3<S> -> Point3<S>)
|
||||
array_op!(impl<S> Point2<S> - Point2<S> -> Vec2<S>)
|
||||
array_op!(impl<S> Point3<S> - Point3<S> -> Vec3<S>)
|
||||
|
||||
impl<S: Field> AffineSpace<S, Vec2<S>> for Point2<S>;
|
||||
impl<S: Field> AffineSpace<S, Vec3<S>> for Point3<S>;
|
||||
impl<S: Clone + Num> Point<S, Vec2<S>, [S, ..2]> for Point2<S>;
|
||||
impl<S: Clone + Num> Point<S, Vec3<S>, [S, ..3]> for Point3<S>;
|
|
@ -13,14 +13,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::*;
|
||||
use types::vector::Vec3;
|
||||
use vector::Vec3;
|
||||
|
||||
/// A quaternion in scalar/vector form
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct Quat<T> { s: T, v: Vec3<T> }
|
||||
|
||||
impl<T: Field> Quat<T> {
|
||||
impl<T: Clone + Num> Quat<T> {
|
||||
/// Construct a new quaternion from one scalar component and three
|
||||
/// imaginary components
|
||||
#[inline]
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::Zero;
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::ScalarMul;
|
||||
use traits::alg::VectorSpace;
|
||||
|
||||
/// An affine space is a set of points closed under affine combinations.
|
||||
pub trait AffineSpace
|
||||
<
|
||||
S: Field,
|
||||
V: VectorSpace<S>
|
||||
>
|
||||
: Eq
|
||||
+ Zero
|
||||
+ Add<V, Self>
|
||||
+ Sub<Self, V>
|
||||
+ ScalarMul<S>
|
||||
{
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num;
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::InnerProductSpace;
|
||||
|
||||
/// The Euclidean space is a vector space over the Real numbers.
|
||||
pub trait EuclideanSpace
|
||||
<
|
||||
S:Real + Field
|
||||
>
|
||||
: InnerProductSpace<S>
|
||||
{
|
||||
fn dot(&self, other: &Self) -> S {
|
||||
self.inner(other)
|
||||
}
|
||||
|
||||
/// Returns `true` if the vector is perpendicular (at right angles to)
|
||||
/// the other vector.
|
||||
fn is_perpendicular(&self, other: &Self) -> bool {
|
||||
self.is_orthogonal(other)
|
||||
}
|
||||
|
||||
/// Returns the squared length of the vector. This does not perform an
|
||||
/// expensive square root operation like in the `length` method and can
|
||||
/// therefore be more efficient for comparing the lengths of two vectors.
|
||||
fn length2(&self) -> S {
|
||||
self.dot(self)
|
||||
}
|
||||
|
||||
/// The norm of the vector.
|
||||
fn length(&self) -> S {
|
||||
num::sqrt(self.dot(self))
|
||||
}
|
||||
|
||||
/// The angle between the vector and `other`.
|
||||
fn angle(&self, other: &Self) -> S;
|
||||
|
||||
/// Returns a vector with the same direction, but with a `length` (or
|
||||
/// `norm`) of `1`.
|
||||
fn normalize(&self) -> Self {
|
||||
self.normalize_to(num::one::<S>())
|
||||
}
|
||||
|
||||
/// Returns a vector with the same direction and a given `length`.
|
||||
fn normalize_to(&self, length: S) -> Self {
|
||||
*self * (length / self.length())
|
||||
}
|
||||
|
||||
/// Returns the result of linarly interpolating the length of the vector
|
||||
/// to the length of `other` by the specified amount.
|
||||
fn lerp(&self, other: &Self, amount: S) -> Self {
|
||||
*self + (*other - *self) * amount
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::Ring;
|
||||
|
||||
/// A commutative ring that contains a multiplicative inverse.
|
||||
pub trait Field
|
||||
: Ring<Self>
|
||||
+ Div<Self,Self>
|
||||
+ Rem<Self,Self>
|
||||
{
|
||||
}
|
||||
|
||||
// impls for concrete types
|
||||
|
||||
impl Field for u8;
|
||||
impl Field for u16;
|
||||
impl Field for u32;
|
||||
impl Field for u64;
|
||||
impl Field for uint;
|
||||
impl Field for i8;
|
||||
impl Field for i16;
|
||||
impl Field for i32;
|
||||
impl Field for i64;
|
||||
impl Field for int;
|
||||
impl Field for f32;
|
||||
impl Field for f64;
|
||||
impl Field for float;
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::VectorSpace;
|
||||
|
||||
/// A vector space with the inner product operation.
|
||||
pub trait InnerProductSpace
|
||||
<
|
||||
S: Field
|
||||
>
|
||||
: VectorSpace<S>
|
||||
{
|
||||
fn norm(&self) -> S;
|
||||
fn inner(&self, other: &Self) -> S;
|
||||
fn is_orthogonal(&self, other: &Self) -> bool;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::Array;
|
||||
use traits::alg::ClonableArray;
|
||||
use traits::alg::Field;
|
||||
use traits::alg::Ring;
|
||||
use traits::alg::VectorSpace;
|
||||
|
||||
pub trait Matrix
|
||||
<
|
||||
S: Field + Clone + ApproxEq<S>,
|
||||
RV: Clone + VectorSpace<S> + ClonableArray<S, RVSlice>, RVSlice, RSlice,
|
||||
CV: Clone + VectorSpace<S> + ClonableArray<S, CVSlice>, CVSlice, CSlice,
|
||||
MT//: Matrix<S, CV, CSlice, RV, RSlice, Self>
|
||||
>
|
||||
: Ring<S>
|
||||
+ ClonableArray<CV, RSlice>
|
||||
{
|
||||
#[inline]
|
||||
fn c<'a>(&'a self, c: uint) -> &'a CV { self.i(c) }
|
||||
|
||||
#[inline]
|
||||
fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut CV { self.mut_i(c) }
|
||||
|
||||
#[inline]
|
||||
fn swap_c(&mut self, a: uint, b: uint) {
|
||||
let tmp = self.c(a).clone();
|
||||
*self.mut_c(a) = self.c(b).clone();
|
||||
*self.mut_c(b) = tmp;
|
||||
}
|
||||
|
||||
fn r(&self, r: uint) -> RV;
|
||||
|
||||
#[inline]
|
||||
fn swap_r(&mut self, a: uint, b: uint) {
|
||||
for c in self.mut_iter() { c.swap(a, b) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cr<'a>(&'a self, c: uint, r: uint) -> &'a S { self.i(c).i(r) }
|
||||
|
||||
#[inline]
|
||||
fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut S {
|
||||
self.mut_i(c).mut_i(r)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) {
|
||||
let (ca, ra) = a;
|
||||
let (cb, rb) = b;
|
||||
let tmp = self.cr(ca, ra).clone();
|
||||
*self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
|
||||
*self.mut_cr(cb, rb) = tmp;
|
||||
}
|
||||
|
||||
// fn swap_cr(&mut self, (ca, ra): (uint, uint), (cb, rb): (uint, uint)) {
|
||||
// let tmp = self.cr(ca, ra).clone();
|
||||
// *self.mut_cr(ca, ra) = self.cr(cb, rb).clone();
|
||||
// *self.mut_cr(cb, rb) = tmp;
|
||||
// }
|
||||
|
||||
fn transpose(&self) -> MT;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_escape];
|
||||
|
||||
pub use self::affine_space::AffineSpace;
|
||||
pub use self::array::{Array, ClonableArray};
|
||||
pub use self::euclidean_space::EuclideanSpace;
|
||||
pub use self::field::Field;
|
||||
pub use self::inner_product_space::InnerProductSpace;
|
||||
pub use self::matrix::Matrix;
|
||||
pub use self::module::Module;
|
||||
pub use self::ordered_ring::OrderedRing;
|
||||
pub use self::ring::Ring;
|
||||
pub use self::scalar_mul::ScalarMul;
|
||||
pub use self::square_matrix::SquareMatrix;
|
||||
pub use self::vector_space::VectorSpace;
|
||||
|
||||
pub mod affine_space;
|
||||
pub mod array;
|
||||
pub mod euclidean_space;
|
||||
pub mod field;
|
||||
pub mod inner_product_space;
|
||||
pub mod matrix;
|
||||
pub mod module;
|
||||
pub mod ordered_ring;
|
||||
pub mod ring;
|
||||
pub mod scalar_mul;
|
||||
pub mod square_matrix;
|
||||
pub mod vector_space;
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::Zero;
|
||||
|
||||
// use traits::alg::Field;
|
||||
use traits::alg::ScalarMul;
|
||||
|
||||
/// An algebraic structure that generalizes the notion of a vector space.
|
||||
pub trait Module
|
||||
<
|
||||
S/*: Field*/
|
||||
>
|
||||
: Eq
|
||||
+ Add<Self,Self>
|
||||
+ ScalarMul<S>
|
||||
+ Zero
|
||||
{
|
||||
}
|
||||
|
||||
// impls for concrete types
|
||||
|
||||
impl Module<u8> for u8;
|
||||
impl Module<u16> for u16;
|
||||
impl Module<u32> for u32;
|
||||
impl Module<u64> for u64;
|
||||
impl Module<uint> for uint;
|
||||
impl Module<i8> for i8;
|
||||
impl Module<i16> for i16;
|
||||
impl Module<i32> for i32;
|
||||
impl Module<i64> for i64;
|
||||
impl Module<int> for int;
|
||||
impl Module<f32> for f32;
|
||||
impl Module<f64> for f64;
|
||||
impl Module<float> for float;
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::Ring;
|
||||
|
||||
/// A ring that can also be ordered.
|
||||
pub trait OrderedRing
|
||||
<
|
||||
S
|
||||
>
|
||||
: Ring<S>
|
||||
+ Orderable
|
||||
{
|
||||
}
|
||||
|
||||
// impls for concrete types
|
||||
|
||||
impl OrderedRing<u8> for u8;
|
||||
impl OrderedRing<u16> for u16;
|
||||
impl OrderedRing<u32> for u32;
|
||||
impl OrderedRing<u64> for u64;
|
||||
impl OrderedRing<uint> for uint;
|
||||
impl OrderedRing<i8> for i8;
|
||||
impl OrderedRing<i16> for i16;
|
||||
impl OrderedRing<i32> for i32;
|
||||
impl OrderedRing<i64> for i64;
|
||||
impl OrderedRing<int> for int;
|
||||
impl OrderedRing<f32> for f32;
|
||||
impl OrderedRing<f64> for f64;
|
||||
impl OrderedRing<float> for float;
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::One;
|
||||
|
||||
use traits::alg::Module;
|
||||
|
||||
/// A module that also requires the additive inverse operation (subtraction)
|
||||
/// and the additive inverse.
|
||||
pub trait Ring
|
||||
<
|
||||
S
|
||||
>
|
||||
: Module<S>
|
||||
+ Neg<Self>
|
||||
+ Sub<Self,Self>
|
||||
+ One
|
||||
{
|
||||
}
|
||||
|
||||
// impls for concrete types
|
||||
|
||||
impl Ring<u8> for u8;
|
||||
impl Ring<u16> for u16;
|
||||
impl Ring<u32> for u32;
|
||||
impl Ring<u64> for u64;
|
||||
impl Ring<uint> for uint;
|
||||
impl Ring<i8> for i8;
|
||||
impl Ring<i16> for i16;
|
||||
impl Ring<i32> for i32;
|
||||
impl Ring<i64> for i64;
|
||||
impl Ring<int> for int;
|
||||
impl Ring<f32> for f32;
|
||||
impl Ring<f64> for f64;
|
||||
impl Ring<float> for float;
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_escape];
|
||||
|
||||
// use traits::alg::Field;
|
||||
|
||||
/// Enforces the multiplication of an type by a scalar.
|
||||
pub trait ScalarMul
|
||||
<
|
||||
S//: Field
|
||||
>
|
||||
: Mul<S, Self>
|
||||
+ Div<S, Self>
|
||||
+ Rem<S, Self>
|
||||
{
|
||||
}
|
||||
|
||||
// impls for concrete types
|
||||
|
||||
impl ScalarMul<u8> for u8;
|
||||
impl ScalarMul<u16> for u16;
|
||||
impl ScalarMul<u32> for u32;
|
||||
impl ScalarMul<u64> for u64;
|
||||
impl ScalarMul<uint> for uint;
|
||||
impl ScalarMul<i8> for i8;
|
||||
impl ScalarMul<i16> for i16;
|
||||
impl ScalarMul<i32> for i32;
|
||||
impl ScalarMul<i64> for i64;
|
||||
impl ScalarMul<int> for int;
|
||||
impl ScalarMul<f32> for f32;
|
||||
impl ScalarMul<f64> for f64;
|
||||
impl ScalarMul<float> for float;
|
||||
|
||||
macro_rules! scalar_op(
|
||||
(impl<$S:ident> ($Op:ident, $op:ident) for $Self:ty -> $Result:ty) => (
|
||||
impl<$S: Field> $Op<$S, $Self> for $Self {
|
||||
#[inline(always)]
|
||||
fn $op(&self, s: &$S) -> $Result { self.map(|x| x.$op(s)) }
|
||||
}
|
||||
);
|
||||
(impl $Self:ty + $S:ident -> $Result:ty) => (scalar_op!(impl<$S> (Add, add) for $Self -> $Result));
|
||||
(impl $Self:ty - $S:ident -> $Result:ty) => (scalar_op!(impl<$S> (Sub, sub) for $Self -> $Result));
|
||||
(impl $Self:ty * $S:ident -> $Result:ty) => (scalar_op!(impl<$S> (Mul, mul) for $Self -> $Result));
|
||||
(impl $Self:ty / $S:ident -> $Result:ty) => (scalar_op!(impl<$S> (Div, div) for $Self -> $Result));
|
||||
(impl $Self:ty % $S:ident -> $Result:ty) => (scalar_op!(impl<$S> (Rem, rem) for $Self -> $Result));
|
||||
)
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num;
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::Matrix;
|
||||
use traits::alg::VectorSpace;
|
||||
|
||||
pub trait SquareMatrix
|
||||
<
|
||||
S: Field + ApproxEq<S>,
|
||||
V: VectorSpace<S>,
|
||||
VVSlice, VSlice
|
||||
>
|
||||
: Matrix<S, V, VVSlice, VSlice, V, VVSlice, VSlice, Self>
|
||||
{
|
||||
fn transpose_self(&mut self);
|
||||
fn trace(&self) -> S;
|
||||
fn determinant(&self) -> S;
|
||||
fn invert(&self) -> Option<Self>;
|
||||
|
||||
#[inline]
|
||||
fn invert_self(&mut self) {
|
||||
*self = self.invert().expect("Attempted to invert a matrix with zero determinant.");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_invertible(&self) -> bool {
|
||||
!self.determinant().approx_eq(&num::zero::<S>())
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::Module;
|
||||
|
||||
/// A vector space is a set that is closed under vector addition and
|
||||
/// scalar multiplication.
|
||||
pub trait VectorSpace
|
||||
<
|
||||
S: Field
|
||||
>
|
||||
: Module<S>
|
||||
+ Neg<Self>
|
||||
+ Sub<Self,Self>
|
||||
{
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub use self::vector_ext::VectorExt;
|
||||
|
||||
pub mod vector_ext;
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::{zero, one};
|
||||
|
||||
use traits::alg::Field;
|
||||
use traits::alg::VectorSpace;
|
||||
use traits::alg::Array;
|
||||
|
||||
pub trait VectorExt
|
||||
<
|
||||
S: Field,
|
||||
Slice
|
||||
>
|
||||
: VectorSpace<S>
|
||||
+ Array<S, Slice>
|
||||
{
|
||||
#[inline] fn add_s(&self, s: S) -> Self { self.map(|x| x.add(&s)) }
|
||||
#[inline] fn sub_s(&self, s: S) -> Self { self.map(|x| x.sub(&s)) }
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { self.map(|x| x.mul(&s)) }
|
||||
#[inline] fn div_s(&self, s: S) -> Self { self.map(|x| x.div(&s)) }
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { self.map(|x| x.rem(&s)) }
|
||||
|
||||
#[inline] fn add_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.add(b) ) }
|
||||
#[inline] fn sub_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.sub(b) ) }
|
||||
#[inline] fn mul_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.mul(b) ) }
|
||||
#[inline] fn div_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.div(b) ) }
|
||||
#[inline] fn rem_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.rem(b) ) }
|
||||
|
||||
#[inline] fn neg_self(&mut self) { for x in self.mut_iter() { *x = x.neg() } }
|
||||
#[inline] fn add_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.add(&s) } }
|
||||
#[inline] fn sub_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.sub(&s) } }
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.mul(&s) } }
|
||||
#[inline] fn div_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.div(&s) } }
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.rem(&s) } }
|
||||
|
||||
#[inline] fn add_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.add(b) } }
|
||||
#[inline] fn sub_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.sub(b) } }
|
||||
#[inline] fn mul_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.mul(b) } }
|
||||
#[inline] fn div_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.div(b) } }
|
||||
#[inline] fn rem_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.rem(b) } }
|
||||
|
||||
#[inline] fn comp_add(&self) -> S { self.iter().fold(zero::<S>(), |a, b| a.add(b)) }
|
||||
#[inline] fn comp_mul(&self) -> S { self.iter().fold(one::<S>(), |a, b| a.mul(b)) }
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_escape];
|
||||
|
||||
/// Import this module for the strict, algebraic trait heirachy.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~rust
|
||||
/// use lmath::traits::alg::*;
|
||||
/// ~~~
|
||||
pub mod alg;
|
||||
|
||||
/// Import this module to access utility traits that do not neccsarily match
|
||||
/// up with the strict algebraic properties of the respective types, and yet
|
||||
/// still may be useful for computer graphics work.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~rust
|
||||
/// use lmath::traits::ext::*;
|
||||
/// ~~~
|
||||
pub mod ext;
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
pub mod matrix;
|
||||
pub mod point;
|
||||
pub mod quaternion;
|
||||
pub mod vector;
|
|
@ -1,162 +0,0 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::{Zero, zero};
|
||||
use std::num::{sqrt, atan2};
|
||||
|
||||
use traits::alg::*;
|
||||
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec1<S> { x: S }
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec2<S> { x: S, y: S }
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec3<S> { x: S, y: S, z: S }
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec4<S> { x: S, y: S, z: S, w: S }
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec5<S> { x: S, y: S, z: S, w: S, a: S }
|
||||
#[deriving(Eq, Zero, Clone)] pub struct Vec6<S> { x: S, y: S, z: S, w: S, a: S, b: S }
|
||||
|
||||
macro_rules! impl_vec(
|
||||
($Self:ident <$S:ident> { $($field:ident),+ }) => (
|
||||
impl<$S: Field> $Self<$S> {
|
||||
#[inline]
|
||||
pub fn new($($field: $S),+) -> $Self<$S> {
|
||||
$Self { $($field: $field),+ }
|
||||
}
|
||||
|
||||
/// The additive identity of the vector.
|
||||
#[inline]
|
||||
pub fn zero() -> $Self<$S> { zero() }
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
impl_vec!(Vec1<S> { x })
|
||||
impl_vec!(Vec2<S> { x, y })
|
||||
impl_vec!(Vec3<S> { x, y, z })
|
||||
impl_vec!(Vec4<S> { x, y, z, w })
|
||||
impl_vec!(Vec5<S> { x, y, z, w, a })
|
||||
impl_vec!(Vec6<S> { x, y, z, w, a, b })
|
||||
|
||||
macro_rules! impl_vec_clonable(
|
||||
($Self:ident <$S:ident>) => (
|
||||
impl<$S:Clone + Field> $Self<$S> {
|
||||
/// Construct a vector from a single value.
|
||||
#[inline]
|
||||
pub fn from_value(value: $S) -> $Self<$S> {
|
||||
Array::build(|_| value.clone())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
impl_vec_clonable!(Vec1<S>)
|
||||
impl_vec_clonable!(Vec2<S>)
|
||||
impl_vec_clonable!(Vec3<S>)
|
||||
impl_vec_clonable!(Vec4<S>)
|
||||
impl_vec_clonable!(Vec5<S>)
|
||||
impl_vec_clonable!(Vec6<S>)
|
||||
|
||||
macro_rules! impl_vec_common(
|
||||
($vec_ops_mod:ident, $Self:ty, [$S:ident, ..$n:expr]) => (
|
||||
pub mod $vec_ops_mod {
|
||||
use super::*;
|
||||
use traits::alg::*;
|
||||
use traits::ext::*;
|
||||
|
||||
array!(impl<$S> $Self -> [$S, ..$n])
|
||||
impl<$S: Clone + Field> ClonableArray<$S, [$S, ..$n]> for $Self;
|
||||
|
||||
scalar_op!(impl $Self * $S -> $Self)
|
||||
scalar_op!(impl $Self / $S -> $Self)
|
||||
scalar_op!(impl $Self % $S -> $Self)
|
||||
array_op!(impl<$S> $Self + $Self -> $Self)
|
||||
array_op!(impl<$S> $Self - $Self -> $Self)
|
||||
array_op!(impl<$S> -$Self -> $Self)
|
||||
|
||||
impl<$S: Field> ScalarMul<$S> for $Self;
|
||||
impl<$S: Field> Module<$S> for $Self;
|
||||
impl<$S: Field> VectorSpace<$S> for $Self;
|
||||
|
||||
impl<$S: Clone + Field> VectorExt<$S, [$S, ..$n]> for $Self;
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
impl_vec_common!(vec1_ops, Vec1<S>, [S, ..1])
|
||||
impl_vec_common!(vec2_ops, Vec2<S>, [S, ..2])
|
||||
impl_vec_common!(vec3_ops, Vec3<S>, [S, ..3])
|
||||
impl_vec_common!(vec4_ops, Vec4<S>, [S, ..4])
|
||||
impl_vec_common!(vec5_ops, Vec5<S>, [S, ..5])
|
||||
impl_vec_common!(vec6_ops, Vec6<S>, [S, ..6])
|
||||
|
||||
/// Operations specific to two-dimensional vectors.
|
||||
impl<S: Field> Vec2<S> {
|
||||
/// The perpendicular dot product of the vector and `other`.
|
||||
pub fn perp_dot(&self, other: &Vec2<S>) -> S {
|
||||
(self.x * other.y) - (self.y * other.x)
|
||||
}
|
||||
}
|
||||
|
||||
/// Operations specific to three-dimensional vectors.
|
||||
impl<S: Field> Vec3<S> {
|
||||
/// Returns the cross product of the vector and `other`.
|
||||
pub fn cross(&self, other: &Vec3<S>) -> Vec3<S> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_vec_inner_product(
|
||||
($Self:ident <$S:ident>) => (
|
||||
impl<$S:Real + Field + ApproxEq<$S>> InnerProductSpace<$S> for $Self<$S> {
|
||||
#[inline]
|
||||
fn norm(&self) -> $S {
|
||||
sqrt(self.inner(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner(&self, other: &$Self<$S>) -> $S {
|
||||
self.iter().zip(other.iter())
|
||||
.map(|(a, b)| a.mul(b))
|
||||
.fold(zero::<$S>(), |a, b| a.add(&b))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_orthogonal(&self, other: &$Self<$S>) -> bool {
|
||||
self.inner(other).approx_eq(&zero())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
impl_vec_inner_product!(Vec1<S>)
|
||||
impl_vec_inner_product!(Vec2<S>)
|
||||
impl_vec_inner_product!(Vec3<S>)
|
||||
impl_vec_inner_product!(Vec4<S>)
|
||||
impl_vec_inner_product!(Vec5<S>)
|
||||
impl_vec_inner_product!(Vec6<S>)
|
||||
|
||||
// Euclidean spaces only really make sense for 2D and 3D vector spaces
|
||||
|
||||
impl<S:Real + Field + ApproxEq<S>> EuclideanSpace<S> for Vec2<S> {
|
||||
fn angle(&self, other: &Vec2<S>) -> S {
|
||||
atan2(self.perp_dot(other), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S:Real + Field + ApproxEq<S>> EuclideanSpace<S> for Vec3<S> {
|
||||
fn angle(&self, other: &Vec3<S>) -> S {
|
||||
atan2(self.cross(other).length(), self.dot(other))
|
||||
}
|
||||
}
|
190
src/cgmath/vector.rs
Normal file
190
src/cgmath/vector.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::num::{zero, one};
|
||||
use std::num::{sqrt, atan2};
|
||||
|
||||
use array::*;
|
||||
|
||||
#[deriving(Eq, Clone, Zero)] pub struct Vec2<S> { x: S, y: S }
|
||||
#[deriving(Eq, Clone, Zero)] pub struct Vec3<S> { x: S, y: S, z: S }
|
||||
#[deriving(Eq, Clone, Zero)] pub struct Vec4<S> { x: S, y: S, z: S, w: S }
|
||||
|
||||
macro_rules! vec(
|
||||
(impl $Self:ident <$S:ident> { $($field:ident),+ }) => (
|
||||
impl<$S: Clone + Num> $Self<$S> {
|
||||
#[inline]
|
||||
pub fn new($($field: $S),+) -> $Self<$S> {
|
||||
$Self { $($field: $field),+ }
|
||||
}
|
||||
|
||||
/// The additive identity of the vector.
|
||||
#[inline]
|
||||
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
|
||||
|
||||
/// The additive identity of the vector.
|
||||
#[inline]
|
||||
pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
|
||||
|
||||
/// Construct a vector from a single value.
|
||||
#[inline]
|
||||
pub fn from_value(value: $S) -> $Self<$S> {
|
||||
Array::build(|_| value.clone())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
vec!(impl Vec2<S> { x, y })
|
||||
vec!(impl Vec3<S> { x, y, z })
|
||||
vec!(impl Vec4<S> { x, y, z, w })
|
||||
|
||||
array!(impl<S> Vec2<S> -> [S, ..2])
|
||||
array!(impl<S> Vec3<S> -> [S, ..3])
|
||||
array!(impl<S> Vec4<S> -> [S, ..4])
|
||||
|
||||
pub trait Vector
|
||||
<
|
||||
S: Clone + Num,
|
||||
Slice
|
||||
>
|
||||
: Array<S, Slice>
|
||||
{
|
||||
#[inline] fn neg(&self) -> Self { self.map(|x| x.neg()) }
|
||||
#[inline] fn neg_self(&mut self) { for x in self.mut_iter() { *x = x.neg() } }
|
||||
|
||||
#[inline] fn add_s(&self, s: S) -> Self { self.map(|x| x.add(&s)) }
|
||||
#[inline] fn sub_s(&self, s: S) -> Self { self.map(|x| x.sub(&s)) }
|
||||
#[inline] fn mul_s(&self, s: S) -> Self { self.map(|x| x.mul(&s)) }
|
||||
#[inline] fn div_s(&self, s: S) -> Self { self.map(|x| x.div(&s)) }
|
||||
#[inline] fn rem_s(&self, s: S) -> Self { self.map(|x| x.rem(&s)) }
|
||||
|
||||
#[inline] fn add_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.add(b) ) }
|
||||
#[inline] fn sub_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.sub(b) ) }
|
||||
#[inline] fn mul_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.mul(b) ) }
|
||||
#[inline] fn div_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.div(b) ) }
|
||||
#[inline] fn rem_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.rem(b) ) }
|
||||
|
||||
#[inline] fn add_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.add(&s) } }
|
||||
#[inline] fn sub_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.sub(&s) } }
|
||||
#[inline] fn mul_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.mul(&s) } }
|
||||
#[inline] fn div_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.div(&s) } }
|
||||
#[inline] fn rem_self_s(&mut self, s: S) { for x in self.mut_iter() { *x = x.rem(&s) } }
|
||||
|
||||
#[inline] fn add_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.add(b) } }
|
||||
#[inline] fn sub_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.sub(b) } }
|
||||
#[inline] fn mul_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.mul(b) } }
|
||||
#[inline] fn div_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.div(b) } }
|
||||
#[inline] fn rem_self_v(&mut self, other: &Self) { for (a, b) in self.mut_iter().zip(other.iter()) { *a = a.rem(b) } }
|
||||
|
||||
#[inline] fn comp_add(&self) -> S { self.iter().fold(zero::<S>(), |a, b| a.add(b)) }
|
||||
#[inline] fn comp_mul(&self) -> S { self.iter().fold(one::<S>(), |a, b| a.mul(b)) }
|
||||
|
||||
#[inline]
|
||||
fn dot(&self, other: &Self) -> S {
|
||||
self.iter().zip(other.iter())
|
||||
.map(|(a, b)| a.mul(b))
|
||||
.fold(zero::<S>(), |a, b| a.add(&b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Num> Vector<S, [S, ..2]> for Vec2<S>;
|
||||
impl<S: Clone + Num> Vector<S, [S, ..3]> for Vec3<S>;
|
||||
impl<S: Clone + Num> Vector<S, [S, ..4]> for Vec4<S>;
|
||||
|
||||
/// Operations specific to numeric two-dimensional vectors.
|
||||
impl<S: Clone + Num> Vec2<S> {
|
||||
/// The perpendicular dot product of the vector and `other`.
|
||||
#[inline]
|
||||
pub fn perp_dot(&self, other: &Vec2<S>) -> S {
|
||||
(self.x * other.y) - (self.y * other.x)
|
||||
}
|
||||
}
|
||||
|
||||
/// Operations specific to numeric three-dimensional vectors.
|
||||
impl<S: Clone + Num> Vec3<S> {
|
||||
/// Returns the cross product of the vector and `other`.
|
||||
#[inline]
|
||||
pub fn cross(&self, other: &Vec3<S>) -> Vec3<S> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EuclideanVector
|
||||
<
|
||||
S: Clone + Real + ApproxEq<S>,
|
||||
Slice
|
||||
>
|
||||
: Vector<S, Slice>
|
||||
{
|
||||
/// Returns `true` if the vector is perpendicular (at right angles to)
|
||||
/// the other vector.
|
||||
fn is_perpendicular(&self, other: &Self) -> bool {
|
||||
self.dot(other).approx_eq(&zero())
|
||||
}
|
||||
|
||||
/// Returns the squared length of the vector. This does not perform an
|
||||
/// expensive square root operation like in the `length` method and can
|
||||
/// therefore be more efficient for comparing the lengths of two vectors.
|
||||
#[inline]
|
||||
fn length2(&self) -> S {
|
||||
self.dot(self)
|
||||
}
|
||||
|
||||
/// The norm of the vector.
|
||||
#[inline]
|
||||
fn length(&self) -> S {
|
||||
sqrt(self.dot(self))
|
||||
}
|
||||
|
||||
/// The angle between the vector and `other`.
|
||||
fn angle(&self, other: &Self) -> S;
|
||||
|
||||
/// Returns a vector with the same direction, but with a `length` (or
|
||||
/// `norm`) of `1`.
|
||||
#[inline]
|
||||
fn normalize(&self) -> Self {
|
||||
self.normalize_to(one::<S>())
|
||||
}
|
||||
|
||||
/// Returns a vector with the same direction and a given `length`.
|
||||
#[inline]
|
||||
fn normalize_to(&self, length: S) -> Self {
|
||||
self.mul_s(length / self.length())
|
||||
}
|
||||
|
||||
/// Returns the result of linarly interpolating the length of the vector
|
||||
/// to the length of `other` by the specified amount.
|
||||
#[inline]
|
||||
fn lerp(&self, other: &Self, amount: S) -> Self {
|
||||
self.add_v(&other.sub_v(self).mul_s(amount))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Real + ApproxEq<S>> EuclideanVector<S, [S, ..2]> for Vec2<S> {
|
||||
#[inline]
|
||||
fn angle(&self, other: &Vec2<S>) -> S {
|
||||
atan2(self.perp_dot(other), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Clone + Real + ApproxEq<S>> EuclideanVector<S, [S, ..3]> for Vec3<S> {
|
||||
#[inline]
|
||||
fn angle(&self, other: &Vec3<S>) -> S {
|
||||
atan2(self.cross(other).length(), self.dot(other))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue