Add min and max functions to vector

This commit is contained in:
Brendan Zabarauskas 2012-09-08 15:54:31 +10:00
parent 015f0d8eb1
commit 820ea22407
6 changed files with 181 additions and 103 deletions

49
src/math.rs Normal file
View file

@ -0,0 +1,49 @@
import cmp::Ord;
trait Abs {
pure fn abs() -> self;
}
impl int: Abs {
#[inline(always)]
pure fn abs() -> int {
if self >= 0 { self }
else {-self }
}
}
impl float: Abs {
#[inline(always)]
pure fn abs() -> float {
if self >= 0f { self }
else {-self }
}
}
impl f32: Abs {
#[inline(always)]
pure fn abs() -> f32 {
if self >= 0f32 { self }
else {-self }
}
}
impl f64: Abs {
#[inline(always)]
pure fn abs() -> f64 {
if self >= 0f64 { self }
else {-self }
}
}
#[inline(always)]
pure fn min<T:copy Ord>(&&a:T, &&b:T) -> T {
if a < b { a }
else { b }
}
#[inline(always)]
pure fn max<T:copy Ord>(&&a:T, &&b:T) -> T {
if a > b { a }
else { b }
}

View file

@ -8,6 +8,7 @@
use std; use std;
mod mat; mod mat;
mod math;
mod projection; mod projection;
mod quat; mod quat;
mod vec; mod vec;

View file

@ -1,16 +1,15 @@
import std::cmp::FuzzyEq; import std::cmp::FuzzyEq;
import cmp::Ord; import cmp::Ord;
import num::Num; import num::Num;
import float::{sqrt, abs, fmin, fmax}; import float::sqrt;
import math::{Abs, min, max};
import to_str::ToStr; import to_str::ToStr;
// TODO: Unittests! I've probably made lots of mistakes...
// //
// N-dimensional Vector // N-dimensional Vector
// //
trait Vector<T:Num Ord FuzzyEq> { trait Vector<T:Num Ord FuzzyEq> {
pure fn dim() -> uint; static pure fn dim() -> uint;
pure fn index(&&index:uint) -> T; pure fn index(&&index:uint) -> T;
@ -36,8 +35,11 @@ trait Vector<T:Num Ord FuzzyEq> {
pure fn lerp(&&other:self, &&value:T) -> self; pure fn lerp(&&other:self, &&value:T) -> self;
pure fn abs() -> self; pure fn abs() -> self;
// pure fn min(&&other:self) -> self; pure fn min(&&other:self) -> self;
// pure fn max(&&other:self) -> self; pure fn max(&&other:self) -> self;
static pure fn zero() -> self;
static pure fn identity() -> self;
} }
@ -45,10 +47,15 @@ trait Vector<T:Num Ord FuzzyEq> {
trait Vector2<T:Num Ord FuzzyEq> { trait Vector2<T:Num Ord FuzzyEq> {
// This is where I wish rust had properties ;) // This is where I wish rust had properties ;)
pure fn x() -> T; pure fn x() -> T;
pure fn y() -> T; pure fn y() -> T;
// static pure fn make(x:float, y:float) -> self;
// static pure fn unit_x() -> self;
// static pure fn unit_y() -> self;
} }
trait Vector3<T:Num Ord FuzzyEq> { trait Vector3<T:Num Ord FuzzyEq> {
@ -56,6 +63,12 @@ trait Vector3<T:Num Ord FuzzyEq> {
pure fn y() -> T; pure fn y() -> T;
pure fn z() -> T; pure fn z() -> T;
// static pure fn make(x:float, y:float, z:float) -> self;
// static pure fn unit_x() -> self;
// static pure fn unit_y() -> self;
// static pure fn unit_z() -> self;
fn cross(&&other:self) -> self; fn cross(&&other:self) -> self;
} }
@ -64,6 +77,13 @@ trait Vector4<T:Num Ord FuzzyEq> {
pure fn y() -> T; pure fn y() -> T;
pure fn z() -> T; pure fn z() -> T;
pure fn w() -> T; pure fn w() -> T;
// static pure fn make(x:float, y:float, z:float, w:float) -> self;
// static pure fn unit_x() -> self;
// static pure fn unit_y() -> self;
// static pure fn unit_z() -> self;
// static pure fn unit_w() -> self;
} }
@ -76,6 +96,11 @@ trait Vector4<T:Num Ord FuzzyEq> {
// //
struct vec2 { data:[float * 2] } struct vec2 { data:[float * 2] }
const vec2_zero :vec2 = vec2 { data: [ 0f, 0f ] };
const vec2_unit_x :vec2 = vec2 { data: [ 1f, 0f ] };
const vec2_unit_y :vec2 = vec2 { data: [ 0f, 1f ] };
const vec2_identity :vec2 = vec2 { data: [ 1f, 1f ] };
// //
// Constructor // Constructor
// //
@ -84,14 +109,6 @@ pure fn vec2(x:float, y:float) -> vec2 {
vec2 { data: [ x, y ] } vec2 { data: [ x, y ] }
} }
//
// Constants
//
#[inline(always)] pure fn vec2_zero() -> vec2 { vec2 (0f, 0f) }
#[inline(always)] pure fn vec2_unit_x() -> vec2 { vec2 (1f, 0f) }
#[inline(always)] pure fn vec2_unit_y() -> vec2 { vec2 (0f, 1f) }
#[inline(always)] pure fn vec2_identity() -> vec2 { vec2 (1f, 1f) }
impl vec2: Vector2<float> { impl vec2: Vector2<float> {
#[inline(always)] pure fn x() -> float { self.data[0] } #[inline(always)] pure fn x() -> float { self.data[0] }
#[inline(always)] pure fn y() -> float { self.data[1] } #[inline(always)] pure fn y() -> float { self.data[1] }
@ -99,7 +116,7 @@ impl vec2: Vector2<float> {
impl vec2: Vector<float> { impl vec2: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn dim() -> uint { 2 } static pure fn dim() -> uint { 2 }
#[inline(always)] #[inline(always)]
pure fn index(&&i: uint) -> float { pure fn index(&&i: uint) -> float {
@ -194,21 +211,24 @@ impl vec2: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn abs() -> vec2 { pure fn abs() -> vec2 {
vec2(abs(self[0]), vec2(self[0].abs(),
abs(self[1])) self[1].abs())
} }
// #[inline(always)] #[inline(always)]
// pure fn min(&&other:vec2) -> vec2 { pure fn min(&&other:vec2) -> vec2 {
// vec2(fmin(self[0], other[0]), vec2(min(self[0], other[0]),
// fmin(self[1], other[1])) min(self[1], other[1]))
// } }
// #[inline(always)] #[inline(always)]
// pure fn max(&&other:vec2) -> vec2 { pure fn max(&&other:vec2) -> vec2 {
// vec2(fmin(self[0], other[0]), vec2(max(self[0], other[0]),
// fmin(self[1], other[1])) max(self[1], other[1]))
// } }
#[inline(always)] static pure fn zero() -> vec2 { vec2(1f, 1f) }
#[inline(always)] static pure fn identity() -> vec2 { vec2(1f, 1f) }
} }
impl vec2: ToStr { impl vec2: ToStr {
@ -227,14 +247,11 @@ impl vec2: ToStr {
// //
struct vec3 { data:[float * 3] } struct vec3 { data:[float * 3] }
// const vec3_zero :vec3 = vec3 { data: [ 0f, 0f, 0f ] };
// Constants const vec3_unit_x :vec3 = vec3 { data: [ 1f, 0f, 0f ] };
// const vec3_unit_y :vec3 = vec3 { data: [ 0f, 1f, 0f ] };
#[inline(always)] pure fn vec3_zero() -> vec3 { vec3(0f, 0f, 0f) } const vec3_unit_z :vec3 = vec3 { data: [ 0f, 0f, 1f ] };
#[inline(always)] pure fn vec3_unit_x() -> vec3 { vec3(1f, 0f, 0f) } const vec3_identity :vec3 = vec3 { data: [ 1f, 1f, 1f ] };
#[inline(always)] pure fn vec3_unit_y() -> vec3 { vec3(0f, 1f, 0f) }
#[inline(always)] pure fn vec3_unit_z() -> vec3 { vec3(0f, 0f, 1f) }
#[inline(always)] pure fn vec3_identity() -> vec3 { vec3(1f, 1f, 1f) }
// //
// Constructor // Constructor
@ -259,7 +276,7 @@ impl vec3: Vector3<float> {
impl vec3: Vector<float> { impl vec3: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn dim() -> uint { 3 } static pure fn dim() -> uint { 3 }
#[inline(always)] #[inline(always)]
pure fn index(&&i: uint) -> float { pure fn index(&&i: uint) -> float {
@ -364,24 +381,27 @@ impl vec3: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn abs() -> vec3 { pure fn abs() -> vec3 {
vec3(abs(self[0]), vec3(self[0].abs(),
abs(self[1]), self[1].abs(),
abs(self[2])) self[2].abs())
} }
// #[inline(always)] #[inline(always)]
// pure fn min(&&other:vec3) -> vec3 { pure fn min(&&other:vec3) -> vec3 {
// vec3(fmin(self[0], other[0]), vec3(min(self[0], other[0]),
// fmin(self[1], other[1]), min(self[1], other[1]),
// fmin(self[2], other[2])) min(self[2], other[2]))
// } }
// #[inline(always)] #[inline(always)]
// pure fn max(&&other:vec3) -> vec3 { pure fn max(&&other:vec3) -> vec3 {
// vec3(fmin(self[0], other[0]), vec3(max(self[0], other[0]),
// fmin(self[1], other[1]), max(self[1], other[1]),
// fmin(self[2], other[2])) max(self[2], other[2]))
// } }
#[inline(always)] static pure fn zero() -> vec3 { vec3(1f, 1f, 1f) }
#[inline(always)] static pure fn identity() -> vec3 { vec3(1f, 1f, 1f) }
} }
impl vec3: ToStr { impl vec3: ToStr {
@ -400,15 +420,12 @@ impl vec3: ToStr {
// //
struct vec4 { data:[float * 4] } struct vec4 { data:[float * 4] }
// const vec4_zero :vec4 = vec4 { data: [ 0f, 0f, 0f, 0f ] };
// Constants const vec4_unit_x :vec4 = vec4 { data: [ 1f, 0f, 0f, 0f ] };
// const vec4_unit_y :vec4 = vec4 { data: [ 0f, 1f, 0f, 0f ] };
#[inline(always)] pure fn vec4_zero() -> vec4 { vec4(0f, 0f, 0f, 0f) } const vec4_unit_z :vec4 = vec4 { data: [ 0f, 0f, 1f, 0f ] };
#[inline(always)] pure fn vec4_unit_x() -> vec4 { vec4(1f, 0f, 0f, 0f) } const vec4_unit_w :vec4 = vec4 { data: [ 0f, 0f, 0f, 1f ] };
#[inline(always)] pure fn vec4_unit_y() -> vec4 { vec4(0f, 1f, 0f, 0f) } const vec4_identity :vec4 = vec4 { data: [ 1f, 1f, 1f, 1f ] };
#[inline(always)] pure fn vec4_unit_z() -> vec4 { vec4(0f, 0f, 1f, 0f) }
#[inline(always)] pure fn vec4_unit_w() -> vec4 { vec4(0f, 0f, 0f, 1f) }
#[inline(always)] pure fn vec4_identity() -> vec4 { vec4(1f, 1f, 1f, 1f) }
// //
// Constructor // Constructor
@ -427,7 +444,7 @@ impl vec4: Vector4<float> {
impl vec4: Vector<float> { impl vec4: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn dim() -> uint { 4 } static pure fn dim() -> uint { 4 }
#[inline(always)] #[inline(always)]
pure fn index(&&i: uint) -> float { pure fn index(&&i: uint) -> float {
@ -542,27 +559,30 @@ impl vec4: Vector<float> {
#[inline(always)] #[inline(always)]
pure fn abs() -> vec4 { pure fn abs() -> vec4 {
vec4(abs(self[0]), vec4(self[0].abs(),
abs(self[1]), self[1].abs(),
abs(self[2]), self[2].abs(),
abs(self[3])) self[3].abs())
} }
// #[inline(always)] #[inline(always)]
// pure fn min(&&other:vec4) -> vec4 { pure fn min(&&other:vec4) -> vec4 {
// vec4(fmin(self[0], other[0]), vec4(min(self[0], other[0]),
// fmin(self[1], other[1]), min(self[1], other[1]),
// fmin(self[2], other[2]), min(self[2], other[2]),
// fmin(self[3], other[3])) min(self[3], other[3]))
// } }
// #[inline(always)] #[inline(always)]
// pure fn max(&&other:vec4) -> vec4 { pure fn max(&&other:vec4) -> vec4 {
// vec4(fmin(self[0], other[0]), vec4(max(self[0], other[0]),
// fmin(self[1], other[1]), max(self[1], other[1]),
// fmin(self[2], other[2]), max(self[2], other[2]),
// fmin(self[3], other[3])) max(self[3], other[3]))
// } }
#[inline(always)] static pure fn zero() -> vec4 { vec4(1f, 1f, 1f, 1f) }
#[inline(always)] static pure fn identity() -> vec4 { vec4(1f, 1f, 1f, 1f) }
} }
impl vec4: ToStr { impl vec4: ToStr {

1
test/test_math.rs Normal file
View file

@ -0,0 +1 @@
// TODO

View file

@ -9,6 +9,7 @@ use std;
use om3d; use om3d;
mod test_mat; mod test_mat;
mod test_math;
mod test_projection; mod test_projection;
mod test_quat; mod test_quat;
mod test_vec; mod test_vec;

View file

@ -5,6 +5,8 @@ import om3d::vec::*;
#[test] #[test]
fn test_vec2() { fn test_vec2() {
// assert vec2::dim == 2;
let a = vec2 { data: [ 1f, 2f ] }; let a = vec2 { data: [ 1f, 2f ] };
let b = vec2 { data: [ 3f, 4f ] }; let b = vec2 { data: [ 3f, 4f ] };
let f1 = 1.5f; let f1 = 1.5f;
@ -12,10 +14,10 @@ fn test_vec2() {
assert a == vec2(1f, 2f); assert a == vec2(1f, 2f);
assert vec2_zero() == vec2(0f, 0f); assert vec2_zero == vec2(0f, 0f);
assert vec2_unit_x() == vec2(1f, 0f); assert vec2_unit_x == vec2(1f, 0f);
assert vec2_unit_y() == vec2(0f, 1f); assert vec2_unit_y == vec2(0f, 1f);
assert vec2_identity() == vec2(1f, 1f); assert vec2_identity == vec2(1f, 1f);
assert a[0] == 1f; assert a[0] == 1f;
assert a[1] == 2f; assert a[1] == 2f;
@ -45,13 +47,15 @@ fn test_vec2() {
let f3 = 0.75f; let f3 = 0.75f;
assert c.lerp(d, f3) == vec2(0.250f, -0.250f); assert c.lerp(d, f3) == vec2(0.250f, -0.250f);
assert c.abs() == vec2(2.0f, 1.0f); assert c.abs() == vec2( 2.0f, 1.0f);
assert c.min(d) == vec2(-2.0f, -1.0f);
// TODO min, max assert c.max(d) == vec2( 1.0f, 0.0f);
} }
#[test] #[test]
fn test_vec3() { fn test_vec3() {
// assert vec3::dim == 3;
let a = vec3 { data: [ 1f, 2f, 3f ] }; let a = vec3 { data: [ 1f, 2f, 3f ] };
let b = vec3 { data: [ 4f, 5f, 6f ] }; let b = vec3 { data: [ 4f, 5f, 6f ] };
let f1 = 1.5f; let f1 = 1.5f;
@ -59,11 +63,11 @@ fn test_vec3() {
assert a == vec3(1f, 2f, 3f); assert a == vec3(1f, 2f, 3f);
assert vec3_zero() == vec3(0f, 0f, 0f); assert vec3_zero == vec3(0f, 0f, 0f);
assert vec3_unit_x() == vec3(1f, 0f, 0f); assert vec3_unit_x == vec3(1f, 0f, 0f);
assert vec3_unit_y() == vec3(0f, 1f, 0f); assert vec3_unit_y == vec3(0f, 1f, 0f);
assert vec3_unit_z() == vec3(0f, 0f, 1f); assert vec3_unit_z == vec3(0f, 0f, 1f);
assert vec3_identity() == vec3(1f, 1f, 1f); assert vec3_identity == vec3(1f, 1f, 1f);
assert a[0] == 1f; assert a[0] == 1f;
assert a[1] == 2f; assert a[1] == 2f;
@ -97,13 +101,15 @@ fn test_vec3() {
let f3 = 0.75f; let f3 = 0.75f;
assert c.lerp(d, f3) == vec3(0.250f, -0.250f, 0.625f); assert c.lerp(d, f3) == vec3(0.250f, -0.250f, 0.625f);
assert c.abs() == vec3(2.0f, 1.0f, 1.0f); assert c.abs() == vec3( 2.0f, 1.0f, 1.0f);
assert c.min(d) == vec3(-2.0f, -1.0f, 0.5f);
// TODO min, max assert c.max(d) == vec3( 1.0f, 0.0f, 1.0f);
} }
#[test] #[test]
fn test_vec4() { fn test_vec4() {
// assert vec4::dim == 4;
let a = vec4 { data: [ 1f, 2f, 3f, 4f ] }; let a = vec4 { data: [ 1f, 2f, 3f, 4f ] };
let b = vec4 { data: [ 5f, 6f, 7f, 8f ] }; let b = vec4 { data: [ 5f, 6f, 7f, 8f ] };
let f1 = 1.5f; let f1 = 1.5f;
@ -111,12 +117,12 @@ fn test_vec4() {
assert a == vec4(1f, 2f, 3f, 4f); assert a == vec4(1f, 2f, 3f, 4f);
assert vec4_zero() == vec4(0f, 0f, 0f, 0f); assert vec4_zero == vec4(0f, 0f, 0f, 0f);
assert vec4_unit_x() == vec4(1f, 0f, 0f, 0f); assert vec4_unit_x == vec4(1f, 0f, 0f, 0f);
assert vec4_unit_y() == vec4(0f, 1f, 0f, 0f); assert vec4_unit_y == vec4(0f, 1f, 0f, 0f);
assert vec4_unit_z() == vec4(0f, 0f, 1f, 0f); assert vec4_unit_z == vec4(0f, 0f, 1f, 0f);
assert vec4_unit_w() == vec4(0f, 0f, 0f, 1f); assert vec4_unit_w == vec4(0f, 0f, 0f, 1f);
assert vec4_identity() == vec4(1f, 1f, 1f, 1f); assert vec4_identity == vec4(1f, 1f, 1f, 1f);
assert a[0] == 1f; assert a[0] == 1f;
assert a[1] == 2f; assert a[1] == 2f;
@ -152,7 +158,7 @@ fn test_vec4() {
let f3 = 0.75f; let f3 = 0.75f;
assert c.lerp(d, f3) == vec4(0.250f, -0.250f, 0.625f, 1.250f); assert c.lerp(d, f3) == vec4(0.250f, -0.250f, 0.625f, 1.250f);
assert c.abs() == vec4(2.0f, 1.0f, 1.0f, 2.0f); assert c.abs() == vec4( 2.0f, 1.0f, 1.0f, 2.0f);
assert c.min(d) == vec4(-2.0f, -1.0f, 0.5f, 1.0f);
// TODO min, max assert c.max(d) == vec4( 1.0f, 0.0f, 1.0f, 2.0f);
} }