use simple_sds::int_vector::IntVector;
use simple_sds::ops::{Vector, Access, Push, BitVec, Select};
use simple_sds::serialize::Serialize;
use simple_sds::sparse_vector::SparseVector;
use simple_sds::bits;
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap};
use std::collections::btree_map::Iter as TagIter;
use std::collections::hash_map::Entry;
use std::convert::TryFrom;
use std::io::{Error, ErrorKind};
use std::iter::FusedIterator;
use std::ops::Range;
use std::path::PathBuf;
use std::str::Utf8Error;
use std::{cmp, fmt, io, mem};
#[cfg(test)]
mod tests;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Orientation {
Forward = 0,
Reverse = 1,
}
impl Orientation {
#[inline]
pub fn flip(&self) -> Orientation {
match *self {
Self::Forward => Self::Reverse,
Self::Reverse => Self::Forward,
}
}
}
impl fmt::Display for Orientation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Orientation::Forward => write!(f, "forward"),
Orientation::Reverse => write!(f, "reverse"),
}
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct GraphPosition {
pub node: usize,
pub orientation: Orientation,
pub offset: usize,
}
impl GraphPosition {
#[inline]
pub fn new(node: usize, orientation: Orientation, offset: usize) -> Self {
GraphPosition {
node, orientation, offset,
}
}
#[inline]
pub fn to_gbwt(&self) -> usize {
encode_node(self.node, self.orientation)
}
}
const fn generate_complement_table() -> [u8; 256] {
let mut result: [u8; 256] = [b'N'; 256];
result[b'A' as usize] = b'T'; result[b'a' as usize] = b'T';
result[b'C' as usize] = b'G'; result[b'c' as usize] = b'G';
result[b'G' as usize] = b'C'; result[b'g' as usize] = b'C';
result[b'T' as usize] = b'A'; result[b't' as usize] = b'A';
result
}
pub const COMPLEMENT: [u8; 256] = generate_complement_table();
pub fn reverse_complement(sequence: &[u8]) -> Vec<u8> {
let mut result: Vec<u8> = Vec::with_capacity(sequence.len());
for &c in sequence.iter().rev() {
result.push(COMPLEMENT[c as usize]);
}
result
}
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Run {
pub value: usize,
pub len: usize,
}
impl Run {
#[inline]
pub fn new(value: usize, len: usize) -> Self {
Run {
value, len,
}
}
}
impl From<(usize, usize)> for Run {
#[inline]
fn from(run: (usize, usize)) -> Self {
Self::new(run.0, run.1)
}
}
#[inline]
pub fn encode_node(id: usize, orientation: Orientation) -> usize {
2 * id + (orientation as usize)
}
#[inline]
pub fn node_id(id: usize) -> usize {
id / 2
}
#[inline]
pub fn node_orientation(id: usize) -> Orientation {
match id & 1 {
0 => Orientation::Forward,
_ => Orientation::Reverse,
}
}
#[inline]
pub fn decode_node(id: usize) -> (usize, Orientation) {
(node_id(id), node_orientation(id))
}
#[inline]
pub fn flip_node(id: usize) -> usize {
id ^ 1
}
pub fn edge_is_canonical(from: (usize, Orientation), to: (usize, Orientation)) -> bool {
if from.1 == Orientation::Forward {
to.0 >= from.0
} else {
(to.0 > from.0) || (to.0 == from.0 && to.1 == Orientation::Forward)
}
}
pub fn encoded_edge_is_canonical(from: usize, to: usize) -> bool {
edge_is_canonical(decode_node(from), decode_node(to))
}
#[inline]
pub fn encode_path(id: usize, orientation: Orientation) -> usize {
2 * id + (orientation as usize)
}
#[inline]
pub fn path_id(id: usize) -> usize {
id / 2
}
#[inline]
pub fn path_orientation(id: usize) -> Orientation {
match id & 1 {
0 => Orientation::Forward,
_ => Orientation::Reverse,
}
}
#[inline]
pub fn decode_path(id: usize) -> (usize, Orientation) {
(path_id(id), path_orientation(id))
}
#[inline]
pub fn flip_path(id: usize) -> usize {
id ^ 1
}
pub fn path_is_canonical(path: &[(usize, Orientation)]) -> bool {
if path.is_empty() {
return true;
}
let first = path[0];
let last = path[path.len() - 1];
if first.1 == last.1 {
return first.1 == Orientation::Forward;
}
edge_is_canonical(first, last)
}
pub fn encoded_path_is_canonical(path: &[usize]) -> bool {
if path.is_empty() {
return true;
}
let first = decode_node(path[0]);
let last = decode_node(path[path.len() - 1]);
if first.1 == last.1 {
return first.1 == Orientation::Forward;
}
edge_is_canonical(first, last)
}
pub fn reverse_path(path: &[usize]) -> Vec<usize> {
let mut result: Vec<usize> = path.iter().map(|x| flip_node(*x)).collect();
result.reverse();
result
}
pub fn reverse_path_in_place(path: &mut [usize]) {
path.reverse();
for node in path.iter_mut() {
*node = flip_node(*node);
}
}
#[inline]
pub fn intersect(a: &Range<usize>, b: &Range<usize>) -> Range<usize> {
cmp::max(a.start, b.start)..cmp::min(a.end, b.end)
}
pub fn get_test_data(filename: &'static str) -> PathBuf {
let mut buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
buf.push("test-data");
buf.push(filename);
buf
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringArray {
index: IntVector,
strings: Vec<u8>,
}
impl StringArray {
#[inline]
pub fn len(&self) -> usize {
self.index.len() - 1
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn str_len(&self, i: usize) -> usize {
(self.index.get(i + 1) - self.index.get(i)) as usize
}
pub fn range_len(&self, strings: Range<usize>) -> usize {
(self.index.get(strings.end) - self.index.get(strings.start)) as usize
}
pub fn bytes(&self, i: usize) -> &[u8] {
let start = self.index.get(i) as usize;
let limit = self.index.get(i + 1) as usize;
&self.strings[start..limit]
}
pub fn range(&self, strings: Range<usize>) -> &[u8] {
let start = self.index.get(strings.start) as usize;
let limit = self.index.get(strings.end) as usize;
&self.strings[start..limit]
}
pub fn str(&self, i: usize) -> Result<&str, Utf8Error> {
std::str::from_utf8(self.bytes(i))
}
pub fn string(&self, i: usize) -> Result<String, Utf8Error> {
match self.str(i) {
Ok(v) => Ok(v.to_string()),
Err(e) => Err(e),
}
}
pub fn iter(&self) -> StringIter<'_> {
StringIter {
parent: self,
next: 0,
limit: self.len(),
}
}
fn with_capacity(n: usize, total_len: usize) -> StringArray {
let mut index = IntVector::with_capacity(n + 1, bits::bit_len(total_len as u64)).unwrap();
index.push(0);
let strings: Vec<u8> = Vec::with_capacity(total_len);
StringArray {
index, strings,
}
}
fn append(&mut self, string: &str) {
self.strings.extend(string.bytes());
self.index.push(self.strings.len() as u64);
}
fn alphabet(data: &[u8]) -> (Vec<usize>, Vec<u8>, usize) {
let mut bytes_to_packed: Vec<usize> = vec![0; 1 << 8];
for byte in data {
bytes_to_packed[*byte as usize] = 1;
}
let sigma = bytes_to_packed.iter().sum();
let width = bits::bit_len(cmp::max(sigma, 1) as u64 - 1);
let mut packed_to_bytes: Vec<u8> = vec![0; sigma];
let mut rank = 0;
for (index, value) in bytes_to_packed.iter_mut().enumerate() {
if *value != 0 {
*value = rank;
packed_to_bytes[rank] = index as u8;
rank += 1;
}
}
(bytes_to_packed, packed_to_bytes, width)
}
}
impl Serialize for StringArray {
fn serialize_header<T: io::Write>(&self, _: &mut T) -> io::Result<()> {
Ok(())
}
fn serialize_body<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
let sv = SparseVector::try_from_iter(self.index.iter().take(self.len()).map(|x| x as usize)).unwrap();
sv.serialize(writer)?;
drop(sv);
let (pack, alphabet, width) = Self::alphabet(&self.strings);
alphabet.serialize(writer)?;
let mut packed = IntVector::new(width).unwrap();
packed.extend(self.strings.iter().map(|x| pack[*x as usize]));
packed.serialize(writer)?;
Ok(())
}
fn load<T: io::Read>(reader: &mut T) -> io::Result<Self> {
let sv = SparseVector::load(reader)?;
let alphabet = Vec::<u8>::load(reader)?;
let packed = IntVector::load(reader)?;
let strings: Vec<u8> = packed.into_iter().map(|x| alphabet[x as usize]).collect();
let mut index = IntVector::with_capacity(sv.count_ones() + 1, bits::bit_len(strings.len() as u64)).unwrap();
index.extend(sv.one_iter().map(|(_, x)| x));
index.push(strings.len() as u64);
if index.get(0) != 0 {
return Err(Error::new(ErrorKind::InvalidData, "StringArray: First string does not start at offset 0"));
}
Ok(StringArray {
index, strings,
})
}
fn size_in_elements(&self) -> usize {
let sv = SparseVector::try_from_iter(self.index.iter().take(self.len()).map(|x| x as usize)).unwrap();
let (_, alphabet, width) = Self::alphabet(&self.strings);
sv.size_in_elements() + alphabet.size_in_elements() + IntVector::size_by_params(self.strings.len(), width)
}
}
impl<T: AsRef<str>> From<&[T]> for StringArray {
fn from(v: &[T]) -> Self {
let total_len = v.iter().fold(0, |sum, item| sum + item.as_ref().len());
let mut result = StringArray::with_capacity(v.len(), total_len);
for string in v.iter() {
result.append(string.as_ref());
}
result
}
}
impl<T: AsRef<str>> From<Vec<T>> for StringArray {
fn from(v: Vec<T>) -> Self {
StringArray::from(v.as_slice())
}
}
#[derive(Clone, Debug)]
pub struct StringIter<'a> {
parent: &'a StringArray,
next: usize,
limit: usize,
}
impl<'a> Iterator for StringIter<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.next >= self.limit {
None
} else {
let result = Some(self.parent.bytes(self.next));
self.next += 1;
result
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.limit - self.next;
(remaining, Some(remaining))
}
}
impl<'a> DoubleEndedIterator for StringIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.next >= self.limit {
None
} else {
self.limit -= 1;
Some(self.parent.bytes(self.limit))
}
}
}
impl<'a> ExactSizeIterator for StringIter<'a> {}
impl<'a> FusedIterator for StringIter<'a> {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Dictionary {
strings: StringArray,
sorted_ids: IntVector,
}
impl Dictionary {
#[inline]
pub fn len(&self) -> usize {
self.strings.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn id<T: AsRef<[u8]>>(&self, string: T) -> Option<usize> {
let mut low = 0;
let mut high = self.len();
while low < high {
let mid = low + (high - low) / 2;
let id = self.sorted_ids.get(mid) as usize;
match string.as_ref().cmp(self.bytes(id)) {
Ordering::Less => high = mid,
Ordering::Equal => return Some(id),
Ordering::Greater => low = mid + 1,
}
}
None
}
pub fn bytes(&self, i: usize) -> &[u8] {
self.strings.bytes(i)
}
pub fn str(&self, i: usize) -> Result<&str, Utf8Error> {
self.strings.str(i)
}
pub fn string(&self, i: usize) -> Result<String, Utf8Error> {
self.strings.string(i)
}
}
impl Serialize for Dictionary {
fn serialize_header<T: io::Write>(&self, _: &mut T) -> io::Result<()> {
Ok(())
}
fn serialize_body<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
self.strings.serialize(writer)?;
self.sorted_ids.serialize(writer)?;
Ok(())
}
fn load<T: io::Read>(reader: &mut T) -> io::Result<Self> {
let strings = StringArray::load(reader)?;
let sorted_ids = IntVector::load(reader)?;
Ok(Dictionary {
strings, sorted_ids,
})
}
fn size_in_elements(&self) -> usize {
self.strings.size_in_elements() + self.sorted_ids.size_in_elements()
}
}
impl TryFrom<StringArray> for Dictionary {
type Error = &'static str;
fn try_from(source: StringArray) -> Result<Self, Self::Error> {
let mut sorted: Vec<usize> = Vec::with_capacity(source.len());
for i in 0..source.len() {
sorted.push(i);
}
sorted.sort_unstable_by(|a, b| source.bytes(*a).cmp(source.bytes(*b)));
for i in 1..sorted.len() {
if source.bytes(sorted[i - 1]) == source.bytes(sorted[i]) {
return Err("Cannot build a dictionary from a source with duplicate strings");
}
}
let width = if sorted.is_empty() { 1 } else { bits::bit_len(sorted.len() as u64 - 1) };
let mut sorted_ids = IntVector::with_capacity(sorted.len(), width).unwrap();
sorted_ids.extend(sorted);
Ok(Dictionary {
strings: source,
sorted_ids,
})
}
}
impl<T: AsRef<str>> TryFrom<&[T]> for Dictionary {
type Error = &'static str;
fn try_from(source: &[T]) -> Result<Self, Self::Error> {
Self::try_from(StringArray::from(source))
}
}
impl<T: AsRef<str>> TryFrom<Vec<T>> for Dictionary {
type Error = &'static str;
fn try_from(source: Vec<T>) -> Result<Self, Self::Error> {
Self::try_from(StringArray::from(source))
}
}
impl AsRef<StringArray> for Dictionary {
#[inline]
fn as_ref(&self) -> &StringArray {
&(self.strings)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Tags {
tags: BTreeMap<String, String>,
}
impl Tags {
pub fn new() -> Tags {
Tags::default()
}
pub fn len(&self) -> usize {
self.tags.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, key: &str) -> Option<&String> {
let key = key.to_lowercase();
self.tags.get(&key)
}
pub fn contains_key(&self, key: &str) -> bool {
let key = key.to_lowercase();
self.tags.contains_key(&key)
}
pub fn insert(&mut self, key: &str, value: &str) {
let key = key.to_lowercase();
let _ = self.tags.insert(key, value.to_string());
}
pub fn remove(&mut self, key: &str) -> Option<String> {
let key = key.to_lowercase();
self.tags.remove(&key)
}
pub fn iter(&self) -> TagIter<'_, String, String> {
self.tags.iter()
}
fn linearize(&self) -> StringArray {
let mut linearized: Vec<&str> = Vec::with_capacity(2 * self.len());
for (key, value) in self.iter() {
linearized.push(key); linearized.push(value);
}
StringArray::from(linearized)
}
}
impl Serialize for Tags {
fn serialize_header<T: io::Write>(&self, _: &mut T) -> io::Result<()> {
Ok(())
}
fn serialize_body<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
let linearized = self.linearize();
linearized.serialize(writer)?;
Ok(())
}
fn load<T: io::Read>(reader: &mut T) -> io::Result<Self> {
let linearized = StringArray::load(reader)?;
if linearized.len() % 2 != 0 {
return Err(Error::new(ErrorKind::InvalidData, "Tags: Key without a value"));
}
let mut result = Tags::new();
for i in 0..linearized.len() / 2 {
let key = linearized.str(2 * i).map_err(|_| Error::new(ErrorKind::InvalidData, "Tags: Invalid UTF-8 in a key"))?;
let value = linearized.str(2 * i + 1).map_err(|_| Error::new(ErrorKind::InvalidData, "Tags: Invalid UTF-8 in a value"))?;
result.insert(key, value);
}
if result.len() != linearized.len() / 2 {
return Err(Error::new(ErrorKind::InvalidData, "Tags: Duplicate keys"));
}
Ok(result)
}
fn size_in_elements(&self) -> usize {
let linearized = self.linearize();
linearized.size_in_elements()
}
}
impl AsRef<BTreeMap<String, String>> for Tags {
#[inline]
fn as_ref(&self) -> &BTreeMap<String, String> {
&(self.tags)
}
}
impl From<ByteCode> for Vec<u8> {
fn from(source: ByteCode) -> Self {
source.bytes
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ByteCode {
bytes: Vec<u8>
}
impl ByteCode {
const MASK: u8 = 0x7F;
const FLAG: u8 = 0x80;
const SHIFT: usize = 7;
pub fn new() -> Self {
ByteCode::default()
}
pub fn write(&mut self, value: usize) {
let mut value = value;
while value > (Self::MASK as usize) {
self.bytes.push(((value as u8) & Self::MASK) | Self::FLAG);
value >>= Self::SHIFT;
}
self.bytes.push(value as u8);
}
pub fn write_byte(&mut self, byte: u8) {
self.bytes.push(byte);
}
#[inline]
pub fn len(&self) -> usize {
self.bytes.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl AsRef<[u8]> for ByteCode {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
#[derive(Clone, Debug)]
pub struct ByteCodeIter<'a> {
bytes: &'a [u8],
offset: usize,
}
impl<'a> ByteCodeIter<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
ByteCodeIter {
bytes,
offset: 0,
}
}
pub fn byte(&mut self) -> Option<u8> {
if self.offset >= self.bytes.len() {
return None;
}
let result = Some(self.bytes[self.offset]);
self.offset += 1;
result
}
#[inline]
pub fn offset(&self) -> usize {
self.offset
}
}
impl<'a> Iterator for ByteCodeIter<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
let mut offset = 0;
let mut result = 0;
while self.offset < self.bytes.len() {
let value = unsafe { *self.bytes.get_unchecked(self.offset) };
self.offset += 1;
result += ((value & ByteCode::MASK) as usize) << offset;
offset += ByteCode::SHIFT;
if value & ByteCode::FLAG == 0 {
return Some(result);
}
}
None
}
}
impl<'a> FusedIterator for ByteCodeIter<'a> {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RLE {
bytes: ByteCode,
sigma: usize,
threshold: usize,
}
impl RLE {
const THRESHOLD: usize = 255;
const UNIVERSE: usize = 256;
pub fn new() -> Self {
RLE::default()
}
pub fn with_sigma(sigma: usize) -> Self {
let (sigma, threshold) = Self::sanitize(sigma);
RLE {
bytes: ByteCode::new(),
sigma,
threshold,
}
}
pub fn write(&mut self, run: Run) {
if run.len == 0 {
return;
}
assert!(run.value < self.sigma(), "RLE: Cannot encode value {} with alphabet size {}", run.value, self.sigma);
unsafe { self.write_unchecked(run); }
}
pub unsafe fn write_unchecked(&mut self, run: Run) {
if self.sigma >= Self::THRESHOLD {
self.bytes.write(run.value);
self.bytes.write(run.len - 1);
} else if run.len < self.threshold {
self.write_basic(run.value, run.len);
} else {
self.write_basic(run.value, self.threshold);
self.bytes.write(run.len - self.threshold);
}
}
pub fn write_byte(&mut self, byte: u8) {
self.bytes.write_byte(byte);
}
pub fn write_int(&mut self, value: usize) {
self.bytes.write(value);
}
#[inline]
pub fn len(&self) -> usize {
self.bytes.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn sigma(&self) -> usize {
self.sigma
}
pub fn set_sigma(&mut self, sigma: usize) {
let (sigma, threshold) = Self::sanitize(sigma);
self.sigma = sigma;
self.threshold = threshold;
}
fn write_basic(&mut self, value: usize, len: usize) {
let code = value + self.sigma * (len - 1);
self.bytes.write_byte(code as u8);
}
fn sanitize(sigma: usize) -> (usize, usize) {
let sigma = if sigma == 0 { usize::MAX } else { sigma };
let threshold = if sigma < Self::THRESHOLD { Self::UNIVERSE / sigma } else { 0 };
(sigma, threshold)
}
}
impl Default for RLE {
fn default() -> Self {
let (sigma, threshold) = Self::sanitize(0);
RLE {
bytes: ByteCode::new(),
sigma,
threshold,
}
}
}
impl AsRef<[u8]> for RLE {
#[inline]
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl From<RLE> for Vec<u8> {
fn from(source: RLE) -> Self {
Self::from(source.bytes)
}
}
#[derive(Clone, Debug)]
pub struct RLEIter<'a> {
source: ByteCodeIter<'a>,
sigma: usize,
threshold: usize,
}
impl<'a> RLEIter<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
let (sigma, threshold) = RLE::sanitize(0);
RLEIter {
source: ByteCodeIter::new(bytes),
sigma,
threshold,
}
}
pub fn with_sigma(bytes: &'a [u8], sigma: usize) -> Self {
let (sigma, threshold) = RLE::sanitize(sigma);
RLEIter {
source: ByteCodeIter::new(bytes),
sigma,
threshold,
}
}
#[inline]
pub fn byte(&mut self) -> Option<u8> {
self.source.byte()
}
#[inline]
pub fn int(&mut self) -> Option<usize> {
self.source.next()
}
#[inline]
pub fn offset(&self) -> usize {
self.source.offset()
}
#[inline]
pub fn sigma(&self) -> usize {
self.sigma
}
pub fn set_sigma(&mut self, sigma: usize) {
let (sigma, threshold) = RLE::sanitize(sigma);
self.sigma = sigma;
self.threshold = threshold;
}
}
impl<'a> Iterator for RLEIter<'a> {
type Item = Run;
fn next(&mut self) -> Option<Self::Item> {
let mut run = Run::default();
if self.sigma >= RLE::THRESHOLD {
if let Some(value) = self.source.next() { run.value = value; } else { return None; }
if let Some(len) = self.source.next() { run.len = len + 1; } else { return None; }
} else {
if let Some(byte) = self.source.byte() {
run.value = (byte as usize) % self.sigma;
run.len = (byte as usize) / self.sigma + 1;
} else {
return None;
}
if run.len == self.threshold {
if let Some(len) = self.source.next() { run.len += len; } else { return None; }
}
}
Some(run)
}
}
impl<'a> FusedIterator for RLEIter<'a> {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DisjointSets {
parents: Vec<usize>,
ranks: Vec<u8>,
offset: usize,
}
impl DisjointSets {
pub fn new(len: usize, offset: usize) -> Self {
if len > usize::MAX - offset {
panic!("DisjointSets: length {} + offset {} too large", len, offset);
}
DisjointSets {
parents: (0..len).collect(),
ranks: vec![0; len],
offset,
}
}
pub fn len(&self) -> usize {
self.parents.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn find(&mut self, value: usize) -> usize {
let mut value = value - self.offset;
while self.parents[value] != value {
let next = self.parents[value];
self.parents[value] = self.parents[next];
value = next;
}
value
}
pub fn union(&mut self, a: usize, b: usize) {
let mut a = self.find(a);
let mut b = self.find(b);
if a == b {
return;
}
if self.ranks[a] < self.ranks[b] {
mem::swap(&mut a, &mut b);
}
self.parents[b] = a;
if self.ranks[b] == self.ranks[a] {
self.ranks[a] += 1;
}
}
pub fn extract<F: Fn(usize) -> bool>(&mut self, include_value: F) -> Vec<Vec<usize>> {
let mut result: Vec<Vec<usize>> = Vec::new();
let mut root_to_set: HashMap<usize, usize> = HashMap::new();
for value in self.offset..self.len() + self.offset {
if !include_value(value) {
continue;
}
let root = self.find(value);
match root_to_set.entry(root) {
Entry::Occupied(e) => {
result[*e.get()].push(value);
},
Entry::Vacant(e) => {
e.insert(result.len());
result.push(vec![value]);
},
}
}
result
}
}