use std::mem; use num::FromPrimitive; use na::{self, Real, DefaultAllocator}; use aliases::{Vec, Mat}; use traits::{Number, Dimension, Alloc}; /// For each matrix or vector component `x` if `x >= 0`; otherwise, it returns `-x`. pub fn abs(x: &Mat) -> Mat where DefaultAllocator: Alloc { x.abs() } /// For each matrix or vector component returns a value equal to the nearest integer that is greater than or equal to `x`. pub fn ceil(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.ceil()) } /// Returns `min(max(x, min_val), max_val)`. pub fn clamp(x: N, min_val: N, max_val: N) -> N { na::clamp(x, min_val, max_val) } /// Returns `min(max(x, min_val), max_val)` for each component in `x` using the floating-point values `min_val and `max_val`. pub fn clamp2(x: &Vec, min_val: N, max_val: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::clamp(x, min_val, max_val)) } /// Returns `min(max(x, min_val), max_val)` for each component in `x` using the components of `min_val` and `max_val` as bounds. pub fn clamp3(x: &Vec, min_val: &Vec, max_val: &Vec) -> Vec where DefaultAllocator: Alloc { na::clamp(x.clone(), min_val.clone(), max_val.clone()) } /// Returns a signed integer value representing the encoding of a floating-point value. /// /// The floating-point value's bit-level representation is preserved. pub fn float_bits_to_int(v: f32) -> i32 { unsafe { mem::transmute(v) } } /// Returns a signed integer value representing the encoding of each component of `v`. /// /// The floating point value's bit-level representation is preserved. pub fn float_bits_to_int_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| float_bits_to_int(v)) } /// Returns an unsigned integer value representing the encoding of a floating-point value. /// /// The floating-point value's bit-level representation is preserved. pub fn float_bits_to_uint(v: f32) -> u32 { unsafe { mem::transmute(v) } } /// Returns an unsigned integer value representing the encoding of each component of `v`. /// /// The floating point value's bit-level representation is preserved. pub fn float_bits_to_uint_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| float_bits_to_uint(v)) } /// Returns componentwise a value equal to the nearest integer that is less then or equal to `x`. 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 //} /// Returns the fractional part of `x`. pub fn fract(x: N) -> N { x.fract() } /// Returns the fractional part of each component of `x`. 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) //} /// Returns a floating-point value corresponding to a signed integer encoding of a floating-point value. /// /// If an inf or NaN is passed in, it will not signal, and the resulting floating point value is unspecified. Otherwise, the bit-level representation is preserved. pub fn int_bits_to_float(v: i32) -> f32 { unsafe { mem::transmute(v) } } /// For each components of `v`, returns a floating-point value corresponding to a signed integer encoding of a floating-point value. /// /// If an inf or NaN is passed in, it will not signal, and the resulting floating point value is unspecified. Otherwise, the bit-level representation is preserved. 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() //} /// The maximum between two numbers. pub fn max(x: N, y: N) -> N { na::sup(&x, &y) } /// The maximum between each component of `x` and `y`. pub fn max2(x: &Vec, y: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::sup(&x, &y)) } /// Component-wise maximum between `x` and `y`. pub fn max3(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { na::sup(x, y) } /// The minimum between two numbers. pub fn min(x: N, y: N) -> N { na::inf(&x, &y) } /// The minimum between each component of `x` and `y`. pub fn min2(x: &Vec,y: N) -> Vec where DefaultAllocator: Alloc { x.map(|x| na::inf(&x, &y)) } /// Component-wise minimum between `x` and `y`. pub fn min3(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { na::inf(x, y) } /// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of x and y using the floating-point value a. /// /// The value for a is not restricted to the range `[0, 1]`. pub fn mix(x: N, y: N, a: N) -> N { x * (N::one() - a) + y * a } /// Component-wise modulus. /// /// Returns `x - y * floor(x / y)` for each component in `x` using the corresponding component of `y`. pub fn mod_(x: &Vec, y: &Vec) -> Vec where DefaultAllocator: Alloc { x.zip_map(y, |x, y| x % y) } /// Modulus between two values. pub fn modf(x: N, i: N) -> N { x % i } /// Component-wise rounding. /// /// Values equal to `0.5` are rounded away from `0.0`. pub fn round(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.round()) } //pub fn roundEven(x: &Vec) -> Vec // where DefaultAllocator: Alloc { // unimplemented!() //} /// Returns 1 if `x > 0`, 0 if `x == 0`, or -1 if `x < 0`. pub fn sign(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.signum()) } /// Returns 0.0 if `x <= edge0` and `1.0 if x >= edge1` and performs smooth Hermite interpolation between 0 and 1 when `edge0 < x < edge1`. /// /// This is useful in cases where you would want a threshold function with a smooth transition. /// This is equivalent to: `let result = clamp((x - edge0) / (edge1 - edge0), 0, 1); return t * t * (3 - 2 * t);` Results are undefined if `edge0 >= edge1`. 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) } /// Returns 0.0 if `x < edge`, otherwise it returns 1.0. pub fn step(edge: N, x: N) -> N { if edge > x { N::zero() } else { N::one() } } /// Returns 0.0 if `x[i] < edge`, otherwise it returns 1.0. pub fn step2(edge: N, x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| step(edge, x)) } /// Returns 0.0 if `x[i] < edge[i]`, otherwise it returns 1.0. pub fn step3(edge: &Vec, x: &Vec) -> Vec where DefaultAllocator: Alloc { edge.zip_map(x, |edge, x| step(edge, x)) } /// Returns a value equal to the nearest integer to `x` whose absolute value is not larger than the absolute value of `x`. pub fn trunc(x: &Vec) -> Vec where DefaultAllocator: Alloc { x.map(|x| x.trunc()) } /// Returns a floating-point value corresponding to a unsigned integer encoding of a floating-point value. /// /// If an `inf` or `NaN` is passed in, it will not signal, and the resulting floating point value is unspecified. Otherwise, the bit-level representation is preserved. pub fn uint_bits_to_float(v: u32) -> f32 { unsafe { mem::transmute(v) } } /// For each component of `v`, returns a floating-point value corresponding to a unsigned integer encoding of a floating-point value. /// /// If an inf or NaN is passed in, it will not signal, and the resulting floating point value is unspecified. Otherwise, the bit-level representation is preserved. pub fn uint_bits_to_float_vec(v: &Vec) -> Vec where DefaultAllocator: Alloc { v.map(|v| uint_bits_to_float(v)) }