Use traits from numeric library in funs module

This commit is contained in:
Brendan Zabarauskas 2012-12-17 16:09:56 +10:00
parent 49c27ad4f1
commit 04e7ab0dfb
5 changed files with 456 additions and 808 deletions

View file

@ -5,180 +5,11 @@
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/ */
use angle::{Radians, Degrees}; use numeric::traits::*;
use vec::{Vec2, Vec3, Vec4}; use vec::{Vec2, Vec3, Vec4};
pub trait Sign { // Approx
pure fn abs(&self) -> self;
pure fn sign(&self) -> self;
}
#[inline(always)] pub pure fn abs<T:Sign>(x: &T) -> T { x.abs() }
#[inline(always)] pub pure fn sign<T:Sign>(x: &T) -> T { x.sign() }
pub impl i8: Sign {
#[inline(always)] pure fn abs(&self) -> i8 { if (*self) >= 0 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> i8 { if (*self) > 0 { 1 } else if (*self) == 0 { 0 } else { -1 } }
}
pub impl i16: Sign {
#[inline(always)] pure fn abs(&self) -> i16 { if (*self) >= 0 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> i16 { if (*self) > 0 { 1 } else if (*self) == 0 { 0 } else { -1 } }
}
pub impl i32: Sign {
#[inline(always)] pure fn abs(&self) -> i32 { if (*self) >= 0 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> i32 { if (*self) > 0 { 1 } else if (*self) == 0 { 0 } else { -1 } }
}
pub impl i64: Sign {
#[inline(always)] pure fn abs(&self) -> i64 { if (*self) >= 0 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> i64 { if (*self) > 0 { 1 } else if (*self) == 0 { 0 } else { -1 } }
}
pub impl int: Sign {
#[inline(always)] pure fn abs(&self) -> int { if (*self) >= 0 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> int { if (*self) > 0 { 1 } else if (*self) == 0 { 0 } else { -1 } }
}
pub impl f32: Sign {
#[inline(always)] pure fn abs(&self) -> f32 { if (*self) >= 0f32 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> f32 { if (*self) > 0f32 { 1f32 } else if (*self) == 0f32 { 0f32 } else { -1f32 } }
}
pub impl f64: Sign {
#[inline(always)] pure fn abs(&self) -> f64 { if (*self) >= 0f64 { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> f64 { if (*self) > 0f64 { 1f64 } else if (*self) == 0f64 { 0f64 } else { -1f64 } }
}
pub impl float: Sign {
#[inline(always)] pure fn abs(&self) -> float { if (*self) >= 0f { (*self) } else { -(*self) } }
#[inline(always)] pure fn sign(&self) -> float { if (*self) > 0f { 1f } else if (*self) == 0f { 0f } else { -1f } }
}
pub impl<T:Sign> Radians<T>: Sign{
#[inline(always)] pure fn abs(&self) -> Radians<T> { Radians(abs(&**self)) }
#[inline(always)] pure fn sign(&self) -> Radians<T> { Radians(sign(&**self)) }
}
pub impl<T:Sign> Degrees<T>: Sign{
#[inline(always)] pure fn abs(&self) -> Degrees<T> { Degrees(abs(&**self)) }
#[inline(always)] pure fn sign(&self) -> Degrees<T> { Degrees(sign(&**self)) }
}
pub impl<T:Copy Sign> Vec2<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec2<T> {
Vec2::new(abs(&self[0]),
abs(&self[1]))
}
#[inline(always)]
pure fn sign(&self) -> Vec2<T> {
Vec2::new(sign(&self[0]),
sign(&self[1]))
}
}
pub impl<T:Copy Sign> Vec3<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec3<T> {
Vec3::new(abs(&self[0]),
abs(&self[1]),
abs(&self[2]))
}
#[inline(always)]
pure fn sign(&self) -> Vec3<T> {
Vec3::new(sign(&self[0]),
sign(&self[1]),
sign(&self[2]))
}
}
pub impl<T:Copy Sign> Vec4<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec4<T> {
Vec4::new(abs(&self[0]),
abs(&self[1]),
abs(&self[2]),
abs(&self[3]))
}
#[inline(always)]
pure fn sign(&self) -> Vec4<T> {
Vec4::new(sign(&self[0]),
sign(&self[1]),
sign(&self[2]),
sign(&self[3]))
}
}
pub trait Approx {
pure fn floor(&self) -> self;
pure fn trunc(&self) -> self;
pure fn round(&self) -> self;
// pure fn roundEven(&self) -> self;
pure fn ceil(&self) -> self;
pure fn fract(&self) -> self;
}
#[inline(always)] pub pure fn floor<T:Approx>(x: &T) -> T { x.floor() }
#[inline(always)] pub pure fn trunc<T:Approx>(x: &T) -> T { x.trunc() }
#[inline(always)] pub pure fn round<T:Approx>(x: &T) -> T { x.round() }
// #[inline(always)] pub pure fn roundEven<T:Approx>(x: &T) -> T { x.roundEven() }
#[inline(always)] pub pure fn ceil<T:Approx>(x: &T) -> T { x.ceil() }
#[inline(always)] pub pure fn fract<T:Approx>(x: &T) -> T { x.fract() }
pub impl f32: Approx {
#[inline(always)] pure fn floor(&self) -> f32 { f32::floor(*self) }
#[inline(always)] pure fn trunc(&self) -> f32 { f32::trunc(*self) }
#[inline(always)] pure fn round(&self) -> f32 { f32::round(*self) }
// #[inline(always)] pure fn roundEven(&self) -> f32 {}
#[inline(always)] pure fn ceil(&self) -> f32 { f32::ceil(*self) }
#[inline(always)] pure fn fract(&self) -> f32 { (*self) - floor(self) }
}
pub impl f64: Approx {
#[inline(always)] pure fn floor(&self) -> f64 { f64::floor(*self) }
#[inline(always)] pure fn trunc(&self) -> f64 { f64::trunc(*self) }
#[inline(always)] pure fn round(&self) -> f64 { f64::round(*self) }
// #[inline(always)] pure fn roundEven(&self) -> f64 {}
#[inline(always)] pure fn ceil(&self) -> f64 { f64::ceil(*self) }
#[inline(always)] pure fn fract(&self) -> f64 { (*self) - floor(self) }
}
pub impl float: Approx {
#[inline(always)] pure fn floor(&self) -> float { f64::floor(*self as f64) as float }
#[inline(always)] pure fn trunc(&self) -> float { f64::trunc(*self as f64) as float }
#[inline(always)] pure fn round(&self) -> float { f64::round(*self as f64) as float }
// #[inline(always)] pure fn roundEven(&self) -> float {}
#[inline(always)] pure fn ceil(&self) -> float { f64::ceil(*self as f64) as float }
#[inline(always)] pure fn fract(&self) -> float { (*self) - floor(self) }
}
pub impl<T:Approx> Radians<T>: Approx{
#[inline(always)] pure fn floor(&self) -> Radians<T> { Radians(floor(&**self)) }
#[inline(always)] pure fn trunc(&self) -> Radians<T> { Radians(trunc(&**self)) }
#[inline(always)] pure fn round(&self) -> Radians<T> { Radians(round(&**self)) }
// #[inline(always)] pure fn roundEven(&self) -> Radians<T> { Radians(roundEven(&**self)) }
#[inline(always)] pure fn ceil(&self) -> Radians<T> { Radians(ceil(&**self)) }
#[inline(always)] pure fn fract(&self) -> Radians<T> { Radians(fract(&**self)) }
}
pub impl<T:Approx> Degrees<T>: Approx{
#[inline(always)] pure fn floor(&self) -> Degrees<T> { Degrees(floor(&**self)) }
#[inline(always)] pure fn trunc(&self) -> Degrees<T> { Degrees(trunc(&**self)) }
#[inline(always)] pure fn round(&self) -> Degrees<T> { Degrees(round(&**self)) }
// #[inline(always)] pure fn roundEven(&self) -> Degrees<T> { Degrees(roundEven(&**self)) }
#[inline(always)] pure fn ceil(&self) -> Degrees<T> { Degrees(ceil(&**self)) }
#[inline(always)] pure fn fract(&self) -> Degrees<T> { Degrees(fract(&**self)) }
}
pub impl<T:Copy Approx> Vec2<T>: Approx { pub impl<T:Copy Approx> Vec2<T>: Approx {
#[inline(always)] #[inline(always)]
@ -216,7 +47,6 @@ pub impl<T:Copy Approx> Vec2<T>: Approx {
Vec2::new(fract(&self[0]), Vec2::new(fract(&self[0]),
fract(&self[1])) fract(&self[1]))
} }
} }
pub impl<T:Copy Approx> Vec3<T>: Approx { pub impl<T:Copy Approx> Vec3<T>: Approx {
@ -261,7 +91,6 @@ pub impl<T:Copy Approx> Vec3<T>: Approx {
fract(&self[1]), fract(&self[1]),
fract(&self[2])) fract(&self[2]))
} }
} }
pub impl<T:Copy Approx> Vec4<T>: Approx { pub impl<T:Copy Approx> Vec4<T>: Approx {
@ -312,275 +141,9 @@ pub impl<T:Copy Approx> Vec4<T>: Approx {
fract(&self[2]), fract(&self[2]),
fract(&self[3])) fract(&self[3]))
} }
}
pub trait Extent {
pure fn min(&self, other: &self) -> self;
pure fn max(&self, other: &self) -> self;
pure fn clamp(&self, mn: &self, mx: &self) -> self;
}
#[inline(always)] pub pure fn min<T:Extent>(a: &T, b: &T) -> T { a.min(b) }
#[inline(always)] pub pure fn max<T:Extent>(a: &T, b: &T) -> T { a.max(b) }
#[inline(always)] pub pure fn clamp<T:Extent>(x: &T, mn: &T, mx: &T) -> T { x.clamp(mn, mx) }
pub impl u8: Extent {
#[inline(always)]
pure fn min(&self, other: &u8) -> u8 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &u8) -> u8 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &u8, mx: &u8) -> u8 {
min(&max(self, mn), mx)
}
}
pub impl u16: Extent {
#[inline(always)]
pure fn min(&self, other: &u16) -> u16 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &u16) -> u16 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &u16, mx: &u16) -> u16 {
min(&max(self, mn), mx)
}
}
pub impl u32: Extent {
#[inline(always)]
pure fn min(&self, other: &u32) -> u32 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &u32) -> u32 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &u32, mx: &u32) -> u32 {
min(&max(self, mn), mx)
}
}
pub impl u64: Extent {
#[inline(always)]
pure fn min(&self, other: &u64) -> u64 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &u64) -> u64 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &u64, mx: &u64) -> u64 {
min(&max(self, mn), mx)
}
}
pub impl uint: Extent {
#[inline(always)]
pure fn min(&self, other: &uint) -> uint {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &uint) -> uint {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &uint, mx: &uint) -> uint {
min(&max(self, mn), mx)
}
}
pub impl i8: Extent {
#[inline(always)]
pure fn min(&self, other: &i8) -> i8 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &i8) -> i8 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &i8, mx: &i8) -> i8 {
min(&max(self, mn), mx)
}
}
pub impl i16: Extent {
#[inline(always)]
pure fn min(&self, other: &i16) -> i16 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &i16) -> i16 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &i16, mx: &i16) -> i16 {
min(&max(self, mn), mx)
}
}
pub impl i32: Extent {
#[inline(always)]
pure fn min(&self, other: &i32) -> i32 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &i32) -> i32 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &i32, mx: &i32) -> i32 {
min(&max(self, mn), mx)
}
}
pub impl i64: Extent {
#[inline(always)]
pure fn min(&self, other: &i64) -> i64 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &i64) -> i64 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &i64, mx: &i64) -> i64 {
min(&max(self, mn), mx)
}
}
pub impl int: Extent {
#[inline(always)]
pure fn min(&self, other: &int) -> int {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &int) -> int {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &int, mx: &int) -> int {
min(&max(self, mn), mx)
}
}
pub impl f32: Extent {
#[inline(always)]
pure fn min(&self, other: &f32) -> f32 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &f32) -> f32 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
min(&max(self, mn), mx)
}
}
pub impl f64: Extent {
#[inline(always)]
pure fn min(&self, other: &f64) -> f64 {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &f64) -> f64 {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
min(&max(self, mn), mx)
}
}
pub impl float: Extent {
#[inline(always)]
pure fn min(&self, other: &float) -> float {
if (*self) < (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn max(&self, other: &float) -> float {
if (*self) > (*other) { (*self) } else { (*other) }
}
#[inline(always)]
pure fn clamp(&self, mn: &float, mx: &float) -> float {
min(&max(self, mn), mx)
}
}
pub impl<T:Copy Extent> Radians<T>: Extent{
#[inline(always)]
pure fn min(&self, other: &Radians<T>) -> Radians<T> {
Radians(min(&**self, &**other))
}
#[inline(always)]
pure fn max(&self, other: &Radians<T>) -> Radians<T> {
Radians(max(&**self, &**other))
}
#[inline(always)]
pure fn clamp(&self, mn: &Radians<T>, mx: &Radians<T>) -> Radians<T> {
Radians((**self).clamp(&**mn, &**mx))
}
}
pub impl<T:Copy Extent> Degrees<T>: Extent{
#[inline(always)]
pure fn min(&self, other: &Degrees<T>) -> Degrees<T> {
Degrees(min(&**self, &**other))
}
#[inline(always)]
pure fn max(&self, other: &Degrees<T>) -> Degrees<T> {
Degrees(max(&**self, &**other))
}
#[inline(always)]
pure fn clamp(&self, mn: &Degrees<T>, mx: &Degrees<T>) -> Degrees<T> {
Degrees((**self).clamp(&**mn, &**mx))
}
} }
// Extent
pub impl<T:Copy Extent> Vec2<T>: Extent { pub impl<T:Copy Extent> Vec2<T>: Extent {
#[inline(always)] #[inline(always)]
@ -651,91 +214,7 @@ pub impl<T:Copy Extent> Vec4<T>: Extent {
} }
} }
// Mix
pub trait Mix {
pure fn mix(&self, other: &self, value: &self) -> self;
pure fn smooth_step(&self, edge0: &self, edge1: &self) -> self;
pure fn step(&self, edge: &self) -> self;
}
#[inline(always)] pub pure fn mix<T:Mix>(a: &T, b: &T, value: &T) -> T { a.mix(b, value) }
#[inline(always)] pub pure fn smooth_step<T:Mix>(x: &T, edge0: &T, edge1: &T) -> T { x.smooth_step(edge0, edge1) }
#[inline(always)] pub pure fn step<T:Mix>(x: &T, edge: &T) -> T { x.step(edge) }
pub impl f32: Mix {
#[inline(always)]
pure fn mix(&self, other: &f32, value: &f32) -> f32 {
(*self) * (1.0 - (*value)) + (*other) * (*value)
}
#[inline(always)]
pure fn smooth_step(&self, edge0: &f32, edge1: &f32) -> f32 {
let t = clamp(&((*self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0);
return t * t * (3.0 - 2.0 * t);
}
#[inline(always)]
pure fn step(&self, edge: &f32) -> f32 {
if (*self) < (*edge) { 0.0 } else { 1.0 }
}
}
pub impl f64: Mix {
#[inline(always)]
pure fn mix(&self, other: &f64, value: &f64) -> f64 {
(*self) * (1.0 - (*value)) + (*other) * (*value)
}
#[inline(always)]
pure fn smooth_step(&self, edge0: &f64, edge1: &f64) -> f64 {
let t = clamp(&((*self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0);
return t * t * (3.0 - 2.0 * t);
}
#[inline(always)]
pure fn step(&self, edge: &f64) -> f64 {
if (*self) < (*edge) { 0.0 } else { 1.0 }
}
}
pub impl float: Mix {
#[inline(always)]
pure fn mix(&self, other: &float, value: &float) -> float {
(*self) * (1.0 - (*value)) + (*other) * (*value)
}
#[inline(always)]
pure fn smooth_step(&self, edge0: &float, edge1: &float) -> float {
let t = clamp(&((*self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0);
return t * t * (3.0 - 2.0 * t);
}
#[inline(always)]
pure fn step(&self, edge: &float) -> float {
if (*self) < (*edge) { 0.0 } else { 1.0 }
}
}
// FIXME: ICE!!
pub impl<T:Mix> Radians<T>: Mix {
#[inline(always)]
pure fn mix(&self, other: &Radians<T>, value: &Radians<T>) -> Radians<T> {
Radians((**self).mix(&**other, &**value))
}
#[inline(always)]
pure fn smooth_step(&self, edge0: &Radians<T>, edge1: &Radians<T>) -> Radians<T> {
Radians((**self).smooth_step(&**edge0, &**edge1))
}
#[inline(always)]
pure fn step(&self, edge: &Radians<T>) -> Radians<T> {
Radians((**self).step(&**edge))
}
}
pub impl<T:Copy Mix> Vec2<T>: Mix { pub impl<T:Copy Mix> Vec2<T>: Mix {
#[inline(always)] #[inline(always)]
@ -805,3 +284,53 @@ pub impl<T:Copy Mix> Vec4<T>: Mix {
self[3].step(&edge[3])) self[3].step(&edge[3]))
} }
} }
// Sign
pub impl<T:Copy Sign> Vec2<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec2<T> {
Vec2::new(abs(&self[0]),
abs(&self[1]))
}
#[inline(always)]
pure fn sign(&self) -> Vec2<T> {
Vec2::new(sign(&self[0]),
sign(&self[1]))
}
}
pub impl<T:Copy Sign> Vec3<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec3<T> {
Vec3::new(abs(&self[0]),
abs(&self[1]),
abs(&self[2]))
}
#[inline(always)]
pure fn sign(&self) -> Vec3<T> {
Vec3::new(sign(&self[0]),
sign(&self[1]),
sign(&self[2]))
}
}
pub impl<T:Copy Sign> Vec4<T>: Sign {
#[inline(always)]
pure fn abs(&self) -> Vec4<T> {
Vec4::new(abs(&self[0]),
abs(&self[1]),
abs(&self[2]),
abs(&self[3]))
}
#[inline(always)]
pure fn sign(&self) -> Vec4<T> {
Vec4::new(sign(&self[0]),
sign(&self[1]),
sign(&self[2]),
sign(&self[3]))
}
}

View file

@ -5,55 +5,11 @@
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/ */
use numeric::traits::*;
use vec::{Vec2, Vec3, Vec4}; use vec::{Vec2, Vec3, Vec4};
pub trait Exp { // Exp
pure fn pow(&self, n: &self) -> self;
pure fn exp(&self) -> self;
pure fn log_(&self) -> self;
pure fn exp2(&self) -> self;
pure fn log2(&self) -> self;
pure fn sqrt(&self) -> self;
pure fn inv_sqrt(&self) -> self;
}
#[inline(always)] pub pure fn pow<T:Exp>(x: &T, n: &T) -> T { x.pow(n) }
#[inline(always)] pub pure fn exp<T:Exp>(x: &T) -> T { x.exp() }
#[inline(always)] pub pure fn log_<T:Exp>(x: &T) -> T { x.log_() }
#[inline(always)] pub pure fn exp2<T:Exp>(x: &T) -> T { x.exp2() }
#[inline(always)] pub pure fn log2<T:Exp>(x: &T) -> T { x.log2() }
#[inline(always)] pub pure fn sqrt<T:Exp>(x: &T) -> T { x.sqrt() }
#[inline(always)] pub pure fn inv_sqrt<T:Exp>(x: &T) -> T { x.inv_sqrt() }
pub impl f32: Exp {
#[inline(always)] pure fn pow(&self, n: &f32) -> f32 { f32::pow(*self, *n) }
#[inline(always)] pure fn exp(&self) -> f32 { f32::exp(*self) }
#[inline(always)] pure fn log_(&self) -> f32 { f32::ln(*self) }
#[inline(always)] pure fn exp2(&self) -> f32 { f32::exp2(*self) }
#[inline(always)] pure fn log2(&self) -> f32 { f32::log2(*self) }
#[inline(always)] pure fn sqrt(&self) -> f32 { f32::sqrt(*self) }
#[inline(always)] pure fn inv_sqrt(&self) -> f32 { 1f32 / self.sqrt() } // TODO: optimise? need a wizard
}
pub impl f64: Exp {
#[inline(always)] pure fn pow(&self, n: &f64) -> f64 { f64::pow(*self, *n) }
#[inline(always)] pure fn exp(&self) -> f64 { f64::exp(*self) }
#[inline(always)] pure fn log_(&self) -> f64 { f64::ln(*self) }
#[inline(always)] pure fn exp2(&self) -> f64 { f64::exp2(*self) }
#[inline(always)] pure fn log2(&self) -> f64 { f64::log2(*self) }
#[inline(always)] pure fn sqrt(&self) -> f64 { f64::sqrt(*self) }
#[inline(always)] pure fn inv_sqrt(&self) -> f64 { 1f64 / self.sqrt() } // TODO: optimise? need a wizard
}
pub impl float: Exp {
#[inline(always)] pure fn pow(&self, n: &float) -> float { f64::pow(*self as f64, *n as f64) as float }
#[inline(always)] pure fn exp(&self) -> float { f64::exp(*self as f64) as float }
#[inline(always)] pure fn log_(&self) -> float { f64::ln(*self as f64) as float }
#[inline(always)] pure fn exp2(&self) -> float { f64::exp2(*self as f64) as float }
#[inline(always)] pure fn log2(&self) -> float { f64::log2(*self as f64) as float }
#[inline(always)] pure fn sqrt(&self) -> float { f64::sqrt(*self as f64) as float }
#[inline(always)] pure fn inv_sqrt(&self) -> float { 1f / self.sqrt() } // TODO: optimise? need a wizard
}
pub impl<T:Copy Exp> Vec2<T>: Exp { pub impl<T:Copy Exp> Vec2<T>: Exp {
#[inline(always)] #[inline(always)]

264
src/funs/relational.rs Normal file
View file

@ -0,0 +1,264 @@
/**
* Vector Relational Functions
*
* This module corresponds to Section 8.7 of the [GLSL 4.30.6 specification]
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/
use core::cmp::{Eq, Ord};
use vec::{Vector, Vec2, Vec3, Vec4};
/**
* Component-wise vector comparison methods
*/
pub trait OrdinalVector<T, BoolVec>: Vector<T> {
/**
* Component-wise compare of `self < other`
*/
pure fn less_than(&self, other: &self) -> BoolVec;
/**
* Component-wise compare of `self <= other`
*/
pure fn less_than_equal(&self, other: &self) -> BoolVec;
/**
* Component-wise compare of `self > other`
*/
pure fn greater_than(&self, other: &self) -> BoolVec;
/**
* Component-wise compare of `self >= other`
*/
pure fn greater_than_equal(&self, other: &self) -> BoolVec;
}
/**
* Component-wise equality comparison methods
*/
pub trait EquableVector<T, BoolVec>: Vector<T> {
/**
* Component-wise compare of `self == other`
*/
pure fn equal(&self, other: &self) -> BoolVec;
/**
* Component-wise compare of `self != other`
*/
pure fn not_equal(&self, other: &self) -> BoolVec;
}
/**
* A vector with boolean components
*/
pub trait BooleanVector: Vector<bool> {
/**
* # Return value
*
* `true` if of any component is `true`
*/
pure fn any(&self) -> bool;
/**
* # Return value
*
* `true` only if all components are `true`
*/
pure fn all(&self) -> bool;
/**
* # Return value
*
* the component-wise logical complement
*/
pure fn not(&self) -> self;
}
pub impl<T:Copy Ord> Vec2<T>: OrdinalVector<T, Vec2<bool>> {
#[inline(always)]
pure fn less_than(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] < other[0],
self[1] < other[1])
}
#[inline(always)]
pure fn less_than_equal(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] <= other[0],
self[1] <= other[1])
}
#[inline(always)]
pure fn greater_than(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] > other[0],
self[1] > other[1])
}
#[inline(always)]
pure fn greater_than_equal(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] >= other[0],
self[1] >= other[1])
}
}
pub impl<T:Copy Eq> Vec2<T>: EquableVector<T, Vec2<bool>> {
#[inline(always)]
pure fn equal(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] == other[0],
self[1] == other[1])
}
#[inline(always)]
pure fn not_equal(&self, other: &Vec2<T>) -> Vec2<bool> {
Vec2::new(self[0] != other[0],
self[1] != other[1])
}
}
pub impl Vec2<bool>: BooleanVector {
#[inline(always)]
pure fn any(&self) -> bool {
self[0] || self[1]
}
#[inline(always)]
pure fn all(&self) -> bool {
self[0] && self[1]
}
#[inline(always)]
pure fn not(&self) -> Vec2<bool> {
Vec2::new(!self[0], !self[1])
}
}
pub impl<T:Copy Ord> Vec3<T>: OrdinalVector<T, Vec3<bool>> {
#[inline(always)]
pure fn less_than(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] < other[0],
self[1] < other[1],
self[2] < other[2])
}
#[inline(always)]
pure fn less_than_equal(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] <= other[0],
self[1] <= other[1],
self[2] <= other[2])
}
#[inline(always)]
pure fn greater_than(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] > other[0],
self[1] > other[1],
self[2] > other[2])
}
#[inline(always)]
pure fn greater_than_equal(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] >= other[0],
self[1] >= other[1],
self[2] >= other[2])
}
}
pub impl<T:Copy Eq> Vec3<T>: EquableVector<T, Vec3<bool>> {
#[inline(always)]
pure fn equal(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] == other[0],
self[1] == other[1],
self[2] == other[2])
}
#[inline(always)]
pure fn not_equal(&self, other: &Vec3<T>) -> Vec3<bool> {
Vec3::new(self[0] != other[0],
self[1] != other[1],
self[2] != other[2])
}
}
pub impl Vec3<bool>: BooleanVector {
#[inline(always)]
pure fn any(&self) -> bool {
self[0] || self[1] || self[2]
}
#[inline(always)]
pure fn all(&self) -> bool {
self[0] && self[1] && self[2]
}
#[inline(always)]
pure fn not(&self) -> Vec3<bool> {
Vec3::new(!self[0], !self[1], !self[2])
}
}
pub impl<T:Copy Ord> Vec4<T>: OrdinalVector<T, Vec4<bool>> {
#[inline(always)]
pure fn less_than(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] < other[0],
self[1] < other[1],
self[2] < other[2],
self[3] < other[3])
}
#[inline(always)]
pure fn less_than_equal(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] <= other[0],
self[1] <= other[1],
self[2] <= other[2],
self[3] <= other[3])
}
#[inline(always)]
pure fn greater_than(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] > other[0],
self[1] > other[1],
self[2] > other[2],
self[3] > other[3])
}
#[inline(always)]
pure fn greater_than_equal(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] >= other[0],
self[1] >= other[1],
self[2] >= other[2],
self[3] >= other[3])
}
}
pub impl<T:Copy Eq> Vec4<T>: EquableVector<T, Vec4<bool>> {
#[inline(always)]
pure fn equal(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] == other[0],
self[1] == other[1],
self[2] == other[2],
self[3] == other[3])
}
#[inline(always)]
pure fn not_equal(&self, other: &Vec4<T>) -> Vec4<bool> {
Vec4::new(self[0] != other[0],
self[1] != other[1],
self[2] != other[2],
self[3] != other[3])
}
}
pub impl Vec4<bool>: BooleanVector {
#[inline(always)]
pure fn any(&self) -> bool {
self[0] || self[1] || self[2] || self[3]
}
#[inline(always)]
pure fn all(&self) -> bool {
self[0] && self[1] && self[2] && self[3]
}
#[inline(always)]
pure fn not(&self) -> Vec4<bool> {
Vec4::new(!self[0], !self[1], !self[2], !self[3])
}
}

View file

@ -4,257 +4,156 @@
* This module corresponds to Section 8.1 of the [GLSL 4.30.6 specification] * This module corresponds to Section 8.1 of the [GLSL 4.30.6 specification]
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/ */
use angle::{Radians, Degrees};
use num::types::{Number, Float}; use numeric::traits::*;
use numeric::types::angle::{Angle, Radians};
use numeric::types::float::Float;
use vec::{Vec3, Vec2, Vec4}; use vec::{Vec3, Vec2, Vec4};
/** // // Trig
* Triganomic functions
*
* http://en.wikipedia.org/wiki/Trigonometric_functions
*/
priv trait Trig<T> {
pure fn sin(&self) -> T;
pure fn cos(&self) -> T;
pure fn tan(&self) -> T;
}
#[inline(always)] pub pure fn sin<T:Trig<R>, R>(theta: &T) -> R { theta.sin() } // pub impl<T:Copy Float, A:Copy Angle<T>> Vec2<A>: Trig<Vec2<T>> {
#[inline(always)] pub pure fn cos<T:Trig<R>, R>(theta: &T) -> R { theta.cos() } // #[inline(always)]
#[inline(always)] pub pure fn tan<T:Trig<R>, R>(theta: &T) -> R { theta.tan() } // pure fn sin(&self) -> Vec2<T> {
// Vec2::new(sin(&self[0]),
priv impl<T:Copy Float> Radians<T>: Trig<T> { // sin(&self[1]))
#[inline(always)] pure fn sin(&self) -> T { Number::from(f64::sin(Number::from(**self))) } // }
#[inline(always)] pure fn cos(&self) -> T { Number::from(f64::cos(Number::from(**self))) }
#[inline(always)] pure fn tan(&self) -> T { Number::from(f64::tan(Number::from(**self))) }
}
pub impl<T:Copy Float> Degrees<T>: Trig<T> {
#[inline(always)] pure fn sin(&self) -> T { Number::from(f64::sin(Number::from(*self.to_radians()))) }
#[inline(always)] pure fn cos(&self) -> T { Number::from(f64::cos(Number::from(*self.to_radians()))) }
#[inline(always)] pure fn tan(&self) -> T { Number::from(f64::tan(Number::from(*self.to_radians()))) }
}
pub impl<T:Copy Float> Vec2<Radians<T>>: Trig<Vec2<T>> {
#[inline(always)]
pure fn sin(&self) -> Vec2<T> {
Vec2::new(sin(&self[0]),
sin(&self[1]))
}
#[inline(always)] // #[inline(always)]
pure fn cos(&self) -> Vec2<T> { // pure fn cos(&self) -> Vec2<T> {
Vec2::new(cos(&self[0]), // Vec2::new(cos(&self[0]),
cos(&self[1])) // cos(&self[1]))
} // }
#[inline(always)] // #[inline(always)]
pure fn tan(&self) -> Vec2<T> { // pure fn tan(&self) -> Vec2<T> {
Vec2::new(tan(&self[0]), // Vec2::new(tan(&self[0]),
tan(&self[1])) // tan(&self[1]))
} // }
} // }
pub impl<T:Copy Float> Vec3<Radians<T>>: Trig<Vec3<T>> { // pub impl<T:Copy Float, A:Copy Angle<T>> Vec3<A>: Trig<Vec3<T>> {
#[inline(always)] // #[inline(always)]
pure fn sin(&self) -> Vec3<T> { // pure fn sin(&self) -> Vec3<T> {
Vec3::new(sin(&self[0]), // Vec3::new(sin(&self[0]),
sin(&self[1]), // sin(&self[1]),
sin(&self[2])) // sin(&self[2]))
} // }
#[inline(always)] // #[inline(always)]
pure fn cos(&self) -> Vec3<T> { // pure fn cos(&self) -> Vec3<T> {
Vec3::new(cos(&self[0]), // Vec3::new(cos(&self[0]),
cos(&self[1]), // cos(&self[1]),
cos(&self[2])) // cos(&self[2]))
} // }
#[inline(always)] // #[inline(always)]
pure fn tan(&self) -> Vec3<T> { // pure fn tan(&self) -> Vec3<T> {
Vec3::new(tan(&self[0]), // Vec3::new(tan(&self[0]),
tan(&self[1]), // tan(&self[1]),
tan(&self[2])) // tan(&self[2]))
} // }
} // }
pub impl<T:Copy Float> Vec4<Radians<T>>: Trig<Vec4<T>> { // pub impl<T:Copy Float, A:Copy Angle<T>> Vec4<A>: Trig<Vec4<T>> {
#[inline(always)] // #[inline(always)]
pure fn sin(&self) -> Vec4<T> { // pure fn sin(&self) -> Vec4<T> {
Vec4::new(sin(&self[0]), // Vec4::new(sin(&self[0]),
sin(&self[1]), // sin(&self[1]),
sin(&self[2]), // sin(&self[2]),
sin(&self[3])) // sin(&self[3]))
} // }
#[inline(always)] // #[inline(always)]
pure fn cos(&self) -> Vec4<T> { // pure fn cos(&self) -> Vec4<T> {
Vec4::new(cos(&self[0]), // Vec4::new(cos(&self[0]),
cos(&self[1]), // cos(&self[1]),
cos(&self[2]), // cos(&self[2]),
cos(&self[3])) // cos(&self[3]))
} // }
#[inline(always)] // #[inline(always)]
pure fn tan(&self) -> Vec4<T> { // pure fn tan(&self) -> Vec4<T> {
Vec4::new(tan(&self[0]), // Vec4::new(tan(&self[0]),
tan(&self[1]), // tan(&self[1]),
tan(&self[2]), // tan(&self[2]),
tan(&self[3])) // tan(&self[3]))
} // }
} // }
/** // // InvTrig
* Inverse triganomic functions
*
* http://en.wikipedia.org/wiki/Inverse_trigonometric_functions
*/
pub trait InvTrig {
pure fn asin(&self) -> Radians<self>;
pure fn acos(&self) -> Radians<self>;
pure fn atan(&self) -> Radians<self>;
pure fn atan2(&self, other: &self) -> Radians<self>;
}
#[inline(always)] pub pure fn asin<T:InvTrig>(x: &T) -> Radians<T> { x.asin() } // pub impl<T:Copy Float InvTrig> Vec2<T>: InvTrig<Vec2<Radians<T>>> {
#[inline(always)] pub pure fn acos<T:InvTrig>(x: &T) -> Radians<T> { x.acos() } // #[inline(always)]
#[inline(always)] pub pure fn atan<T:InvTrig>(x: &T) -> Radians<T> { x.atan() } // pure fn asin(&self) -> Vec2<Radians<T>> {
#[inline(always)] pub pure fn atan2<T:InvTrig>(a: &T, b: &T) -> Radians<T> { a.atan2(b) } // Vec2::new(asin(&self[0]),
// asin(&self[1]))
pub impl f32: InvTrig { // }
#[inline(always)] pure fn asin(&self) -> Radians<f32> { Radians(f32::asin(*self)) }
#[inline(always)] pure fn acos(&self) -> Radians<f32> { Radians(f32::acos(*self)) }
#[inline(always)] pure fn atan(&self) -> Radians<f32> { Radians(f32::atan(*self)) }
#[inline(always)] pure fn atan2(&self, other: &f32) -> Radians<f32> { Radians(f32::atan2(*self, *other)) }
}
pub impl f64: InvTrig {
#[inline(always)] pure fn asin(&self) -> Radians<f64> { Radians(f64::asin(*self)) }
#[inline(always)] pure fn acos(&self) -> Radians<f64> { Radians(f64::acos(*self)) }
#[inline(always)] pure fn atan(&self) -> Radians<f64> { Radians(f64::atan(*self)) }
#[inline(always)] pure fn atan2(&self, other: &f64) -> Radians<f64> { Radians(f64::atan2(*self, *other)) }
}
pub impl float: InvTrig {
#[inline(always)] pure fn asin(&self) -> Radians<float> { Radians(f64::asin(*self as f64) as float) }
#[inline(always)] pure fn acos(&self) -> Radians<float> { Radians(f64::acos(*self as f64) as float) }
#[inline(always)] pure fn atan(&self) -> Radians<float> { Radians(f64::atan(*self as f64) as float) }
#[inline(always)] pure fn atan2(&self, other: &float) -> Radians<float> { Radians(f64::atan2(*self as f64, *other as f64) as float) }
}
// TODO: figure out how to merge with InvTrig
pub trait InvTrigV<T> {
pure fn asin(&self) -> T;
pure fn acos(&self) -> T;
pure fn atan(&self) -> T;
}
pub impl<T:Copy Number InvTrig> Vec2<T>: InvTrigV<Vec2<Radians<T>>> {
#[inline(always)]
pure fn asin(&self) -> Vec2<Radians<T>> {
Vec2::new(asin(&self[0]),
asin(&self[1]))
}
#[inline(always)] // #[inline(always)]
pure fn acos(&self) -> Vec2<Radians<T>> { // pure fn acos(&self) -> Vec2<Radians<T>> {
Vec2::new(acos(&self[0]), // Vec2::new(acos(&self[0]),
acos(&self[1])) // acos(&self[1]))
} // }
#[inline(always)] // #[inline(always)]
pure fn atan(&self) -> Vec2<Radians<T>> { // pure fn atan(&self) -> Vec2<Radians<T>> {
Vec2::new(atan(&self[0]), // Vec2::new(atan(&self[0]),
atan(&self[1])) // atan(&self[1]))
} // }
} // }
pub impl<T:Copy Number InvTrig> Vec3<T>: InvTrigV<Vec3<Radians<T>>> { // pub impl<T:Copy Float InvTrig> Vec3<T>: InvTrig<Vec3<Radians<T>>> {
#[inline(always)] // #[inline(always)]
pure fn asin(&self) -> Vec3<Radians<T>> { // pure fn asin(&self) -> Vec3<Radians<T>> {
Vec3::new(asin(&self[0]), // Vec3::new(asin(&self[0]),
asin(&self[1]), // asin(&self[1]),
asin(&self[2])) // asin(&self[2]))
} // }
#[inline(always)] // #[inline(always)]
pure fn acos(&self) -> Vec3<Radians<T>> { // pure fn acos(&self) -> Vec3<Radians<T>> {
Vec3::new(acos(&self[0]), // Vec3::new(acos(&self[0]),
acos(&self[1]), // acos(&self[1]),
acos(&self[2])) // acos(&self[2]))
} // }
#[inline(always)] // #[inline(always)]
pure fn atan(&self) -> Vec3<Radians<T>> { // pure fn atan(&self) -> Vec3<Radians<T>> {
Vec3::new(atan(&self[0]), // Vec3::new(atan(&self[0]),
atan(&self[1]), // atan(&self[1]),
atan(&self[2])) // atan(&self[2]))
} // }
} // }
pub impl<T:Copy Number InvTrig> Vec4<T>: InvTrigV<Vec4<Radians<T>>> { // pub impl<T:Copy Float InvTrig> Vec4<T>: InvTrig<Vec4<Radians<T>>> {
#[inline(always)] // #[inline(always)]
pure fn asin(&self) -> Vec4<Radians<T>> { // pure fn asin(&self) -> Vec4<Radians<T>> {
Vec4::new(asin(&self[0]), // Vec4::new(asin(&self[0]),
asin(&self[1]), // asin(&self[1]),
asin(&self[2]), // asin(&self[2]),
asin(&self[3])) // asin(&self[3]))
} // }
#[inline(always)] // #[inline(always)]
pure fn acos(&self) -> Vec4<Radians<T>> { // pure fn acos(&self) -> Vec4<Radians<T>> {
Vec4::new(acos(&self[0]), // Vec4::new(acos(&self[0]),
acos(&self[1]), // acos(&self[1]),
acos(&self[2]), // acos(&self[2]),
acos(&self[3])) // acos(&self[3]))
} // }
#[inline(always)] // #[inline(always)]
pure fn atan(&self) -> Vec4<Radians<T>> { // pure fn atan(&self) -> Vec4<Radians<T>> {
Vec4::new(atan(&self[0]), // Vec4::new(atan(&self[0]),
atan(&self[1]), // atan(&self[1]),
atan(&self[2]), // atan(&self[2]),
atan(&self[3])) // atan(&self[3]))
} // }
} // }
// Hyp
/**
* Hyperbolic functions
*
* http://en.wikipedia.org/wiki/Hyperbolic_function
*/
pub trait Hyp {
pure fn sinh(&self) -> self;
pure fn cosh(&self) -> self;
pure fn tanh(&self) -> self;
// pure fn asinh() -> self;
// pure fn acosh() -> self;
// pure fn atanh() -> self;
}
#[inline(always)] pub pure fn sinh<T:Hyp>(x: &T) -> T { x.sinh() }
#[inline(always)] pub pure fn cosh<T:Hyp>(x: &T) -> T { x.cosh() }
#[inline(always)] pub pure fn tanh<T:Hyp>(x: &T) -> T { x.tanh() }
pub impl f32: Hyp {
#[inline(always)] pure fn sinh(&self) -> f32 { f32::sinh(*self) }
#[inline(always)] pure fn cosh(&self) -> f32 { f32::cosh(*self) }
#[inline(always)] pure fn tanh(&self) -> f32 { f32::tanh(*self) }
}
pub impl f64: Hyp {
#[inline(always)] pure fn sinh(&self) -> f64 { f64::sinh(*self) }
#[inline(always)] pure fn cosh(&self) -> f64 { f64::cosh(*self) }
#[inline(always)] pure fn tanh(&self) -> f64 { f64::tanh(*self) }
}
pub impl float: Hyp {
#[inline(always)] pure fn sinh(&self) -> float { f64::sinh(*self as f64) as float }
#[inline(always)] pure fn cosh(&self) -> float { f64::cosh(*self as f64) as float }
#[inline(always)] pure fn tanh(&self) -> float { f64::tanh(*self as f64) as float }
}
pub impl <T:Copy Hyp> Vec2<T>: Hyp { pub impl <T:Copy Hyp> Vec2<T>: Hyp {
#[inline(always)] #[inline(always)]

View file

@ -29,14 +29,14 @@ mod test {
} }
pub mod funs { pub mod funs {
// #[path = "funs/common.rs"] #[path = "funs/common.rs"]
// pub mod common; pub mod common;
// #[path = "funs/exponential.rs"] #[path = "funs/exponential.rs"]
// pub mod exponential; pub mod exponential;
#[path = "funs/projection.rs"] #[path = "funs/projection.rs"]
pub mod projection; pub mod projection;
// #[path = "funs/triganomic.rs"] #[path = "funs/triganomic.rs"]
// pub mod triganomic; pub mod triganomic;
#[test] #[test]
mod test { mod test {