use crate::array::*;
use super::handle::{
ArrayBatchOpHandle, ArrayFetchBatchOpHandle, ArrayFetchOpHandle, ArrayOpHandle,
};
pub trait ElementBitWiseOps:
std::ops::BitAndAssign + std::ops::BitOrAssign + std::ops::BitXorAssign + Dist + Sized
{
}
#[doc(alias("One-sided", "onesided"))]
pub trait BitWiseOps<T: ElementBitWiseOps>: private::LamellarArrayPrivate<T> {
fn bit_and<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::And, self.as_lamellar_byte_array())
}
fn blocking_bit_and(&self, index: usize, val: T) {
self.bit_and(index, val).block();
}
fn bit_and_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_and(index, val).spawn();
}
fn batch_bit_and<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::And,
self.as_lamellar_byte_array(),
)
}
fn fetch_bit_and<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAnd,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_bit_and(&self, index: usize, val: T) -> T {
self.fetch_bit_and(index, val).block()
}
fn batch_fetch_bit_and<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAnd,
self.as_lamellar_byte_array(),
)
}
fn bit_or<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Or, self.as_lamellar_byte_array())
}
fn blocking_bit_or(&self, index: usize, val: T) {
self.bit_or(index, val).block();
}
fn bit_or_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_or(index, val).spawn();
}
fn batch_bit_or<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Or,
self.as_lamellar_byte_array(),
)
}
fn fetch_bit_or<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchOr,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_bit_or(&self, index: usize, val: T) -> T {
self.fetch_bit_or(index, val).block()
}
fn batch_fetch_bit_or<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchOr,
self.as_lamellar_byte_array(),
)
}
fn bit_xor<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Xor, self.as_lamellar_byte_array())
}
fn blocking_bit_xor(&self, index: usize, val: T) {
self.bit_xor(index, val).block();
}
fn bit_xor_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_xor(index, val).spawn();
}
fn batch_bit_xor<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Xor,
self.as_lamellar_byte_array(),
)
}
fn fetch_bit_xor<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchXor,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_bit_xor(&self, index: usize, val: T) -> T {
self.fetch_bit_xor(index, val).block()
}
fn batch_fetch_bit_xor<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchXor,
self.as_lamellar_byte_array(),
)
}
}
#[doc(alias("One-sided", "onesided"))]
pub trait UnsafeBitWiseOps<T: ElementBitWiseOps>: private::LamellarArrayPrivate<T> {
unsafe fn bit_and<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::And, self.as_lamellar_byte_array())
}
unsafe fn blocking_bit_and(&self, index: usize, val: T) {
self.bit_and(index, val).block();
}
unsafe fn bit_and_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_and(index, val).spawn();
}
unsafe fn batch_bit_and<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::And,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_bit_and<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAnd,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_bit_and(&self, index: usize, val: T) -> T {
self.fetch_bit_and(index, val).block()
}
unsafe fn batch_fetch_bit_and<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAnd,
self.as_lamellar_byte_array(),
)
}
unsafe fn bit_or<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Or, self.as_lamellar_byte_array())
}
unsafe fn blocking_bit_or(&self, index: usize, val: T) {
self.bit_or(index, val).block();
}
unsafe fn bit_or_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_or(index, val).spawn();
}
unsafe fn batch_bit_or<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Or,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_bit_or<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchOr,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_bit_or(&self, index: usize, val: T) -> T {
self.fetch_bit_or(index, val).block()
}
unsafe fn batch_fetch_bit_or<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchOr,
self.as_lamellar_byte_array(),
)
}
unsafe fn bit_xor<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Xor, self.as_lamellar_byte_array())
}
unsafe fn blocking_bit_xor(&self, index: usize, val: T) {
self.bit_xor(index, val).block();
}
unsafe fn bit_xor_unmanaged(&self, index: usize, val: T) {
let _ = self.bit_xor(index, val).spawn();
}
unsafe fn batch_bit_xor<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Xor,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_bit_xor<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchXor,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_bit_xor(&self, index: usize, val: T) -> T {
self.fetch_bit_xor(index, val).block()
}
unsafe fn batch_fetch_bit_xor<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayFetchBatchOpHandle<T> {
self.inner_array().initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchXor,
self.as_lamellar_byte_array(),
)
}
}
#[doc(hidden)]
pub trait LocalBitWiseOps<T: Dist + ElementBitWiseOps> {
fn local_bit_and(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_bit_and(idx_vals, false);
}
fn local_fetch_bit_and(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_bit_or(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_bit_or(idx_vals, false);
}
fn local_fetch_bit_or(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_bit_xor(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_bit_xor(idx_vals, false);
}
fn local_fetch_bit_xor(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
}
impl<T: Dist + ElementBitWiseOps> LocalBitWiseOps<T> for __LamellarMutLocalData<'_, T> {
local_ops_fn!(local_fetch_bit_and, Option<Vec<T>>,idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_bit_or, Option<Vec<T>>,idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_bit_xor, Option<Vec<T>>,idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
}
impl<T: Dist + ElementBitWiseOps> LocalBitWiseOps<T> for &mut [T] {
fn local_fetch_bit_and(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>> {
if fetch {
Some(
idx_vals
.map(|(i, val)| {
let old = self[i];
self[i] &= val;
old
})
.collect(),
)
} else {
idx_vals.for_each(|(i, val)| {
self[i] &= val;
});
None
}
}
fn local_fetch_bit_or(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>> {
if fetch {
Some(
idx_vals
.map(|(i, val)| {
let old = self[i];
self[i] |= val;
old
})
.collect(),
)
} else {
idx_vals.for_each(|(i, val)| {
self[i] |= val;
});
None
}
}
fn local_fetch_bit_xor(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>> {
if fetch {
Some(
idx_vals
.map(|(i, val)| {
let old = self[i];
self[i] ^= val;
old
})
.collect(),
)
} else {
idx_vals.for_each(|(i, val)| {
self[i] ^= val;
});
None
}
}
}