use super::{
common_types::ConstUnionHack128bit,
macros::*,
num_traits::{Bool, Num},
u32x4,
};
#[cfg(not(feature = "scalar-math"))]
use super::{f32x4, i32x4};
use auto_ops_det::impl_op_ex;
#[cfg(not(target_arch = "spirv"))]
use core::fmt;
use core::ops;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "scalar-math")]
type Inner = [u32; 4];
#[cfg(not(feature = "scalar-math"))]
type Inner = crate::wide::u32x4;
#[allow(non_camel_case_types)]
#[cfg_attr(
all(
feature = "std",
not(feature = "libm_force"),
not(feature = "scalar-math")
),
repr(transparent)
)]
#[cfg_attr(
any(
feature = "libm_force",
feature = "scalar-math",
all(feature = "libm_fallback", not(feature = "std"))
),
repr(align(16))
)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct bool32x4(pub(crate) Inner);
#[cfg(not(feature = "scalar-math"))]
impl_type_cast_methods!(bool32x4, f32x4, cast_f32x4, cast_bool32x4);
#[cfg(not(feature = "scalar-math"))]
impl_type_cast_methods!(bool32x4, i32x4, cast_i32x4, cast_bool32x4);
impl_type_cast_methods!(bool32x4, u32x4, cast_u32x4, cast_bool32x4);
#[cfg(feature = "scalar-math")]
impl bool32x4 {
#[inline]
fn zip_map(self, rhs: Self, f: impl Fn(bool, bool) -> bool) -> Self {
let arr: [bool; 4] = self.into();
let rhs: [bool; 4] = rhs.into();
Self::from([
f(arr[0], rhs[0]),
f(arr[1], rhs[1]),
f(arr[2], rhs[2]),
f(arr[3], rhs[3]),
])
}
}
impl Default for bool32x4 {
fn default() -> Self {
bool32x4::from([false; 4])
}
}
impl From<[bool; 4]> for bool32x4 {
#[inline]
fn from(vals: [bool; 4]) -> Self {
let bits = [0u32, u32::MAX];
bool32x4(add_into!([
bits[vals[0] as usize],
bits[vals[1] as usize],
bits[vals[2] as usize],
bits[vals[3] as usize],
]))
}
}
impl From<bool32x4> for [bool; 4] {
#[inline]
fn from(val: bool32x4) -> Self {
let a: &[u32; 4] = as_array_ref!(val.0);
[a[0] != 0u32, a[1] != 0u32, a[2] != 0u32, a[3] != 0u32]
}
}
impl Num for bool32x4 {
type Element = bool;
type Bool = Self;
#[inline]
fn lanes() -> usize {
4
}
#[inline]
fn splat(val: bool) -> Self {
let results = [bool32x4::FALSE, bool32x4::TRUE];
results[val as usize]
}
#[inline]
fn extract(&self, i: usize) -> Self::Element {
as_array_ref!(self.0)[i] != 0u32
}
#[inline]
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
*as_array_ref!(self.0).get_unchecked(i) != 0u32
}
#[inline]
fn replace(&mut self, i: usize, val: Self::Element) {
let vals = [0u32, u32::MAX];
let arr = as_array_mut!(self.0);
arr[i] = vals[val as usize];
}
#[inline]
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
let vals = [0u32, u32::MAX];
let arr = as_array_mut!(self.0);
*arr.get_unchecked_mut(i) = vals[val as usize];
}
#[inline]
fn select(self, cond: Self::Bool, other: Self) -> Self {
#[cfg(feature = "scalar-math")]
{
let mut arr = [0_u32; 4];
for (i, xi) in arr.iter_mut().enumerate() {
*xi = if cond.0[i] == u32::MAX {
self.0[i]
} else {
other.0[i]
};
}
Self(arr)
}
#[cfg(not(feature = "scalar-math"))]
{
bool32x4(cond.0.blend(self.0, other.0))
}
}
}
impl_wide_partial_eq!(bool32x4);
impl_wide_bit_ops!(bool32x4);
impl Bool for bool32x4 {
#[cfg(feature = "scalar-math")]
const FALSE: bool32x4 = bool32x4([0_u32; 4]);
#[cfg(feature = "scalar-math")]
const TRUE: bool32x4 = bool32x4([u32::MAX; 4]);
#[cfg(not(feature = "scalar-math"))]
const FALSE: bool32x4 = bool32x4(crate::wide::u32x4::ZERO);
#[cfg(not(feature = "scalar-math"))]
const TRUE: bool32x4 = bool32x4(crate::wide::u32x4::MAX);
#[inline]
fn bitmask(self) -> u64 {
let arr = as_array_ref!(self.0);
((arr[0] != 0u32) as u64)
| (((arr[1] != 0u32) as u64) << 1)
| (((arr[2] != 0u32) as u64) << 2)
| (((arr[3] != 0u32) as u64) << 3)
}
#[inline]
fn all(self) -> bool {
self == bool32x4::TRUE
}
#[inline]
fn any(self) -> bool {
self != bool32x4::FALSE
}
#[inline]
fn none(self) -> bool {
self == bool32x4::FALSE
}
}
#[cfg(not(target_arch = "spirv"))]
impl fmt::Display for bool32x4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr: [bool; 4] = (*self).into();
write!(f, "{:?}", arr)
}
}