blob: 5bad4f474b16b75dba53a67bf8049c90a6ff6d73 [file] [log] [blame]
//! Implements portable horizontal bitwise vector reductions.
#![allow(unused)]
macro_rules! impl_reduction_bitwise {
(
[$elem_ty:ident; $elem_count:expr]:
$id:ident | $ielem_ty:ident | $test_tt:tt |
($convert:expr) |
($true:expr, $false:expr)
) => {
impl $id {
/// Lane-wise bitwise `and` of the vector elements.
///
/// Note: if the vector has one lane, the first element of the
/// vector is returned.
#[inline]
pub fn and(self) -> $elem_ty {
#[cfg(not(target_arch = "aarch64"))]
{
use crate::llvm::simd_reduce_and;
let r: $ielem_ty = unsafe { simd_reduce_and(self.0) };
$convert(r)
}
#[cfg(target_arch = "aarch64")]
{
// FIXME: broken on aarch64
// https://github.com/rust-lang-nursery/packed_simd/issues/15
let mut x = self.extract(0) as $elem_ty;
for i in 1..$id::lanes() {
x &= self.extract(i) as $elem_ty;
}
x
}
}
/// Lane-wise bitwise `or` of the vector elements.
///
/// Note: if the vector has one lane, the first element of the
/// vector is returned.
#[inline]
pub fn or(self) -> $elem_ty {
#[cfg(not(target_arch = "aarch64"))]
{
use crate::llvm::simd_reduce_or;
let r: $ielem_ty = unsafe { simd_reduce_or(self.0) };
$convert(r)
}
#[cfg(target_arch = "aarch64")]
{
// FIXME: broken on aarch64
// https://github.com/rust-lang-nursery/packed_simd/issues/15
let mut x = self.extract(0) as $elem_ty;
for i in 1..$id::lanes() {
x |= self.extract(i) as $elem_ty;
}
x
}
}
/// Lane-wise bitwise `xor` of the vector elements.
///
/// Note: if the vector has one lane, the first element of the
/// vector is returned.
#[inline]
pub fn xor(self) -> $elem_ty {
#[cfg(not(target_arch = "aarch64"))]
{
use crate::llvm::simd_reduce_xor;
let r: $ielem_ty = unsafe { simd_reduce_xor(self.0) };
$convert(r)
}
#[cfg(target_arch = "aarch64")]
{
// FIXME: broken on aarch64
// https://github.com/rust-lang-nursery/packed_simd/issues/15
let mut x = self.extract(0) as $elem_ty;
for i in 1..$id::lanes() {
x ^= self.extract(i) as $elem_ty;
}
x
}
}
}
test_if!{
$test_tt:
paste::item! {
pub mod [<$id _reduction_bitwise>] {
use super::*;
#[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn and() {
let v = $id::splat($false);
assert_eq!(v.and(), $false);
let v = $id::splat($true);
assert_eq!(v.and(), $true);
let v = $id::splat($false);
let v = v.replace(0, $true);
if $id::lanes() > 1 {
assert_eq!(v.and(), $false);
} else {
assert_eq!(v.and(), $true);
}
let v = $id::splat($true);
let v = v.replace(0, $false);
assert_eq!(v.and(), $false);
}
#[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn or() {
let v = $id::splat($false);
assert_eq!(v.or(), $false);
let v = $id::splat($true);
assert_eq!(v.or(), $true);
let v = $id::splat($false);
let v = v.replace(0, $true);
assert_eq!(v.or(), $true);
let v = $id::splat($true);
let v = v.replace(0, $false);
if $id::lanes() > 1 {
assert_eq!(v.or(), $true);
} else {
assert_eq!(v.or(), $false);
}
}
#[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn xor() {
let v = $id::splat($false);
assert_eq!(v.xor(), $false);
let v = $id::splat($true);
if $id::lanes() > 1 {
assert_eq!(v.xor(), $false);
} else {
assert_eq!(v.xor(), $true);
}
let v = $id::splat($false);
let v = v.replace(0, $true);
assert_eq!(v.xor(), $true);
let v = $id::splat($true);
let v = v.replace(0, $false);
if $id::lanes() > 1 {
assert_eq!(v.xor(), $true);
} else {
assert_eq!(v.xor(), $false);
}
}
}
}
}
};
}