use std::mem; use num::FromPrimitive; use na::{self, Scalar, Real, DefaultAllocator}; use aliases::{Vec, Mat}; use traits::{Number, Dimension, Alloc}; pub fn abs(x: &Mat) -> Mat where DefaultAllocator: Alloc { x.abs() } pub fn ceil(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.ceil()) } pub fn clamp(x: N, minVal: N, maxVal: N) -> N { na::clamp(x, minVal, maxVal) } pub fn clamp2(x: &Vec,minVal: N, maxVal: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::clamp(x, minVal, maxVal)) } pub fn clamp3(x: &Vec, minVal: &Vec, maxVal: &Vec) -> Vec where DefaultAllocator: Alloc { na::clamp(x.clone(), minVal.clone(), maxVal.clone()) } pub fn float_bits_to_int(v: f32) -> i32 { unsafe { mem::transmute(v) } } pub fn float_bits_to_int_vec(v: Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| float_bits_to_int(v)) } pub fn float_bits_to_uint(v: f32) -> u32 { unsafe { mem::transmute(v) } } pub fn float_bits_to_uint_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| float_bits_to_uint(v)) } pub fn floor(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.floor()) } // FIXME: should be implemented for Vec/Mat? pub fn fma(a: N, b: N, c: N) -> N { // FIXME: use an actual FMA a * b + c } pub fn fract(x: N) -> N { x.fract() } pub fn fract2(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.fract()) } //// FIXME: should be implemented for Vec/Mat? ///// Returns the (significant, exponent) of this float number. //pub fn frexp(x: N, exp: N) -> (N, N) { // // FIXME: is there a better approach? // let e = x.log2().ceil(); // (x * (-e).exp2(), e) //} pub fn int_bits_to_float(v: i32) -> f32 { unsafe { mem::transmute(v) } } pub fn int_bits_to_float_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| int_bits_to_float(v)) } //pub fn isinf(x: &Vec) -> Vec // where DefaultAllocator: Alloc { // unimplemented!() // //} // //pub fn isnan(x: &Vec) -> Vec // where DefaultAllocator: Alloc { // unimplemented!() // //} ///// Returns the (significant, exponent) of this float number. //pub fn ldexp(x: N, exp: N) -> N { // // FIXME: is there a better approach? // x * (exp).exp2() //} pub fn max(x: N, y: N) -> N { na::sup(&x, &y) } pub fn max2(x: &Vec, y: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::sup(&x, &y)) } pub fn max3(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { na::sup(x, y) } pub fn min(x: N, y: N) -> N { na::inf(&x, &y) } pub fn min2(x: &Vec,y: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::inf(&x, &y)) } pub fn min3(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { na::inf(x, y) } pub fn mix(x: N, y: N, a: N) -> N { x * (N::one() - a) + y * a } pub fn mod_(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { x.zip_map(y, |x, y| x % y) } pub fn modf(x: N, i: N) -> N { x % i } pub fn round(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.round()) } //pub fn roundEven(x: &Vec) -> Vec // where DefaultAllocator: Alloc { // unimplemented!() //} pub fn sign(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.signum()) } pub fn smoothstep(edge0: N, edge1: N, x: N) -> N { let _3: N = FromPrimitive::from_f64(3.0).unwrap(); let _2: N = FromPrimitive::from_f64(2.0).unwrap(); let t = na::clamp((x - edge0) / (edge1 - edge0), N::zero(), N::one()); t * t * (_3 - t * _2) } pub fn step(edge: N, x: N) -> N { if edge > x { N::zero() } else { N::one() } } pub fn step2(edge: N, x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| step(edge, x)) } pub fn step3(edge: &Vec, x: &Vec) -> Vec where DefaultAllocator: Alloc { edge.zip_map(x, |edge, x| step(edge, x)) } pub fn trunc(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.trunc()) } pub fn uint_bits_to_float(v: u32) -> f32 { unsafe { mem::transmute(v) } } pub fn uint_bits_to_float_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| uint_bits_to_float(v)) }