From 04e7ab0dfbaafa54673fa71c78ec907cc33e45d9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 17 Dec 2012 16:09:56 +1000 Subject: [PATCH] Use traits from numeric library in funs module --- src/funs/common.rs | 581 ++++------------------------------------ src/funs/exponential.rs | 50 +--- src/funs/relational.rs | 264 ++++++++++++++++++ src/funs/triganomic.rs | 357 +++++++++--------------- src/lmath.rc | 12 +- 5 files changed, 456 insertions(+), 808 deletions(-) create mode 100644 src/funs/relational.rs diff --git a/src/funs/common.rs b/src/funs/common.rs index a5baff9..0ba1492 100644 --- a/src/funs/common.rs +++ b/src/funs/common.rs @@ -5,180 +5,11 @@ * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). */ -use angle::{Radians, Degrees}; +use numeric::traits::*; + use vec::{Vec2, Vec3, Vec4}; -pub trait Sign { - pure fn abs(&self) -> self; - pure fn sign(&self) -> self; -} - -#[inline(always)] pub pure fn abs(x: &T) -> T { x.abs() } -#[inline(always)] pub pure fn 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 Radians: Sign{ - #[inline(always)] pure fn abs(&self) -> Radians { Radians(abs(&**self)) } - #[inline(always)] pure fn sign(&self) -> Radians { Radians(sign(&**self)) } -} - -pub impl Degrees: Sign{ - #[inline(always)] pure fn abs(&self) -> Degrees { Degrees(abs(&**self)) } - #[inline(always)] pure fn sign(&self) -> Degrees { Degrees(sign(&**self)) } -} - - - -pub impl Vec2: Sign { - #[inline(always)] - pure fn abs(&self) -> Vec2 { - Vec2::new(abs(&self[0]), - abs(&self[1])) - } - - #[inline(always)] - pure fn sign(&self) -> Vec2 { - Vec2::new(sign(&self[0]), - sign(&self[1])) - } -} - -pub impl Vec3: Sign { - #[inline(always)] - pure fn abs(&self) -> Vec3 { - Vec3::new(abs(&self[0]), - abs(&self[1]), - abs(&self[2])) - } - - #[inline(always)] - pure fn sign(&self) -> Vec3 { - Vec3::new(sign(&self[0]), - sign(&self[1]), - sign(&self[2])) - } -} - -pub impl Vec4: Sign { - #[inline(always)] - pure fn abs(&self) -> Vec4 { - Vec4::new(abs(&self[0]), - abs(&self[1]), - abs(&self[2]), - abs(&self[3])) - } - - #[inline(always)] - pure fn sign(&self) -> Vec4 { - 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(x: &T) -> T { x.floor() } -#[inline(always)] pub pure fn trunc(x: &T) -> T { x.trunc() } -#[inline(always)] pub pure fn round(x: &T) -> T { x.round() } -// #[inline(always)] pub pure fn roundEven(x: &T) -> T { x.roundEven() } -#[inline(always)] pub pure fn ceil(x: &T) -> T { x.ceil() } -#[inline(always)] pub pure fn fract(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 Radians: Approx{ - #[inline(always)] pure fn floor(&self) -> Radians { Radians(floor(&**self)) } - #[inline(always)] pure fn trunc(&self) -> Radians { Radians(trunc(&**self)) } - #[inline(always)] pure fn round(&self) -> Radians { Radians(round(&**self)) } - // #[inline(always)] pure fn roundEven(&self) -> Radians { Radians(roundEven(&**self)) } - #[inline(always)] pure fn ceil(&self) -> Radians { Radians(ceil(&**self)) } - #[inline(always)] pure fn fract(&self) -> Radians { Radians(fract(&**self)) } -} - -pub impl Degrees: Approx{ - #[inline(always)] pure fn floor(&self) -> Degrees { Degrees(floor(&**self)) } - #[inline(always)] pure fn trunc(&self) -> Degrees { Degrees(trunc(&**self)) } - #[inline(always)] pure fn round(&self) -> Degrees { Degrees(round(&**self)) } - // #[inline(always)] pure fn roundEven(&self) -> Degrees { Degrees(roundEven(&**self)) } - #[inline(always)] pure fn ceil(&self) -> Degrees { Degrees(ceil(&**self)) } - #[inline(always)] pure fn fract(&self) -> Degrees { Degrees(fract(&**self)) } -} - +// Approx pub impl Vec2: Approx { #[inline(always)] @@ -216,7 +47,6 @@ pub impl Vec2: Approx { Vec2::new(fract(&self[0]), fract(&self[1])) } - } pub impl Vec3: Approx { @@ -261,7 +91,6 @@ pub impl Vec3: Approx { fract(&self[1]), fract(&self[2])) } - } pub impl Vec4: Approx { @@ -312,275 +141,9 @@ pub impl Vec4: Approx { fract(&self[2]), 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(a: &T, b: &T) -> T { a.min(b) } -#[inline(always)] pub pure fn max(a: &T, b: &T) -> T { a.max(b) } -#[inline(always)] pub pure fn clamp(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 Radians: Extent{ - #[inline(always)] - pure fn min(&self, other: &Radians) -> Radians { - Radians(min(&**self, &**other)) - } - - #[inline(always)] - pure fn max(&self, other: &Radians) -> Radians { - Radians(max(&**self, &**other)) - } - - #[inline(always)] - pure fn clamp(&self, mn: &Radians, mx: &Radians) -> Radians { - Radians((**self).clamp(&**mn, &**mx)) - } -} - -pub impl Degrees: Extent{ - #[inline(always)] - pure fn min(&self, other: &Degrees) -> Degrees { - Degrees(min(&**self, &**other)) - } - - #[inline(always)] - pure fn max(&self, other: &Degrees) -> Degrees { - Degrees(max(&**self, &**other)) - } - - #[inline(always)] - pure fn clamp(&self, mn: &Degrees, mx: &Degrees) -> Degrees { - Degrees((**self).clamp(&**mn, &**mx)) - } } +// Extent pub impl Vec2: Extent { #[inline(always)] @@ -651,91 +214,7 @@ pub impl Vec4: Extent { } } - -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(a: &T, b: &T, value: &T) -> T { a.mix(b, value) } -#[inline(always)] pub pure fn smooth_step(x: &T, edge0: &T, edge1: &T) -> T { x.smooth_step(edge0, edge1) } -#[inline(always)] pub pure fn step(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 Radians: Mix { - #[inline(always)] - pure fn mix(&self, other: &Radians, value: &Radians) -> Radians { - Radians((**self).mix(&**other, &**value)) - } - - #[inline(always)] - pure fn smooth_step(&self, edge0: &Radians, edge1: &Radians) -> Radians { - Radians((**self).smooth_step(&**edge0, &**edge1)) - } - - #[inline(always)] - pure fn step(&self, edge: &Radians) -> Radians { - Radians((**self).step(&**edge)) - } -} - +// Mix pub impl Vec2: Mix { #[inline(always)] @@ -805,3 +284,53 @@ pub impl Vec4: Mix { self[3].step(&edge[3])) } } + +// Sign + +pub impl Vec2: Sign { + #[inline(always)] + pure fn abs(&self) -> Vec2 { + Vec2::new(abs(&self[0]), + abs(&self[1])) + } + + #[inline(always)] + pure fn sign(&self) -> Vec2 { + Vec2::new(sign(&self[0]), + sign(&self[1])) + } +} + +pub impl Vec3: Sign { + #[inline(always)] + pure fn abs(&self) -> Vec3 { + Vec3::new(abs(&self[0]), + abs(&self[1]), + abs(&self[2])) + } + + #[inline(always)] + pure fn sign(&self) -> Vec3 { + Vec3::new(sign(&self[0]), + sign(&self[1]), + sign(&self[2])) + } +} + +pub impl Vec4: Sign { + #[inline(always)] + pure fn abs(&self) -> Vec4 { + Vec4::new(abs(&self[0]), + abs(&self[1]), + abs(&self[2]), + abs(&self[3])) + } + + #[inline(always)] + pure fn sign(&self) -> Vec4 { + Vec4::new(sign(&self[0]), + sign(&self[1]), + sign(&self[2]), + sign(&self[3])) + } +} diff --git a/src/funs/exponential.rs b/src/funs/exponential.rs index 558f4b2..19a0ad9 100644 --- a/src/funs/exponential.rs +++ b/src/funs/exponential.rs @@ -5,55 +5,11 @@ * (http://www.opengl.org/registry/doc/GLSLangSpec.4.30.6.pdf). */ +use numeric::traits::*; + use vec::{Vec2, Vec3, Vec4}; -pub trait 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(x: &T, n: &T) -> T { x.pow(n) } -#[inline(always)] pub pure fn exp(x: &T) -> T { x.exp() } -#[inline(always)] pub pure fn log_(x: &T) -> T { x.log_() } -#[inline(always)] pub pure fn exp2(x: &T) -> T { x.exp2() } -#[inline(always)] pub pure fn log2(x: &T) -> T { x.log2() } -#[inline(always)] pub pure fn sqrt(x: &T) -> T { x.sqrt() } -#[inline(always)] pub pure fn inv_sqrt(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 -} +// Exp pub impl Vec2: Exp { #[inline(always)] diff --git a/src/funs/relational.rs b/src/funs/relational.rs new file mode 100644 index 0000000..61b0dba --- /dev/null +++ b/src/funs/relational.rs @@ -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: Vector { + /** + * 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: Vector { + /** + * 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 { + /** + * # 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 Vec2: OrdinalVector> { + #[inline(always)] + pure fn less_than(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] < other[0], + self[1] < other[1]) + } + + #[inline(always)] + pure fn less_than_equal(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] <= other[0], + self[1] <= other[1]) + } + + #[inline(always)] + pure fn greater_than(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] > other[0], + self[1] > other[1]) + } + + #[inline(always)] + pure fn greater_than_equal(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] >= other[0], + self[1] >= other[1]) + } +} + +pub impl Vec2: EquableVector> { + #[inline(always)] + pure fn equal(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] == other[0], + self[1] == other[1]) + } + + #[inline(always)] + pure fn not_equal(&self, other: &Vec2) -> Vec2 { + Vec2::new(self[0] != other[0], + self[1] != other[1]) + } +} + +pub impl Vec2: 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 { + Vec2::new(!self[0], !self[1]) + } +} + +pub impl Vec3: OrdinalVector> { + #[inline(always)] + pure fn less_than(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] < other[0], + self[1] < other[1], + self[2] < other[2]) + } + + #[inline(always)] + pure fn less_than_equal(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] <= other[0], + self[1] <= other[1], + self[2] <= other[2]) + } + + #[inline(always)] + pure fn greater_than(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] > other[0], + self[1] > other[1], + self[2] > other[2]) + } + + #[inline(always)] + pure fn greater_than_equal(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] >= other[0], + self[1] >= other[1], + self[2] >= other[2]) + } +} + +pub impl Vec3: EquableVector> { + #[inline(always)] + pure fn equal(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] == other[0], + self[1] == other[1], + self[2] == other[2]) + } + + #[inline(always)] + pure fn not_equal(&self, other: &Vec3) -> Vec3 { + Vec3::new(self[0] != other[0], + self[1] != other[1], + self[2] != other[2]) + } +} + +pub impl Vec3: 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 { + Vec3::new(!self[0], !self[1], !self[2]) + } +} + +pub impl Vec4: OrdinalVector> { + #[inline(always)] + pure fn less_than(&self, other: &Vec4) -> Vec4 { + 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) -> Vec4 { + 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) -> Vec4 { + 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) -> Vec4 { + Vec4::new(self[0] >= other[0], + self[1] >= other[1], + self[2] >= other[2], + self[3] >= other[3]) + } +} + +pub impl Vec4: EquableVector> { + #[inline(always)] + pure fn equal(&self, other: &Vec4) -> Vec4 { + 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) -> Vec4 { + Vec4::new(self[0] != other[0], + self[1] != other[1], + self[2] != other[2], + self[3] != other[3]) + } +} + +pub impl Vec4: 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 { + Vec4::new(!self[0], !self[1], !self[2], !self[3]) + } +} \ No newline at end of file diff --git a/src/funs/triganomic.rs b/src/funs/triganomic.rs index 052ae64..b7eb5be 100644 --- a/src/funs/triganomic.rs +++ b/src/funs/triganomic.rs @@ -4,257 +4,156 @@ * 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). */ -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}; -/** - * Triganomic functions - * - * http://en.wikipedia.org/wiki/Trigonometric_functions - */ -priv trait Trig { - pure fn sin(&self) -> T; - pure fn cos(&self) -> T; - pure fn tan(&self) -> T; -} +// // Trig -#[inline(always)] pub pure fn sin, R>(theta: &T) -> R { theta.sin() } -#[inline(always)] pub pure fn cos, R>(theta: &T) -> R { theta.cos() } -#[inline(always)] pub pure fn tan, R>(theta: &T) -> R { theta.tan() } - -priv impl Radians: Trig { - #[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 Degrees: Trig { - #[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 Vec2>: Trig> { - #[inline(always)] - pure fn sin(&self) -> Vec2 { - Vec2::new(sin(&self[0]), - sin(&self[1])) - } +// pub impl> Vec2: Trig> { +// #[inline(always)] +// pure fn sin(&self) -> Vec2 { +// Vec2::new(sin(&self[0]), +// sin(&self[1])) +// } - #[inline(always)] - pure fn cos(&self) -> Vec2 { - Vec2::new(cos(&self[0]), - cos(&self[1])) - } +// #[inline(always)] +// pure fn cos(&self) -> Vec2 { +// Vec2::new(cos(&self[0]), +// cos(&self[1])) +// } - #[inline(always)] - pure fn tan(&self) -> Vec2 { - Vec2::new(tan(&self[0]), - tan(&self[1])) - } -} +// #[inline(always)] +// pure fn tan(&self) -> Vec2 { +// Vec2::new(tan(&self[0]), +// tan(&self[1])) +// } +// } -pub impl Vec3>: Trig> { - #[inline(always)] - pure fn sin(&self) -> Vec3 { - Vec3::new(sin(&self[0]), - sin(&self[1]), - sin(&self[2])) - } +// pub impl> Vec3: Trig> { +// #[inline(always)] +// pure fn sin(&self) -> Vec3 { +// Vec3::new(sin(&self[0]), +// sin(&self[1]), +// sin(&self[2])) +// } - #[inline(always)] - pure fn cos(&self) -> Vec3 { - Vec3::new(cos(&self[0]), - cos(&self[1]), - cos(&self[2])) - } +// #[inline(always)] +// pure fn cos(&self) -> Vec3 { +// Vec3::new(cos(&self[0]), +// cos(&self[1]), +// cos(&self[2])) +// } - #[inline(always)] - pure fn tan(&self) -> Vec3 { - Vec3::new(tan(&self[0]), - tan(&self[1]), - tan(&self[2])) - } -} +// #[inline(always)] +// pure fn tan(&self) -> Vec3 { +// Vec3::new(tan(&self[0]), +// tan(&self[1]), +// tan(&self[2])) +// } +// } -pub impl Vec4>: Trig> { - #[inline(always)] - pure fn sin(&self) -> Vec4 { - Vec4::new(sin(&self[0]), - sin(&self[1]), - sin(&self[2]), - sin(&self[3])) - } +// pub impl> Vec4: Trig> { +// #[inline(always)] +// pure fn sin(&self) -> Vec4 { +// Vec4::new(sin(&self[0]), +// sin(&self[1]), +// sin(&self[2]), +// sin(&self[3])) +// } - #[inline(always)] - pure fn cos(&self) -> Vec4 { - Vec4::new(cos(&self[0]), - cos(&self[1]), - cos(&self[2]), - cos(&self[3])) - } +// #[inline(always)] +// pure fn cos(&self) -> Vec4 { +// Vec4::new(cos(&self[0]), +// cos(&self[1]), +// cos(&self[2]), +// cos(&self[3])) +// } - #[inline(always)] - pure fn tan(&self) -> Vec4 { - Vec4::new(tan(&self[0]), - tan(&self[1]), - tan(&self[2]), - tan(&self[3])) - } -} +// #[inline(always)] +// pure fn tan(&self) -> Vec4 { +// Vec4::new(tan(&self[0]), +// tan(&self[1]), +// tan(&self[2]), +// tan(&self[3])) +// } +// } -/** - * Inverse triganomic functions - * - * http://en.wikipedia.org/wiki/Inverse_trigonometric_functions - */ -pub trait InvTrig { - pure fn asin(&self) -> Radians; - pure fn acos(&self) -> Radians; - pure fn atan(&self) -> Radians; - pure fn atan2(&self, other: &self) -> Radians; -} +// // InvTrig -#[inline(always)] pub pure fn asin(x: &T) -> Radians { x.asin() } -#[inline(always)] pub pure fn acos(x: &T) -> Radians { x.acos() } -#[inline(always)] pub pure fn atan(x: &T) -> Radians { x.atan() } -#[inline(always)] pub pure fn atan2(a: &T, b: &T) -> Radians { a.atan2(b) } - -pub impl f32: InvTrig { - #[inline(always)] pure fn asin(&self) -> Radians { Radians(f32::asin(*self)) } - #[inline(always)] pure fn acos(&self) -> Radians { Radians(f32::acos(*self)) } - #[inline(always)] pure fn atan(&self) -> Radians { Radians(f32::atan(*self)) } - #[inline(always)] pure fn atan2(&self, other: &f32) -> Radians { Radians(f32::atan2(*self, *other)) } -} - -pub impl f64: InvTrig { - #[inline(always)] pure fn asin(&self) -> Radians { Radians(f64::asin(*self)) } - #[inline(always)] pure fn acos(&self) -> Radians { Radians(f64::acos(*self)) } - #[inline(always)] pure fn atan(&self) -> Radians { Radians(f64::atan(*self)) } - #[inline(always)] pure fn atan2(&self, other: &f64) -> Radians { Radians(f64::atan2(*self, *other)) } -} - -pub impl float: InvTrig { - #[inline(always)] pure fn asin(&self) -> Radians { Radians(f64::asin(*self as f64) as float) } - #[inline(always)] pure fn acos(&self) -> Radians { Radians(f64::acos(*self as f64) as float) } - #[inline(always)] pure fn atan(&self) -> Radians { Radians(f64::atan(*self as f64) as float) } - #[inline(always)] pure fn atan2(&self, other: &float) -> Radians { Radians(f64::atan2(*self as f64, *other as f64) as float) } -} - -// TODO: figure out how to merge with InvTrig -pub trait InvTrigV { - pure fn asin(&self) -> T; - pure fn acos(&self) -> T; - pure fn atan(&self) -> T; -} - -pub impl Vec2: InvTrigV>> { - #[inline(always)] - pure fn asin(&self) -> Vec2> { - Vec2::new(asin(&self[0]), - asin(&self[1])) - } +// pub impl Vec2: InvTrig>> { +// #[inline(always)] +// pure fn asin(&self) -> Vec2> { +// Vec2::new(asin(&self[0]), +// asin(&self[1])) +// } - #[inline(always)] - pure fn acos(&self) -> Vec2> { - Vec2::new(acos(&self[0]), - acos(&self[1])) - } +// #[inline(always)] +// pure fn acos(&self) -> Vec2> { +// Vec2::new(acos(&self[0]), +// acos(&self[1])) +// } - #[inline(always)] - pure fn atan(&self) -> Vec2> { - Vec2::new(atan(&self[0]), - atan(&self[1])) - } -} +// #[inline(always)] +// pure fn atan(&self) -> Vec2> { +// Vec2::new(atan(&self[0]), +// atan(&self[1])) +// } +// } -pub impl Vec3: InvTrigV>> { - #[inline(always)] - pure fn asin(&self) -> Vec3> { - Vec3::new(asin(&self[0]), - asin(&self[1]), - asin(&self[2])) - } +// pub impl Vec3: InvTrig>> { +// #[inline(always)] +// pure fn asin(&self) -> Vec3> { +// Vec3::new(asin(&self[0]), +// asin(&self[1]), +// asin(&self[2])) +// } - #[inline(always)] - pure fn acos(&self) -> Vec3> { - Vec3::new(acos(&self[0]), - acos(&self[1]), - acos(&self[2])) - } +// #[inline(always)] +// pure fn acos(&self) -> Vec3> { +// Vec3::new(acos(&self[0]), +// acos(&self[1]), +// acos(&self[2])) +// } - #[inline(always)] - pure fn atan(&self) -> Vec3> { - Vec3::new(atan(&self[0]), - atan(&self[1]), - atan(&self[2])) - } -} +// #[inline(always)] +// pure fn atan(&self) -> Vec3> { +// Vec3::new(atan(&self[0]), +// atan(&self[1]), +// atan(&self[2])) +// } +// } -pub impl Vec4: InvTrigV>> { - #[inline(always)] - pure fn asin(&self) -> Vec4> { - Vec4::new(asin(&self[0]), - asin(&self[1]), - asin(&self[2]), - asin(&self[3])) - } +// pub impl Vec4: InvTrig>> { +// #[inline(always)] +// pure fn asin(&self) -> Vec4> { +// Vec4::new(asin(&self[0]), +// asin(&self[1]), +// asin(&self[2]), +// asin(&self[3])) +// } - #[inline(always)] - pure fn acos(&self) -> Vec4> { - Vec4::new(acos(&self[0]), - acos(&self[1]), - acos(&self[2]), - acos(&self[3])) - } +// #[inline(always)] +// pure fn acos(&self) -> Vec4> { +// Vec4::new(acos(&self[0]), +// acos(&self[1]), +// acos(&self[2]), +// acos(&self[3])) +// } - #[inline(always)] - pure fn atan(&self) -> Vec4> { - Vec4::new(atan(&self[0]), - atan(&self[1]), - atan(&self[2]), - atan(&self[3])) - } -} +// #[inline(always)] +// pure fn atan(&self) -> Vec4> { +// Vec4::new(atan(&self[0]), +// atan(&self[1]), +// atan(&self[2]), +// atan(&self[3])) +// } +// } - - -/** - * 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(x: &T) -> T { x.sinh() } -#[inline(always)] pub pure fn cosh(x: &T) -> T { x.cosh() } -#[inline(always)] pub pure fn tanh(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 } -} +// Hyp pub impl Vec2: Hyp { #[inline(always)] diff --git a/src/lmath.rc b/src/lmath.rc index 7e5a9aa..101d2df 100644 --- a/src/lmath.rc +++ b/src/lmath.rc @@ -29,14 +29,14 @@ mod test { } pub mod funs { - // #[path = "funs/common.rs"] - // pub mod common; - // #[path = "funs/exponential.rs"] - // pub mod exponential; + #[path = "funs/common.rs"] + pub mod common; + #[path = "funs/exponential.rs"] + pub mod exponential; #[path = "funs/projection.rs"] pub mod projection; - // #[path = "funs/triganomic.rs"] - // pub mod triganomic; + #[path = "funs/triganomic.rs"] + pub mod triganomic; #[test] mod test {