faer/utils/
mod.rs

1#![allow(missing_docs)]
2
3/// compile-time bound-checked indexing types
4pub mod bound;
5
6#[doc(hidden)]
7pub mod thread {
8	use crate::*;
9
10	/// executes the two operations, possibly in parallel, while splitting the amount of parallelism
11	/// between the two
12	#[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	/// unsafe [`Send`] and [`Sync`] pointer type
41	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	/// the amount of threads that should ideally execute an operation with the given parallelism
53	#[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	/// returns the start and length of a subsegment of `0..n`, split between `chunk_count`
63	/// consumers, for the consumer at index `idx`
64	///
65	/// for the same `n` and `chunk_count`, different values of `idx` between in `0..chunk_count`
66	/// will represent distinct subsegments
67	#[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
82/// simd helper utilities based on lifetime-bound indices
83pub mod simd;
84
85/// approximate comparators for testing purposes
86pub mod approx;