Skip to main content

rapier3d/utils/
copysign.rs

1//! SimdSign trait for copying signs between values.
2
3use crate::math::Real;
4use crate::math::SimdReal;
5#[cfg(not(target_arch = "spirv"))]
6use na::{Scalar, Vector2, Vector3};
7use simba::simd::SimdRealField;
8
9/// Trait to copy the sign of each component of one scalar/vector/matrix to another.
10pub trait CopySign<Rhs>: Sized {
11    // See SIMD implementations of copy_sign there: https://stackoverflow.com/a/57872652
12    /// Copy the sign of each component of `self` to the corresponding component of `to`.
13    fn copy_sign_to(self, to: Rhs) -> Rhs;
14}
15
16impl CopySign<Real> for Real {
17    fn copy_sign_to(self, to: Self) -> Self {
18        const MINUS_ZERO: Real = -0.0;
19        let signbit = MINUS_ZERO.to_bits();
20        Real::from_bits((signbit & self.to_bits()) | ((!signbit) & to.to_bits()))
21    }
22}
23
24#[cfg(not(target_arch = "spirv"))]
25impl<N: Scalar + Copy + CopySign<N>> CopySign<Vector2<N>> for N {
26    fn copy_sign_to(self, to: Vector2<N>) -> Vector2<N> {
27        Vector2::new(self.copy_sign_to(to.x), self.copy_sign_to(to.y))
28    }
29}
30
31#[cfg(not(target_arch = "spirv"))]
32impl<N: Scalar + Copy + CopySign<N>> CopySign<Vector3<N>> for N {
33    fn copy_sign_to(self, to: Vector3<N>) -> Vector3<N> {
34        Vector3::new(
35            self.copy_sign_to(to.x),
36            self.copy_sign_to(to.y),
37            self.copy_sign_to(to.z),
38        )
39    }
40}
41
42#[cfg(not(target_arch = "spirv"))]
43impl<N: Scalar + Copy + CopySign<N>> CopySign<Vector2<N>> for Vector2<N> {
44    fn copy_sign_to(self, to: Vector2<N>) -> Vector2<N> {
45        Vector2::new(self.x.copy_sign_to(to.x), self.y.copy_sign_to(to.y))
46    }
47}
48
49#[cfg(not(target_arch = "spirv"))]
50impl<N: Scalar + Copy + CopySign<N>> CopySign<Vector3<N>> for Vector3<N> {
51    fn copy_sign_to(self, to: Vector3<N>) -> Vector3<N> {
52        Vector3::new(
53            self.x.copy_sign_to(to.x),
54            self.y.copy_sign_to(to.y),
55            self.z.copy_sign_to(to.z),
56        )
57    }
58}
59
60impl CopySign<SimdReal> for SimdReal {
61    fn copy_sign_to(self, to: SimdReal) -> SimdReal {
62        to.simd_copysign(self)
63    }
64}