2018-09-21 01:54:12 +08:00
|
|
|
use std::mem;
|
|
|
|
use num::FromPrimitive;
|
|
|
|
use na::{self, Scalar, 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-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-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-21 01:54:12 +08:00
|
|
|
pub fn clamp<N: Number>(x: N, minVal: N, maxVal: N) -> N {
|
|
|
|
na::clamp(x, minVal, maxVal)
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn clamp2<N: Number, D: Dimension>(x: &Vec<N, D>,minVal: N, maxVal: N) -> 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| na::clamp(x, minVal, maxVal))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn clamp3<N: Number, D: Dimension>(x: &Vec<N, D>, minVal: &Vec<N, D>, maxVal: &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
|
|
|
na::clamp(x.clone(), minVal.clone(), maxVal.clone())
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
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-21 01:54:12 +08:00
|
|
|
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-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-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-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-21 01:54:12 +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-21 01:54:12 +08:00
|
|
|
pub fn fract<N: Real>(x: N) -> N {
|
|
|
|
x.fract()
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn fract2<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-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-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()
|
|
|
|
//}
|
|
|
|
|
|
|
|
pub fn max<N: Number>(x: N, y: N) -> N {
|
|
|
|
na::sup(&x, &y)
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn max2<N: Number, D: Dimension>(x: &Vec<N, D>, y: N) -> 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| na::sup(&x, &y))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn max3<N: Number, D: Dimension>(x: &Vec<N, D>, y: &Vec<N, D>) -> Vec<N, D>
|
|
|
|
where DefaultAllocator: Alloc<N, D> {
|
|
|
|
na::sup(x, y)
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn min<N: Number>(x: N, y: N) -> N {
|
|
|
|
na::inf(&x, &y)
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn min2<N: Number, D: Dimension>(x: &Vec<N, D>,y: N) -> 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| na::inf(&x, &y))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn min3<N: Number, D: Dimension>(x: &Vec<N, D>, y: &Vec<N, D>) -> Vec<N, D>
|
|
|
|
where DefaultAllocator: Alloc<N, D> {
|
|
|
|
na::inf(x, y)
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
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-21 01:54:12 +08:00
|
|
|
pub fn mod_<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-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-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-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-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-21 01:54:12 +08:00
|
|
|
pub fn step<N: Number>(edge: N, x: N) -> N {
|
|
|
|
if edge > x {
|
|
|
|
N::zero()
|
|
|
|
} else {
|
|
|
|
N::one()
|
|
|
|
}
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn step2<N: Number, D: Dimension>(edge: N, x: &Vec<N, D>) -> Vec<N, D>
|
|
|
|
where DefaultAllocator: Alloc<N, D> {
|
|
|
|
x.map(|x| step(edge, x))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn step3<N: Number, D: Dimension>(edge: &Vec<N, D>, x: &Vec<N, D>) -> Vec<N, D>
|
|
|
|
where DefaultAllocator: Alloc<N, D> {
|
|
|
|
edge.zip_map(x, |edge, x| step(edge, x))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|
|
|
|
|
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-21 01:54:12 +08:00
|
|
|
pub fn uint_bits_to_float(v: u32) -> f32 {
|
|
|
|
unsafe { mem::transmute(v) }
|
2018-09-20 16:50:34 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-21 01:54:12 +08:00
|
|
|
pub fn uint_bits_to_float_vec<D: Dimension>(v: &Vec<u32, 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| uint_bits_to_float(v))
|
2018-09-20 16:50:34 +08:00
|
|
|
}
|