use std::{collections::BTreeSet, fmt};
use sorted_iter::{assume::AssumeSortedByItemExt, SortedIterator};
use crate::{sorted, BitMatrix};
pub struct Bimultimap<K: Eq + Ord, V: Eq + Ord> {
sparse_keys: sorted::Box<K>,
sparse_values: sorted::Box<V>,
associations: BitMatrix,
}
impl<K: Eq + Ord, V: Eq + Ord> Bimultimap<K, V> {
#[inline]
fn mapped_associates_of(&self, row: usize) -> impl Iterator<Item = usize> + '_ {
let width = self.sparse_values.len();
self.associations.row(width, row)
}
#[must_use]
pub fn keys(&self) -> sorted::Slice<K> {
self.sparse_keys.slice()
}
#[must_use]
pub fn values(&self) -> sorted::Slice<V> {
self.sparse_values.slice()
}
pub fn get(&self, key: &K) -> impl SortedIterator<Item = &V> + '_ {
self.sparse_keys
.binary_search(key)
.into_iter()
.flat_map(|mapped| self.mapped_associates_of(mapped))
.map(|mapped| unsafe { self.sparse_values.get_unchecked(mapped) })
.assume_sorted_by_item()
}
pub fn get_keys_of(&self, value: &V) -> impl SortedIterator<Item = &K> + '_ {
let width = self.sparse_values.len();
self.sparse_values
.binary_search(value)
.into_iter()
.flat_map(move |mapped| self.associations.active_rows_in_column(width, mapped))
.filter_map(|mapped| self.sparse_keys.get(mapped))
.assume_sorted_by_item()
}
}
impl<K: Eq + Ord + Clone, V: Eq + Ord + Clone> FromIterator<(K, V)> for Bimultimap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut values = BTreeSet::new();
let mut keys = BTreeSet::new();
let mut key_values = Vec::new();
for (key, value) in iter {
key_values.push((key.clone(), value.clone()));
keys.insert(key);
values.insert(value);
}
let sparse_keys = sorted::Box::from_sorted_iter(keys.into_iter());
let sparse_values = sorted::Box::from_sorted_iter(values.into_iter());
let mut associations = BitMatrix::new_with_size(sparse_values.len(), sparse_keys.len());
for (key, value) in key_values {
let key_i = sparse_keys.binary_search(&key).unwrap();
let value_i = sparse_values.binary_search(&value).unwrap();
associations
.enable_bit(sparse_values.len(), value_i, key_i)
.unwrap();
}
Bimultimap { sparse_keys, sparse_values, associations }
}
}
impl<K: Eq + Ord + fmt::Debug, V: Eq + Ord + fmt::Debug> fmt::Debug for Bimultimap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (width, height) = (self.sparse_values.len(), self.sparse_keys.len());
f.debug_struct("Bimultimap")
.field("values", &self.sparse_values)
.field("keys", &self.sparse_keys)
.field("map", &self.associations.sextant_display(width, height))
.finish()
}
}