use crate::array::*;
use super::handle::{
ArrayBatchOpHandle, ArrayFetchBatchOpHandle, ArrayFetchOpHandle, ArrayOpHandle,
};
pub trait ElementShiftOps: std::ops::ShlAssign + std::ops::ShrAssign + Dist + Sized {}
#[doc(alias("One-sided", "onesided"))]
pub trait ShiftOps<T: ElementShiftOps>: private::LamellarArrayPrivate<T> {
fn shl(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Shl, self.as_lamellar_byte_array())
}
fn batch_shl<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Shl,
self.as_lamellar_byte_array(),
)
}
fn fetch_shl(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchShl,
self.as_lamellar_byte_array(),
)
.into()
}
fn batch_fetch_shl<'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::FetchShl,
self.as_lamellar_byte_array(),
)
}
fn shr<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Shr, self.as_lamellar_byte_array())
}
fn batch_shr<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Shr,
self.as_lamellar_byte_array(),
)
}
fn fetch_shr<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchShr,
self.as_lamellar_byte_array(),
)
.into()
}
fn batch_fetch_shr<'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::FetchShr,
self.as_lamellar_byte_array(),
)
}
}
#[doc(alias("One-sided", "onesided"))]
pub trait UnsafeShiftOps<T: ElementShiftOps>: private::LamellarArrayPrivate<T> {
unsafe fn shl(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Shl, self.as_lamellar_byte_array())
}
unsafe fn batch_shl<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Shl,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_shl(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchShl,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn batch_fetch_shl<'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::FetchShl,
self.as_lamellar_byte_array(),
)
}
unsafe fn shr<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Shr, self.as_lamellar_byte_array())
}
unsafe fn batch_shr<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Shr,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_shr<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchShr,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn batch_fetch_shr<'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::FetchShr,
self.as_lamellar_byte_array(),
)
}
}
#[doc(hidden)]
pub trait LocalShiftOps<T: Dist + ElementShiftOps> {
fn local_shl(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_shl(idx_vals, false);
}
fn local_fetch_shl(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_shr(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_shr(idx_vals, false);
}
fn local_fetch_shr(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
}
impl<T: Dist + ElementShiftOps> LocalShiftOps<T> for __LamellarMutLocalData<'_, T> {
local_ops_fn!(local_fetch_shl,Option<Vec<T>>,idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_shr,Option<Vec<T>>,idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
}
impl<T: Dist + ElementShiftOps> LocalShiftOps<T> for &mut [T] {
fn local_fetch_shl(
&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_shr(
&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
}
}
}