1#![allow(missing_docs)]
2
3pub mod bound;
5
6#[doc(hidden)]
7pub mod thread {
8 use crate::*;
9
10 #[inline]
13 pub fn join_raw(op_a: impl Send + FnOnce(Par), op_b: impl Send + FnOnce(Par), parallelism: Par) {
14 fn implementation(op_a: &mut (dyn Send + FnMut(Par)), op_b: &mut (dyn Send + FnMut(Par)), parallelism: Par) {
15 match parallelism {
16 Par::Seq => (op_a(parallelism), op_b(parallelism)),
17 #[cfg(feature = "rayon")]
18 Par::Rayon(n_threads) => {
19 let n_threads = n_threads.get();
20 if n_threads == 1 {
21 (op_a(Par::Seq), op_b(Par::Seq))
22 } else {
23 let parallelism = Par::Rayon(core::num::NonZeroUsize::new(n_threads - n_threads / 2).unwrap());
24 rayon::join(|| op_a(parallelism), || op_b(parallelism))
25 }
26 },
27 };
28 }
29 let mut op_a = Some(op_a);
30 let mut op_b = Some(op_b);
31 implementation(
32 &mut |parallelism| (op_a.take().unwrap())(parallelism),
33 &mut |parallelism| (op_b.take().unwrap())(parallelism),
34 parallelism,
35 )
36 }
37
38 pub struct Ptr<T>(pub *mut T);
40 unsafe impl<T> Send for Ptr<T> {}
41 unsafe impl<T> Sync for Ptr<T> {}
42 impl<T> Copy for Ptr<T> {}
43 impl<T> Clone for Ptr<T> {
44 #[inline]
45 fn clone(&self) -> Self {
46 *self
47 }
48 }
49
50 #[inline]
52 pub fn parallelism_degree(parallelism: Par) -> usize {
53 match parallelism {
54 Par::Seq => 1,
55 #[cfg(feature = "rayon")]
56 Par::Rayon(n_threads) => n_threads.get(),
57 }
58 }
59
60 #[inline]
66 pub fn par_split_indices(n: usize, idx: usize, chunk_count: usize) -> (usize, usize) {
67 let chunk_size = n / chunk_count;
68 let rem = n % chunk_count;
69
70 let idx_to_col_start = move |idx| {
71 if idx < rem { idx * (chunk_size + 1) } else { rem + idx * chunk_size }
72 };
73
74 let start = idx_to_col_start(idx);
75 let end = idx_to_col_start(idx + 1);
76 (start, end - start)
77 }
78}
79
80pub mod simd;
82
83pub mod approx;