use bitvec to return SCCs

This commit is contained in:
Folkert 2022-04-24 16:51:51 +02:00
parent a7e781ece2
commit b8db6aae8d
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 47 additions and 10 deletions

View file

@ -30,7 +30,6 @@ use roc_types::types::AliasKind;
use roc_types::types::LambdaSet; use roc_types::types::LambdaSet;
use roc_types::types::{Alias, Type}; use roc_types::types::{Alias, Type};
use std::fmt::Debug; use std::fmt::Debug;
use ven_graph::topological_sort;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Def { pub struct Def {

View file

@ -1,7 +1,8 @@
// see if we get better performance with different integer types // see if we get better performance with different integer types
pub(crate) type Element = usize; type Order = bitvec::order::Lsb0;
pub(crate) type BitVec = bitvec::vec::BitVec<Element>; type Element = usize;
pub(crate) type BitSlice = bitvec::prelude::BitSlice<Element>; type BitVec = bitvec::vec::BitVec<Element, Order>;
type BitSlice = bitvec::prelude::BitSlice<Element, Order>;
/// A square boolean matrix used to store relations /// A square boolean matrix used to store relations
/// ///
@ -172,7 +173,12 @@ impl ReferenceMatrix {
continue 'outer; continue 'outer;
} }
break params.scc; let mut result = Vec::new();
for group in params.scc.components() {
result.push(group.map(|v| v as u32).collect());
}
break result;
} }
} }
} }
@ -202,7 +208,7 @@ struct Params {
c: usize, c: usize,
p: Vec<u32>, p: Vec<u32>,
s: Vec<u32>, s: Vec<u32>,
scc: Vec<Vec<u32>>, scc: Sccs,
scca: Vec<u32>, scca: Vec<u32>,
} }
@ -219,7 +225,10 @@ impl Params {
c: 0, c: 0,
s: Vec::new(), s: Vec::new(),
p: Vec::new(), p: Vec::new(),
scc: Vec::new(), scc: Sccs {
matrix: ReferenceMatrix::new(length),
components: 0,
},
scca: Vec::new(), scca: Vec::new(),
} }
} }
@ -260,15 +269,44 @@ fn recurse_onto(length: usize, bitvec: &BitVec, v: usize, params: &mut Params) {
if params.p.last() == Some(&(v as u32)) { if params.p.last() == Some(&(v as u32)) {
params.p.pop(); params.p.pop();
let mut component = Vec::new();
while let Some(node) = params.s.pop() { while let Some(node) = params.s.pop() {
component.push(node); params
.scc
.matrix
.set_row_col(params.scc.components, node as usize, true);
params.scca.push(node); params.scca.push(node);
params.preorders[node as usize] = Preorder::Removed; params.preorders[node as usize] = Preorder::Removed;
if node as usize == v { if node as usize == v {
break; break;
} }
} }
params.scc.push(component);
params.scc.components += 1;
}
}
#[derive(Debug)]
pub(crate) struct Sccs {
components: usize,
matrix: ReferenceMatrix,
}
impl Sccs {
fn components(&self) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> + '_ {
// work around a panic when requesting a chunk size of 0
let length = if self.matrix.length == 0 {
// the `.take(self.components)` ensures the resulting iterator will be empty
assert!(self.components == 0);
1
} else {
self.matrix.length
};
self.matrix
.bitvec
.chunks(length)
.take(self.components)
.map(|row| row.iter_ones())
} }
} }