Make library generic

This commit is contained in:
Brendan Zabarauskas 2012-11-01 11:34:38 +10:00
parent 891736a2d7
commit bf6bf8b3e6
10 changed files with 963 additions and 598 deletions

View file

@ -1,6 +1,8 @@
use cmp::Ord;
use num::{Num, from_int};
use num_util::*;
// TODO: move to a more appropriate module
pub trait ToPtr<T> {
pure fn to_ptr() -> *T;
@ -10,24 +12,29 @@ pub trait ExactEq {
pure fn exact_eq(other: &self) -> bool;
}
//
// Min
//
#[inline(always)]
pure fn min<T:Copy Ord>(a: &T, b: &T) -> T {
if a < b { *a }
else { *b }
trait MinMax {
pure fn min(other: &self) -> self;
pure fn max(other: &self) -> self;
}
//
// Max
//
#[inline(always)]
pure fn max<T:Copy Ord>(a: &T, b: &T) -> T {
if a > b { *a }
else { *b }
#[inline(always)] pure fn min<T:MinMax>(a: &T, b: &T) -> T { a.min(b) }
#[inline(always)] pure fn max<T:MinMax>(a: &T, b: &T) -> T { a.max(b) }
impl float: MinMax {
pure fn min(other: &float) -> float {
if self < *other { self }
else { *other }
}
pure fn max(other: &float) -> float {
if self > *other { self }
else { *other }
}
}
// #[inline(always)]
// pure fn abs<T:Copy Num Ord>(x: &T) -> T {
// if x >= &from_int(0) { *x } else {-x }
@ -85,14 +92,6 @@ impl int: Abs {
}
}
impl float: Abs {
#[inline(always)]
pure fn abs() -> float {
if self >= 0f { self }
else {-self }
}
}
impl f32: Abs {
#[inline(always)]
pure fn abs() -> f32 {
@ -109,6 +108,14 @@ impl f64: Abs {
}
}
impl float: Abs {
#[inline(always)]
pure fn abs() -> float {
if self >= 0f { self }
else {-self }
}
}
//
// Sqrt
//
@ -121,93 +128,9 @@ pure fn sqrt<T: Sqrt>(x: T) -> T {
x.sqrt()
}
impl u8: Sqrt {
pub impl<T: NumCast> T: Sqrt {
#[inline(always)]
pure fn sqrt() -> u8 {
(self as float).sqrt() as u8
}
}
impl u16: Sqrt {
#[inline(always)]
pure fn sqrt() -> u16 {
(self as float).sqrt() as u16
}
}
impl u32: Sqrt {
#[inline(always)]
pure fn sqrt() -> u32 {
(self as float).sqrt() as u32
}
}
impl u64: Sqrt {
#[inline(always)]
pure fn sqrt() -> u64 {
(self as float).sqrt() as u64
}
}
impl uint: Sqrt {
#[inline(always)]
pure fn sqrt() -> uint {
(self as float).sqrt() as uint
}
}
impl i8: Sqrt {
#[inline(always)]
pure fn sqrt() -> i8 {
(self as float).sqrt() as i8
}
}
impl i16: Sqrt {
#[inline(always)]
pure fn sqrt() -> i16 {
(self as float).sqrt() as i16
}
}
impl i32: Sqrt {
#[inline(always)]
pure fn sqrt() -> i32 {
(self as float).sqrt() as i32
}
}
impl i64: Sqrt {
#[inline(always)]
pure fn sqrt() -> i64 {
(self as float).sqrt() as i64
}
}
impl int: Sqrt {
#[inline(always)]
pure fn sqrt() -> int {
(self as float).sqrt() as int
}
}
impl float: Sqrt {
#[inline(always)]
pure fn sqrt() -> float {
float::sqrt(self)
}
}
impl f32: Sqrt {
#[inline(always)]
pure fn sqrt() -> f32 {
f32::sqrt(self)
}
}
impl f64: Sqrt {
#[inline(always)]
pure fn sqrt() -> f64 {
f64::sqrt(self)
pure fn sqrt() -> T {
f64::sqrt(self.cast()).cast()
}
}

View file

@ -1,7 +1,10 @@
use std::cmp::FuzzyEq;
use cmp::Eq;
use math::{ToPtr, ExactEq, Sqrt};
use quaternion::Quat;
use num::from_int;
use math::*;
use num_util::*;
use quaternion::{Quat, ToQuat};
use vector::{Vec2, Vec3, Vec4};
//
@ -33,18 +36,17 @@ pub trait Matrix<T, V> {
//
// 3x3 Matrix
//
pub trait Matrix3<V3> {
pure fn scale(vec: &V3) -> self;
pure fn to_Mat4() -> Mat4;
pure fn to_Quat() -> Quat;
pub trait Matrix3<T> {
pure fn scale(vec: &Vec3<T>) -> self;
pure fn to_Mat4() -> Mat4<T>;
}
//
// 4x4 Matrix
//
pub trait Matrix4<V3, V4> {
pure fn scale(vec: &V3) -> self;
pure fn translate(vec: &V3) -> self;
pub trait Matrix4<T> {
pure fn scale(vec: &Vec3<T>) -> self;
pure fn translate(vec: &Vec3<T>) -> self;
}
@ -55,19 +57,14 @@ pub trait Matrix4<V3, V4> {
//
// Mat2: A 2x2, column major matrix
//
pub struct Mat2 { data:[Vec2 * 2] }
pub const mat2_zero :Mat2 = Mat2 { data: [ Vec2::zero,
Vec2::zero ] };
pub const mat2_identity :Mat2 = Mat2 { data: [ Vec2::unit_x,
Vec2::unit_y ] };
pub struct Mat2<T> { data:[Vec2<T> * 2] }
//
// Mat2 Constructor
//
#[inline(always)]
pub pure fn Mat2(m00:float, m01:float,
m10:float, m11:float) -> Mat2 {
pub pure fn Mat2<T:Copy>(m00: T, m01: T,
m10: T, m11: T) -> Mat2<T> {
Mat2 { data: [ Vec2(m00, m01),
Vec2(m10, m11) ] }
}
@ -76,21 +73,28 @@ pub pure fn Mat2(m00:float, m01:float,
// Construct Mat2 from column vectors
//
#[inline(always)]
pub pure fn Mat2_v(col0: &Vec2, col1: &Vec2) -> Mat2 {
Mat2 { data: [ *col0, *col1 ] }
pub pure fn Mat2_v<T:Copy>(col0: &Vec2<T>, col1: &Vec2<T>) -> Mat2<T> {
Mat2 { data: [ *move col0, *move col1 ] }
}
pub mod Mat2 {
pub const zero :Mat2 = Mat2 { data: [ Vec2::zero,
Vec2::zero ] };
pub const identity :Mat2 = Mat2 { data: [ Vec2::unit_x,
Vec2::unit_y ] };
#[inline(always)]
pub pure fn zero<T: Num>() -> Mat2<T> {
Mat2 { data: [ Vec2::zero(),
Vec2::zero() ] }
}
#[inline(always)]
pub pure fn identity<T: Num>() -> Mat2<T> {
Mat2 { data: [ Vec2::unit_x(),
Vec2::unit_y() ] }
}
}
//
// Matrix2x2 Implementation
//
pub impl Mat2: Matrix<float, Vec2> {
pub impl<T:Copy Num Sqrt FuzzyEq> Mat2<T>: Matrix<T, Vec2<T>> {
#[inline(always)]
pure fn rows() -> uint { 2 }
@ -101,62 +105,62 @@ pub impl Mat2: Matrix<float, Vec2> {
pure fn is_col_major() -> bool { true }
#[inline(always)]
pure fn row(i: uint) -> Vec2 {
pure fn row(i: uint) -> Vec2<T> {
Vec2(self[0][i],
self[1][i])
}
#[inline(always)]
pure fn col(i: uint) -> Vec2 {
pure fn col(i: uint) -> Vec2<T> {
self.data[i]
}
#[inline(always)]
pure fn mul_t(value: float) -> Mat2 {
pure fn mul_t(value: T) -> Mat2<T> {
Mat2_v(&self[0].mul_t(value),
&self[1].mul_t(value))
}
#[inline(always)]
pure fn mul_v(other: &Vec2) -> Vec2 {
Vec2(self[0][0]*other[0] + self[1][0]*other[1],
self[0][1]*other[0] + self[1][1]*other[1])
pure fn mul_v(other: &Vec2<T>) -> Vec2<T> {
Vec2(self[0][0] * other[0] + self[1][0] * other[1],
self[0][1] * other[0] + self[1][1] * other[1])
}
#[inline(always)]
pure fn add_m(other: &Mat2) -> Mat2 {
pure fn add_m(other: &Mat2<T>) -> Mat2<T> {
Mat2_v(&self[0].add_v(&other[0]),
&self[1].add_v(&other[1]))
}
#[inline(always)]
pure fn sub_m(other: &Mat2) -> Mat2 {
pure fn sub_m(other: &Mat2<T>) -> Mat2<T> {
Mat2_v(&self[0].sub_v(&other[0]),
&self[1].sub_v(&other[1]))
}
#[inline(always)]
pure fn mul_m(other: &Mat2) -> Mat2 {
Mat2(self[0][0]*other[0][0] + self[1][0]*other[0][1],
self[0][1]*other[0][0] + self[1][1]*other[0][1],
pure fn mul_m(other: &Mat2<T>) -> Mat2<T> {
Mat2(self[0][0] * other[0][0] + self[1][0] * other[0][1],
self[0][1] * other[0][0] + self[1][1] * other[0][1],
self[0][0]*other[1][0] + self[1][0]*other[1][1],
self[0][1]*other[1][0] + self[1][1]*other[1][1])
self[0][0] * other[1][0] + self[1][0] * other[1][1],
self[0][1] * other[1][0] + self[1][1] * other[1][1])
}
// TODO - inversion is harrrd D:
// #[inline(always)]
// pure fn invert(other: &Mat2) -> Mat2 {}
// pure fn invert(other: &Mat2<T>) -> Mat2<T> {}
#[inline(always)]
pure fn transpose() -> Mat2 {
pure fn transpose() -> Mat2<T> {
Mat2(self[0][0], self[1][0],
self[0][1], self[1][1])
}
#[inline(always)]
pure fn is_identity() -> bool {
self.fuzzy_eq(&Mat2::identity)
self.fuzzy_eq(&Mat2::identity())
}
#[inline(always)]
@ -167,65 +171,59 @@ pub impl Mat2: Matrix<float, Vec2> {
#[inline(always)]
pure fn is_diagonal() -> bool {
self[0][1].fuzzy_eq(&0f) &&
self[1][0].fuzzy_eq(&0f)
self[0][1].fuzzy_eq(&from_int(0)) &&
self[1][0].fuzzy_eq(&from_int(0))
}
#[inline(always)]
pure fn is_rotated() -> bool {
!self.fuzzy_eq(&Mat2::identity)
!self.fuzzy_eq(&Mat2::identity())
}
}
pub impl Mat2: Index<uint, Vec2> {
pub impl<T:Copy> Mat2<T>: Index<uint, Vec2<T>> {
#[inline(always)]
pure fn index(i: uint) -> Vec2 {
pure fn index(i: uint) -> Vec2<T> {
self.data[i]
}
}
pub impl Mat2: Neg<Mat2> {
pub impl<T:Copy Neg<T>> Mat2<T>: Neg<Mat2<T>> {
#[inline(always)]
pure fn neg() -> Mat2 {
pure fn neg() -> Mat2<T> {
Mat2_v(&-self[0], &-self[1])
}
}
pub impl Mat2: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Mat2<T>: Eq {
#[inline(always)]
pure fn eq(other: &Mat2) -> bool {
pure fn eq(other: &Mat2<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Mat2) -> bool {
pure fn ne(other: &Mat2<T>) -> bool {
!(self == *other)
}
}
impl Mat2: ExactEq {
impl<T:Copy Eq> Mat2<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Mat2) -> bool {
pure fn exact_eq(other: &Mat2<T>) -> bool {
self[0].exact_eq(&other[0]) &&
self[1].exact_eq(&other[1])
}
}
pub impl Mat2: FuzzyEq {
pub impl<T:Copy FuzzyEq> Mat2<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Mat2) -> bool {
pure fn fuzzy_eq(other: &Mat2<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1])
}
}
pub impl Mat2: ToPtr<float> {
#[inline(always)]
pure fn to_ptr() -> *float {
self[0].to_ptr()
}
}
@ -234,15 +232,15 @@ pub impl Mat2: ToPtr<float> {
//
// Mat3: A 3x3, column major matrix
//
pub struct Mat3 { data:[Vec3 * 3] }
pub struct Mat3<T> { data:[Vec3<T> * 3] }
//
// Mat3 Constructor
//
#[inline(always)]
pub pure fn Mat3(m00:float, m01:float, m02:float,
m10:float, m11:float, m12:float,
m20:float, m21:float, m22:float) -> Mat3 {
pub pure fn Mat3<T:Copy>(m00:T, m01:T, m02:T,
m10:T, m11:T, m12:T,
m20:T, m21:T, m22:T) -> Mat3<T> {
Mat3 { data: [ Vec3(m00, m01, m02),
Vec3(m10, m11, m12),
Vec3(m20, m21, m22) ] }
@ -252,23 +250,30 @@ pub pure fn Mat3(m00:float, m01:float, m02:float,
// Construct Mat3 from column vectors
//
#[inline(always)]
pub pure fn Mat3_v(col0: &Vec3, col1: &Vec3, col2: &Vec3) -> Mat3 {
Mat3 { data: [ *col0, *col1, *col2 ] }
pub pure fn Mat3_v<T:Copy>(col0: &Vec3<T>, col1: &Vec3<T>, col2: &Vec3<T>) -> Mat3<T> {
Mat3 { data: [ *move col0, *move col1, *move col2 ] }
}
pub mod Mat3 {
pub const zero :Mat3 = Mat3 { data: [ Vec3::zero,
Vec3::zero,
Vec3::zero ] };
pub const identity :Mat3 = Mat3 { data: [ Vec3::unit_x,
Vec3::unit_y,
Vec3::unit_z ] };
#[inline(always)]
pub pure fn zero<T: Num>() -> Mat3<T> {
Mat3 { data: [ Vec3::zero(),
Vec3::zero(),
Vec3::zero() ] }
}
#[inline(always)]
pub pure fn identity<T: Num>() -> Mat3<T> {
Mat3 { data: [ Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z() ] }
}
}
//
// Matrix3x3 Implementation
//
pub impl Mat3: Matrix<float, Vec3> {
pub impl<T:Copy Num Sqrt FuzzyEq> Mat3<T>: Matrix<T, Vec3<T>> {
#[inline(always)]
pure fn rows() -> uint { 3 }
@ -279,58 +284,58 @@ pub impl Mat3: Matrix<float, Vec3> {
pure fn is_col_major() -> bool { true }
#[inline(always)]
pure fn row(i: uint) -> Vec3 {
pure fn row(i: uint) -> Vec3<T> {
Vec3(self[0][i],
self[1][i],
self[2][i])
}
#[inline(always)]
pure fn col(i: uint) -> Vec3 {
pure fn col(i: uint) -> Vec3<T> {
self.data[i]
}
#[inline(always)]
pure fn mul_t(value: float) -> Mat3 {
pure fn mul_t(value: T) -> Mat3<T> {
Mat3_v(&self[0].mul_t(value),
&self[1].mul_t(value),
&self[2].mul_t(value))
}
#[inline(always)]
pure fn mul_v(other: &Vec3) -> Vec3 {
Vec3(self[0][0]*other[0] + self[1][0]*other[1] + self[2][0]*other[2],
self[0][1]*other[0] + self[1][1]*other[1] + self[2][1]*other[2],
self[0][2]*other[0] + self[1][2]*other[1] + self[2][2]*other[2])
pure fn mul_v(other: &Vec3<T>) -> Vec3<T> {
Vec3(self[0][0] * other[0] + self[1][0] * other[1] + self[2][0] * other[2],
self[0][1] * other[0] + self[1][1] * other[1] + self[2][1] * other[2],
self[0][2] * other[0] + self[1][2] * other[1] + self[2][2] * other[2])
}
#[inline(always)]
pure fn add_m(other: &Mat3) -> Mat3 {
pure fn add_m(other: &Mat3<T>) -> Mat3<T> {
Mat3_v(&self[0].add_v(&other[0]),
&self[1].add_v(&other[1]),
&self[2].add_v(&other[2]))
}
#[inline(always)]
pure fn sub_m(other: &Mat3) -> Mat3 {
pure fn sub_m(other: &Mat3<T>) -> Mat3<T> {
Mat3_v(&self[0].sub_v(&other[0]),
&self[1].sub_v(&other[1]),
&self[2].sub_v(&other[2]))
}
#[inline(always)]
pure fn mul_m(other: &Mat3) -> Mat3 {
Mat3(self[0][0]*other[0][0] + self[1][0]*other[0][1] + self[2][0]*other[0][2],
self[0][1]*other[0][0] + self[1][1]*other[0][1] + self[2][1]*other[0][2],
self[0][2]*other[0][0] + self[1][2]*other[0][1] + self[2][2]*other[0][2],
pure fn mul_m(other: &Mat3<T>) -> Mat3<T> {
Mat3(self[0][0] * other[0][0] + self[1][0] * other[0][1] + self[2][0] * other[0][2],
self[0][1] * other[0][0] + self[1][1] * other[0][1] + self[2][1] * other[0][2],
self[0][2] * other[0][0] + self[1][2] * other[0][1] + self[2][2] * other[0][2],
self[0][0]*other[1][0] + self[1][0]*other[1][1] + self[2][0]*other[1][2],
self[0][1]*other[1][0] + self[1][1]*other[1][1] + self[2][1]*other[1][2],
self[0][2]*other[1][0] + self[1][2]*other[1][1] + self[2][2]*other[1][2],
self[0][0] * other[1][0] + self[1][0] * other[1][1] + self[2][0] * other[1][2],
self[0][1] * other[1][0] + self[1][1] * other[1][1] + self[2][1] * other[1][2],
self[0][2] * other[1][0] + self[1][2] * other[1][1] + self[2][2] * other[1][2],
self[0][0]*other[2][0] + self[1][0]*other[2][1] + self[2][0]*other[2][2],
self[0][1]*other[2][0] + self[1][1]*other[2][1] + self[2][1]*other[2][2],
self[0][2]*other[2][0] + self[1][2]*other[2][1] + self[2][2]*other[2][2])
self[0][0] * other[2][0] + self[1][0] * other[2][1] + self[2][0] * other[2][2],
self[0][1] * other[2][0] + self[1][1] * other[2][1] + self[2][1] * other[2][2],
self[0][2] * other[2][0] + self[1][2] * other[2][1] + self[2][2] * other[2][2])
}
// TODO - inversion is harrrd D:
@ -338,7 +343,7 @@ pub impl Mat3: Matrix<float, Vec3> {
// pure fn invert(other: &Mat3) -> Mat3 {}
#[inline(always)]
pure fn transpose() -> Mat3 {
pure fn transpose() -> Mat3<T> {
Mat3(self[0][0], self[1][0], self[2][0],
self[0][1], self[1][1], self[2][1],
self[0][2], self[1][2], self[2][2])
@ -346,7 +351,7 @@ pub impl Mat3: Matrix<float, Vec3> {
#[inline(always)]
pure fn is_identity() -> bool {
self.fuzzy_eq(&Mat3::identity)
self.fuzzy_eq(&Mat3::identity())
}
#[inline(always)]
@ -363,126 +368,130 @@ pub impl Mat3: Matrix<float, Vec3> {
#[inline(always)]
pure fn is_diagonal() -> bool {
self[0][1].fuzzy_eq(&0f) &&
self[0][2].fuzzy_eq(&0f) &&
self[0][1].fuzzy_eq(&from_int(0)) &&
self[0][2].fuzzy_eq(&from_int(0)) &&
self[1][0].fuzzy_eq(&0f) &&
self[1][2].fuzzy_eq(&0f) &&
self[1][0].fuzzy_eq(&from_int(0)) &&
self[1][2].fuzzy_eq(&from_int(0)) &&
self[2][0].fuzzy_eq(&0f) &&
self[2][1].fuzzy_eq(&0f)
self[2][0].fuzzy_eq(&from_int(0)) &&
self[2][1].fuzzy_eq(&from_int(0))
}
#[inline(always)]
pure fn is_rotated() -> bool {
!self.fuzzy_eq(&Mat3::identity)
!self.fuzzy_eq(&Mat3::identity())
}
}
pub impl Mat3: Matrix3<Vec3> {
pub impl<T:Copy Num Sqrt FuzzyEq> Mat3<T>: Matrix3<T> {
#[inline(always)]
pure fn scale(vec: &Vec3) -> Mat3 {
self.mul_m(&Mat3(vec.x, 0f, 0f,
0f, vec.y, 0f,
0f, 0f, vec.z))
pure fn scale(vec: &Vec3<T>) -> Mat3<T> {
self.mul_m(&Mat3( vec.x, from_int(0), from_int(0),
from_int(0), vec.y, from_int(0),
from_int(0), from_int(0), vec.z))
}
#[inline(always)]
pure fn to_Mat4() -> Mat4 {
Mat4(self[0][0], self[0][1], self[0][2], 0f,
self[1][0], self[1][1], self[1][2], 0f,
self[2][0], self[2][1], self[2][2], 0f,
0f, 0f, 0f, 1f)
pure fn to_Mat4() -> Mat4<T> {
Mat4( self[0][0], self[0][1], self[0][2], from_int(0),
self[1][0], self[1][1], self[1][2], from_int(0),
self[2][0], self[2][1], self[2][2], from_int(0),
from_int(0), from_int(0), from_int(0), from_int(1))
}
pure fn to_Quat() -> Quat {
}
pub impl<T:Copy Num NumCast Ord> Mat3<T>: ToQuat<T> {
pure fn to_Quat() -> Quat<T> {
// Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's
// paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf
let mut s:float;
let w:float, x:float, y:float, z:float;
let trace:float = self[0][0] + self[1][1] + self[2][2];
let mut s: float;
let w: float, x: float, y: float, z: float;
let trace: float = cast(self[0][0] + self[1][1] + self[2][2]);
if trace >= 0f {
if trace >= from_int(0) {
s = (trace + 1f).sqrt();
w = 0.5 * s;
s = 0.5 / s;
x = self[1][2] - self[2][1] * s;
y = self[2][0] - self[0][2] * s;
z = self[0][1] - self[1][0] * s;
x = (self[1][2] - self[2][1]).cast::<float>() * s;
y = (self[2][0] - self[0][2]).cast::<float>() * s;
z = (self[0][1] - self[1][0]).cast::<float>() * s;
} else if (self[0][0] > self[1][1]) && (self[0][0] > self[2][2]) {
s = (1f + self[0][0] - self[1][1] - self[2][2]).sqrt();
s = (1f + (self[0][0] - self[1][1] - self[2][2]).cast::<float>()).sqrt();
w = 0.5 * s;
s = 0.5 / s;
x = self[0][1] - self[1][0] * s;
y = self[2][0] - self[0][2] * s;
z = self[1][2] - self[2][1] * s;
x = (self[0][1] - self[1][0]).cast::<float>() * s;
y = (self[2][0] - self[0][2]).cast::<float>() * s;
z = (self[1][2] - self[2][1]).cast::<float>() * s;
} else if self[1][1] > self[2][2] {
s = (1f + self[1][1] - self[0][0] - self[2][2]).sqrt();
s = (1f + (self[1][1] - self[0][0] - self[2][2]).cast::<float>()).sqrt();
w = 0.5 * s;
s = 0.5 / s;
x = self[0][1] - self[1][0] * s;
y = self[1][2] - self[2][1] * s;
z = self[2][0] - self[0][2] * s;
x = (self[0][1] - self[1][0]).cast::<float>() * s;
y = (self[1][2] - self[2][1]).cast::<float>() * s;
z = (self[2][0] - self[0][2]).cast::<float>() * s;
} else {
s = (1f + self[2][2] - self[0][0] - self[1][1]).sqrt();
s = (1f + (self[2][2] - self[0][0] - self[1][1]).cast::<float>()).sqrt();
w = 0.5 * s;
s = 0.5 / s;
x = self[2][0] - self[0][2] * s;
y = self[1][2] - self[2][1] * s;
z = self[0][1] - self[1][0] * s;
x = (self[2][0] - self[0][2]).cast::<float>() * s;
y = (self[1][2] - self[2][1]).cast::<float>() * s;
z = (self[0][1] - self[1][0]).cast::<float>() * s;
}
return Quat(w, x, y, z);
Quat(from(w), from(x), from(y), from(z))
}
}
pub impl Mat3: Index<uint, Vec3> {
pub impl<T:Copy> Mat3<T>: Index<uint, Vec3<T>> {
#[inline(always)]
pure fn index(i: uint) -> Vec3 {
pure fn index(i: uint) -> Vec3<T> {
self.data[i]
}
}
pub impl Mat3: Neg<Mat3> {
pub impl<T:Copy Neg<T>> Mat3<T>: Neg<Mat3<T>> {
#[inline(always)]
pure fn neg() -> Mat3 {
pure fn neg() -> Mat3<T> {
Mat3_v(&-self[0], &-self[1], &-self[2])
}
}
pub impl Mat3: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Mat3<T>: Eq {
#[inline(always)]
pure fn eq(other: &Mat3) -> bool {
pure fn eq(other: &Mat3<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Mat3) -> bool {
pure fn ne(other: &Mat3<T>) -> bool {
!(self == *other)
}
}
impl Mat3: ExactEq {
pub impl<T:Copy Eq> Mat3<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Mat3) -> bool {
pure fn exact_eq(other: &Mat3<T>) -> bool {
self[0].exact_eq(&other[0]) &&
self[1].exact_eq(&other[1]) &&
self[2].exact_eq(&other[2])
}
}
pub impl Mat3: FuzzyEq {
pub impl<T:Copy FuzzyEq> Mat3<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Mat3) -> bool {
pure fn fuzzy_eq(other: &Mat3<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1]) &&
self[2].fuzzy_eq(&other[2])
}
}
pub impl Mat3: ToPtr<float> {
pub impl<T:Copy> Mat3<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
self[0].to_ptr()
}
}
@ -495,16 +504,16 @@ pub impl Mat3: ToPtr<float> {
//
// Mat4: A 4x4, column major matrix
//
pub struct Mat4 { data:[Vec4 * 4] }
pub struct Mat4<T> { data:[Vec4<T> * 4] }
//
// Mat4 Constructor
//
#[inline(always)]
pub pure fn Mat4(m00:float, m01:float, m02:float, m03:float,
m10:float, m11:float, m12:float, m13:float,
m20:float, m21:float, m22:float, m23:float,
m30:float, m31:float, m32:float, m33:float) -> Mat4 {
pub pure fn Mat4<T:Copy>(m00: T, m01: T, m02: T, m03: T,
m10: T, m11: T, m12: T, m13: T,
m20: T, m21: T, m22: T, m23: T,
m30: T, m31: T, m32: T, m33: T) -> Mat4<T> {
Mat4 { data: [ Vec4(m00, m01, m02, m03),
Vec4(m10, m11, m12, m13),
Vec4(m20, m21, m22, m23),
@ -515,25 +524,32 @@ pub pure fn Mat4(m00:float, m01:float, m02:float, m03:float,
// Construct Mat4 from column vectors
//
#[inline(always)]
pub pure fn Mat4_v(col0: &Vec4, col1: &Vec4, col2: &Vec4, col3: &Vec4) -> Mat4 {
Mat4 { data: [ *col0, *col1, *col2, *col3 ] }
pub pure fn Mat4_v<T:Copy>(col0: &Vec4<T>, col1: &Vec4<T>, col2: &Vec4<T>, col3: &Vec4<T>) -> Mat4<T> {
Mat4 { data: [ *move col0, *move col1, *move col2, *move col3 ] }
}
pub mod Mat4 {
pub const zero :Mat4 = Mat4 { data: [ Vec4::zero,
Vec4::zero,
Vec4::zero,
Vec4::zero ] };
pub const identity :Mat4 = Mat4 { data: [ Vec4::unit_x,
Vec4::unit_y,
Vec4::unit_z,
Vec4::unit_w ] };
#[inline(always)]
pub pure fn zero<T: Num>() -> Mat4<T> {
Mat4 { data: [ Vec4::zero(),
Vec4::zero(),
Vec4::zero(),
Vec4::zero() ] }
}
#[inline(always)]
pub pure fn identity<T: Num>() -> Mat4<T> {
Mat4 { data: [ Vec4::unit_x(),
Vec4::unit_y(),
Vec4::unit_z(),
Vec4::unit_w() ] }
}
}
//
// Matrix4x4 Implementation
//
pub impl Mat4: Matrix<float, Vec4> {
pub impl<T:Copy Num Sqrt FuzzyEq> Mat4<T>: Matrix<T, Vec4<T>> {
#[inline(always)]
pure fn rows() -> uint { 4 }
@ -544,7 +560,7 @@ pub impl Mat4: Matrix<float, Vec4> {
pure fn is_col_major() -> bool { true }
#[inline(always)]
pure fn row(i: uint) -> Vec4 {
pure fn row(i: uint) -> Vec4<T> {
Vec4(self[0][i],
self[1][i],
self[2][i],
@ -552,12 +568,12 @@ pub impl Mat4: Matrix<float, Vec4> {
}
#[inline(always)]
pure fn col(i: uint) -> Vec4 {
pure fn col(i: uint) -> Vec4<T> {
self.data[i]
}
#[inline(always)]
pure fn mul_t(value: float) -> Mat4 {
pure fn mul_t(value: T) -> Mat4<T> {
Mat4_v(&self[0].mul_t(value),
&self[1].mul_t(value),
&self[2].mul_t(value),
@ -565,15 +581,15 @@ pub impl Mat4: Matrix<float, Vec4> {
}
#[inline(always)]
pure fn mul_v(other: &Vec4) -> Vec4 {
Vec4(self[0][0]*other[0] + self[1][0]*other[1] + self[2][0]*other[2] + self[3][0]*other[3],
self[0][1]*other[0] + self[1][1]*other[1] + self[2][1]*other[2] + self[3][1]*other[3],
self[0][2]*other[0] + self[1][2]*other[1] + self[2][2]*other[2] + self[3][2]*other[3],
self[0][3]*other[0] + self[1][3]*other[1] + self[2][3]*other[2] + self[3][3]*other[3])
pure fn mul_v(other: &Vec4<T>) -> Vec4<T> {
Vec4(self[0][0] * other[0] + self[1][0] * other[1] + self[2][0] * other[2] + self[3][0] * other[3],
self[0][1] * other[0] + self[1][1] * other[1] + self[2][1] * other[2] + self[3][1] * other[3],
self[0][2] * other[0] + self[1][2] * other[1] + self[2][2] * other[2] + self[3][2] * other[3],
self[0][3] * other[0] + self[1][3] * other[1] + self[2][3] * other[2] + self[3][3] * other[3])
}
#[inline(always)]
pure fn add_m(other: &Mat4) -> Mat4 {
pure fn add_m(other: &Mat4<T>) -> Mat4<T> {
Mat4_v(&self[0].add_v(&other[0]),
&self[1].add_v(&other[1]),
&self[2].add_v(&other[2]),
@ -581,7 +597,7 @@ pub impl Mat4: Matrix<float, Vec4> {
}
#[inline(always)]
pure fn sub_m(other: &Mat4) -> Mat4 {
pure fn sub_m(other: &Mat4<T>) -> Mat4<T> {
Mat4_v(&self[0].sub_v(&other[0]),
&self[1].sub_v(&other[1]),
&self[2].sub_v(&other[2]),
@ -589,34 +605,34 @@ pub impl Mat4: Matrix<float, Vec4> {
}
#[inline(always)]
pure fn mul_m(other: &Mat4) -> Mat4 {
Mat4(self[0][0]*other[0][0] + self[1][0]*other[0][1] + self[2][0]*other[0][2] + self[3][0]*other[0][3],
self[0][1]*other[0][0] + self[1][1]*other[0][1] + self[2][1]*other[0][2] + self[3][1]*other[0][3],
self[0][2]*other[0][0] + self[1][2]*other[0][1] + self[2][2]*other[0][2] + self[3][2]*other[0][3],
self[0][3]*other[0][0] + self[1][3]*other[0][1] + self[2][3]*other[0][2] + self[3][3]*other[0][3],
pure fn mul_m(other: &Mat4<T>) -> Mat4<T> {
Mat4(self[0][0] * other[0][0] + self[1][0] * other[0][1] + self[2][0] * other[0][2] + self[3][0] * other[0][3],
self[0][1] * other[0][0] + self[1][1] * other[0][1] + self[2][1] * other[0][2] + self[3][1] * other[0][3],
self[0][2] * other[0][0] + self[1][2] * other[0][1] + self[2][2] * other[0][2] + self[3][2] * other[0][3],
self[0][3] * other[0][0] + self[1][3] * other[0][1] + self[2][3] * other[0][2] + self[3][3] * other[0][3],
self[0][0]*other[1][0] + self[1][0]*other[1][1] + self[2][0]*other[1][2] + self[3][0]*other[1][3],
self[0][1]*other[1][0] + self[1][1]*other[1][1] + self[2][1]*other[1][2] + self[3][1]*other[1][3],
self[0][2]*other[1][0] + self[1][2]*other[1][1] + self[2][2]*other[1][2] + self[3][2]*other[1][3],
self[0][3]*other[1][0] + self[1][3]*other[1][1] + self[2][3]*other[1][2] + self[3][3]*other[1][3],
self[0][0] * other[1][0] + self[1][0] * other[1][1] + self[2][0] * other[1][2] + self[3][0] * other[1][3],
self[0][1] * other[1][0] + self[1][1] * other[1][1] + self[2][1] * other[1][2] + self[3][1] * other[1][3],
self[0][2] * other[1][0] + self[1][2] * other[1][1] + self[2][2] * other[1][2] + self[3][2] * other[1][3],
self[0][3] * other[1][0] + self[1][3] * other[1][1] + self[2][3] * other[1][2] + self[3][3] * other[1][3],
self[0][0]*other[2][0] + self[1][0]*other[2][1] + self[2][0]*other[2][2] + self[3][0]*other[2][3],
self[0][1]*other[2][0] + self[1][1]*other[2][1] + self[2][1]*other[2][2] + self[3][1]*other[2][3],
self[0][2]*other[2][0] + self[1][2]*other[2][1] + self[2][2]*other[2][2] + self[3][2]*other[2][3],
self[0][3]*other[2][0] + self[1][3]*other[2][1] + self[2][3]*other[2][2] + self[3][3]*other[2][3],
self[0][0] * other[2][0] + self[1][0] * other[2][1] + self[2][0] * other[2][2] + self[3][0] * other[2][3],
self[0][1] * other[2][0] + self[1][1] * other[2][1] + self[2][1] * other[2][2] + self[3][1] * other[2][3],
self[0][2] * other[2][0] + self[1][2] * other[2][1] + self[2][2] * other[2][2] + self[3][2] * other[2][3],
self[0][3] * other[2][0] + self[1][3] * other[2][1] + self[2][3] * other[2][2] + self[3][3] * other[2][3],
self[0][0]*other[3][0] + self[1][0]*other[3][1] + self[2][0]*other[3][2] + self[3][0]*other[3][3],
self[0][1]*other[3][0] + self[1][1]*other[3][1] + self[2][1]*other[3][2] + self[3][1]*other[3][3],
self[0][2]*other[3][0] + self[1][2]*other[3][1] + self[2][2]*other[3][2] + self[3][2]*other[3][3],
self[0][3]*other[3][0] + self[1][3]*other[3][1] + self[2][3]*other[3][2] + self[3][3]*other[3][3])
self[0][0] * other[3][0] + self[1][0] * other[3][1] + self[2][0] * other[3][2] + self[3][0] * other[3][3],
self[0][1] * other[3][0] + self[1][1] * other[3][1] + self[2][1] * other[3][2] + self[3][1] * other[3][3],
self[0][2] * other[3][0] + self[1][2] * other[3][1] + self[2][2] * other[3][2] + self[3][2] * other[3][3],
self[0][3] * other[3][0] + self[1][3] * other[3][1] + self[2][3] * other[3][2] + self[3][3] * other[3][3])
}
// TODO - inversion is harrrd D:
// #[inline(always)]
// pure fn invert(other: &Mat4) -> Mat4 {}
// pure fn invert(other: &Mat4<T>) -> Mat4<T> {}
#[inline(always)]
pure fn transpose() -> Mat4 {
pure fn transpose() -> Mat4<T> {
Mat4(self[0][0], self[1][0], self[2][0], self[3][0],
self[0][1], self[1][1], self[2][1], self[3][1],
self[0][2], self[1][2], self[2][2], self[3][2],
@ -625,7 +641,7 @@ pub impl Mat4: Matrix<float, Vec4> {
#[inline(always)]
pure fn is_identity() -> bool {
self.fuzzy_eq(&Mat4::identity)
self.fuzzy_eq(&Mat4::identity())
}
#[inline(always)]
@ -649,40 +665,40 @@ pub impl Mat4: Matrix<float, Vec4> {
#[inline(always)]
pure fn is_diagonal() -> bool {
self[0][1].fuzzy_eq(&0f) &&
self[0][2].fuzzy_eq(&0f) &&
self[0][3].fuzzy_eq(&0f) &&
self[0][1].fuzzy_eq(&from_int(0)) &&
self[0][2].fuzzy_eq(&from_int(0)) &&
self[0][3].fuzzy_eq(&from_int(0)) &&
self[1][0].fuzzy_eq(&0f) &&
self[1][2].fuzzy_eq(&0f) &&
self[1][3].fuzzy_eq(&0f) &&
self[1][0].fuzzy_eq(&from_int(0)) &&
self[1][2].fuzzy_eq(&from_int(0)) &&
self[1][3].fuzzy_eq(&from_int(0)) &&
self[2][0].fuzzy_eq(&0f) &&
self[2][1].fuzzy_eq(&0f) &&
self[2][3].fuzzy_eq(&0f) &&
self[2][0].fuzzy_eq(&from_int(0)) &&
self[2][1].fuzzy_eq(&from_int(0)) &&
self[2][3].fuzzy_eq(&from_int(0)) &&
self[3][0].fuzzy_eq(&0f) &&
self[3][1].fuzzy_eq(&0f) &&
self[3][2].fuzzy_eq(&0f)
self[3][0].fuzzy_eq(&from_int(0)) &&
self[3][1].fuzzy_eq(&from_int(0)) &&
self[3][2].fuzzy_eq(&from_int(0))
}
#[inline(always)]
pure fn is_rotated() -> bool {
!self.fuzzy_eq(&Mat4::identity)
!self.fuzzy_eq(&Mat4::identity())
}
}
pub impl Mat4: Matrix4<Vec3, Vec4> {
pub impl<T:Copy Num Sqrt FuzzyEq> Mat4<T>: Matrix4<T> {
#[inline(always)]
pure fn scale(vec: &Vec3) -> Mat4 {
self.mul_m(&Mat4(vec.x, 0f, 0f, 0f,
0f, vec.y, 0f, 0f,
0f, 0f, vec.z, 0f,
0f, 0f, 0f, 1f))
pure fn scale(vec: &Vec3<T>) -> Mat4<T> {
self.mul_m(&Mat4( vec.x, from_int(0), from_int(0), from_int(0),
from_int(0), vec.y, from_int(0), from_int(0),
from_int(0), from_int(0), vec.z, from_int(0),
from_int(0), from_int(0), from_int(0), from_int(1)))
}
#[inline(always)]
pure fn translate(vec: &Vec3) -> Mat4 {
pure fn translate(vec: &Vec3<T>) -> Mat4<T> {
Mat4_v(&self[0],
&self[1],
&self[2],
@ -693,35 +709,36 @@ pub impl Mat4: Matrix4<Vec3, Vec4> {
}
}
pub impl Mat4: Index<uint, Vec4> {
pub impl<T:Copy> Mat4<T>: Index<uint, Vec4<T>> {
#[inline(always)]
pure fn index(i: uint) -> Vec4 {
pure fn index(i: uint) -> Vec4<T> {
self.data[i]
}
}
pub impl Mat4: Neg<Mat4> {
pub impl<T:Copy Neg<T>> Mat4<T>: Neg<Mat4<T>> {
#[inline(always)]
pure fn neg() -> Mat4 {
pure fn neg() -> Mat4<T> {
Mat4_v(&-self[0], &-self[1], &-self[2], &-self[3])
}
}
pub impl Mat4: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Mat4<T>: Eq {
#[inline(always)]
pure fn eq(other: &Mat4) -> bool {
pure fn eq(other: &Mat4<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Mat4) -> bool {
pure fn ne(other: &Mat4<T>) -> bool {
!(self == *other)
}
}
impl Mat4: ExactEq {
pub impl<T:Copy Eq> Mat4<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Mat4) -> bool {
pure fn exact_eq(other: &Mat4<T>) -> bool {
self[0].exact_eq(&other[0]) &&
self[1].exact_eq(&other[1]) &&
self[2].exact_eq(&other[2]) &&
@ -729,9 +746,9 @@ impl Mat4: ExactEq {
}
}
pub impl Mat4: FuzzyEq {
pub impl<T:Copy FuzzyEq> Mat4<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Mat4) -> bool {
pure fn fuzzy_eq(other: &Mat4<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1]) &&
self[2].fuzzy_eq(&other[2]) &&
@ -739,9 +756,9 @@ pub impl Mat4: FuzzyEq {
}
}
pub impl Mat4: ToPtr<float> {
pub impl<T:Copy> Mat4<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
self[0].to_ptr()
}
}

428
src/num_util.rs Normal file
View file

@ -0,0 +1,428 @@
trait UnSigned {} // Needs trait inheritence to work properly
pub impl u8: UnSigned {}
pub impl u16: UnSigned {}
pub impl u32: UnSigned {}
pub impl u64: UnSigned {}
pub impl uint: UnSigned {}
trait Signed {} // Needs trait inheritence to work properly
pub impl<T: Neg<T>> T: Signed {}
trait Integer {} // Needs trait inheritence to work properly
pub impl u8: Integer {}
pub impl u16: Integer {}
pub impl u32: Integer {}
pub impl u64: Integer {}
pub impl uint: Integer {}
pub impl i8: Integer {}
pub impl i16: Integer {}
pub impl i32: Integer {}
pub impl i64: Integer {}
pub impl int: Integer {}
trait FloatingPoint {} // Needs trait inheritence to work properly
pub impl f32: FloatingPoint {}
pub impl f64: FloatingPoint {}
pub impl float: FloatingPoint {}
pub impl u8 : Add<u8,u8> { #[inline(always)] pure fn add(rhs: &u8) -> u8 { self + *rhs } }
pub impl u16 : Add<u16,u16> { #[inline(always)] pure fn add(rhs: &u16) -> u16 { self + *rhs } }
pub impl u32 : Add<u32,u32> { #[inline(always)] pure fn add(rhs: &u32) -> u32 { self + *rhs } }
pub impl u64 : Add<u64,u64> { #[inline(always)] pure fn add(rhs: &u64) -> u64 { self + *rhs } }
pub impl uint : Add<uint,uint> { #[inline(always)] pure fn add(rhs: &uint) -> uint { self + *rhs } }
pub impl i8 : Add<i8,i8> { #[inline(always)] pure fn add(rhs: &i8) -> i8 { self + *rhs } }
pub impl i16 : Add<i16,i16> { #[inline(always)] pure fn add(rhs: &i16) -> i16 { self + *rhs } }
pub impl i32 : Add<i32,i32> { #[inline(always)] pure fn add(rhs: &i32) -> i32 { self + *rhs } }
pub impl i64 : Add<i64,i64> { #[inline(always)] pure fn add(rhs: &i64) -> i64 { self + *rhs } }
pub impl int : Add<int,int> { #[inline(always)] pure fn add(rhs: &int) -> int { self + *rhs } }
pub impl f32 : Add<f32,f32> { #[inline(always)] pure fn add(rhs: &f32) -> f32 { self + *rhs } }
pub impl f64 : Add<f64,f64> { #[inline(always)] pure fn add(rhs: &f64) -> f64 { self + *rhs } }
pub impl float : Add<float,float> { #[inline(always)] pure fn add(rhs: &float) -> float { self + *rhs } }
pub impl u8 : Sub<u8,u8> { #[inline(always)] pure fn sub(rhs: &u8) -> u8 { self - *rhs } }
pub impl u16 : Sub<u16,u16> { #[inline(always)] pure fn sub(rhs: &u16) -> u16 { self - *rhs } }
pub impl u32 : Sub<u32,u32> { #[inline(always)] pure fn sub(rhs: &u32) -> u32 { self - *rhs } }
pub impl u64 : Sub<u64,u64> { #[inline(always)] pure fn sub(rhs: &u64) -> u64 { self - *rhs } }
pub impl uint : Sub<uint,uint> { #[inline(always)] pure fn sub(rhs: &uint) -> uint { self - *rhs } }
pub impl i8 : Sub<i8,i8> { #[inline(always)] pure fn sub(rhs: &i8) -> i8 { self - *rhs } }
pub impl i16 : Sub<i16,i16> { #[inline(always)] pure fn sub(rhs: &i16) -> i16 { self - *rhs } }
pub impl i32 : Sub<i32,i32> { #[inline(always)] pure fn sub(rhs: &i32) -> i32 { self - *rhs } }
pub impl i64 : Sub<i64,i64> { #[inline(always)] pure fn sub(rhs: &i64) -> i64 { self - *rhs } }
pub impl int : Sub<int,int> { #[inline(always)] pure fn sub(rhs: &int) -> int { self - *rhs } }
pub impl f32 : Sub<f32,f32> { #[inline(always)] pure fn sub(rhs: &f32) -> f32 { self - *rhs } }
pub impl f64 : Sub<f64,f64> { #[inline(always)] pure fn sub(rhs: &f64) -> f64 { self - *rhs } }
pub impl float : Sub<float,float> { #[inline(always)] pure fn sub(rhs: &float) -> float { self - *rhs } }
pub impl u8 : Mul<u8,u8> { #[inline(always)] pure fn mul(rhs: &u8) -> u8 { self * *rhs } }
pub impl u16 : Mul<u16,u16> { #[inline(always)] pure fn mul(rhs: &u16) -> u16 { self * *rhs } }
pub impl u32 : Mul<u32,u32> { #[inline(always)] pure fn mul(rhs: &u32) -> u32 { self * *rhs } }
pub impl u64 : Mul<u64,u64> { #[inline(always)] pure fn mul(rhs: &u64) -> u64 { self * *rhs } }
pub impl uint : Mul<uint,uint> { #[inline(always)] pure fn mul(rhs: &uint) -> uint { self * *rhs } }
pub impl i8 : Mul<i8,i8> { #[inline(always)] pure fn mul(rhs: &i8) -> i8 { self * *rhs } }
pub impl i16 : Mul<i16,i16> { #[inline(always)] pure fn mul(rhs: &i16) -> i16 { self * *rhs } }
pub impl i32 : Mul<i32,i32> { #[inline(always)] pure fn mul(rhs: &i32) -> i32 { self * *rhs } }
pub impl i64 : Mul<i64,i64> { #[inline(always)] pure fn mul(rhs: &i64) -> i64 { self * *rhs } }
pub impl int : Mul<int,int> { #[inline(always)] pure fn mul(rhs: &int) -> int { self * *rhs } }
pub impl f32 : Mul<f32,f32> { #[inline(always)] pure fn mul(rhs: &f32) -> f32 { self * *rhs } }
pub impl f64 : Mul<f64,f64> { #[inline(always)] pure fn mul(rhs: &f64) -> f64 { self * *rhs } }
pub impl float : Mul<float,float> { #[inline(always)] pure fn mul(rhs: &float) -> float { self * *rhs } }
pub impl u8 : Div<u8,u8> { #[inline(always)] pure fn div(rhs: &u8) -> u8 { self / *rhs } }
pub impl u16 : Div<u16,u16> { #[inline(always)] pure fn div(rhs: &u16) -> u16 { self / *rhs } }
pub impl u32 : Div<u32,u32> { #[inline(always)] pure fn div(rhs: &u32) -> u32 { self / *rhs } }
pub impl u64 : Div<u64,u64> { #[inline(always)] pure fn div(rhs: &u64) -> u64 { self / *rhs } }
pub impl uint : Div<uint,uint> { #[inline(always)] pure fn div(rhs: &uint) -> uint { self / *rhs } }
pub impl i8 : Div<i8,i8> { #[inline(always)] pure fn div(rhs: &i8) -> i8 { self / *rhs } }
pub impl i16 : Div<i16,i16> { #[inline(always)] pure fn div(rhs: &i16) -> i16 { self / *rhs } }
pub impl i32 : Div<i32,i32> { #[inline(always)] pure fn div(rhs: &i32) -> i32 { self / *rhs } }
pub impl i64 : Div<i64,i64> { #[inline(always)] pure fn div(rhs: &i64) -> i64 { self / *rhs } }
pub impl int : Div<int,int> { #[inline(always)] pure fn div(rhs: &int) -> int { self / *rhs } }
pub impl f32 : Div<f32,f32> { #[inline(always)] pure fn div(rhs: &f32) -> f32 { self / *rhs } }
pub impl f64 : Div<f64,f64> { #[inline(always)] pure fn div(rhs: &f64) -> f64 { self / *rhs } }
pub impl float : Div<float,float> { #[inline(always)] pure fn div(rhs: &float) -> float { self / *rhs } }
pub impl u8 : Modulo<u8,u8> { #[inline(always)] pure fn modulo(rhs: &u8) -> u8 { self % *rhs } }
pub impl u16 : Modulo<u16,u16> { #[inline(always)] pure fn modulo(rhs: &u16) -> u16 { self % *rhs } }
pub impl u32 : Modulo<u32,u32> { #[inline(always)] pure fn modulo(rhs: &u32) -> u32 { self % *rhs } }
pub impl u64 : Modulo<u64,u64> { #[inline(always)] pure fn modulo(rhs: &u64) -> u64 { self % *rhs } }
pub impl uint : Modulo<uint,uint> { #[inline(always)] pure fn modulo(rhs: &uint) -> uint { self % *rhs } }
pub impl i8 : Modulo<i8,i8> { #[inline(always)] pure fn modulo(rhs: &i8) -> i8 { self % *rhs } }
pub impl i16 : Modulo<i16,i16> { #[inline(always)] pure fn modulo(rhs: &i16) -> i16 { self % *rhs } }
pub impl i32 : Modulo<i32,i32> { #[inline(always)] pure fn modulo(rhs: &i32) -> i32 { self % *rhs } }
pub impl i64 : Modulo<i64,i64> { #[inline(always)] pure fn modulo(rhs: &i64) -> i64 { self % *rhs } }
pub impl int : Modulo<int,int> { #[inline(always)] pure fn modulo(rhs: &int) -> int { self % *rhs } }
pub impl f32 : Modulo<f32,f32> { #[inline(always)] pure fn modulo(rhs: &f32) -> f32 { self % *rhs } }
pub impl f64 : Modulo<f64,f64> { #[inline(always)] pure fn modulo(rhs: &f64) -> f64 { self % *rhs } }
pub impl float : Modulo<float,float> { #[inline(always)] pure fn modulo(rhs: &float) -> float { self % *rhs } }
pub impl i8 : Neg<i8> { #[inline(always)] pure fn neg() -> i8 { -self } }
pub impl i16 : Neg<i16> { #[inline(always)] pure fn neg() -> i16 { -self } }
pub impl i32 : Neg<i32> { #[inline(always)] pure fn neg() -> i32 { -self } }
pub impl i64 : Neg<i64> { #[inline(always)] pure fn neg() -> i64 { -self } }
pub impl int : Neg<int> { #[inline(always)] pure fn neg() -> int { -self } }
pub impl f32 : Neg<f32> { #[inline(always)] pure fn neg() -> f32 { -self } }
pub impl f64 : Neg<f64> { #[inline(always)] pure fn neg() -> f64 { -self } }
pub impl float : Neg<float> { #[inline(always)] pure fn neg() -> float { -self } }
trait NumCast {
static pure fn from<T:NumCast>(n: T) -> self;
pure fn cast<T:NumCast>() -> T;
pure fn cast_u8() -> u8;
pure fn cast_u16() -> u16;
pure fn cast_u32() -> u32;
pure fn cast_u64() -> u64;
pure fn cast_uint() -> uint;
pure fn cast_i8() -> i8;
pure fn cast_i16() -> i16;
pure fn cast_i32() -> i32;
pure fn cast_i64() -> i64;
pure fn cast_int() -> int;
pure fn cast_f32() -> f32;
pure fn cast_f64() -> f64;
pure fn cast_float() -> float;
}
#[inline(always)]
pub pure fn cast<T:NumCast, U:NumCast>(n: T) -> U { n.cast() }
pub impl u8: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> u8 { n.cast_u8() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl u16: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> u16 { n.cast_u16() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl u32: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> u32 { n.cast_u32() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl u64: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> u64 { n.cast_u64() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl uint: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> uint { n.cast_uint() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl i8: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> i8 { n.cast_i8() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl i16: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> i16 { n.cast_i16() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl i32: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> i32 { n.cast_i32() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl i64: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> i64 { n.cast_i64() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl int: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> int { n.cast_int() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl f32: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> f32 { n.cast_f32() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl f64: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> f64 { n.cast_f64() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self }
#[inline(always)] pure fn cast_float() -> float { self as float }
}
pub impl float: NumCast {
#[inline(always)] static pure fn from<T:NumCast>(n: T) -> float { n.cast_float() }
#[inline(always)] pure fn cast<T:NumCast>() -> T { from(self) }
#[inline(always)] pure fn cast_u8() -> u8 { self as u8 }
#[inline(always)] pure fn cast_u16() -> u16 { self as u16 }
#[inline(always)] pure fn cast_u32() -> u32 { self as u32 }
#[inline(always)] pure fn cast_u64() -> u64 { self as u64 }
#[inline(always)] pure fn cast_uint() -> uint { self as uint }
#[inline(always)] pure fn cast_i8() -> i8 { self as i8 }
#[inline(always)] pure fn cast_i16() -> i16 { self as i16 }
#[inline(always)] pure fn cast_i32() -> i32 { self as i32 }
#[inline(always)] pure fn cast_i64() -> i64 { self as i64 }
#[inline(always)] pure fn cast_int() -> int { self as int }
#[inline(always)] pure fn cast_f32() -> f32 { self as f32 }
#[inline(always)] pure fn cast_f64() -> f64 { self as f64 }
#[inline(always)] pure fn cast_float() -> float { self }
}

View file

@ -9,6 +9,7 @@ extern mod std;
pub mod matrix;
pub mod math;
pub mod num_util;
pub mod projection;
pub mod quaternion;
pub mod vector;

View file

@ -1,6 +1,8 @@
use float::consts::pi;
use float::tan;
use matrix::Mat4;
use num_util::*;
//
// Create a perspective projection matrix
@ -9,7 +11,7 @@ use matrix::Mat4;
// http://www.opengl.org/wiki/GluPerspective_code
//
#[inline(always)]
pure fn perspective(fovy:float, aspectRatio:float, near:float, far:float) -> Mat4 {
pure fn perspective<T:Copy NumCast Neg<T>>(fovy: float, aspectRatio: float, near: float, far: float) -> Mat4<T> {
let ymax = near * tan(fovy * pi / 360f);
let xmax = ymax * aspectRatio;
return frustum(-xmax, xmax, -ymax, ymax, near, far);
@ -23,23 +25,23 @@ pure fn perspective(fovy:float, aspectRatio:float, near:float, far:float) -> Mat
// TODO: double check algorithm
//
#[inline(always)]
pure fn frustum(left:float, right:float, bottom:float, top:float, near:float, far:float) -> Mat4 {
let m00 = (2f * near) / (right - left);
let m01 = 0f;
let m02 = 0f;
let m03 = 0f;
let m10 = 0f;
let m11 = (2f * near)/(top - bottom);
let m12 = 0f;
let m13 = 0f;
let m20 = (right + left) / (right - left);
let m21 = (top + bottom) / (top - bottom);
let m22 = -(far + near) / (far - near);
let m23 = -1f;
let m30 = 0f;
let m31 = 0f;
let m32 = -(2f * far * near) / (far - near);
let m33 = 0f;
pure fn frustum<T:Copy NumCast Neg<T>>(left: float, right: float, bottom: float, top: float, near: float, far: float) -> Mat4<T> {
let m00 = cast((2f * near) / (right - left));
let m01 = cast(0f);
let m02 = cast(0f);
let m03 = cast(0f);
let m10 = cast(0f);
let m11 = cast((2f * near) / (top - bottom));
let m12 = cast(0f);
let m13 = cast(0f);
let m20 = cast((right + left) / (right - left));
let m21 = cast((top + bottom) / (top - bottom));
let m22 = cast(-(far + near) / (far - near));
let m23 = cast(-1f);
let m30 = cast(0f);
let m31 = cast(0f);
let m32 = cast(-(2f * far * near) / (far - near));
let m33 = cast(0f);
return Mat4(m00, m01, m02, m03,
m10, m11, m12, m13,

View file

@ -1,8 +1,10 @@
use cast::transmute;
use vec::raw::buf_as_slice;
use ptr::to_unsafe_ptr;
use cmp::Eq;
use num::from_int;
use ptr::to_unsafe_ptr;
use vec::raw::buf_as_slice;
use std::cmp::FuzzyEq;
use math::{ToPtr, ExactEq, Sqrt};
use matrix::{Mat3, Mat4};
use vector::Vec3;
@ -27,8 +29,12 @@ pub trait Quaternion<T> {
pure fn magnitude2() -> T;
pure fn magnitude() -> T;
pure fn to_Mat3() -> Mat3;
pure fn to_Mat4() -> Mat4;
pure fn to_Mat3() -> Mat3<T>;
pure fn to_Mat4() -> Mat4<T>;
}
pub trait ToQuat<T> {
pure fn to_Quat() -> Quat<T>;
}
@ -39,30 +45,30 @@ pub trait Quaternion<T> {
//
// Quat struct definition
//
pub struct Quat { w: float, x: float, y: float, z: float }
pub struct Quat<T> { w: T, x: T, y: T, z: T }
//
// Quat Constructor
//
#[inline(always)]
pub pure fn Quat(w: float, x: float, y: float, z: float) -> Quat {
Quat { w: w, x: x, y: y, z: z }
pub pure fn Quat<T:Copy>(w: T, x: T, y: T, z: T) -> Quat<T> {
Quat { w: move w, x: move x, y: move y, z: move z }
}
pub mod Quat {
pub const zero :Quat = Quat { w: 0f, x: 0f, y: 0f, z: 0f };
pub const identity :Quat = Quat { w: 1f, x: 0f, y: 0f, z: 0f };
#[inline(always)] pub pure fn zero <T: Num>() -> Quat<T> { Quat { w: from_int(0), x: from_int(0), y: from_int(0), z: from_int(0) } }
#[inline(always)] pub pure fn identity <T: Num>() -> Quat<T> { Quat { w: from_int(1), x: from_int(0), y: from_int(0), z: from_int(0) } }
}
//
// Quaternion Implementation
//
pub impl Quat: Quaternion<float> {
pub impl<T:Copy Num Sqrt FuzzyEq> Quat<T>: Quaternion<T> {
#[inline(always)]
pure fn dim() -> uint { 4 }
#[inline(always)]
pure fn mul_t(value: float) -> Quat {
pure fn mul_t(value: T) -> Quat<T> {
Quat(self[0] * value,
self[1] * value,
self[2] * value,
@ -70,7 +76,7 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn div_t(value: float) -> Quat {
pure fn div_t(value: T) -> Quat<T> {
Quat(self[0] / value,
self[1] / value,
self[2] / value,
@ -78,7 +84,7 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn add_q(other: &Quat) -> Quat{
pure fn add_q(other: &Quat<T>) -> Quat<T> {
Quat(self[0] + other[0],
self[1] + other[1],
self[2] + other[2],
@ -86,7 +92,7 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn sub_q(other: &Quat) -> Quat{
pure fn sub_q(other: &Quat<T>) -> Quat<T> {
Quat(self[0] - other[0],
self[1] - other[1],
self[2] - other[2],
@ -94,7 +100,7 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn mul_q(other: &Quat) -> Quat {
pure fn mul_q(other: &Quat<T>) -> Quat<T> {
Quat(self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
self.w * other.y + self.y * other.w + self.z * other.x - self.x * other.z,
@ -102,17 +108,19 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn conjugate() -> Quat {
pure fn conjugate() -> Quat<T> {
Quat(self.w, -self.x, -self.y, -self.z)
}
#[inline(always)]
pure fn inverse() -> Quat {
self.conjugate().mul_t((1f / self.magnitude2()))
pure fn inverse() -> Quat<T> {
let mut n: T = from_int(1);
n /= self.magnitude2();
self.conjugate().mul_t(n)
}
#[inline(always)]
pure fn magnitude2() -> float {
pure fn magnitude2() -> T {
self.w * self.w +
self.x * self.x +
self.y * self.y +
@ -120,12 +128,12 @@ pub impl Quat: Quaternion<float> {
}
#[inline(always)]
pure fn magnitude() -> float {
pure fn magnitude() -> T {
self.magnitude2().sqrt()
}
#[inline(always)]
pure fn to_Mat3() -> Mat3 {
pure fn to_Mat3() -> Mat3<T> {
let x2 = self.x + self.x;
let y2 = self.y + self.y;
let z2 = self.z + self.z;
@ -142,50 +150,53 @@ pub impl Quat: Quaternion<float> {
let wz2 = z2 * self.w;
let wx2 = x2 * self.w;
return Mat3(1f - yy2 - zz2, xy2 - wz2, xz2 + wy2,
xy2 + wz2, 1f - xx2 - zz2, yz2 - wx2,
xz2 - wy2, yz2 + wx2, 1f - xx2 - yy2);
let _1: T = from_int(1);
Mat3(_1 - yy2 - zz2, xy2 - wz2, xz2 + wy2,
xy2 + wz2, _1 - xx2 - zz2, yz2 - wx2,
xz2 - wy2, yz2 + wx2, _1 - xx2 - yy2)
}
#[inline(always)]
pure fn to_Mat4() -> Mat4 {
pure fn to_Mat4() -> Mat4<T> {
self.to_Mat3().to_Mat4()
}
}
pub impl Quat: Index<uint, float> {
pub impl<T:Copy> Quat<T>: Index<uint, T> {
#[inline(always)]
pure fn index(i: uint) -> float {
pure fn index(i: uint) -> T {
unsafe {
do buf_as_slice(
transmute::<*Quat, *float>(
transmute::<*Quat<T>, *T>(
to_unsafe_ptr(&self)), 4) |slice| { slice[i] }
}
}
}
pub impl Quat: Neg<Quat> {
pub impl<T:Copy Neg<T>> Quat<T>: Neg<Quat<T>> {
#[inline(always)]
pure fn neg() -> Quat {
pure fn neg() -> Quat<T> {
Quat(-self[0], -self[1], -self[2], -self[3])
}
}
pub impl Quat: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Quat<T>: Eq {
#[inline(always)]
pure fn eq(other: &Quat) -> bool {
pure fn eq(other: &Quat<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Quat) -> bool {
pure fn ne(other: &Quat<T>) -> bool {
!(self == *other)
}
}
impl Quat: ExactEq {
pub impl<T:Copy Eq> Quat<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Quat) -> bool {
pure fn exact_eq(other: &Quat<T>) -> bool {
self[0] == other[0] &&
self[1] == other[1] &&
self[2] == other[2] &&
@ -193,9 +204,9 @@ impl Quat: ExactEq {
}
}
pub impl Quat: FuzzyEq {
pub impl<T:Copy FuzzyEq> Quat<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Quat) -> bool {
pure fn fuzzy_eq(other: &Quat<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1]) &&
self[2].fuzzy_eq(&other[2]) &&
@ -203,15 +214,9 @@ pub impl Quat: FuzzyEq {
}
}
pub impl Quat: ToPtr<float> {
pub impl<T:Copy> Quat<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
to_unsafe_ptr(&self[0])
}
}
pub impl Quat: ToStr {
pure fn to_str() -> ~str {
fmt!("Quat[ %f, %f, %f, %f ]", self.w, self.x, self.y, self.z)
}
}

View file

@ -49,10 +49,10 @@ fn test_Mat2() {
// fuzzy_eq
// eq
assert Mat2::identity.is_identity();
assert Mat2::identity.is_symmetric();
assert Mat2::identity.is_diagonal();
assert !Mat2::identity.is_rotated();
assert Mat2::identity::<float>().is_identity();
assert Mat2::identity::<float>().is_symmetric();
assert Mat2::identity::<float>().is_diagonal();
assert !Mat2::identity::<float>().is_rotated();
assert !a.is_identity();
assert !a.is_symmetric();
@ -126,10 +126,10 @@ fn test_Mat3() {
// fuzzy_eq
// eq
assert Mat3::identity.is_identity();
assert Mat3::identity.is_symmetric();
assert Mat3::identity.is_diagonal();
assert !Mat3::identity.is_rotated();
assert Mat3::identity::<float>().is_identity();
assert Mat3::identity::<float>().is_symmetric();
assert Mat3::identity::<float>().is_diagonal();
assert !Mat3::identity::<float>().is_rotated();
assert !a.is_identity();
assert !a.is_symmetric();
@ -224,10 +224,10 @@ fn test_Mat4() {
// fuzzy_eq
// eq
assert Mat4::identity.is_identity();
assert Mat4::identity.is_symmetric();
assert Mat4::identity.is_diagonal();
assert !Mat4::identity.is_rotated();
assert Mat4::identity::<float>().is_identity();
assert Mat4::identity::<float>().is_symmetric();
assert Mat4::identity::<float>().is_diagonal();
assert !Mat4::identity::<float>().is_rotated();
assert !a.is_identity();
assert !a.is_symmetric();

View file

@ -13,8 +13,8 @@ fn test_Quat() {
assert a == Quat(1f, 2f, 3f, 4f);
assert Quat::zero == Quat(0f, 0f, 0f, 0f);
assert Quat::identity == Quat(1f, 0f, 0f, 0f);
assert Quat::zero() == Quat(0f, 0f, 0f, 0f);
assert Quat::identity() == Quat(1f, 0f, 0f, 0f);
assert a.w == 1f;
assert a.x == 2f;

View file

@ -12,12 +12,10 @@ fn test_Vec2() {
let f1 = 1.5f;
let f2 = 0.5f;
assert a == Vec2(1f, 2f);
assert Vec2::zero == Vec2(0f, 0f);
assert Vec2::unit_x == Vec2(1f, 0f);
assert Vec2::unit_y == Vec2(0f, 1f);
assert Vec2::identity == Vec2(1f, 1f);
assert Vec2::zero() == Vec2(0f, 0f);
assert Vec2::unit_x() == Vec2(1f, 0f);
assert Vec2::unit_y() == Vec2(0f, 1f);
assert Vec2::identity() == Vec2(1f, 1f);
assert a.x == 1f;
assert a.y == 2f;
@ -63,11 +61,11 @@ fn test_Vec3() {
assert a == Vec3(1f, 2f, 3f);
assert Vec3::zero == Vec3(0f, 0f, 0f);
assert Vec3::unit_x == Vec3(1f, 0f, 0f);
assert Vec3::unit_y == Vec3(0f, 1f, 0f);
assert Vec3::unit_z == Vec3(0f, 0f, 1f);
assert Vec3::identity == Vec3(1f, 1f, 1f);
assert Vec3::zero() == Vec3(0f, 0f, 0f);
assert Vec3::unit_x() == Vec3(1f, 0f, 0f);
assert Vec3::unit_y() == Vec3(0f, 1f, 0f);
assert Vec3::unit_z() == Vec3(0f, 0f, 1f);
assert Vec3::identity() == Vec3(1f, 1f, 1f);
assert a.x == 1f;
assert a.y == 2f;
@ -117,12 +115,12 @@ fn test_Vec4() {
assert a == Vec4(1f, 2f, 3f, 4f);
assert Vec4::zero == Vec4(0f, 0f, 0f, 0f);
assert Vec4::unit_x == Vec4(1f, 0f, 0f, 0f);
assert Vec4::unit_y == Vec4(0f, 1f, 0f, 0f);
assert Vec4::unit_z == Vec4(0f, 0f, 1f, 0f);
assert Vec4::unit_w == Vec4(0f, 0f, 0f, 1f);
assert Vec4::identity == Vec4(1f, 1f, 1f, 1f);
assert Vec4::zero() == Vec4(0f, 0f, 0f, 0f);
assert Vec4::unit_x() == Vec4(1f, 0f, 0f, 0f);
assert Vec4::unit_y() == Vec4(0f, 1f, 0f, 0f);
assert Vec4::unit_z() == Vec4(0f, 0f, 1f, 0f);
assert Vec4::unit_w() == Vec4(0f, 0f, 0f, 1f);
assert Vec4::identity() == Vec4(1f, 1f, 1f, 1f);
assert a.x == 1f;
assert a.y == 2f;

View file

@ -1,9 +1,11 @@
use cast::transmute;
use vec::raw::buf_as_slice;
use ptr::to_unsafe_ptr;
use cmp::Eq;
use cmp::{Eq, Ord};
use num::from_int;
use std::cmp::FuzzyEq;
use math::{ToPtr, Abs, abs, ExactEq, max, min, Sqrt};
use math::*;
//
// N-dimensional Vector
@ -26,8 +28,6 @@ pub trait Vector<T> {
pure fn normalize() -> self;
pure fn lerp(other: &self, value: T) -> self;
pure fn min(other: &self) -> self;
pure fn max(other: &self) -> self;
}
pub trait Vector3<T> {
@ -37,177 +37,172 @@ pub trait Vector3<T> {
//
// Vec2
//
pub struct Vec2 { x: float, y: float }
pub struct Vec2<T> { x: T, y: T }
//
// Constructor
//
#[inline(always)]
pub pure fn Vec2(x: float, y: float) -> Vec2 {
Vec2 { x: x, y: y }
pub pure fn Vec2<T:Copy>(x: T, y: T) -> Vec2<T> {
Vec2 { x: move x, y: move y }
}
pub mod Vec2 {
pub const zero :Vec2 = Vec2 { x: 0f, y: 0f };
pub const unit_x :Vec2 = Vec2 { x: 1f, y: 0f };
pub const unit_y :Vec2 = Vec2 { x: 0f, y: 1f };
pub const identity :Vec2 = Vec2 { x: 1f, y: 1f };
#[inline(always)] pub pure fn zero <T: Num>() -> Vec2<T> { Vec2 { x: from_int(0), y: from_int(0) } }
#[inline(always)] pub pure fn unit_x <T: Num>() -> Vec2<T> { Vec2 { x: from_int(1), y: from_int(0) } }
#[inline(always)] pub pure fn unit_y <T: Num>() -> Vec2<T> { Vec2 { x: from_int(0), y: from_int(1) } }
#[inline(always)] pub pure fn identity <T: Num>() -> Vec2<T> { Vec2 { x: from_int(1), y: from_int(1) } }
}
pub impl Vec2: Vector<float> {
pub impl<T:Copy Num Sqrt> Vec2<T>: Vector<T> {
#[inline(always)]
static pure fn dim() -> uint { 2 }
#[inline(always)]
pure fn add_t(value: float) -> Vec2 {
pure fn add_t(value: T) -> Vec2<T> {
Vec2(self[0] + value,
self[1] + value)
}
#[inline(always)]
pure fn sub_t(value: float) -> Vec2 {
pure fn sub_t(value: T) -> Vec2<T> {
Vec2(self[0] - value,
self[1] - value)
}
#[inline(always)]
pure fn mul_t(value: float) -> Vec2 {
pure fn mul_t(value: T) -> Vec2<T> {
Vec2(self[0] * value,
self[1] * value)
}
#[inline(always)]
pure fn div_t(value: float) -> Vec2 {
pure fn div_t(value: T) -> Vec2<T> {
Vec2(self[0] / value,
self[1] / value)
}
#[inline(always)]
pure fn add_v(other: &Vec2) -> Vec2{
pure fn add_v(other: &Vec2<T>) -> Vec2<T> {
Vec2(self[0] + other[0],
self[1] + other[1])
}
#[inline(always)]
pure fn sub_v(other: &Vec2) -> Vec2{
pure fn sub_v(other: &Vec2<T>) -> Vec2<T> {
Vec2(self[0] - other[0],
self[1] - other[1])
}
#[inline(always)]
pure fn dot(other: &Vec2) -> float {
pure fn dot(other: &Vec2<T>) -> T {
self[0] * other[0] +
self[1] * other[1]
}
#[inline(always)]
pure fn magnitude2() -> float {
pure fn magnitude2() -> T {
self[0] * self[0] +
self[1] * self[1]
}
#[inline(always)]
pure fn magnitude() -> float {
pure fn magnitude() -> T {
self.magnitude2().sqrt()
}
#[inline(always)]
pure fn normalize() -> Vec2 {
let n = 1f / self.magnitude();
pure fn normalize() -> Vec2<T> {
let mut n: T = from_int(1);
n /= self.magnitude();
return self.mul_t(n);
}
#[inline(always)]
pure fn lerp(other: &Vec2, value: float) -> Vec2 {
pure fn lerp(other: &Vec2<T>, value: T) -> Vec2<T> {
self.add_v(&other.sub_v(&self).mul_t(value))
}
}
pub impl<T:Copy> Vec2<T>: Index<uint, T> {
#[inline(always)]
pure fn min(other: &Vec2) -> Vec2 {
pure fn index(i: uint) -> T {
unsafe { do buf_as_slice(
transmute::<*Vec2<T>, *T>(
to_unsafe_ptr(&self)), 2) |slice| { slice[i] }
}
}
}
pub impl<T:Copy MinMax> Vec2<T>: MinMax {
#[inline(always)]
pure fn min(other: &Vec2<T>) -> Vec2<T> {
Vec2(min(&self[0], &other[0]),
min(&self[1], &other[1]))
}
#[inline(always)]
pure fn max(other: &Vec2) -> Vec2 {
pure fn max(other: &Vec2<T>) -> Vec2<T> {
Vec2(max(&self[0], &other[0]),
max(&self[1], &other[1]))
}
}
pub impl Vec2: Index<uint, float> {
pub impl<T:Copy Abs> Vec2<T>: Abs {
#[inline(always)]
pure fn index(i: uint) -> float {
unsafe {
do buf_as_slice(
transmute::<*Vec2, *float>(
to_unsafe_ptr(&self)), 2) |slice| { slice[i] }
}
}
}
pub impl Vec2: Abs {
#[inline(always)]
pure fn abs() -> Vec2 {
pure fn abs() -> Vec2<T> {
Vec2(abs(&self[0]),
abs(&self[1]))
}
}
pub impl Vec2: Neg<Vec2> {
pub impl<T:Copy Neg<T>> Vec2<T>: Neg<Vec2<T>> {
#[inline(always)]
pure fn neg() -> Vec2 {
pure fn neg() -> Vec2<T> {
Vec2(-self[0], -self[1])
}
}
pub impl Vec2: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Vec2<T>: Eq {
#[inline(always)]
pure fn eq(other: &Vec2) -> bool {
pure fn eq(other: &Vec2<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Vec2) -> bool {
pure fn ne(other: &Vec2<T>) -> bool {
!(self == *other)
}
}
impl Vec2: ExactEq {
impl<T:Copy Eq> Vec2<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Vec2) -> bool {
pure fn exact_eq(other: &Vec2<T>) -> bool {
self[0] == other[0] &&
self[1] == other[1]
}
}
pub impl Vec2: FuzzyEq {
pub impl<T:Copy FuzzyEq> Vec2<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Vec2) -> bool {
pure fn fuzzy_eq(other: &Vec2<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1])
}
}
pub impl Vec2: ToPtr<float> {
pub impl<T:Copy> Vec2<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
to_unsafe_ptr(&self[0])
}
}
pub impl Vec2: ToStr {
pure fn to_str() -> ~str {
fmt!("Vec2[ %f, %f ]", self[0], self[1])
}
}
@ -216,193 +211,191 @@ pub impl Vec2: ToStr {
//
// Vec3
//
pub struct Vec3 { x: float, y: float, z: float }
pub struct Vec3<T> { x: T, y: T, z: T }
//
// Constructor
//
#[inline(always)]
pub pure fn Vec3(x: float, y: float, z: float) -> Vec3 {
Vec3 { x: x, y: y, z: z }
pub pure fn Vec3<T:Copy>(x: T, y: T, z: T) -> Vec3<T> {
Vec3 { x: move x, y: move y, z: move z }
}
pub mod Vec3 {
pub const zero :Vec3 = Vec3 { x: 0f, y: 0f, z: 0f };
pub const unit_x :Vec3 = Vec3 { x: 1f, y: 0f, z: 0f };
pub const unit_y :Vec3 = Vec3 { x: 0f, y: 1f, z: 0f };
pub const unit_z :Vec3 = Vec3 { x: 0f, y: 0f, z: 1f };
pub const identity :Vec3 = Vec3 { x: 1f, y: 1f, z: 1f };
#[inline(always)] pub pure fn zero <T: Num>() -> Vec3<T> { Vec3 { x: from_int(0), y: from_int(0), z: from_int(0) } }
#[inline(always)] pub pure fn unit_x <T: Num>() -> Vec3<T> { Vec3 { x: from_int(1), y: from_int(0), z: from_int(0) } }
#[inline(always)] pub pure fn unit_y <T: Num>() -> Vec3<T> { Vec3 { x: from_int(0), y: from_int(1), z: from_int(0) } }
#[inline(always)] pub pure fn unit_z <T: Num>() -> Vec3<T> { Vec3 { x: from_int(0), y: from_int(0), z: from_int(1) } }
#[inline(always)] pub pure fn identity <T: Num>() -> Vec3<T> { Vec3 { x: from_int(1), y: from_int(1), z: from_int(1) } }
}
pub impl Vec3: Vector3<float> {
pub impl<T:Copy Num> Vec3<T>: Vector3<T> {
#[inline(always)]
fn cross(other: &Vec3) -> Vec3 {
fn cross(other: &Vec3<T>) -> Vec3<T> {
Vec3((self[1] * other[2]) - (self[2] * other[1]),
(self[2] * other[0]) - (self[0] * other[2]),
(self[0] * other[1]) - (self[1] * other[0]))
}
}
pub impl Vec3: Vector<float> {
pub impl<T:Copy Num Sqrt> Vec3<T>: Vector<T> {
#[inline(always)]
static pure fn dim() -> uint { 3 }
#[inline(always)]
pure fn add_t(value: float) -> Vec3 {
pure fn add_t(value: T) -> Vec3<T> {
Vec3(self[0] + value,
self[1] + value,
self[2] + value)
}
#[inline(always)]
pure fn sub_t(value: float) -> Vec3 {
pure fn sub_t(value: T) -> Vec3<T> {
Vec3(self[0] - value,
self[1] - value,
self[2] - value)
}
#[inline(always)]
pure fn mul_t(value: float) -> Vec3 {
pure fn mul_t(value: T) -> Vec3<T> {
Vec3(self[0] * value,
self[1] * value,
self[2] * value)
}
#[inline(always)]
pure fn div_t(value: float) -> Vec3 {
pure fn div_t(value: T) -> Vec3<T> {
Vec3(self[0] / value,
self[1] / value,
self[2] / value)
}
#[inline(always)]
pure fn add_v(other: &Vec3) -> Vec3{
pure fn add_v(other: &Vec3<T>) -> Vec3<T>{
Vec3(self[0] + other[0],
self[1] + other[1],
self[2] + other[2])
}
#[inline(always)]
pure fn sub_v(other: &Vec3) -> Vec3{
pure fn sub_v(other: &Vec3<T>) -> Vec3<T>{
Vec3(self[0] - other[0],
self[1] - other[1],
self[2] - other[2])
}
#[inline(always)]
pure fn dot(other: &Vec3) -> float {
pure fn dot(other: &Vec3<T>) -> T {
self[0] * other[0] +
self[1] * other[1] +
self[2] * other[2]
}
#[inline(always)]
pure fn magnitude2() -> float {
pure fn magnitude2() -> T {
self[0] * self[0] +
self[1] * self[1] +
self[2] * self[2]
}
#[inline(always)]
pure fn magnitude() -> float {
pure fn magnitude() -> T {
self.magnitude2().sqrt()
}
#[inline(always)]
pure fn normalize() -> Vec3 {
let n = 1f / self.magnitude();
pure fn normalize() -> Vec3<T> {
let mut n: T = from_int(1);
n /= self.magnitude();
return self.mul_t(n);
}
#[inline(always)]
pure fn lerp(other: &Vec3, value: float) -> Vec3 {
pure fn lerp(other: &Vec3<T>, value: T) -> Vec3<T> {
self.add_v(&other.sub_v(&self).mul_t(value))
}
}
pub impl<T:Copy> Vec3<T>: Index<uint, T> {
#[inline(always)]
pure fn min(other: &Vec3) -> Vec3 {
pure fn index(i: uint) -> T {
unsafe { do buf_as_slice(
transmute::<*Vec3<T>, *T>(
to_unsafe_ptr(&self)), 3) |slice| { slice[i] }
}
}
}
pub impl<T:Copy MinMax> Vec3<T>: MinMax {
#[inline(always)]
pure fn min(other: &Vec3<T>) -> Vec3<T> {
Vec3(min(&self[0], &other[0]),
min(&self[1], &other[1]),
min(&self[2], &other[2]))
}
#[inline(always)]
pure fn max(other: &Vec3) -> Vec3 {
pure fn max(other: &Vec3<T>) -> Vec3<T> {
Vec3(max(&self[0], &other[0]),
max(&self[1], &other[1]),
max(&self[2], &other[2]))
}
}
pub impl Vec3: Index<uint, float> {
pub impl<T:Copy Abs> Vec3<T>: Abs {
#[inline(always)]
pure fn index(i: uint) -> float {
unsafe { do buf_as_slice(
transmute::<*Vec3, *float>(
to_unsafe_ptr(&self)), 3) |slice| { slice[i] }
}
}
}
pub impl Vec3: Abs {
#[inline(always)]
pure fn abs() -> Vec3 {
pure fn abs() -> Vec3<T> {
Vec3(abs(&self[0]),
abs(&self[1]),
abs(&self[2]))
}
}
pub impl Vec3: Neg<Vec3> {
pub impl<T:Copy Neg<T>> Vec3<T>: Neg<Vec3<T>> {
#[inline(always)]
pure fn neg() -> Vec3 {
pure fn neg() -> Vec3<T> {
Vec3(-self[0], -self[1], -self[2])
}
}
pub impl Vec3: Eq {
// TODO: make work for T:Integer
pub impl<T:Copy FuzzyEq> Vec3<T>: Eq {
#[inline(always)]
pure fn eq(other: &Vec3) -> bool {
pure fn eq(other: &Vec3<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Vec3) -> bool {
pure fn ne(other: &Vec3<T>) -> bool {
!(self == *other)
}
}
impl Vec3: ExactEq {
pub impl<T:Copy Eq> Vec3<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Vec3) -> bool {
pure fn exact_eq(other: &Vec3<T>) -> bool {
self[0] == other[0] &&
self[1] == other[1] &&
self[2] == other[2]
}
}
pub impl Vec3: FuzzyEq {
pub impl<T:Copy FuzzyEq> Vec3<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Vec3) -> bool {
pure fn fuzzy_eq(other: &Vec3<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1]) &&
self[2].fuzzy_eq(&other[2])
}
}
pub impl Vec3: ToPtr<float> {
pub impl<T:Copy> Vec3<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
to_unsafe_ptr(&self[0])
}
}
pub impl Vec3: ToStr {
pure fn to_str() -> ~str {
fmt!("Vec3[ %f, %f, %f ]", self[0], self[1], self[2])
}
}
@ -411,31 +404,31 @@ pub impl Vec3: ToStr {
//
// Vec4
//
pub struct Vec4 { x: float, y: float, z: float, w: float }
pub struct Vec4<T> { x: T, y: T, z: T, w: T }
pub mod Vec4 {
pub const zero :Vec4 = Vec4 { x: 0f, y: 0f, z: 0f, w: 0f };
pub const unit_x :Vec4 = Vec4 { x: 1f, y: 0f, z: 0f, w: 0f };
pub const unit_y :Vec4 = Vec4 { x: 0f, y: 1f, z: 0f, w: 0f };
pub const unit_z :Vec4 = Vec4 { x: 0f, y: 0f, z: 1f, w: 0f };
pub const unit_w :Vec4 = Vec4 { x: 0f, y: 0f, z: 0f, w: 1f };
pub const identity :Vec4 = Vec4 { x: 1f, y: 1f, z: 1f, w: 1f };
#[inline(always)] pub pure fn zero <T: Num>() -> Vec4<T> { Vec4 { x: from_int(0), y: from_int(0), z: from_int(0), w: from_int(0) } }
#[inline(always)] pub pure fn unit_x <T: Num>() -> Vec4<T> { Vec4 { x: from_int(1), y: from_int(0), z: from_int(0), w: from_int(0) } }
#[inline(always)] pub pure fn unit_y <T: Num>() -> Vec4<T> { Vec4 { x: from_int(0), y: from_int(1), z: from_int(0), w: from_int(0) } }
#[inline(always)] pub pure fn unit_z <T: Num>() -> Vec4<T> { Vec4 { x: from_int(0), y: from_int(0), z: from_int(1), w: from_int(0) } }
#[inline(always)] pub pure fn unit_w <T: Num>() -> Vec4<T> { Vec4 { x: from_int(0), y: from_int(0), z: from_int(0), w: from_int(1) } }
#[inline(always)] pub pure fn identity <T: Num>() -> Vec4<T> { Vec4 { x: from_int(1), y: from_int(1), z: from_int(1), w: from_int(1) } }
}
//
// Constructor
//
#[inline(always)]
pub pure fn Vec4(x: float, y: float, z: float, w: float) -> Vec4 {
Vec4 { x: x, y: y, z: z, w: w }
pub pure fn Vec4<T:Copy>(x: T, y: T, z: T, w: T) -> Vec4<T> {
Vec4 { x: move x, y: move y, z: move z, w: move w }
}
pub impl Vec4: Vector<float> {
pub impl<T:Copy Num Sqrt> Vec4<T>: Vector<T> {
#[inline(always)]
static pure fn dim() -> uint { 4 }
#[inline(always)]
pure fn add_t(value: float) -> Vec4 {
pure fn add_t(value: T) -> Vec4<T> {
Vec4(self[0] + value,
self[1] + value,
self[2] + value,
@ -443,7 +436,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn sub_t(value: float) -> Vec4 {
pure fn sub_t(value: T) -> Vec4<T> {
Vec4(self[0] - value,
self[1] - value,
self[2] - value,
@ -451,7 +444,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn mul_t(value: float) -> Vec4 {
pure fn mul_t(value: T) -> Vec4<T> {
Vec4(self[0] * value,
self[1] * value,
self[2] * value,
@ -459,7 +452,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn div_t(value: float) -> Vec4 {
pure fn div_t(value: T) -> Vec4<T> {
Vec4(self[0] / value,
self[1] / value,
self[2] / value,
@ -467,7 +460,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn add_v(other: &Vec4) -> Vec4{
pure fn add_v(other: &Vec4<T>) -> Vec4<T> {
Vec4(self[0] + other[0],
self[1] + other[1],
self[2] + other[2],
@ -475,7 +468,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn sub_v(other: &Vec4) -> Vec4{
pure fn sub_v(other: &Vec4<T>) -> Vec4<T> {
Vec4(self[0] - other[0],
self[1] - other[1],
self[2] - other[2],
@ -483,7 +476,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn dot(other: &Vec4) -> float {
pure fn dot(other: &Vec4<T>) -> T {
self[0] * other[0] +
self[1] * other[1] +
self[2] * other[2] +
@ -491,7 +484,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn magnitude2() -> float {
pure fn magnitude2() -> T {
self[0] * self[0] +
self[1] * self[1] +
self[2] * self[2] +
@ -499,23 +492,37 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn magnitude() -> float {
pure fn magnitude() -> T {
self.magnitude2().sqrt()
}
#[inline(always)]
pure fn normalize() -> Vec4 {
let n = 1f / self.magnitude();
pure fn normalize() -> Vec4<T> {
let mut n: T = from_int(1);
n /= self.magnitude();
return self.mul_t(n);
}
#[inline(always)]
pure fn lerp(other: &Vec4, value: float) -> Vec4 {
pure fn lerp(other: &Vec4<T>, value: T) -> Vec4<T> {
self.add_v(&other.sub_v(&self).mul_t(value))
}
}
pub impl<T:Copy> Vec4<T>: Index<uint, T> {
#[inline(always)]
pure fn min(other: &Vec4) -> Vec4 {
pure fn index(i: uint) -> T {
unsafe {
do buf_as_slice(
transmute::<*Vec4<T>, *T>(
to_unsafe_ptr(&self)), 4) |slice| { slice[i] }
}
}
}
pub impl<T:Copy MinMax> Vec4<T>: MinMax {
#[inline(always)]
pure fn min(other: &Vec4<T>) -> Vec4<T> {
Vec4(min(&self[0], &other[0]),
min(&self[1], &other[1]),
min(&self[2], &other[2]),
@ -523,7 +530,7 @@ pub impl Vec4: Vector<float> {
}
#[inline(always)]
pure fn max(other: &Vec4) -> Vec4 {
pure fn max(other: &Vec4<T>) -> Vec4<T> {
Vec4(max(&self[0], &other[0]),
max(&self[1], &other[1]),
max(&self[2], &other[2]),
@ -531,20 +538,9 @@ pub impl Vec4: Vector<float> {
}
}
pub impl Vec4: Index<uint, float> {
pub impl<T:Copy Abs> Vec4<T>: Abs {
#[inline(always)]
pure fn index(i: uint) -> float {
unsafe {
do buf_as_slice(
transmute::<*Vec4, *float>(
to_unsafe_ptr(&self)), 4) |slice| { slice[i] }
}
}
}
pub impl Vec4: Abs {
#[inline(always)]
pure fn abs() -> Vec4 {
pure fn abs() -> Vec4<T> {
Vec4(abs(&self[0]),
abs(&self[1]),
abs(&self[2]),
@ -552,28 +548,29 @@ pub impl Vec4: Abs {
}
}
pub impl Vec4: Neg<Vec4> {
pub impl<T:Copy Neg<T>> Vec4<T>: Neg<Vec4<T>> {
#[inline(always)]
pure fn neg() -> Vec4 {
pure fn neg() -> Vec4<T> {
Vec4(-self[0], -self[1], -self[2], -self[3])
}
}
pub impl Vec4: Eq {
pub impl<T:Copy FuzzyEq> Vec4<T>: Eq {
#[inline(always)]
pure fn eq(other: &Vec4) -> bool {
pure fn eq(other: &Vec4<T>) -> bool {
self.fuzzy_eq(other)
}
#[inline(always)]
pure fn ne(other: &Vec4) -> bool {
pure fn ne(other: &Vec4<T>) -> bool {
!(self == *other)
}
}
impl Vec4: ExactEq {
// TODO: make work for T:Integer
pub impl<T:Copy Eq> Vec4<T>: ExactEq {
#[inline(always)]
pure fn exact_eq(other: &Vec4) -> bool {
pure fn exact_eq(other: &Vec4<T>) -> bool {
self[0] == other[0] &&
self[1] == other[1] &&
self[2] == other[2] &&
@ -581,9 +578,9 @@ impl Vec4: ExactEq {
}
}
pub impl Vec4: FuzzyEq {
pub impl<T:Copy FuzzyEq> Vec4<T>: FuzzyEq {
#[inline(always)]
pure fn fuzzy_eq(other: &Vec4) -> bool {
pure fn fuzzy_eq(other: &Vec4<T>) -> bool {
self[0].fuzzy_eq(&other[0]) &&
self[1].fuzzy_eq(&other[1]) &&
self[2].fuzzy_eq(&other[2]) &&
@ -591,15 +588,9 @@ pub impl Vec4: FuzzyEq {
}
}
pub impl Vec4: ToPtr<float> {
pub impl<T:Copy> Vec4<T>: ToPtr<T> {
#[inline(always)]
pure fn to_ptr() -> *float {
pure fn to_ptr() -> *T {
to_unsafe_ptr(&self[0])
}
}
pub impl Vec4: ToStr {
pure fn to_str() -> ~str {
fmt!("Vec4[ %f, %f, %f, %f ]", self[0], self[1], self[2], self[3])
}
}