#![allow(missing_docs)]
pub mod bound;
#[doc(hidden)]
pub mod thread {
use crate::*;
#[inline]
pub fn join_raw(
op_a: impl Send + FnOnce(Par),
op_b: impl Send + FnOnce(Par),
parallelism: Par,
) {
fn implementation<'a>(
op_a: &'a mut (dyn Send + FnMut(Par)),
op_b: &'a mut (dyn Send + FnMut(Par)),
parallelism: Par,
) {
match parallelism {
Par::Seq => {
(op_a(parallelism), op_b(parallelism));
},
#[cfg(feature = "rayon")]
Par::Rayon(n_threads) => {
let n_threads = n_threads.get();
if n_threads == 1 {
(op_a(Par::Seq), op_b(Par::Seq));
} else {
let parallelism = Par::Rayon(
core::num::NonZeroUsize::new(
n_threads - n_threads / 2,
)
.unwrap(),
);
spindle::for_each(2, [op_a, op_b], |op| {
op(parallelism)
});
}
},
};
}
let mut op_a = Some(op_a);
let mut op_b = Some(op_b);
implementation(
&mut |parallelism| op_a.take().unwrap()(parallelism),
&mut |parallelism| op_b.take().unwrap()(parallelism),
parallelism,
)
}
pub struct Ptr<T>(pub *mut T);
unsafe impl<T> Send for Ptr<T> {}
unsafe impl<T> Sync for Ptr<T> {}
impl<T> Copy for Ptr<T> {}
impl<T> Clone for Ptr<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
#[inline]
pub fn parallelism_degree(parallelism: Par) -> usize {
match parallelism {
Par::Seq => 1,
#[cfg(feature = "rayon")]
Par::Rayon(n_threads) => n_threads.get(),
}
}
#[inline]
pub fn par_split_indices(
n: usize,
idx: usize,
chunk_count: usize,
) -> (usize, usize) {
let chunk_size = n / chunk_count;
let rem = n % chunk_count;
let idx_to_col_start = move |idx| {
if idx < rem {
idx * (chunk_size + 1)
} else {
rem + idx * chunk_size
}
};
let start = idx_to_col_start(idx);
let end = idx_to_col_start(idx + 1);
(start, end - start)
}
}
pub mod approx;
pub mod simd;