#[cfg(feature = "parallel")]
pub(crate) use rayon::prelude::*;
use qip_iterators::into_iter;
use std::sync::{Arc, Mutex};
pub fn entwine_bits(
n: usize,
mut selector: usize,
mut off_bits: usize,
mut on_bits: usize,
) -> usize {
let mut result = 0;
for i in 0..n {
if selector & 1 == 0 {
let bit = off_bits & 1;
off_bits >>= 1;
result |= bit << i;
} else {
let bit = on_bits & 1;
on_bits >>= 1;
result |= bit << i;
}
selector >>= 1;
}
result
}
#[inline]
pub fn extract_bits(num: usize, indices: &[usize]) -> usize {
indices.iter().enumerate().fold(0, |acc, (i, index)| {
let bit = (num >> index) & 1;
acc | (bit << i)
})
}
pub fn transpose_sparse<T: Sync + Send>(sparse_mat: Vec<Vec<(usize, T)>>) -> Vec<Vec<(usize, T)>> {
let sparse_len = sparse_mat.len();
let flat_mat: Vec<_> = into_iter!(sparse_mat)
.enumerate()
.map(|(row, v)| {
let v: Vec<_> = v.into_iter().map(|(col, val)| (col, (row, val))).collect();
v
})
.flatten()
.collect();
let mut col_mat = <Vec<Arc<Mutex<Vec<(usize, T)>>>>>::new();
col_mat.resize_with(sparse_len, || Arc::new(Mutex::new(vec![])));
into_iter!(flat_mat).for_each(|(col, (row, val)): (usize, (usize, T))| {
col_mat[col].lock().unwrap().push((row, val))
});
let col_mat: Vec<_> = into_iter!(col_mat)
.map(|v| {
if let Ok(v) = Arc::try_unwrap(v) {
v.into_inner().unwrap()
} else {
panic!()
}
})
.collect();
into_iter!(col_mat)
.map(|mut v: Vec<(usize, T)>| {
v.sort_by_key(|(row, _)| *row);
v
})
.collect()
}