use crate::traits::Backend;
use value_traits::slices::SliceByValue;
use super::shard_edge::FuseLge3Shards;
use crate::bits::BitFieldVec;
use crate::func::shard_edge::ShardEdge;
use crate::traits::Word;
use crate::utils::*;
use mem_dbg::*;
use std::borrow::Borrow;
#[derive(Debug, Clone, MemSize, MemDbg)]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VFunc<K: ?Sized, D, S = [u64; 2], E = FuseLge3Shards> {
pub(crate) shard_edge: E,
pub(crate) seed: u64,
pub(crate) num_keys: usize,
pub(crate) data: D,
pub(crate) _marker: std::marker::PhantomData<(*const K, S)>,
}
impl<K: ?Sized, D: SliceByValue, S, E> Backend for VFunc<K, D, S, E> {
type Word = D::Value;
}
impl<K: ?Sized, W: Word, S: Sig, E: ShardEdge<S, 3>> VFunc<K, BitFieldVec<Box<[W]>>, S, E> {
#[must_use]
pub fn empty() -> Self {
Self {
shard_edge: E::default(),
seed: 0,
num_keys: 0,
data: BitFieldVec::<Vec<W>>::new(0, 0).into(),
_marker: std::marker::PhantomData,
}
}
}
impl<K: ?Sized + ToSig<S>, D: SliceByValue<Value: Word + BinSafe>, S: Sig, E: ShardEdge<S, 3>>
VFunc<K, D, S, E>
{
#[inline]
pub fn get_by_sig(&self, sig: S) -> D::Value {
let edge = self.shard_edge.edge(sig);
unsafe {
self.data.get_value_unchecked(edge[0])
^ self.data.get_value_unchecked(edge[1])
^ self.data.get_value_unchecked(edge[2])
}
}
#[inline(always)]
pub fn get(&self, key: impl Borrow<K>) -> D::Value {
self.get_by_sig(K::to_sig(key.borrow(), self.seed))
}
pub const fn len(&self) -> usize {
self.num_keys
}
pub const fn is_empty(&self) -> bool {
self.num_keys == 0
}
}
use crate::traits::{TryIntoUnaligned, Unaligned};
impl<K: ?Sized, W: Word, S: Sig, E: ShardEdge<S, 3>> TryIntoUnaligned
for VFunc<K, BitFieldVec<Box<[W]>>, S, E>
{
type Unaligned = VFunc<K, Unaligned<BitFieldVec<Box<[W]>>>, S, E>;
fn try_into_unaligned(
self,
) -> Result<Self::Unaligned, crate::traits::UnalignedConversionError> {
Ok(VFunc {
shard_edge: self.shard_edge,
seed: self.seed,
num_keys: self.num_keys,
data: self.data.try_into_unaligned()?,
_marker: std::marker::PhantomData,
})
}
}
impl<K: ?Sized, W: Word, S: Sig, E: ShardEdge<S, 3>>
From<Unaligned<VFunc<K, BitFieldVec<Box<[W]>>, S, E>>>
for VFunc<K, BitFieldVec<Box<[W]>>, S, E>
{
fn from(vf: Unaligned<VFunc<K, BitFieldVec<Box<[W]>>, S, E>>) -> Self {
VFunc {
shard_edge: vf.shard_edge,
seed: vf.seed,
num_keys: vf.num_keys,
data: BitFieldVec::from(vf.data),
_marker: std::marker::PhantomData,
}
}
}
#[cfg(feature = "rayon")]
mod build {
use super::*;
use crate::func::VBuilder;
use crate::traits::bit_field_slice::BitFieldSliceMut;
use anyhow::Result;
use core::error::Error;
use dsi_progress_logger::ProgressLog;
use lender::*;
use rdst::RadixKey;
use std::ops::{BitXor, BitXorAssign};
use value_traits::slices::SliceByValueMut;
impl<K, W, S, E> VFunc<K, Box<[W]>, S, E>
where
K: ?Sized + ToSig<S> + std::fmt::Debug,
W: Word + BinSafe,
S: Sig + Send + Sync,
E: ShardEdge<S, 3>,
SigVal<S, W>: RadixKey,
SigVal<E::LocalSig, W>: BitXor + BitXorAssign,
{
pub fn try_new<B: ?Sized + Borrow<K>>(
keys: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend B>,
values: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend W>,
n: usize,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item:
BitFieldSliceMut,
for<'a> <Box<[W]> as SliceByValueMut>::ChunksMut<'a>: Send,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item: Send,
{
Self::try_new_with_builder(keys, values, n, VBuilder::default(), pl)
}
pub fn try_new_with_builder<B: ?Sized + Borrow<K>>(
keys: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend B>,
values: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend W>,
n: usize,
builder: VBuilder<Box<[W]>, S, E>,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item:
BitFieldSliceMut,
for<'a> <Box<[W]> as SliceByValueMut>::ChunksMut<'a>: Send,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item: Send,
{
Ok(builder
.expected_num_keys(n)
.try_build_func(
keys,
values,
|_bit_width, len| vec![W::ZERO; len].into(),
pl,
)?
.0)
}
pub fn try_par_new(
keys: &[impl Borrow<K> + Sync],
values: &[W],
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
K: Sync,
S: Send,
W: Copy,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item:
BitFieldSliceMut,
for<'a> <Box<[W]> as SliceByValueMut>::ChunksMut<'a>: Send,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item: Send,
{
Self::try_par_new_with_builder(keys, values, VBuilder::default(), pl)
}
pub fn try_par_new_with_builder(
keys: &[impl Borrow<K> + Sync],
values: &[W],
builder: VBuilder<Box<[W]>, S, E>,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
K: Sync,
S: Send,
W: Copy,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item:
BitFieldSliceMut,
for<'a> <Box<[W]> as SliceByValueMut>::ChunksMut<'a>: Send,
for<'a> <<Box<[W]> as SliceByValueMut>::ChunksMut<'a> as Iterator>::Item: Send,
{
let n = keys.len();
builder.expected_num_keys(n).try_par_populate_and_build(
keys,
&|i| values[i],
&mut |builder, seed, mut store, _max_value, _num_keys, pl, _state: &mut ()| {
let data: Box<[W]> = vec![
W::ZERO;
builder.shard_edge.num_vertices()
* builder.shard_edge.num_shards()
]
.into();
let func = builder.try_build_from_shard_iter(
seed,
data,
store.drain(),
&|_, sv| sv.val,
&|_| {},
pl,
)?;
Ok(func)
},
pl,
(),
)
}
}
impl<K, W, S, E> VFunc<K, BitFieldVec<Box<[W]>>, S, E>
where
K: ?Sized + ToSig<S> + std::fmt::Debug,
W: Word + BinSafe,
S: Sig + Send + Sync,
E: ShardEdge<S, 3>,
SigVal<S, W>: RadixKey,
SigVal<E::LocalSig, W>: BitXor + BitXorAssign,
{
pub fn try_new<B: ?Sized + Borrow<K>>(
keys: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend B>,
values: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend W>,
n: usize,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self> {
Self::try_new_with_builder(keys, values, n, VBuilder::default(), pl)
}
pub fn try_new_with_builder<B: ?Sized + Borrow<K>>(
keys: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend B>,
values: impl FallibleRewindableLender<
RewindError: Error + Send + Sync + 'static,
Error: Error + Send + Sync + 'static,
> + for<'lend> FallibleLending<'lend, Lend = &'lend W>,
n: usize,
builder: VBuilder<BitFieldVec<Box<[W]>>, S, E>,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self> {
builder
.expected_num_keys(n)
.try_build_func(
keys,
values,
|bit_width, len| BitFieldVec::<Box<[W]>>::new_padded(bit_width, len),
pl,
)
.map(|res| res.0)
}
pub fn try_par_new(
keys: &[impl Borrow<K> + Sync],
values: &[W],
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
K: Sync,
S: Send,
W: Copy,
{
Self::try_par_new_with_builder(keys, values, VBuilder::default(), pl)
}
pub fn try_par_new_with_builder(
keys: &[impl Borrow<K> + Sync],
values: &[W],
builder: VBuilder<BitFieldVec<Box<[W]>>, S, E>,
pl: &mut (impl ProgressLog + Clone + Send + Sync),
) -> Result<Self>
where
K: Sync,
S: Send,
W: Copy,
{
let n = keys.len();
builder.expected_num_keys(n).try_par_populate_and_build(
keys,
&|i| values[i],
&mut |builder, seed, mut store, max_value, _num_keys, pl, _state: &mut ()| {
builder.bit_width = max_value.bit_len() as usize;
let data = BitFieldVec::<Box<[W]>>::new_padded(
builder.bit_width,
builder.shard_edge.num_vertices() * builder.shard_edge.num_shards(),
);
let func = builder.try_build_from_shard_iter(
seed,
data,
store.drain(),
&|_, sv| sv.val,
&|_| {},
pl,
)?;
Ok(func)
},
pl,
(),
)
}
}
}