Repository: bitshifter/glam-rs
Pull request #12 (2019-07-22 11:09:33)

Added basic logic operations for the vector mask types.
Implemented bitwise `and`, `or`, and `not` operators for `Vec4Mask`, `Vec3Mask`, and `Vec2Mask`.


Patch:
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index 3024d24..ae4320c 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -402,3 +402,51 @@ impl Vec2Mask {
         )
     }
 }
+
+impl BitAnd for Vec2Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        Self(
+            self.0 & rhs.0,
+            self.1 & rhs.1,
+        )
+    }
+}
+
+impl BitAndAssign for Vec2Mask {
+    fn bitand_assign(&mut self, rhs: Self) {
+        *self = *self & rhs
+    }
+}
+
+impl BitOr for Vec2Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        Self(
+            self.0 | rhs.0,
+            self.1 | rhs.1,
+        )
+    }
+}
+
+impl BitOrAssign for Vec2Mask {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs
+    }
+}
+
+impl Not for Vec2Mask {
+    type Output = Self;
+
+    #[inline]
+    fn not(self) -> Self {
+        Self(
+            !self.0,
+            !self.1,
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/f32/vec3_f32.rs b/src/f32/vec3_f32.rs
index 2596016..58daa5f 100644
--- a/src/f32/vec3_f32.rs
+++ b/src/f32/vec3_f32.rs
@@ -406,3 +406,54 @@ impl Vec3Mask {
         )
     }
 }
+
+impl BitAnd for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        Self(
+            self.0 & rhs.0,
+            self.1 & rhs.1,
+            self.2 & rhs.2,
+        )
+    }
+}
+
+impl BitAndAssign for Vec3Mask {
+    fn bitand_assign(&mut self, rhs: Self) {
+        *self = *self & rhs
+    }
+}
+
+impl BitOr for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        Self(
+            self.0 | rhs.0,
+            self.1 | rhs.1,
+            self.2 | rhs.2,
+        )
+    }
+}
+
+impl BitOrAssign for Vec3Mask {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs
+    }
+}
+
+impl Not for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn not(self) -> Self {
+        Self(
+            !self.0,
+            !self.1,
+            !self.2,
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/f32/vec3_sse2.rs b/src/f32/vec3_sse2.rs
index 322d34b..7a84377 100644
--- a/src/f32/vec3_sse2.rs
+++ b/src/f32/vec3_sse2.rs
@@ -546,3 +546,51 @@ impl Default for Vec3Mask {
         unsafe { Self(_mm_setzero_ps()) }
     }
 }
+
+impl BitAnd for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        unsafe {
+            Self(_mm_and_ps(self.0, rhs.0))
+        }
+    }
+}
+
+impl BitAndAssign for Vec3Mask {
+    fn bitand_assign(&mut self, rhs: Self) {
+        *self = *self & rhs
+    }
+}
+
+impl BitOr for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        unsafe {
+            Self(_mm_or_ps(self.0, rhs.0))
+        }
+    }
+}
+
+impl BitOrAssign for Vec3Mask {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs
+    }
+}
+
+impl Not for Vec3Mask {
+    type Output = Self;
+
+    #[inline]
+    fn not(self) -> Self {
+        unsafe {
+            Self(_mm_andnot_ps(
+                self.0,
+                _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))
+            ))
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/f32/vec4_f32.rs b/src/f32/vec4_f32.rs
index b4d68a4..fd88c17 100644
--- a/src/f32/vec4_f32.rs
+++ b/src/f32/vec4_f32.rs
@@ -621,3 +621,58 @@ impl Vec4Mask {
         )
     }
 }
+
+impl BitAnd for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        Self(
+            self.0 & rhs.0,
+            self.1 & rhs.1,
+            self.2 & rhs.2,
+            self.3 & rhs.3,
+        )
+    }
+}
+
+impl BitAndAssign for Vec4Mask {
+    fn bitand_assign(&mut self, rhs: Self) {
+        *self = *self & rhs
+    }
+}
+
+
+impl BitOr for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        Self(
+            self.0 | rhs.0,
+            self.1 | rhs.1,
+            self.2 | rhs.2,
+            self.3 | rhs.3,
+        )
+    }
+}
+
+impl BitOrAssign for Vec4Mask {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs
+    }
+}
+
+impl Not for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn not(self) -> Self {
+        Self(
+            !self.0,
+            !self.1,
+            !self.2,
+            !self.3,
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/f32/vec4_sse2.rs b/src/f32/vec4_sse2.rs
index aeeb90b..83bfd09 100644
--- a/src/f32/vec4_sse2.rs
+++ b/src/f32/vec4_sse2.rs
@@ -673,3 +673,51 @@ impl Default for Vec4Mask {
         unsafe { Self(_mm_setzero_ps()) }
     }
 }
+
+impl BitAnd for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        unsafe {
+            Self(_mm_and_ps(self.0, rhs.0))
+        }
+    }
+}
+
+impl BitAndAssign for Vec4Mask {
+    fn bitand_assign(&mut self, rhs: Self) {
+        *self = *self & rhs
+    }
+}
+
+impl BitOr for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        unsafe {
+            Self(_mm_or_ps(self.0, rhs.0))
+        }
+    }
+}
+
+impl BitOrAssign for Vec4Mask {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs
+    }
+}
+
+impl Not for Vec4Mask {
+    type Output = Self;
+
+    #[inline]
+    fn not(self) -> Self {
+        unsafe {
+            Self(_mm_andnot_ps(
+                self.0,
+                _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))
+            ))
+        }
+    }
+}
\ No newline at end of file


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index 32807bf..73d8871 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -239,6 +239,62 @@ fn test_vec2mask_select() {
     );
 }
 
+#[test]
+fn test_vec2mask_and() {
+    assert_eq!(
+        (Vec2Mask::new(false, false) & Vec2Mask::new(false, false)).bitmask(),
+        0b00,
+    );
+    assert_eq!(
+        (Vec2Mask::new(true, true) & Vec2Mask::new(true, false)).bitmask(),
+        0b01,
+    );
+    assert_eq!(
+        (Vec2Mask::new(true, false) & Vec2Mask::new(false, true)).bitmask(),
+        0b00,
+    );
+    assert_eq!(
+        (Vec2Mask::new(true, true) & Vec2Mask::new(true, true)).bitmask(),
+        0b11,
+    );
+
+    let mut mask = Vec2Mask::new(true, true);
+    mask &= Vec2Mask::new(true, false);
+    assert_eq!(mask.bitmask(), 0b01);
+}
+
+#[test]
+fn test_vec2mask_or() {
+    assert_eq!(
+        (Vec2Mask::new(false, false) | Vec2Mask::new(false, false)).bitmask(),
+        0b00,
+    );
+    assert_eq!(
+        (Vec2Mask::new(false, false) | Vec2Mask::new(false, true)).bitmask(),
+        0b10,
+    );
+    assert_eq!(
+        (Vec2Mask::new(true, false) | Vec2Mask::new(false, true)).bitmask(),
+        0b11,
+    );
+    assert_eq!(
+        (Vec2Mask::new(true, true) | Vec2Mask::new(true, true)).bitmask(),
+        0b11,
+    );
+
+    let mut mask = Vec2Mask::new(true, true);
+    mask |= Vec2Mask::new(true, false);
+    assert_eq!(mask.bitmask(), 0b11);
+}
+
+#[test]
+fn test_vec2mask_not() {
+    assert_eq!((!Vec2Mask::new(false, false)).bitmask(), 0b11);
+    assert_eq!((!Vec2Mask::new(true, false)).bitmask(), 0b10);
+    assert_eq!((!Vec2Mask::new(false, true)).bitmask(), 0b01);
+    assert_eq!((!Vec2Mask::new(true, true)).bitmask(), 0b00);
+}
+
 #[cfg(feature = "rand")]
 #[test]
 fn test_vec2_rand() {
diff --git a/tests/vec3.rs b/tests/vec3.rs
index 7baadad..8753be0 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -271,6 +271,86 @@ fn test_vec3mask_select() {
     );
 }
 
+#[test]
+fn test_vec3mask_and() {
+    assert_eq!(
+        (
+            Vec3Mask::new(false, false, false)
+            & Vec3Mask::new(false, false, false)
+        ).bitmask(),
+        0b000,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, true, true)
+            & Vec3Mask::new(true, true, true)
+        ).bitmask(),
+        0b111,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, false, true)
+            & Vec3Mask::new(false, true, false)
+        ).bitmask(),
+        0b000,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, false, true)
+            & Vec3Mask::new(true, true, true)
+        ).bitmask(),
+        0b101,
+    );
+
+    let mut mask = Vec3Mask::new(true, true, false);
+    mask &= Vec3Mask::new(true, false, false);
+    assert_eq!(mask.bitmask(), 0b001);
+}
+
+#[test]
+fn test_vec3mask_or() {
+    assert_eq!(
+        (
+            Vec3Mask::new(false, false, false)
+            | Vec3Mask::new(false, false, false)
+        ).bitmask(),
+        0b000,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, true, true)
+            | Vec3Mask::new(true, true, true)
+        ).bitmask(),
+        0b111,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, false, true)
+            | Vec3Mask::new(false, true, false)
+        ).bitmask(),
+        0b111,
+    );
+    assert_eq!(
+        (
+            Vec3Mask::new(true, false, true)
+            | Vec3Mask::new(true, false, true)
+        ).bitmask(),
+        0b101,
+    );
+
+    let mut mask = Vec3Mask::new(true, true, false);
+    mask |= Vec3Mask::new(true, false, false);
+    assert_eq!(mask.bitmask(), 0b011);
+}
+
+#[test]
+fn test_vec3mask_not() {
+    assert_eq!((!Vec3Mask::new(false, false, false)).bitmask(), 0b111);
+    assert_eq!((!Vec3Mask::new(true, true, true)).bitmask(), 0b000);
+    assert_eq!((!Vec3Mask::new(true, false, true)).bitmask(), 0b010);
+    assert_eq!((!Vec3Mask::new(false, true, false)).bitmask(), 0b101);
+}
+
 #[cfg(feature = "rand")]
 #[test]
 fn test_vec3_rand() {
diff --git a/tests/vec4.rs b/tests/vec4.rs
index 603f3e2..6a7cfbc 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -307,6 +307,86 @@ fn test_vec4mask_select() {
     );
 }
 
+#[test]
+fn test_vec4mask_and() {
+    assert_eq!(
+        (
+            Vec4Mask::new(false, false, false, false)
+            & Vec4Mask::new(false, false, false, false)
+        ).bitmask(),
+        0b0000,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, true, true, true)
+            & Vec4Mask::new(true, true, true, true)
+        ).bitmask(),
+        0b1111,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, false, true, false)
+            & Vec4Mask::new(false, true, false, true)
+        ).bitmask(),
+        0b0000,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, false, true, true)
+            & Vec4Mask::new(true, true, true, false)
+        ).bitmask(),
+        0b0101,
+    );
+
+    let mut mask = Vec4Mask::new(true, true, false, false);
+    mask &= Vec4Mask::new(true, false, true, false);
+    assert_eq!(mask.bitmask(), 0b0001);
+}
+
+#[test]
+fn test_vec4mask_or() {
+    assert_eq!(
+        (
+            Vec4Mask::new(false, false, false, false)
+            | Vec4Mask::new(false, false, false, false)
+        ).bitmask(),
+        0b0000,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, true, true, true)
+            | Vec4Mask::new(true, true, true, true)
+        ).bitmask(),
+        0b1111,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, false, true, false)
+            | Vec4Mask::new(false, true, false, true)
+        ).bitmask(),
+        0b1111,
+    );
+    assert_eq!(
+        (
+            Vec4Mask::new(true, false, true, false)
+            | Vec4Mask::new(true, false, true, false)
+        ).bitmask(),
+        0b0101,
+    );
+
+    let mut mask = Vec4Mask::new(true, true, false, false);
+    mask |= Vec4Mask::new(true, false, true, false);
+    assert_eq!(mask.bitmask(), 0b0111);
+}
+
+#[test]
+fn test_vec4mask_not() {
+    assert_eq!((!Vec4Mask::new(false, false, false, false)).bitmask(), 0b1111);
+    assert_eq!((!Vec4Mask::new(true, true, true, true)).bitmask(), 0b0000);
+    assert_eq!((!Vec4Mask::new(true, false, true, false)).bitmask(), 0b1010);
+    assert_eq!((!Vec4Mask::new(false, true, false, true)).bitmask(), 0b0101);
+}
+
 #[cfg(feature = "serde")]
 #[test]
 fn test_vec4_serde() {