use crate::{Vec2, Vec3, Vec4};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BVec2 {
pub x: bool,
pub y: bool,
}
impl BVec2 {
pub const FALSE: BVec2 = BVec2 { x: false, y: false };
pub const TRUE: BVec2 = BVec2 { x: true, y: true };
#[inline(always)]
pub const fn new(x: bool, y: bool) -> Self {
Self { x, y }
}
#[inline(always)]
pub const fn splat(v: bool) -> Self {
Self { x: v, y: v }
}
#[inline(always)]
pub fn all(self) -> bool {
self.x && self.y
}
#[inline(always)]
pub fn any(self) -> bool {
self.x || self.y
}
#[inline(always)]
pub fn none(self) -> bool {
!self.x && !self.y
}
#[inline(always)]
pub fn and(self, other: Self) -> Self {
Self { x: self.x && other.x, y: self.y && other.y }
}
#[inline(always)]
pub fn or(self, other: Self) -> Self {
Self { x: self.x || other.x, y: self.y || other.y }
}
#[inline(always)]
pub fn xor(self, other: Self) -> Self {
Self { x: self.x ^ other.x, y: self.y ^ other.y }
}
#[inline(always)]
pub fn select(self, a: Vec2, b: Vec2) -> Vec2 {
Vec2::new(
if self.x { a.x } else { b.x },
if self.y { a.y } else { b.y },
)
}
}
impl std::ops::Not for BVec2 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self { x: !self.x, y: !self.y }
}
}
impl std::ops::BitAnd for BVec2 {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
self.and(other)
}
}
impl std::ops::BitOr for BVec2 {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
self.or(other)
}
}
impl std::ops::BitXor for BVec2 {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.xor(other)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BVec3 {
pub x: bool,
pub y: bool,
pub z: bool,
}
impl BVec3 {
pub const FALSE: BVec3 = BVec3 { x: false, y: false, z: false };
pub const TRUE: BVec3 = BVec3 { x: true, y: true, z: true };
#[inline(always)]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
Self { x, y, z }
}
#[inline(always)]
pub const fn splat(v: bool) -> Self {
Self { x: v, y: v, z: v }
}
#[inline(always)]
pub fn all(self) -> bool {
self.x && self.y && self.z
}
#[inline(always)]
pub fn any(self) -> bool {
self.x || self.y || self.z
}
#[inline(always)]
pub fn none(self) -> bool {
!self.x && !self.y && !self.z
}
#[inline(always)]
pub fn and(self, other: Self) -> Self {
Self {
x: self.x && other.x,
y: self.y && other.y,
z: self.z && other.z,
}
}
#[inline(always)]
pub fn or(self, other: Self) -> Self {
Self {
x: self.x || other.x,
y: self.y || other.y,
z: self.z || other.z,
}
}
#[inline(always)]
pub fn xor(self, other: Self) -> Self {
Self {
x: self.x ^ other.x,
y: self.y ^ other.y,
z: self.z ^ other.z,
}
}
#[inline(always)]
pub fn select(self, a: Vec3, b: Vec3) -> Vec3 {
Vec3::new(
if self.x { a.x } else { b.x },
if self.y { a.y } else { b.y },
if self.z { a.z } else { b.z },
)
}
}
impl std::ops::Not for BVec3 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self { x: !self.x, y: !self.y, z: !self.z }
}
}
impl std::ops::BitAnd for BVec3 {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
self.and(other)
}
}
impl std::ops::BitOr for BVec3 {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
self.or(other)
}
}
impl std::ops::BitXor for BVec3 {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.xor(other)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BVec4 {
pub x: bool,
pub y: bool,
pub z: bool,
pub w: bool,
}
impl BVec4 {
pub const FALSE: BVec4 = BVec4 { x: false, y: false, z: false, w: false };
pub const TRUE: BVec4 = BVec4 { x: true, y: true, z: true, w: true };
#[inline(always)]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
Self { x, y, z, w }
}
#[inline(always)]
pub const fn splat(v: bool) -> Self {
Self { x: v, y: v, z: v, w: v }
}
#[inline(always)]
pub fn all(self) -> bool {
self.x && self.y && self.z && self.w
}
#[inline(always)]
pub fn any(self) -> bool {
self.x || self.y || self.z || self.w
}
#[inline(always)]
pub fn none(self) -> bool {
!self.x && !self.y && !self.z && !self.w
}
#[inline(always)]
pub fn and(self, other: Self) -> Self {
Self {
x: self.x && other.x,
y: self.y && other.y,
z: self.z && other.z,
w: self.w && other.w,
}
}
#[inline(always)]
pub fn or(self, other: Self) -> Self {
Self {
x: self.x || other.x,
y: self.y || other.y,
z: self.z || other.z,
w: self.w || other.w,
}
}
#[inline(always)]
pub fn xor(self, other: Self) -> Self {
Self {
x: self.x ^ other.x,
y: self.y ^ other.y,
z: self.z ^ other.z,
w: self.w ^ other.w,
}
}
#[inline(always)]
pub fn select(self, a: Vec4, b: Vec4) -> Vec4 {
Vec4::new(
if self.x { a.x } else { b.x },
if self.y { a.y } else { b.y },
if self.z { a.z } else { b.z },
if self.w { a.w } else { b.w },
)
}
}
impl std::ops::Not for BVec4 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self { x: !self.x, y: !self.y, z: !self.z, w: !self.w }
}
}
impl std::ops::BitAnd for BVec4 {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
self.and(other)
}
}
impl std::ops::BitOr for BVec4 {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
self.or(other)
}
}
impl std::ops::BitXor for BVec4 {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.xor(other)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bvec2_all_any() {
assert!(BVec2::TRUE.all());
assert!(!BVec2::FALSE.all());
assert!(BVec2::new(true, false).any());
assert!(!BVec2::FALSE.any());
}
#[test]
fn test_bvec3_select() {
let mask = BVec3::new(true, false, true);
let a = Vec3::new(1.0, 2.0, 3.0);
let b = Vec3::new(4.0, 5.0, 6.0);
let result = mask.select(a, b);
assert_eq!(result.x, 1.0);
assert_eq!(result.y, 5.0);
assert_eq!(result.z, 3.0);
}
#[test]
fn test_bvec4_bitops() {
let a = BVec4::new(true, false, true, false);
let b = BVec4::new(true, true, false, false);
assert_eq!(a & b, BVec4::new(true, false, false, false));
assert_eq!(a | b, BVec4::new(true, true, true, false));
assert_eq!(a ^ b, BVec4::new(false, true, true, false));
}
}