use crate::array::*;
use super::handle::{
ArrayBatchOpHandle, ArrayFetchBatchOpHandle, ArrayFetchOpHandle, ArrayOpHandle,
};
pub trait ElementArithmeticOps:
std::ops::AddAssign
+ std::ops::SubAssign
+ std::ops::MulAssign
+ std::ops::DivAssign
+ std::ops::RemAssign
+ Dist
+ Sized
{
}
#[doc(alias("One-sided", "onesided"))]
pub trait ArithmeticOps<T: Dist + ElementArithmeticOps>: private::LamellarArrayPrivate<T> {
fn add(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Add, self.as_lamellar_byte_array())
}
fn blocking_add(&self, index: usize, val: T) {
self.add(index, val).block();
}
fn add_unmanaged(&self, index: usize, val: T) {
let _ = self.add(index, val).spawn();
}
fn batch_add<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Add,
self.as_lamellar_byte_array(),
)
}
fn fetch_add(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAdd,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_add(&self, index: usize, val: T) -> T {
self.fetch_add(index, val).block()
}
fn batch_fetch_add<'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::FetchAdd,
self.as_lamellar_byte_array(),
)
}
fn sub<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Sub, self.as_lamellar_byte_array())
}
fn blocking_sub(&self, index: usize, val: T) {
self.sub(index, val).block();
}
fn sub_unmanaged(&self, index: usize, val: T) {
let _ = self.sub(index, val).spawn();
}
fn batch_sub<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Sub,
self.as_lamellar_byte_array(),
)
}
fn fetch_sub<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchSub,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_sub(&self, index: usize, val: T) -> T {
self.fetch_sub(index, val).block()
}
fn batch_fetch_sub<'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::FetchSub,
self.as_lamellar_byte_array(),
)
}
fn mul<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Mul, self.as_lamellar_byte_array())
}
fn blocking_mul(&self, index: usize, val: T) {
self.mul(index, val).block();
}
fn mul_unmanaged(&self, index: usize, val: T) {
let _ = self.mul(index, val).spawn();
}
fn batch_mul<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Mul,
self.as_lamellar_byte_array(),
)
}
fn fetch_mul<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchMul,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_mul(&self, index: usize, val: T) -> T {
self.fetch_mul(index, val).block()
}
fn batch_fetch_mul<'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::FetchMul,
self.as_lamellar_byte_array(),
)
}
fn div<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Div, self.as_lamellar_byte_array())
}
fn blocking_div(&self, index: usize, val: T) {
self.div(index, val).block();
}
fn div_unmanaged(&self, index: usize, val: T) {
let _ = self.div(index, val).spawn();
}
fn batch_div<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Div,
self.as_lamellar_byte_array(),
)
}
fn fetch_div<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchDiv,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_div(&self, index: usize, val: T) -> T {
self.fetch_div(index, val).block()
}
fn batch_fetch_div<'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::FetchDiv,
self.as_lamellar_byte_array(),
)
}
fn rem<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Rem, self.as_lamellar_byte_array())
}
fn blocking_rem(&self, index: usize, val: T) {
self.rem(index, val).block();
}
fn rem_unmanaged(&self, index: usize, val: T) {
let _ = self.rem(index, val).spawn();
}
fn batch_rem<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Rem,
self.as_lamellar_byte_array(),
)
}
fn fetch_rem<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchRem,
self.as_lamellar_byte_array(),
)
.into()
}
fn blocking_fetch_rem(&self, index: usize, val: T) -> T {
self.fetch_rem(index, val).block()
}
fn batch_fetch_rem<'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::FetchRem,
self.as_lamellar_byte_array(),
)
}
}
#[doc(alias("One-sided", "onesided"))]
pub trait UnsafeArithmeticOps<T: Dist + ElementArithmeticOps>:
private::LamellarArrayPrivate<T>
{
unsafe fn add(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Add, self.as_lamellar_byte_array())
}
unsafe fn blocking_add(&self, index: usize, val: T) {
self.add(index, val).block();
}
unsafe fn add_unmanaged(&self, index: usize, val: T) {
let _ = self.add(index, val).spawn();
}
unsafe fn batch_add<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Add,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_add(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchAdd,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_add(&self, index: usize, val: T) -> T {
self.fetch_add(index, val).block()
}
unsafe fn batch_fetch_add<'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::FetchAdd,
self.as_lamellar_byte_array(),
)
}
unsafe fn sub<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Sub, self.as_lamellar_byte_array())
}
unsafe fn blocking_sub(&self, index: usize, val: T) {
self.sub(index, val).block();
}
unsafe fn sub_unmanaged(&self, index: usize, val: T) {
let _ = self.sub(index, val).spawn();
}
unsafe fn batch_sub<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Sub,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_sub<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchSub,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_sub(&self, index: usize, val: T) -> T {
self.fetch_sub(index, val).block()
}
unsafe fn batch_fetch_sub<'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::FetchSub,
self.as_lamellar_byte_array(),
)
}
unsafe fn mul<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Mul, self.as_lamellar_byte_array())
}
unsafe fn blocking_mul(&self, index: usize, val: T) {
self.mul(index, val).block();
}
unsafe fn mul_unmanaged(&self, index: usize, val: T) {
let _ = self.mul(index, val).spawn();
}
unsafe fn batch_mul<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Mul,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_mul<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchMul,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_mul(&self, index: usize, val: T) -> T {
self.fetch_mul(index, val).block()
}
unsafe fn batch_fetch_mul<'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::FetchMul,
self.as_lamellar_byte_array(),
)
}
unsafe fn div<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Div, self.as_lamellar_byte_array())
}
unsafe fn blocking_div(&self, index: usize, val: T) {
self.div(index, val).block();
}
unsafe fn div_unmanaged(&self, index: usize, val: T) {
let _ = self.div(index, val).spawn();
}
unsafe fn batch_div<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Div,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_div<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchDiv,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_div(&self, index: usize, val: T) -> T {
self.fetch_div(index, val).block()
}
unsafe fn batch_fetch_div<'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::FetchDiv,
self.as_lamellar_byte_array(),
)
}
unsafe fn rem<'a>(&self, index: usize, val: T) -> ArrayOpHandle<T> {
self.inner_array()
.initiate_op(val, index, ArrayOpCmd::Rem, self.as_lamellar_byte_array())
}
unsafe fn blocking_rem(&self, index: usize, val: T) {
self.rem(index, val).block();
}
unsafe fn rem_unmanaged(&self, index: usize, val: T) {
let _ = self.rem(index, val).spawn();
}
unsafe fn batch_rem<'a>(
&self,
index: impl OpInput<'a, usize>,
val: impl OpInput<'a, T>,
) -> ArrayBatchOpHandle {
self.inner_array().initiate_batch_op(
val,
index,
ArrayOpCmd::Rem,
self.as_lamellar_byte_array(),
)
}
unsafe fn fetch_rem<'a>(&self, index: usize, val: T) -> ArrayFetchOpHandle<T> {
self.inner_array()
.initiate_batch_fetch_op_2(
val,
index,
ArrayOpCmd::FetchRem,
self.as_lamellar_byte_array(),
)
.into()
}
unsafe fn blocking_fetch_rem(&self, index: usize, val: T) -> T {
self.fetch_rem(index, val).block()
}
unsafe fn batch_fetch_rem<'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::FetchRem,
self.as_lamellar_byte_array(),
)
}
}
#[doc(hidden)]
pub trait LocalArithmeticOps<T: Dist + ElementArithmeticOps> {
fn local_add(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_add(idx_vals, false);
}
fn local_fetch_add(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_sub(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_sub(idx_vals, false);
}
fn local_fetch_sub(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_mul(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_mul(idx_vals, false);
}
fn local_fetch_mul(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_div(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_div(idx_vals, false);
}
fn local_fetch_div(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
fn local_rem(&mut self, idx_vals: impl Iterator<Item = (usize, T)>) {
self.local_fetch_rem(idx_vals, false);
}
fn local_fetch_rem(
&mut self,
idx_vals: impl Iterator<Item = (usize, T)>,
fetch: bool,
) -> Option<Vec<T>>;
}
impl<T: Dist + ElementArithmeticOps> LocalArithmeticOps<T> for __LamellarMutLocalData<'_, T> {
local_ops_fn!(local_fetch_add, Option<Vec<T>>, idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_sub, Option<Vec<T>>, idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_mul, Option<Vec<T>>, idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_div, Option<Vec<T>>, idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
local_ops_fn!(local_fetch_rem, Option<Vec<T>>, idx_vals: impl Iterator<Item = (usize, T)>,fetch: bool);
}
impl<T: Dist + ElementArithmeticOps> LocalArithmeticOps<T> for &mut [T] {
fn local_fetch_add(
&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_sub(
&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_mul(
&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_div(
&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_rem(
&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
}
}
}