use std::collections::BinaryHeap;
use rustc_hash::{FxBuildHasher, FxHashMap};
use crate::combinadic::BinomialTable;
use crate::distances::Distances;
use crate::field::{Coeffs, Entry, HeapEntry};
use crate::simplex::Simplex;
use crate::union_find::UnionFind;
use crate::{Bar, RipsParams};
pub(crate) type Pivots = FxHashMap<u64, (u64, usize)>;
#[derive(Debug, Clone)]
pub(crate) struct RawH1Term {
pub(crate) simplex: Simplex,
pub(crate) coefficient: u64,
}
#[derive(Debug, Clone)]
pub(crate) struct RawH1Class {
pub(crate) bar: Bar,
pub(crate) scale: f64,
pub(crate) birth: Simplex,
pub(crate) death: Option<Simplex>,
pub(crate) terms: Vec<RawH1Term>,
}
pub(super) struct Dim0Walk {
pub(super) union_find: UnionFind,
pub(super) cycles: Vec<(Simplex, [usize; 2])>,
pub(super) columns: Vec<Simplex>,
}
pub(super) struct SerialReduction<'a> {
pub(super) pivots: Pivots,
pub(super) entries: Vec<Entry>,
pub(super) offsets: Vec<usize>,
pub(super) coboundary: BinaryHeap<HeapEntry>,
pub(super) reduction: BinaryHeap<HeapEntry>,
pub(super) cofacets: Vec<Entry>,
pub(super) vertices: Vec<usize>,
pub(super) cofacet_vertices: Vec<usize>,
pub(super) pairs: PairScratch,
pub(super) essential_terms: Vec<Entry>,
pub(super) classes: Option<&'a mut Vec<RawH1Class>>,
}
impl<'a> SerialReduction<'a> {
pub(super) fn new(column_count: usize, classes: Option<&'a mut Vec<RawH1Class>>) -> Self {
Self {
pivots: FxHashMap::with_capacity_and_hasher(column_count, FxBuildHasher),
entries: Vec::new(),
offsets: vec![0],
coboundary: BinaryHeap::new(),
reduction: BinaryHeap::new(),
cofacets: Vec::new(),
vertices: Vec::new(),
cofacet_vertices: Vec::new(),
pairs: PairScratch::default(),
essential_terms: Vec::new(),
classes,
}
}
}
#[derive(Default)]
pub(crate) struct PairScratch {
pub(super) facet: Vec<usize>,
pub(super) cofacet: Vec<usize>,
pub(super) base: PairTable,
pub(super) cofacet_table: PairTable,
pub(super) added: Vec<f64>,
}
#[derive(Default)]
pub(crate) struct PairTable {
pub(super) d: Vec<f64>,
pub(super) filled: usize,
pub(super) owner: Option<(u64, usize)>,
}
impl PairTable {
pub(super) fn holds(&self, owner: (u64, usize)) -> bool {
self.owner == Some(owner)
}
pub(super) fn reset(&mut self, owner: (u64, usize)) {
self.d.clear();
self.filled = 0;
self.owner = Some(owner);
}
#[inline]
pub(super) fn at(&self, p: usize, q: usize) -> f64 {
self.d[q * (q - 1) / 2 + p]
}
pub(super) fn set_edge(&mut self, diameter: f64) {
self.d.push(diameter);
self.filled = 2;
}
pub(super) fn fill<D: Distances>(&mut self, dist: &D, vertices: &[usize], upto: usize) {
while self.filled < upto {
let q = self.filled;
let vq = vertices[q];
for &vp in &vertices[..q] {
self.d.push(dist.get(vp, vq));
}
self.filled += 1;
}
}
pub(super) fn fill_cofacet(
&mut self,
owner: (u64, usize),
base: &PairTable,
added: &[f64],
at: usize,
) {
let m = added.len() + 1;
self.reset(owner);
for q in 0..m {
for p in 0..q {
let x = if q == at {
added[p]
} else if p == at {
added[q - 1]
} else {
let base_p = if p < at { p } else { p - 1 };
let base_q = if q < at { q } else { q - 1 };
base.at(base_p, base_q)
};
self.d.push(x);
}
}
self.filled = m;
}
pub(super) fn omit_max(&self, m: usize, omit: usize) -> f64 {
let mut d = 0.0f64;
for q in 0..m {
if q == omit {
continue;
}
for p in 0..q {
if p != omit {
d = d.max(self.at(p, q));
}
}
}
d
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum Pairing {
Facet,
Cofacet,
}
#[derive(Clone, Copy)]
pub(crate) struct ApparentPair {
pub(crate) other: Simplex,
pub(crate) k: usize,
}
pub(crate) struct Engine<'a, C: Coeffs, D: Distances> {
pub(crate) dist: &'a D,
pub(crate) bt: BinomialTable,
pub(crate) n: usize,
pub(super) effective_threshold: f64,
pub(crate) max_dim: usize,
pub(crate) params: &'a RipsParams,
pub(crate) ops: C,
pub(super) pool: Option<rayon::ThreadPool>,
pub(super) adjacency: Option<crate::adjacency::Adjacency>,
}