use std::ops::{Index, IndexMut};
#[cfg(feature = "par-internals")]
use rayon::prelude::*;
use crate::cmap::{LinkError, NULL_DART_ID};
use crate::stm::{TVar, Transaction, TransactionClosureResult, abort};
use super::identifiers::DartIdType;
pub struct BetaFunctions<const N: usize>(Vec<[TVar<DartIdType>; N]>);
#[allow(unused)]
impl<const N: usize> BetaFunctions<N> {
#[cfg(not(feature = "par-internals"))]
pub fn new(n_darts: usize) -> Self {
Self(
(0..n_darts)
.map(|_| std::array::from_fn(|_| TVar::new(NULL_DART_ID)))
.collect(),
)
}
#[cfg(feature = "par-internals")]
pub fn new(n_darts: usize) -> Self {
Self(
(0..n_darts)
.into_par_iter()
.map(|_| std::array::from_fn(|_| TVar::new(NULL_DART_ID)))
.collect(),
)
}
#[cfg(not(feature = "par-internals"))]
pub fn extend(&mut self, len: usize) {
self.0
.extend((0..len).map(|_| std::array::from_fn(|_| TVar::new(NULL_DART_ID))));
}
#[cfg(feature = "par-internals")]
pub fn extend(&mut self, len: usize) {
self.0.par_extend(
(0..len)
.into_par_iter()
.map(|_| std::array::from_fn(|_| TVar::new(NULL_DART_ID))),
);
}
pub fn capacity(&self) -> usize {
self.0.capacity()
}
}
impl<const N: usize> Index<(u8, DartIdType)> for BetaFunctions<N> {
type Output = TVar<DartIdType>;
fn index(&self, (beta_id, dart_id): (u8, DartIdType)) -> &Self::Output {
&self.0[dart_id as usize][beta_id as usize]
}
}
impl<const N: usize> IndexMut<(u8, DartIdType)> for BetaFunctions<N> {
fn index_mut(&mut self, (beta_id, dart_id): (u8, DartIdType)) -> &mut Self::Output {
&mut self.0[dart_id as usize][beta_id as usize]
}
}
impl<const N: usize> BetaFunctions<N> {
pub fn one_link_core(
&self,
t: &mut Transaction,
ld: DartIdType,
rd: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let b1ld = self[(1, ld)].exchange(t, rd)?;
let b0rd = self[(0, rd)].exchange(t, ld)?;
if b1ld != NULL_DART_ID {
return abort(LinkError::NonFreeBase(1, ld, rd));
}
if b0rd != NULL_DART_ID {
return abort(LinkError::NonFreeImage(0, ld, rd));
}
Ok(())
}
pub fn two_link_core(
&self,
t: &mut Transaction,
ld: DartIdType,
rd: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let b2ld = self[(2, ld)].exchange(t, rd)?;
let b2rd = self[(2, rd)].exchange(t, ld)?;
if b2ld != NULL_DART_ID {
return abort(LinkError::NonFreeBase(2, ld, rd));
}
if b2rd != NULL_DART_ID {
return abort(LinkError::NonFreeImage(2, ld, rd));
}
Ok(())
}
pub fn three_link_core(
&self,
t: &mut Transaction,
ld: DartIdType,
rd: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let b3ld = self[(3, ld)].exchange(t, rd)?;
let b3rd = self[(3, rd)].exchange(t, ld)?;
if b3ld != NULL_DART_ID {
return abort(LinkError::NonFreeBase(3, ld, rd));
}
if b3rd != NULL_DART_ID {
return abort(LinkError::NonFreeImage(3, ld, rd));
}
Ok(())
}
pub fn one_unlink_core(
&self,
t: &mut Transaction,
ld: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let rd = self[(1, ld)].exchange(t, NULL_DART_ID)?;
if rd == NULL_DART_ID {
return abort(LinkError::AlreadyFree(1, ld));
}
self[(0, rd)].write(t, NULL_DART_ID)?;
Ok(())
}
pub fn two_unlink_core(
&self,
t: &mut Transaction,
ld: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let rd = self[(2, ld)].exchange(t, NULL_DART_ID)?;
if rd == NULL_DART_ID {
return abort(LinkError::AlreadyFree(2, ld));
}
self[(2, rd)].write(t, NULL_DART_ID)?;
Ok(())
}
pub fn three_unlink_core(
&self,
t: &mut Transaction,
ld: DartIdType,
) -> TransactionClosureResult<(), LinkError> {
let rd = self[(3, ld)].exchange(t, NULL_DART_ID)?;
if rd == NULL_DART_ID {
return abort(LinkError::AlreadyFree(3, ld));
}
self[(3, rd)].write(t, NULL_DART_ID)?;
Ok(())
}
}