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<'a>(op_a: &'a mut (dyn Send + FnMut(Par)), op_b: &'a mut (dyn Send + FnMut(Par)), parallelism: Par) {
15 match parallelism {
16 Par::Seq => {
17 (op_a(parallelism), op_b(parallelism));
18 },
19 #[cfg(feature = "rayon")]
20 Par::Rayon(n_threads) => {
21 let n_threads = n_threads.get();
22 if n_threads == 1 {
23 (op_a(Par::Seq), op_b(Par::Seq));
24 } else {
25 let parallelism = Par::Rayon(core::num::NonZeroUsize::new(n_threads - n_threads / 2).unwrap());
26 spindle::for_each(2, [op_a, op_b], |op| op(parallelism));
27 }
28 },
29 };
30 }
31 let mut op_a = Some(op_a);
32 let mut op_b = Some(op_b);
33 implementation(
34 &mut |parallelism| (op_a.take().unwrap())(parallelism),
35 &mut |parallelism| (op_b.take().unwrap())(parallelism),
36 parallelism,
37 )
38 }
39
40 pub struct Ptr<T>(pub *mut T);
42 unsafe impl<T> Send for Ptr<T> {}
43 unsafe impl<T> Sync for Ptr<T> {}
44 impl<T> Copy for Ptr<T> {}
45 impl<T> Clone for Ptr<T> {
46 #[inline]
47 fn clone(&self) -> Self {
48 *self
49 }
50 }
51
52 #[inline]
54 pub fn parallelism_degree(parallelism: Par) -> usize {
55 match parallelism {
56 Par::Seq => 1,
57 #[cfg(feature = "rayon")]
58 Par::Rayon(n_threads) => n_threads.get(),
59 }
60 }
61
62 #[inline]
68 pub fn par_split_indices(n: usize, idx: usize, chunk_count: usize) -> (usize, usize) {
69 let chunk_size = n / chunk_count;
70 let rem = n % chunk_count;
71
72 let idx_to_col_start = move |idx| {
73 if idx < rem { idx * (chunk_size + 1) } else { rem + idx * chunk_size }
74 };
75
76 let start = idx_to_col_start(idx);
77 let end = idx_to_col_start(idx + 1);
78 (start, end - start)
79 }
80}
81
82pub mod simd;
84
85pub mod approx;