use {
crate::Node,
core::{
cell::Cell,
ops::Deref,
ptr,
},
};
pub trait Rc: Deref<Target = Cell<Class<Self>>> + Clone
{
fn new(value: Cell<Class<Self>>) -> Self;
}
#[derive(Clone)]
#[non_exhaustive]
pub enum Class<R>
{
#[non_exhaustive]
Representative
{
weight: usize,
},
#[non_exhaustive]
Link
{
next: R,
},
}
impl<R> Default for Class<R>
{
#[inline]
fn default() -> Self
{
Self::Representative { weight: 1 }
}
}
impl<R: Rc> Class<R>
{
#[allow(clippy::new_ret_no_self)] fn new() -> R
{
R::new(Cell::new(Self::default()))
}
fn clone_inner(it: &R) -> Self
{
let dummy = Self::default();
let inner = it.replace(dummy);
let result = inner.clone();
it.set(inner);
result
}
fn get_rep_and_weight(it: &R) -> (R, usize)
{
let it_inner = Self::clone_inner(it);
match it_inner {
Self::Representative { weight } => (R::clone(it), weight),
Self::Link { mut next } => {
let mut cur = R::clone(it);
loop {
let next_inner = Self::clone_inner(&next);
match next_inner {
Self::Representative { weight } => break (next, weight),
Self::Link { next: next_next } => {
cur.set(Self::Link { next: R::clone(&next_next) });
cur = next;
next = next_next;
},
}
}
},
}
}
fn get_rep(it: &R) -> R
{
Self::get_rep_and_weight(it).0
}
fn eq_rep(
it: &R,
other: &R,
) -> bool
{
debug_assert!(matches!(
(Self::clone_inner(it), Self::clone_inner(other)),
(Self::Representative { .. }, Self::Representative { .. })
));
ptr::eq(&**it, &**other)
}
fn set_rep(
it: &R,
weight: usize,
)
{
it.set(Self::Representative { weight });
}
fn set_link(
it: &R,
next: R,
)
{
it.set(Self::Link { next });
}
}
pub trait Table: Default
{
type Node: Node;
type Rc: Rc;
fn get(
&self,
k: &<Self::Node as Node>::Id,
) -> Option<&Self::Rc>;
fn insert(
&mut self,
k: <Self::Node as Node>::Id,
v: Self::Rc,
);
}
#[derive(Default)]
pub(crate) struct EquivClasses<T>
{
table: T,
}
impl<T: Table> EquivClasses<T>
{
fn none_seen(
&mut self,
ak: &<T::Node as Node>::Id,
bk: &<T::Node as Node>::Id,
)
{
let ac = Class::new();
let bc = T::Rc::clone(&ac);
self.table.insert(ak.clone(), ac);
self.table.insert(bk.clone(), bc);
}
fn some_seen(
&mut self,
oc: &T::Rc,
k: &<T::Node as Node>::Id,
)
{
let r = Class::get_rep(oc);
self.table.insert(k.clone(), r);
}
fn all_seen(
ac: &T::Rc,
bc: &T::Rc,
) -> bool
{
let (ar, aw) = Class::get_rep_and_weight(ac);
let (br, bw) = Class::get_rep_and_weight(bc);
if Class::eq_rep(&ar, &br) {
true
}
else {
let (larger_rep, smaller_rep);
if aw >= bw {
larger_rep = ar;
smaller_rep = br;
}
else {
larger_rep = br;
smaller_rep = ar;
}
Class::set_rep(&larger_rep, aw.saturating_add(bw));
Class::set_link(&smaller_rep, larger_rep);
false
}
}
pub(crate) fn same_class(
&mut self,
ak: &<T::Node as Node>::Id,
bk: &<T::Node as Node>::Id,
) -> bool
{
match (self.table.get(ak), self.table.get(bk)) {
(None, None) => {
self.none_seen(ak, bk);
false
},
(Some(ac), None) => {
let ac = &T::Rc::clone(ac); self.some_seen(ac, bk);
false
},
(None, Some(bc)) => {
let bc = &T::Rc::clone(bc); self.some_seen(bc, ak);
false
},
(Some(ac), Some(bc)) => Self::all_seen(ac, bc),
}
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
pub mod premade
{
#[cfg(feature = "alloc")]
pub use alloc::*;
#[cfg(feature = "std")]
pub use std::*;
#[cfg(feature = "alloc")]
mod alloc
{
extern crate alloc;
pub mod rc
{
use {
super::{
super::super::{
Class,
Rc as RcTrait,
},
alloc,
},
core::{
cell::Cell,
ops::Deref,
},
};
#[derive(Clone)]
pub struct Rc(alloc::rc::Rc<Cell<Class<Self>>>);
impl Deref for Rc
{
type Target = Cell<Class<Self>>;
#[inline]
fn deref(&self) -> &Self::Target
{
&*self.0
}
}
impl RcTrait for Rc
{
#[inline]
fn new(val: Cell<Class<Self>>) -> Self
{
Self(alloc::rc::Rc::new(val))
}
}
}
}
#[cfg(feature = "std")]
mod std
{
extern crate std;
pub mod hash_map
{
use {
super::{
super::{
super::Table as TableTrait,
rc::Rc,
},
std,
},
crate::Node,
std::collections::HashMap,
};
pub trait Params
{
const INITIAL_CAPACITY: usize = 2_usize.pow(12);
type Node: Node;
}
pub struct Table<P: Params>(HashMap<<P::Node as Node>::Id, Rc>);
impl<P: Params> Default for Table<P>
{
#[inline]
fn default() -> Self
{
Self(HashMap::with_capacity(P::INITIAL_CAPACITY))
}
}
impl<P: Params> TableTrait for Table<P>
{
type Node = P::Node;
type Rc = Rc;
#[inline]
fn get(
&self,
k: &<Self::Node as Node>::Id,
) -> Option<&Self::Rc>
{
HashMap::get(&self.0, k)
}
#[inline]
fn insert(
&mut self,
k: <Self::Node as Node>::Id,
v: Self::Rc,
)
{
drop(HashMap::insert(&mut self.0, k, v));
}
}
}
}
}
#[cfg(test)]
mod tests
{
#[allow(unused_imports)]
use super::*;
#[cfg(feature = "alloc")]
#[test]
fn eq_rep()
{
use premade::rc::Rc;
fn rep(weight: usize) -> Rc
{
Rc::new(Cell::new(Class::Representative { weight }))
}
{
let r = &rep(0);
assert!(Class::eq_rep(r, r));
}
{
let r1 = rep(2);
let r2 = Rc::clone(&r1);
assert!(Class::eq_rep(&r1, &r2));
}
{
let r1 = rep(3);
let r2 = rep(3);
assert!(!Class::eq_rep(&r1, &r2));
}
}
#[cfg(feature = "alloc")]
#[test]
fn get_rep()
{
use premade::rc::Rc;
fn link(next: &Rc) -> Rc
{
let new = Class::new();
Class::set_link(&new, Rc::clone(next));
new
}
let rep1 = Class::new();
let link1 = link(&rep1);
let link2 = link(&rep1);
let link3 = link(&link1);
let link4 = link(&link2);
let link5 = link(&link4);
let link6 = link(&link5);
assert!(Class::eq_rep(&Class::get_rep(&link1), &rep1));
assert!(Class::eq_rep(&Class::get_rep(&link2), &rep1));
assert!(Class::eq_rep(&Class::get_rep(&link3), &rep1));
assert!(Class::eq_rep(&Class::get_rep(&link4), &rep1));
assert!(Class::eq_rep(&Class::get_rep(&link5), &rep1));
assert!(Class::eq_rep(&Class::get_rep(&link6), &rep1));
let rep2 = Class::new();
let link7 = link(&rep2);
assert!(!Class::eq_rep(&Class::get_rep(&link7), &rep1));
}
#[cfg(feature = "std")]
#[test]
fn same_class()
{
use premade::hash_map::{
Params,
Table,
};
struct Args;
impl Params for Args
{
type Node = CharKeyed;
}
struct CharKeyed;
#[allow(clippy::unreachable)]
impl Node for CharKeyed
{
type Cmp = bool;
type Id = char;
type Index = u8;
fn id(&self) -> Self::Id
{
unreachable!()
}
fn get_edge(
&self,
_index: &Self::Index,
) -> Option<Self>
{
unreachable!()
}
fn equiv_modulo_edges(
&self,
_other: &Self,
) -> bool
{
unreachable!()
}
}
let mut ec = EquivClasses::<Table<Args>>::default();
let keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
assert!(!ec.same_class(&keys[0], &keys[1]));
assert!(ec.same_class(&keys[0], &keys[1]));
assert!(!ec.same_class(&keys[0], &keys[2]));
assert!(ec.same_class(&keys[0], &keys[2]));
assert!(ec.same_class(&keys[1], &keys[2]));
assert!(!ec.same_class(&keys[3], &keys[2]));
assert!(ec.same_class(&keys[3], &keys[2]));
assert!(ec.same_class(&keys[3], &keys[1]));
assert!(ec.same_class(&keys[3], &keys[0]));
assert!(!ec.same_class(&keys[4], &keys[5]));
assert!(ec.same_class(&keys[4], &keys[5]));
assert!(!ec.same_class(&keys[5], &keys[6]));
assert!(ec.same_class(&keys[5], &keys[6]));
assert!(ec.same_class(&keys[4], &keys[6]));
assert!(!ec.same_class(&keys[1], &keys[4]));
assert!(ec.same_class(&keys[1], &keys[4]));
assert!(ec.same_class(&keys[1], &keys[5]));
assert!(ec.same_class(&keys[1], &keys[6]));
for a in &keys {
for b in &keys {
assert!(ec.same_class(a, b));
}
}
}
}