Skip to main content

rapier2d/utils/
copysign.rs

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