2018-09-21 01:54:12 +08:00
use std ::mem ;
use num ::FromPrimitive ;
2018-09-22 19:18:59 +08:00
use na ::{ self , Real , DefaultAllocator } ;
2018-09-20 16:50:34 +08:00
2018-09-21 01:54:12 +08:00
use aliases ::{ Vec , Mat } ;
use traits ::{ Number , Dimension , Alloc } ;
2018-09-20 16:50:34 +08:00
2018-09-22 19:18:59 +08:00
/// For each matrix or vector component `x` if `x >= 0`; otherwise, it returns `-x`.
2018-09-21 01:54:12 +08:00
pub fn abs < N : Number , R : Dimension , C : Dimension > ( x : & Mat < N , R , C > ) -> Mat < N , R , C >
where DefaultAllocator : Alloc < N , R , C > {
x . abs ( )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// For each matrix or vector component returns a value equal to the nearest integer that is greater than or equal to `x`.
2018-09-21 01:54:12 +08:00
pub fn ceil < N : Real , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . map ( | x | x . ceil ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns `min(max(x, min_val), max_val)`.
pub fn clamp < N : Number > ( x : N , min_val : N , max_val : N ) -> N {
na ::clamp ( x , min_val , max_val )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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 < N : Number , D : Dimension > ( x : & Vec < N , D > , min_val : N , max_val : N ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-22 19:18:59 +08:00
x . map ( | x | na ::clamp ( x , min_val , max_val ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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 < N : Number , D : Dimension > ( x : & Vec < N , D > , min_val : & Vec < N , D > , max_val : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-22 19:18:59 +08:00
na ::clamp ( x . clone ( ) , min_val . clone ( ) , max_val . clone ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns a signed integer value representing the encoding of a floating-point value.
///
/// The floating-point value's bit-level representation is preserved.
2018-09-21 01:54:12 +08:00
pub fn float_bits_to_int ( v : f32 ) -> i32 {
unsafe { mem ::transmute ( v ) }
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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 < D : Dimension > ( v : & Vec < f32 , D > ) -> Vec < i32 , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < f32 , D > {
2018-09-21 01:54:12 +08:00
v . map ( | v | float_bits_to_int ( v ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns an unsigned integer value representing the encoding of a floating-point value.
///
/// The floating-point value's bit-level representation is preserved.
2018-09-21 01:54:12 +08:00
pub fn float_bits_to_uint ( v : f32 ) -> u32 {
unsafe { mem ::transmute ( v ) }
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns an unsigned integer value representing the encoding of each component of `v`.
///
/// The floating point value's bit-level representation is preserved.
2018-09-21 01:54:12 +08:00
pub fn float_bits_to_uint_vec < D : Dimension > ( v : & Vec < f32 , D > ) -> Vec < u32 , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < f32 , D > {
2018-09-21 01:54:12 +08:00
v . map ( | v | float_bits_to_uint ( v ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns componentwise a value equal to the nearest integer that is less then or equal to `x`.
2018-09-21 01:54:12 +08:00
pub fn floor < N : Real , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
where DefaultAllocator : Alloc < N , D > {
x . map ( | x | x . floor ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
//// FIXME: should be implemented for Vec/Mat?
//pub fn fma<N: Number>(a: N, b: N, c: N) -> N {
// // FIXME: use an actual FMA
// a * b + c
//}
2018-09-20 16:50:34 +08:00
2018-09-22 19:18:59 +08:00
/// Returns the fractional part of each component of `x`.
2018-09-23 00:42:38 +08:00
pub fn fract < N : Real , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . map ( | x | x . fract ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-21 01:54:12 +08:00
//// FIXME: should be implemented for Vec/Mat?
///// Returns the (significant, exponent) of this float number.
//pub fn frexp<N: Real>(x: N, exp: N) -> (N, N) {
// // FIXME: is there a better approach?
// let e = x.log2().ceil();
// (x * (-e).exp2(), e)
//}
2018-09-20 16:50:34 +08:00
2018-09-22 19:18:59 +08:00
/// 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.
2018-09-21 01:54:12 +08:00
pub fn int_bits_to_float ( v : i32 ) -> f32 {
unsafe { mem ::transmute ( v ) }
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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.
2018-09-21 01:54:12 +08:00
pub fn int_bits_to_float_vec < D : Dimension > ( v : & Vec < i32 , D > ) -> Vec < f32 , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < f32 , D > {
2018-09-21 01:54:12 +08:00
v . map ( | v | int_bits_to_float ( v ) )
2018-09-20 16:50:34 +08:00
}
2018-09-21 01:54:12 +08:00
//pub fn isinf<N: Scalar, D: Dimension>(x: &Vec<N, D>) -> Vec<bool, D>
// where DefaultAllocator: Alloc<N, D> {
// unimplemented!()
//
//}
//
//pub fn isnan<N: Scalar, D: Dimension>(x: &Vec<N, D>) -> Vec<bool, D>
// where DefaultAllocator: Alloc<N, D> {
// unimplemented!()
//
//}
2018-09-20 16:50:34 +08:00
2018-09-21 01:54:12 +08:00
///// Returns the (significant, exponent) of this float number.
//pub fn ldexp<N: Real>(x: N, exp: N) -> N {
// // FIXME: is there a better approach?
// x * (exp).exp2()
//}
2018-09-22 19:18:59 +08:00
/// 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]`.
2018-09-21 01:54:12 +08:00
pub fn mix < N : Number > ( x : N , y : N , a : N ) -> N {
x * ( N ::one ( ) - a ) + y * a
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:21:02 +08:00
/// Component-wise modulus.
2018-09-22 19:18:59 +08:00
///
/// Returns `x - y * floor(x / y)` for each component in `x` using the corresponding component of `y`.
2018-09-22 23:36:08 +08:00
pub fn modf_vec < N : Number , D : Dimension > ( x : & Vec < N , D > , y : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . zip_map ( y , | x , y | x % y )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Modulus between two values.
2018-09-21 01:54:12 +08:00
pub fn modf < N : Number > ( x : N , i : N ) -> N {
x % i
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:21:02 +08:00
/// Component-wise rounding.
2018-09-22 19:18:59 +08:00
///
/// Values equal to `0.5` are rounded away from `0.0`.
2018-09-21 01:54:12 +08:00
pub fn round < N : Real , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . map ( | x | x . round ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-21 01:54:12 +08:00
//pub fn roundEven<N: Scalar, D: Dimension>(x: &Vec<N, D>) -> Vec<N, D>
// where DefaultAllocator: Alloc<N, D> {
// unimplemented!()
//}
2018-09-20 16:50:34 +08:00
2018-09-22 19:18:59 +08:00
/// Returns 1 if `x > 0`, 0 if `x == 0`, or -1 if `x < 0`.
2018-09-21 01:54:12 +08:00
pub fn sign < N : Number , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . map ( | x | x . signum ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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`.
2018-09-21 01:54:12 +08:00
pub fn smoothstep < N : Number > ( 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 )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns 0.0 if `x < edge`, otherwise it returns 1.0.
2018-09-22 23:36:08 +08:00
pub fn step_scalar < N : Number > ( edge : N , x : N ) -> N {
2018-09-21 01:54:12 +08:00
if edge > x {
N ::zero ( )
} else {
N ::one ( )
}
2018-09-20 16:50:34 +08:00
}
2018-09-22 23:36:08 +08:00
2018-09-22 19:18:59 +08:00
/// Returns 0.0 if `x[i] < edge`, otherwise it returns 1.0.
2018-09-22 23:36:08 +08:00
pub fn step < N : Number , D : Dimension > ( edge : N , x : & Vec < N , D > ) -> Vec < N , D >
2018-09-21 01:54:12 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-22 23:36:08 +08:00
x . map ( | x | step_scalar ( edge , x ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns 0.0 if `x[i] < edge[i]`, otherwise it returns 1.0.
2018-09-22 23:36:08 +08:00
pub fn step_vec < N : Number , D : Dimension > ( edge : & Vec < N , D > , x : & Vec < N , D > ) -> Vec < N , D >
2018-09-21 01:54:12 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-22 23:36:08 +08:00
edge . zip_map ( x , | edge , x | step_scalar ( edge , x ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// Returns a value equal to the nearest integer to `x` whose absolute value is not larger than the absolute value of `x`.
2018-09-21 01:54:12 +08:00
pub fn trunc < N : Real , D : Dimension > ( x : & Vec < N , D > ) -> Vec < N , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < N , D > {
2018-09-21 01:54:12 +08:00
x . map ( | x | x . trunc ( ) )
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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.
2018-09-22 23:36:08 +08:00
pub fn uint_bits_to_float_scalar ( v : u32 ) -> f32 {
2018-09-21 01:54:12 +08:00
unsafe { mem ::transmute ( v ) }
2018-09-20 16:50:34 +08:00
}
2018-09-22 19:18:59 +08:00
/// 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.
2018-09-22 23:36:08 +08:00
pub fn uint_bits_to_float < D : Dimension > ( v : & Vec < u32 , D > ) -> Vec < f32 , D >
2018-09-20 16:50:34 +08:00
where DefaultAllocator : Alloc < f32 , D > {
2018-09-22 23:36:08 +08:00
v . map ( | v | uint_bits_to_float_scalar ( v ) )
2018-09-20 16:50:34 +08:00
}