Add and use Number::from static method

This commit is contained in:
Brendan Zabarauskas 2012-12-03 16:19:53 +10:00
parent ddc7559153
commit 248242dda5
9 changed files with 151 additions and 126 deletions

View file

@ -1,5 +1,3 @@
use num::cast::{NumCast, cast};
pub trait Channel { pub trait Channel {
static pure fn channel_max() -> self; static pure fn channel_max() -> self;

View file

@ -1,5 +1,5 @@
use core::cast::transmute; use core::cast::transmute;
use core::cmp::{Eq, Ord}; use core::cmp::Eq;
use core::ptr::to_unsafe_ptr; use core::ptr::to_unsafe_ptr;
use core::sys::size_of; use core::sys::size_of;
use core::vec::raw::buf_as_slice; use core::vec::raw::buf_as_slice;
@ -8,8 +8,7 @@ use angle::Degrees;
use channel::Channel; use channel::Channel;
use dim::{Dimensional, ToPtr}; use dim::{Dimensional, ToPtr};
use funs::common::Sign; use funs::common::Sign;
use num::cast::{cast, NumCast}; use num::kinds::{Float, Number};
use num::kinds::Float;
pub trait Color<T>: Dimensional<T>, ToPtr<T>, Eq { pub trait Color<T>: Dimensional<T>, ToPtr<T>, Eq {
@ -65,18 +64,18 @@ pub pure fn to_hsv<T:Copy Float>(color: &RGB<T>) -> HSV<T> {
// Algorithm taken from the Wikipedia article on HSL and HSV: // Algorithm taken from the Wikipedia article on HSL and HSV:
// http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV // http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
let _0 = Float::from_float(0f); let _0 = Number::from(0f);
let mx = [color.r, color.g, color.b].max(); let mx = [color.r, color.g, color.b].max();
let mn = [color.r, color.g, color.b].min(); let mn = [color.r, color.g, color.b].min();
let chr = mx - mn; let chr = mx - mn;
if chr != Float::from_float(0f) { if chr != Number::from(0f) {
let h = Degrees( let h = Degrees(
if color.r == mx { ((color.g - color.b) / chr) % Float::from_float(6f) } if color.r == mx { ((color.g - color.b) / chr) % Number::from(6f) }
else if color.g == mx { ((color.b - color.r) / chr) + Float::from_float(2f) } else if color.g == mx { ((color.b - color.r) / chr) + Number::from(2f) }
else /* color.b == mx */{ ((color.r - color.g) / chr) + Float::from_float(4f) } else /* color.b == mx */{ ((color.r - color.g) / chr) + Number::from(4f) }
* Float::from_float(60f)); * Number::from(60f));
let s = chr / mx; let s = chr / mx;
@ -95,24 +94,24 @@ pub pure fn to_rgb<T:Copy Float Sign>(color: &HSV<T>) -> RGB<T> {
// Algorithm taken from the Wikipedia article on HSL and HSV: // Algorithm taken from the Wikipedia article on HSL and HSV:
// http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV // http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
let _0: T = Float::from_float(0f); let _0: T = Number::from(0f);
let _1: T = Float::from_float(1f); let _1: T = Number::from(1f);
let _2: T = Float::from_float(2f); let _2: T = Number::from(2f);
let chr = color.v * color.s; let chr = color.v * color.s;
let h_ = (* color.h) / Float::from_float(60f); // TODO: it'd be nice if Degrees / Degrees returned a scalar let h_ = (* color.h) / Number::from(60f); // TODO: it'd be nice if Degrees / Degrees returned a scalar
// the 2nd largest component // the 2nd largest component
let x = chr * (_1 - ((h_ % _2) - _1).abs()); let x = chr * (_1 - ((h_ % _2) - _1).abs());
let mut color_rgb = let mut color_rgb =
if h_ < Float::from_float(1f) { RGB::new(chr, x, _0) } if h_ < Number::from(1f) { RGB::new(chr, x, _0) }
else if h_ < Float::from_float(2f) { RGB::new( x, chr, _0) } else if h_ < Number::from(2f) { RGB::new( x, chr, _0) }
else if h_ < Float::from_float(3f) { RGB::new( _0, chr, x) } else if h_ < Number::from(3f) { RGB::new( _0, chr, x) }
else if h_ < Float::from_float(4f) { RGB::new( _0, x, chr) } else if h_ < Number::from(4f) { RGB::new( _0, x, chr) }
else if h_ < Float::from_float(5f) { RGB::new( x, _0, chr) } else if h_ < Number::from(5f) { RGB::new( x, _0, chr) }
else if h_ < Float::from_float(6f) { RGB::new(chr, _0, x) } else if h_ < Number::from(6f) { RGB::new(chr, _0, x) }
else { RGB::new( _0, _0, _0) }; else { RGB::new( _0, _0, _0) };
// match the value by adding the same amount to each component // match the value by adding the same amount to each component
@ -164,7 +163,7 @@ pub impl<T:Copy> RGB<T>: ToPtr<T> {
} }
} }
pub impl<T:Copy Num NumCast Channel Eq Ord> RGB<T>: Color<T> { pub impl<T:Copy Number Channel> RGB<T>: Color<T> {
#[inline(always)] #[inline(always)]
pure fn inverse(&self) -> RGB<T> { pure fn inverse(&self) -> RGB<T> {
RGB::new(self.r.inverse(), RGB::new(self.r.inverse(),
@ -218,7 +217,7 @@ pub impl<T:Copy Num NumCast Channel Eq Ord> RGB<T>: Color<T> {
#[inline(always)] pure fn to_hsv_f64(&self) -> HSV<f64> { to_hsv(&self.to_rgb_f64()) } #[inline(always)] pure fn to_hsv_f64(&self) -> HSV<f64> { to_hsv(&self.to_rgb_f64()) }
} }
pub impl<T:Copy Num NumCast Channel Eq Ord> RGB<T>: Color3<T> { pub impl<T:Copy Number Channel> RGB<T>: Color3<T> {
#[inline(always)] pure fn to_rgba_u8(&self, a: u8) -> RGBA<u8> { RGBA::from_rgb_a(&self.to_rgb_u8(), a) } #[inline(always)] pure fn to_rgba_u8(&self, a: u8) -> RGBA<u8> { RGBA::from_rgb_a(&self.to_rgb_u8(), a) }
#[inline(always)] pure fn to_rgba_u16(&self, a: u16) -> RGBA<u16> { RGBA::from_rgb_a(&self.to_rgb_u16(), a) } #[inline(always)] pure fn to_rgba_u16(&self, a: u16) -> RGBA<u16> { RGBA::from_rgb_a(&self.to_rgb_u16(), a) }
#[inline(always)] pure fn to_rgba_u32(&self, a: u32) -> RGBA<u32> { RGBA::from_rgb_a(&self.to_rgb_u32(), a) } #[inline(always)] pure fn to_rgba_u32(&self, a: u32) -> RGBA<u32> { RGBA::from_rgb_a(&self.to_rgb_u32(), a) }
@ -287,7 +286,7 @@ pub impl<T:Copy> RGBA<T>: ToPtr<T> {
} }
} }
pub impl<T:Copy Num NumCast Channel Eq Ord> RGBA<T>: Color<T> { pub impl<T:Copy Number Channel> RGBA<T>: Color<T> {
#[inline(always)] #[inline(always)]
pure fn inverse(&self) -> RGBA<T> { pure fn inverse(&self) -> RGBA<T> {
RGBA::new(self.r.inverse(), RGBA::new(self.r.inverse(),
@ -342,7 +341,7 @@ pub impl<T:Copy Num NumCast Channel Eq Ord> RGBA<T>: Color<T> {
#[inline(always)] pure fn to_hsv_f64(&self) -> HSV<f64> { to_hsv(&self.to_rgb_f64()) } #[inline(always)] pure fn to_hsv_f64(&self) -> HSV<f64> { to_hsv(&self.to_rgb_f64()) }
} }
pub impl<T:Copy Num NumCast Channel Eq Ord> RGBA<T>: Color4<T> { pub impl<T:Copy Number Channel> RGBA<T>: Color4<T> {
#[inline(always)] pure fn to_rgba_u8(&self) -> RGBA<u8> { RGBA::from_rgb_a(&self.to_rgb_u8(), self.a.to_channel_u8()) } #[inline(always)] pure fn to_rgba_u8(&self) -> RGBA<u8> { RGBA::from_rgb_a(&self.to_rgb_u8(), self.a.to_channel_u8()) }
#[inline(always)] pure fn to_rgba_u16(&self) -> RGBA<u16> { RGBA::from_rgb_a(&self.to_rgb_u16(), self.a.to_channel_u16()) } #[inline(always)] pure fn to_rgba_u16(&self) -> RGBA<u16> { RGBA::from_rgb_a(&self.to_rgb_u16(), self.a.to_channel_u16()) }
#[inline(always)] pure fn to_rgba_u32(&self) -> RGBA<u32> { RGBA::from_rgb_a(&self.to_rgb_u32(), self.a.to_channel_u32()) } #[inline(always)] pure fn to_rgba_u32(&self) -> RGBA<u32> { RGBA::from_rgb_a(&self.to_rgb_u32(), self.a.to_channel_u32()) }

View file

@ -5,7 +5,6 @@
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/ */
use num::cast::cast;
use angle::{Radians, Degrees}; use angle::{Radians, Degrees};
use vec::{Vec2, Vec3, Vec4}; use vec::{Vec2, Vec3, Vec4};
@ -135,29 +134,29 @@ pub trait Approx {
#[inline(always)] pub pure fn fract<T:Approx>(x: &T) -> T { x.fract() } #[inline(always)] pub pure fn fract<T:Approx>(x: &T) -> T { x.fract() }
pub impl f32: Approx { pub impl f32: Approx {
#[inline(always)] pure fn floor(&self) -> f32 { cast(cmath::c_float_utils::floor(*self)) } #[inline(always)] pure fn floor(&self) -> f32 { f32::floor(*self) }
#[inline(always)] pure fn trunc(&self) -> f32 { cast(cmath::c_float_utils::trunc(*self)) } #[inline(always)] pure fn trunc(&self) -> f32 { f32::trunc(*self) }
#[inline(always)] pure fn round(&self) -> f32 { cast(cmath::c_float_utils::round(*self)) } #[inline(always)] pure fn round(&self) -> f32 { f32::round(*self) }
// #[inline(always)] pure fn roundEven(&self) -> f32 {} // #[inline(always)] pure fn roundEven(&self) -> f32 {}
#[inline(always)] pure fn ceil(&self) -> f32 { cast(cmath::c_float_utils::ceil(*self)) } #[inline(always)] pure fn ceil(&self) -> f32 { f32::ceil(*self) }
#[inline(always)] pure fn fract(&self) -> f32 { (*self) - floor(&*self) } #[inline(always)] pure fn fract(&self) -> f32 { (*self) - floor(&*self) }
} }
pub impl f64: Approx { pub impl f64: Approx {
#[inline(always)] pure fn floor(&self) -> f64 { cast(cmath::c_double_utils::floor(*self)) } #[inline(always)] pure fn floor(&self) -> f64 { f64::floor(*self) }
#[inline(always)] pure fn trunc(&self) -> f64 { cast(cmath::c_double_utils::trunc(*self)) } #[inline(always)] pure fn trunc(&self) -> f64 { f64::trunc(*self) }
#[inline(always)] pure fn round(&self) -> f64 { cast(cmath::c_double_utils::round(*self)) } #[inline(always)] pure fn round(&self) -> f64 { f64::round(*self) }
// #[inline(always)] pure fn roundEven(&self) -> f64 {} // #[inline(always)] pure fn roundEven(&self) -> f64 {}
#[inline(always)] pure fn ceil(&self) -> f64 { cast(cmath::c_double_utils::ceil(*self)) } #[inline(always)] pure fn ceil(&self) -> f64 { f64::ceil(*self) }
#[inline(always)] pure fn fract(&self) -> f64 { (*self) - floor(&*self) } #[inline(always)] pure fn fract(&self) -> f64 { (*self) - floor(&*self) }
} }
pub impl float: Approx { pub impl float: Approx {
#[inline(always)] pure fn floor(&self) -> float { cast(cmath::c_float_utils::floor(cast(*self))) } #[inline(always)] pure fn floor(&self) -> float { f64::floor(*self as f64) as float }
#[inline(always)] pure fn trunc(&self) -> float { cast(cmath::c_float_utils::trunc(cast(*self))) } #[inline(always)] pure fn trunc(&self) -> float { f64::trunc(*self as f64) as float }
#[inline(always)] pure fn round(&self) -> float { cast(cmath::c_float_utils::round(cast(*self))) } #[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 roundEven(&self) -> float {}
#[inline(always)] pure fn ceil(&self) -> float { cast(cmath::c_float_utils::ceil(cast(*self))) } #[inline(always)] pure fn ceil(&self) -> float { f64::ceil(*self as f64) as float }
#[inline(always)] pure fn fract(&self) -> float { (*self) - floor(&*self) } #[inline(always)] pure fn fract(&self) -> float { (*self) - floor(&*self) }
} }

View file

@ -5,7 +5,6 @@
* (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf).
*/ */
use num::cast::{NumCast, cast};
use vec::{Vec2, Vec3, Vec4}; use vec::{Vec2, Vec3, Vec4};
pub trait Exp { pub trait Exp {
@ -27,32 +26,32 @@ pub trait Exp {
#[inline(always)] pub pure fn inv_sqrt<T:Exp>(x: &T) -> T { x.inv_sqrt() } #[inline(always)] pub pure fn inv_sqrt<T:Exp>(x: &T) -> T { x.inv_sqrt() }
pub impl f32: Exp { pub impl f32: Exp {
#[inline(always)] pure fn pow(&self, n: &f32) -> f32 { cast(cmath::c_float_utils::pow(*self, n.cast())) } #[inline(always)] pure fn pow(&self, n: &f32) -> f32 { f32::pow(*self, *n) }
#[inline(always)] pure fn exp(&self) -> f32 { cast(cmath::c_float_utils::exp(*self)) } #[inline(always)] pure fn exp(&self) -> f32 { f32::exp(*self) }
#[inline(always)] pure fn log_(&self) -> f32 { cast(cmath::c_float_utils::ln(*self)) } #[inline(always)] pure fn log_(&self) -> f32 { f32::ln(*self) }
#[inline(always)] pure fn exp2(&self) -> f32 { cast(cmath::c_float_utils::exp2(*self)) } #[inline(always)] pure fn exp2(&self) -> f32 { f32::exp2(*self) }
#[inline(always)] pure fn log2(&self) -> f32 { cast(cmath::c_float_utils::log2(*self)) } #[inline(always)] pure fn log2(&self) -> f32 { f32::log2(*self) }
#[inline(always)] pure fn sqrt(&self) -> f32 { cast(cmath::c_float_utils::sqrt(*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 #[inline(always)] pure fn inv_sqrt(&self) -> f32 { 1f32 / self.sqrt() } // TODO: optimise? need a wizard
} }
pub impl f64: Exp { pub impl f64: Exp {
#[inline(always)] pure fn pow(&self, n: &f64) -> f64 { cast(cmath::c_double_utils::pow(*self, n.cast())) } #[inline(always)] pure fn pow(&self, n: &f64) -> f64 { f64::pow(*self, *n) }
#[inline(always)] pure fn exp(&self) -> f64 { cast(cmath::c_double_utils::exp(*self)) } #[inline(always)] pure fn exp(&self) -> f64 { f64::exp(*self) }
#[inline(always)] pure fn log_(&self) -> f64 { cast(cmath::c_double_utils::ln(*self)) } #[inline(always)] pure fn log_(&self) -> f64 { f64::ln(*self) }
#[inline(always)] pure fn exp2(&self) -> f64 { cast(cmath::c_double_utils::exp2(*self)) } #[inline(always)] pure fn exp2(&self) -> f64 { f64::exp2(*self) }
#[inline(always)] pure fn log2(&self) -> f64 { cast(cmath::c_double_utils::log2(*self)) } #[inline(always)] pure fn log2(&self) -> f64 { f64::log2(*self) }
#[inline(always)] pure fn sqrt(&self) -> f64 { cast(cmath::c_double_utils::sqrt(*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 #[inline(always)] pure fn inv_sqrt(&self) -> f64 { 1f64 / self.sqrt() } // TODO: optimise? need a wizard
} }
pub impl float: Exp { pub impl float: Exp {
#[inline(always)] pure fn pow(&self, n: &float) -> float { cast(cmath::c_float_utils::pow(cast(*self), n.cast())) } #[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 { cast(cmath::c_float_utils::exp(cast(*self))) } #[inline(always)] pure fn exp(&self) -> float { f64::exp(*self as f64) as float }
#[inline(always)] pure fn log_(&self) -> float { cast(cmath::c_float_utils::ln(cast(*self))) } #[inline(always)] pure fn log_(&self) -> float { f64::ln(*self as f64) as float }
#[inline(always)] pure fn exp2(&self) -> float { cast(cmath::c_float_utils::exp2(cast(*self))) } #[inline(always)] pure fn exp2(&self) -> float { f64::exp2(*self as f64) as float }
#[inline(always)] pure fn log2(&self) -> float { cast(cmath::c_float_utils::log2(cast(*self))) } #[inline(always)] pure fn log2(&self) -> float { f64::log2(*self as f64) as float }
#[inline(always)] pure fn sqrt(&self) -> float { cast(cmath::c_float_utils::sqrt(cast(*self))) } #[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 #[inline(always)] pure fn inv_sqrt(&self) -> float { 1f / self.sqrt() } // TODO: optimise? need a wizard
} }

View file

@ -1,8 +1,7 @@
use funs::triganomic::tan; use funs::triganomic::tan;
use angle::Angle; use angle::Angle;
use num::kinds::{Float, Number};
use mat::Mat4; use mat::Mat4;
use num::cast::{NumCast, cast};
use num::kinds::Float;
/** /**
* Create a perspective projection matrix * Create a perspective projection matrix
@ -26,8 +25,8 @@ pub pure fn perspective<T:Copy Float, A:Angle<T>>(fovy: A, aspectRatio: T, near:
*/ */
#[inline(always)] #[inline(always)]
pub pure fn frustum<T:Copy Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> { pub pure fn frustum<T:Copy Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
let _0: T = cast(0); let _0: T = Number::from(0);
let _2: T = cast(2); let _2: T = Number::from(2);
let c0r0 = (_2 * near) / (right - left); let c0r0 = (_2 * near) / (right - left);
let c0r1 = _0; let c0r1 = _0;
@ -40,7 +39,7 @@ pub pure fn frustum<T:Copy Float>(left: T, right: T, bottom: T, top: T, near: T,
let c2r0 = (right + left) / (right - left); let c2r0 = (right + left) / (right - left);
let c2r1 = (top + bottom) / (top - bottom); let c2r1 = (top + bottom) / (top - bottom);
let c2r2 = -(far + near) / (far - near); let c2r2 = -(far + near) / (far - near);
let c2r3 = cast(-1); let c2r3 = Number::from(-1);
let c3r0 = _0; let c3r0 = _0;
let c3r1 = _0; let c3r1 = _0;
let c3r2 = -(_2 * far * near) / (far - near); let c3r2 = -(_2 * far * near) / (far - near);

View file

@ -4,8 +4,9 @@
* 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 num::cast::{NumCast, cast};
use angle::Radians; use angle::Radians;
use num::cast::cast;
use num::kinds::Number;
use vec::{Vec3, Vec2, Vec4}; use vec::{Vec3, Vec2, Vec4};
/** /**
@ -23,13 +24,13 @@ priv trait Trig<T> {
#[inline(always)] pub pure fn cos<T:Trig<R>, R>(theta: &T) -> R { theta.cos() } #[inline(always)] pub pure fn cos<T:Trig<R>, R>(theta: &T) -> R { theta.cos() }
#[inline(always)] pub pure fn tan<T:Trig<R>, R>(theta: &T) -> R { theta.tan() } #[inline(always)] pub pure fn tan<T:Trig<R>, R>(theta: &T) -> R { theta.tan() }
priv impl<T:Copy Num NumCast> Radians<T>: Trig<T> { priv impl<T:Copy Number> Radians<T>: Trig<T> {
#[inline(always)] pure fn sin(&self) -> T { cast(f64::sin(cast(**self))) } #[inline(always)] pure fn sin(&self) -> T { cast(f64::sin(cast(**self))) }
#[inline(always)] pure fn cos(&self) -> T { cast(f64::cos(cast(**self))) } #[inline(always)] pure fn cos(&self) -> T { cast(f64::cos(cast(**self))) }
#[inline(always)] pure fn tan(&self) -> T { cast(f64::tan(cast(**self))) } #[inline(always)] pure fn tan(&self) -> T { cast(f64::tan(cast(**self))) }
} }
pub impl<T:Copy Num NumCast> Vec2<Radians<T>>: Trig<Vec2<T>> { pub impl<T:Copy Number> Vec2<Radians<T>>: Trig<Vec2<T>> {
#[inline(always)] #[inline(always)]
pure fn sin(&self) -> Vec2<T> { pure fn sin(&self) -> Vec2<T> {
Vec2::new(sin(&self[0]), Vec2::new(sin(&self[0]),
@ -49,7 +50,7 @@ pub impl<T:Copy Num NumCast> Vec2<Radians<T>>: Trig<Vec2<T>> {
} }
} }
pub impl<T:Copy Num NumCast> Vec3<Radians<T>>: Trig<Vec3<T>> { pub impl<T:Copy Number> Vec3<Radians<T>>: 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]),
@ -72,7 +73,7 @@ pub impl<T:Copy Num NumCast> Vec3<Radians<T>>: Trig<Vec3<T>> {
} }
} }
pub impl<T:Copy Num NumCast> Vec4<Radians<T>>: Trig<Vec4<T>> { pub impl<T:Copy Number> Vec4<Radians<T>>: 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]),
@ -126,9 +127,9 @@ pub impl f64: InvTrig {
} }
pub impl float: InvTrig { pub impl float: InvTrig {
#[inline(always)] pure fn asin(&self) -> Radians<float> { Radians(f64::asin(cast(*self)).to_float()) } #[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(cast(*self)).to_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(cast(*self)).to_float()) } #[inline(always)] pure fn atan(&self) -> Radians<float> { Radians(f64::atan(*self as f64) as float) }
} }
// TODO: figure out how to merge with InvTrig // TODO: figure out how to merge with InvTrig
@ -138,7 +139,7 @@ pub trait InvTrigV<T> {
pure fn atan(&self) -> T; pure fn atan(&self) -> T;
} }
pub impl<T:Copy Num NumCast InvTrig> Vec2<T>: InvTrigV<Vec2<Radians<T>>> { pub impl<T:Copy Number InvTrig> Vec2<T>: InvTrigV<Vec2<Radians<T>>> {
#[inline(always)] #[inline(always)]
pure fn asin(&self) -> Vec2<Radians<T>> { pure fn asin(&self) -> Vec2<Radians<T>> {
Vec2::new(asin(&self[0]), Vec2::new(asin(&self[0]),
@ -158,7 +159,7 @@ pub impl<T:Copy Num NumCast InvTrig> Vec2<T>: InvTrigV<Vec2<Radians<T>>> {
} }
} }
pub impl<T:Copy Num NumCast InvTrig> Vec3<T>: InvTrigV<Vec3<Radians<T>>> { pub impl<T:Copy Number InvTrig> Vec3<T>: InvTrigV<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]),
@ -181,7 +182,7 @@ pub impl<T:Copy Num NumCast InvTrig> Vec3<T>: InvTrigV<Vec3<Radians<T>>> {
} }
} }
pub impl<T:Copy Num NumCast InvTrig> Vec4<T>: InvTrigV<Vec4<Radians<T>>> { pub impl<T:Copy Number InvTrig> Vec4<T>: InvTrigV<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]),
@ -240,9 +241,9 @@ pub impl f64: Hyp {
} }
pub impl float: Hyp { pub impl float: Hyp {
#[inline(always)] pure fn sinh(&self) -> float { cast(f64::sinh(cast(*self))) } #[inline(always)] pure fn sinh(&self) -> float { f64::sinh(*self as f64) as float }
#[inline(always)] pure fn cosh(&self) -> float { cast(f64::cosh(cast(*self))) } #[inline(always)] pure fn cosh(&self) -> float { f64::cosh(*self as f64) as float }
#[inline(always)] pure fn tanh(&self) -> float { cast(f64::tanh(cast(*self))) } #[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 {

View file

@ -11,7 +11,7 @@ use funs::common::*;
use funs::exponential::*; use funs::exponential::*;
use num::cast::*; use num::cast::*;
use num::default_eq::DefaultEq; use num::default_eq::DefaultEq;
use num::kinds::Float; use num::kinds::{Float, Number};
use quat::{Quat, ToQuat}; use quat::{Quat, ToQuat};
use vec::{NumericVector, Vec2, Vec3, Vec4}; use vec::{NumericVector, Vec2, Vec3, Vec4};
@ -122,15 +122,15 @@ pub impl<T:Copy Float> Mat2<T>: Matrix<T, Vec2<T>> {
#[inline(always)] #[inline(always)]
static pure fn identity() -> Mat2<T> { static pure fn identity() -> Mat2<T> {
let _0 = cast(0); let _0 = Number::from(0);
let _1 = cast(1); let _1 = Number::from(1);
Mat2::new(_1, _0, Mat2::new(_1, _0,
_0, _1) _0, _1)
} }
#[inline(always)] #[inline(always)]
static pure fn zero() -> Mat2<T> { static pure fn zero() -> Mat2<T> {
let _0 = cast(0); let _0 = Number::from(0);
Mat2::new(_0, _0, Mat2::new(_0, _0,
_0, _0) _0, _0)
} }
@ -511,46 +511,49 @@ pub impl<T:Copy Float> Mat3<T>: Matrix3<T, Vec3<T>> {
} }
} }
pub impl<T:Copy Float> Mat3<T>: ToQuat<T> { pub impl<T:Copy Float Exp> Mat3<T>: ToQuat<T> {
pure fn to_Quat() -> Quat<T> { pure fn to_Quat() -> Quat<T> {
// Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's // Implemented using a mix of ideas from jMonkeyEngine and Ken Shoemake's
// paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf // paper on Quaternions: http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf
let mut s: float; let mut s;
let w: float, x: float, y: float, z: float; let w, x, y, z;
let trace: float = cast(self.trace()); let trace = self.trace();
let _1: T = Number::from(1.0);
let half: T = Number::from(0.5);
if trace >= cast(0) { if trace >= cast(0) {
s = (trace + 1f).sqrt(); s = (_1 + trace).sqrt();
w = 0.5 * s; w = half * s;
s = 0.5 / s; s = half / s;
x = (self[1][2] - self[2][1]).cast::<float>() * s; x = (self[1][2] - self[2][1]) * s;
y = (self[2][0] - self[0][2]).cast::<float>() * s; y = (self[2][0] - self[0][2]) * s;
z = (self[0][1] - self[1][0]).cast::<float>() * s; z = (self[0][1] - self[1][0]) * s;
} else if (self[0][0] > self[1][1]) && (self[0][0] > self[2][2]) { } 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]).cast::<float>()).sqrt(); s = (half + (self[0][0] - self[1][1] - self[2][2])).sqrt();
w = 0.5 * s; w = half * s;
s = 0.5 / s; s = half / s;
x = (self[0][1] - self[1][0]).cast::<float>() * s; x = (self[0][1] - self[1][0]) * s;
y = (self[2][0] - self[0][2]).cast::<float>() * s; y = (self[2][0] - self[0][2]) * s;
z = (self[1][2] - self[2][1]).cast::<float>() * s; z = (self[1][2] - self[2][1]) * s;
} else if self[1][1] > self[2][2] { } else if self[1][1] > self[2][2] {
s = (1f + (self[1][1] - self[0][0] - self[2][2]).cast::<float>()).sqrt(); s = (half + (self[1][1] - self[0][0] - self[2][2])).sqrt();
w = 0.5 * s; w = half * s;
s = 0.5 / s; s = half / s;
x = (self[0][1] - self[1][0]).cast::<float>() * s; x = (self[0][1] - self[1][0]) * s;
y = (self[1][2] - self[2][1]).cast::<float>() * s; y = (self[1][2] - self[2][1]) * s;
z = (self[2][0] - self[0][2]).cast::<float>() * s; z = (self[2][0] - self[0][2]) * s;
} else { } else {
s = (1f + (self[2][2] - self[0][0] - self[1][1]).cast::<float>()).sqrt(); s = (half + (self[2][2] - self[0][0] - self[1][1])).sqrt();
w = 0.5 * s; w = half * s;
s = 0.5 / s; s = half / s;
x = (self[2][0] - self[0][2]).cast::<float>() * s; x = (self[2][0] - self[0][2]) * s;
y = (self[1][2] - self[2][1]).cast::<float>() * s; y = (self[1][2] - self[2][1]) * s;
z = (self[0][1] - self[1][0]).cast::<float>() * s; z = (self[0][1] - self[1][0]) * s;
} }
Quat::new(cast(w), cast(x), cast(y), cast(z)) Quat::new(w, x, y, z)
} }
} }

View file

@ -6,71 +6,99 @@ use num::default_eq::DefaultEq;
pub trait Number: DefaultEq, Eq, Num, NumCast, Ord { pub trait Number: DefaultEq, Eq, Num, NumCast, Ord {
static pure fn from<T:Number>(n: T) -> self;
static pure fn zero() -> self; static pure fn zero() -> self;
static pure fn one() -> self; static pure fn one() -> self;
} }
pub impl u8: Number { pub impl u8: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> u8 { n.to_u8() }
#[inline(always)] static pure fn zero() -> u8 { 0u8 } #[inline(always)] static pure fn zero() -> u8 { 0u8 }
#[inline(always)] static pure fn one() -> u8 { 1u8 } #[inline(always)] static pure fn one() -> u8 { 1u8 }
} }
pub impl u16: Number { pub impl u16: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> u16 { n.to_u16() }
#[inline(always)] static pure fn zero() -> u16 { 0u16 } #[inline(always)] static pure fn zero() -> u16 { 0u16 }
#[inline(always)] static pure fn one() -> u16 { 1u16 } #[inline(always)] static pure fn one() -> u16 { 1u16 }
} }
pub impl u32: Number { pub impl u32: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> u32 { n.to_u32() }
#[inline(always)] static pure fn zero() -> u32 { 0u32 } #[inline(always)] static pure fn zero() -> u32 { 0u32 }
#[inline(always)] static pure fn one() -> u32 { 1u32 } #[inline(always)] static pure fn one() -> u32 { 1u32 }
} }
pub impl u64: Number { pub impl u64: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> u64 { n.to_u64() }
#[inline(always)] static pure fn zero() -> u64 { 0u64 } #[inline(always)] static pure fn zero() -> u64 { 0u64 }
#[inline(always)] static pure fn one() -> u64 { 1u64 } #[inline(always)] static pure fn one() -> u64 { 1u64 }
} }
pub impl uint: Number { pub impl uint: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> uint { n.to_uint() }
#[inline(always)] static pure fn zero() -> uint { 0u } #[inline(always)] static pure fn zero() -> uint { 0u }
#[inline(always)] static pure fn one() -> uint { 1u } #[inline(always)] static pure fn one() -> uint { 1u }
} }
pub impl i8: Number { pub impl i8: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> i8 { n.to_i8() }
#[inline(always)] static pure fn zero() -> i8 { 0i8 } #[inline(always)] static pure fn zero() -> i8 { 0i8 }
#[inline(always)] static pure fn one() -> i8 { 1i8 } #[inline(always)] static pure fn one() -> i8 { 1i8 }
} }
pub impl i16: Number { pub impl i16: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> i16 { n.to_i16() }
#[inline(always)] static pure fn zero() -> i16 { 0i16 } #[inline(always)] static pure fn zero() -> i16 { 0i16 }
#[inline(always)] static pure fn one() -> i16 { 1i16 } #[inline(always)] static pure fn one() -> i16 { 1i16 }
} }
pub impl i32: Number { pub impl i32: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> i32 { n.to_i32() }
#[inline(always)] static pure fn zero() -> i32 { 0i32 } #[inline(always)] static pure fn zero() -> i32 { 0i32 }
#[inline(always)] static pure fn one() -> i32 { 1i32 } #[inline(always)] static pure fn one() -> i32 { 1i32 }
} }
pub impl i64: Number { pub impl i64: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> i64 { n.to_i64() }
#[inline(always)] static pure fn zero() -> i64 { 0i64 } #[inline(always)] static pure fn zero() -> i64 { 0i64 }
#[inline(always)] static pure fn one() -> i64 { 1i64 } #[inline(always)] static pure fn one() -> i64 { 1i64 }
} }
pub impl int: Number { pub impl int: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> int { n.to_int() }
#[inline(always)] static pure fn zero() -> int { 0 } #[inline(always)] static pure fn zero() -> int { 0 }
#[inline(always)] static pure fn one() -> int { 1 } #[inline(always)] static pure fn one() -> int { 1 }
} }
pub impl f32: Number { pub impl f32: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> f32 { n.to_f32() }
#[inline(always)] static pure fn zero() -> f32 { 0f32 } #[inline(always)] static pure fn zero() -> f32 { 0f32 }
#[inline(always)] static pure fn one() -> f32 { 1f32 } #[inline(always)] static pure fn one() -> f32 { 1f32 }
} }
pub impl f64: Number { pub impl f64: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> f64 { n.to_f64() }
#[inline(always)] static pure fn zero() -> f64 { 0f64 } #[inline(always)] static pure fn zero() -> f64 { 0f64 }
#[inline(always)] static pure fn one() -> f64 { 1f64 } #[inline(always)] static pure fn one() -> f64 { 1f64 }
} }
pub impl float: Number { pub impl float: Number {
#[inline(always)] static pure fn from<T:Number>(n: T) -> float { n.to_float() }
#[inline(always)] static pure fn zero() -> float { 0f } #[inline(always)] static pure fn zero() -> float { 0f }
#[inline(always)] static pure fn one() -> float { 1f } #[inline(always)] static pure fn one() -> float { 1f }
} }

View file

@ -11,7 +11,6 @@ use funs::common::*;
use funs::exponential::*; use funs::exponential::*;
use funs::triganomic::*; use funs::triganomic::*;
use mat::{Mat3, Mat4}; use mat::{Mat3, Mat4};
use num::cast::*;
use num::default_eq::DefaultEq; use num::default_eq::DefaultEq;
use num::kinds::{Float, Number}; use num::kinds::{Float, Number};
use vec::Vec3; use vec::Vec3;
@ -21,8 +20,8 @@ use vec::Vec3;
/// The base quaternion trait /// The base quaternion trait
/// ///
pub trait Quaternion<T>: Dimensional<T>, ToPtr<T>, Eq, DefaultEq, Neg<self> { pub trait Quaternion<T>: Dimensional<T>, ToPtr<T>, Eq, DefaultEq, Neg<self> {
static pure fn identity() -> self; static pure fn identity() -> self; /// The multiplicative identity
static pure fn zero() -> self; static pure fn zero() -> self; /// The additive identity
pure fn mul_t(&self, value: T) -> self; pure fn mul_t(&self, value: T) -> self;
pure fn div_t(&self, value: T) -> self; pure fn div_t(&self, value: T) -> self;
@ -99,18 +98,18 @@ pub impl<T:Copy> Quat<T>: ToPtr<T> {
pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T> { pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T> {
#[inline(always)] #[inline(always)]
static pure fn identity() -> Quat<T> { static pure fn identity() -> Quat<T> {
Quat::new(Number::one(), Quat::new(Number::from(1),
Number::one(), Number::from(0),
Number::one(), Number::from(0),
Number::one()) Number::from(0))
} }
#[inline(always)] #[inline(always)]
static pure fn zero() -> Quat<T> { static pure fn zero() -> Quat<T> {
Quat::new(Number::zero(), Quat::new(Number::from(0),
Number::zero(), Number::from(0),
Number::zero(), Number::from(0),
Number::zero()) Number::from(0))
} }
#[inline(always)] #[inline(always)]
@ -132,7 +131,7 @@ pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T> {
#[inline(always)] #[inline(always)]
pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T> { pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T> {
let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s)); let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s));
self.v.cross(&tmp).mul_t(cast(2)).add_v(vec) self.v.cross(&tmp).mul_t(Number::from(2)).add_v(vec)
} }
#[inline(always)] #[inline(always)]
@ -186,14 +185,14 @@ pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T> {
#[inline(always)] #[inline(always)]
pure fn normalize(&self) -> Quat<T> { pure fn normalize(&self) -> Quat<T> {
let mut n: T = cast(1); let mut n: T = Number::from(1);
n /= self.length(); n /= self.length();
return self.mul_t(n); return self.mul_t(n);
} }
#[inline(always)] #[inline(always)]
pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> { pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
let _1: T = cast(1); let _1: T = Number::from(1);
self.mul_t(_1 - amount).add_q(&other.mul_t(amount)).normalize() self.mul_t(_1 - amount).add_q(&other.mul_t(amount)).normalize()
} }
@ -215,13 +214,13 @@ pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T> {
*/ */
#[inline(always)] #[inline(always)]
pure fn slerp(&self, other: &Quat<T>, amount: T) -> Quat<T> { pure fn slerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
let dot: T = cast(self.dot(other)); let dot: T = Number::from(self.dot(other));
// if quaternions are close together use `nlerp` // if quaternions are close together use `nlerp`
let dot_threshold = cast(0.9995); let dot_threshold = Number::from(0.9995);
if dot > dot_threshold { return self.nlerp(other, amount) } if dot > dot_threshold { return self.nlerp(other, amount) }
let robust_dot = dot.clamp(&-cast(1), &cast(1)); // stay within the domain of acos() let robust_dot = dot.clamp(&-Number::from(1), &Number::from(1)); // stay within the domain of acos()
let theta_0 = acos(&robust_dot); // the angle between the quaternions let theta_0 = acos(&robust_dot); // the angle between the quaternions
let theta = theta_0 * amount; // the fraction of theta specified by `amount` let theta = theta_0 * amount; // the fraction of theta specified by `amount`