RMath: implement Bool4 type.

This commit is contained in:
Nathan Vegdahl 2022-07-15 15:20:44 -07:00
parent fa7be4e58c
commit 5535775006

View File

@ -1,12 +1,14 @@
use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
use std::ops::{
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, SubAssign,
};
use approx::ulps_eq;
use crate::{difference_of_products, two_prod, two_sum};
pub use fallback::Float4;
pub use fallback::{Bool4, Float4};
mod fallback {
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
use crate::FMulAdd;
@ -78,6 +80,64 @@ mod fallback {
// a.max(b)
// }
//-----------------------------------------------------
// Comparisons.
/// Less than.
#[inline(always)]
pub fn lt(self, rhs: Self) -> Bool4 {
Bool4([
self.0[0] < rhs.0[0],
self.0[1] < rhs.0[1],
self.0[2] < rhs.0[2],
self.0[3] < rhs.0[3],
])
}
/// Less than or equal.
#[inline(always)]
pub fn lte(self, rhs: Self) -> Bool4 {
Bool4([
self.0[0] <= rhs.0[0],
self.0[1] <= rhs.0[1],
self.0[2] <= rhs.0[2],
self.0[3] <= rhs.0[3],
])
}
/// Greater than.
#[inline(always)]
pub fn gt(self, rhs: Self) -> Bool4 {
Bool4([
self.0[0] > rhs.0[0],
self.0[1] > rhs.0[1],
self.0[2] > rhs.0[2],
self.0[3] > rhs.0[3],
])
}
/// Greater than or equal.
#[inline(always)]
pub fn gte(self, rhs: Self) -> Bool4 {
Bool4([
self.0[0] >= rhs.0[0],
self.0[1] >= rhs.0[1],
self.0[2] >= rhs.0[2],
self.0[3] >= rhs.0[3],
])
}
/// Equal.
#[inline(always)]
pub fn eq(self, rhs: Self) -> Bool4 {
Bool4([
self.0[0] == rhs.0[0],
self.0[1] == rhs.0[1],
self.0[2] == rhs.0[2],
self.0[3] == rhs.0[3],
])
}
//-----------------------------------------------------
// Individual components.
@ -265,14 +325,87 @@ mod fallback {
}
impl FMulAdd for Float4 {
#[inline(always)]
fn fma(self, b: Self, c: Self) -> Self {
self.mul_add(b, c)
}
}
//---------------------------------------------------------
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Bool4([bool; 4]);
impl Bool4 {
#[inline(always)]
pub fn to_bools(self) -> [bool; 4] {
self.0
}
#[inline(always)]
pub fn to_bitmask(self) -> u8 {
self.0[0] as u8
| ((self.0[1] as u8) << 1)
| ((self.0[2] as u8) << 2)
| ((self.0[3] as u8) << 3)
}
}
impl BitAnd for Bool4 {
type Output = Self;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self {
Self([
self.0[0] & rhs.0[0],
self.0[1] & rhs.0[1],
self.0[2] & rhs.0[2],
self.0[3] & rhs.0[3],
])
}
}
impl BitOr for Bool4 {
type Output = Self;
#[inline(always)]
fn bitor(self, rhs: Self) -> Self {
Self([
self.0[0] | rhs.0[0],
self.0[1] | rhs.0[1],
self.0[2] | rhs.0[2],
self.0[3] | rhs.0[3],
])
}
}
impl BitXor for Bool4 {
type Output = Self;
#[inline(always)]
fn bitxor(self, rhs: Self) -> Self {
Self([
self.0[0] ^ rhs.0[0],
self.0[1] ^ rhs.0[1],
self.0[2] ^ rhs.0[2],
self.0[3] ^ rhs.0[3],
])
}
}
impl Not for Bool4 {
type Output = Self;
#[inline(always)]
fn not(self) -> Self {
Self([!self.0[0], !self.0[1], !self.0[2], !self.0[3]])
}
}
}
//-------------------------------------------------------------
// Float4 impls that don't depend on its inner representation.
// Impls that don't depend on inner representation.
impl Float4 {
/// 3D dot product (only uses the first 3 components).
@ -562,3 +695,24 @@ impl DivAssign<f32> for Float4 {
*self = *self / rhs;
}
}
impl BitAndAssign for Bool4 {
#[inline(always)]
fn bitand_assign(&mut self, rhs: Self) {
*self = *self & rhs;
}
}
impl BitOrAssign for Bool4 {
#[inline(always)]
fn bitor_assign(&mut self, rhs: Self) {
*self = *self | rhs;
}
}
impl BitXorAssign for Bool4 {
#[inline(always)]
fn bitxor_assign(&mut self, rhs: Self) {
*self = *self ^ rhs;
}
}