diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs index 45657873..83c1e41f 100644 --- a/src/f32/vec2.rs +++ b/src/f32/vec2.rs @@ -295,6 +295,13 @@ impl Vec2 { pub(crate) fn neg_mul_sub(self, a: Self, b: Self) -> Self { Self(b.0 - (self.0 * a.0), b.1 - (self.1 * a.1)) } + + /// Returns a new `Vec2` containing the absolute value of each component of the original + /// `Vec2`. + #[inline] + pub fn abs(self) -> Self { + Self(self.0.abs(), self.1.abs()) + } } impl fmt::Display for Vec2 { diff --git a/src/f32/vec3_f32.rs b/src/f32/vec3_f32.rs index 0a41e9ac..fff4825c 100644 --- a/src/f32/vec3_f32.rs +++ b/src/f32/vec3_f32.rs @@ -213,6 +213,11 @@ impl Vec3 { b.2 - (self.2 * a.2), ) } + + #[inline] + pub fn abs(self) -> Self { + Self(self.0.abs(), self.1.abs(), self.2.abs()) + } } impl fmt::Display for Vec3 { diff --git a/src/f32/vec3_sse2.rs b/src/f32/vec3_sse2.rs index 23e5eaa3..caf6012d 100644 --- a/src/f32/vec3_sse2.rs +++ b/src/f32/vec3_sse2.rs @@ -359,6 +359,18 @@ impl Vec3 { pub(crate) fn neg_mul_sub(self, a: Self, b: Self) -> Self { unsafe { Self(_mm_sub_ps(b.0, _mm_mul_ps(self.0, a.0))) } } + + /// Returns a new `Vec3` containing the absolute value of each component of the original + /// `Vec3`. + #[inline] + pub fn abs(self) -> Self { + unsafe { + Self(_mm_and_ps( + self.0, + _mm_castsi128_ps(_mm_set1_epi32(0x7f_ff_ff_ff)), + )) + } + } } impl fmt::Display for Vec3 { diff --git a/src/f32/vec4_f32.rs b/src/f32/vec4_f32.rs index b686966d..815f33e1 100644 --- a/src/f32/vec4_f32.rs +++ b/src/f32/vec4_f32.rs @@ -353,6 +353,11 @@ impl Vec4 { b.3 - (self.3 * a.3), ) } + + #[inline] + pub fn abs(self) -> Self { + Self(self.0.abs(), self.1.abs(), self.2.abs(), self.3.abs()) + } } impl fmt::Display for Vec4 { diff --git a/src/f32/vec4_sse2.rs b/src/f32/vec4_sse2.rs index 3e6c78ac..7c39d329 100644 --- a/src/f32/vec4_sse2.rs +++ b/src/f32/vec4_sse2.rs @@ -395,6 +395,18 @@ impl Vec4 { pub(crate) fn neg_mul_sub(self, a: Self, b: Self) -> Self { unsafe { Self(_mm_sub_ps(b.0, _mm_mul_ps(self.0, a.0))) } } + + /// Returns a new `Vec4` containing the absolute value of each component of the original + /// `Vec4`. + #[inline] + pub fn abs(self) -> Self { + unsafe { + Self(_mm_and_ps( + self.0, + _mm_castsi128_ps(_mm_set1_epi32(0x7f_ff_ff_ff)), + )) + } + } } impl fmt::Display for Vec4 { diff --git a/tests/vec2.rs b/tests/vec2.rs index 52d6036a..4351940a 100644 --- a/tests/vec2.rs +++ b/tests/vec2.rs @@ -305,6 +305,20 @@ fn test_vec2_rand() { assert_eq!(a, b.into()); } +#[test] +fn test_vec2_sign() { + assert_eq!(Vec2::zero().sign(), Vec2::one()); + assert_eq!(Vec2::one().sign(), Vec2::one()); + assert_eq!((-Vec2::one()).sign(), -Vec2::one()); +} + +#[test] +fn test_vec2_abs() { + assert_eq!(Vec2::zero().abs(), Vec2::zero()); + assert_eq!(Vec2::one().abs(), Vec2::one()); + assert_eq!((-Vec2::one()).abs(), Vec2::one()); +} + #[cfg(feature = "serde")] #[test] fn test_vec2_serde() { diff --git a/tests/vec3.rs b/tests/vec3.rs index f668127b..b3d1572e 100644 --- a/tests/vec3.rs +++ b/tests/vec3.rs @@ -346,6 +346,20 @@ fn test_vec3_rand() { assert_eq!(a, b.into()); } +#[test] +fn test_vec3_sign() { + assert_eq!(Vec3::zero().sign(), Vec3::one()); + assert_eq!(Vec3::one().sign(), Vec3::one()); + assert_eq!((-Vec3::one()).sign(), -Vec3::one()); +} + +#[test] +fn test_vec3_abs() { + assert_eq!(Vec3::zero().abs(), Vec3::zero()); + assert_eq!(Vec3::one().abs(), Vec3::one()); + assert_eq!((-Vec3::one()).abs(), Vec3::one()); +} + #[cfg(feature = "serde")] #[test] fn test_vec3_serde() { diff --git a/tests/vec4.rs b/tests/vec4.rs index f6ac4db3..6f8285b3 100644 --- a/tests/vec4.rs +++ b/tests/vec4.rs @@ -250,6 +250,13 @@ fn test_vec4_sign() { assert_eq!(Vec4::splat(core::f32::NEG_INFINITY).sign(), -Vec4::one()); } +#[test] +fn test_vec4_abs() { + assert_eq!(Vec4::zero().abs(), Vec4::zero()); + assert_eq!(Vec4::one().abs(), Vec4::one()); + assert_eq!((-Vec4::one()).abs(), Vec4::one()); +} + // #[test] // fn dup_element() { // let a = vec4(1.0, 2.0, 3.0, 4.0);