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(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	/// unsafe [`Send`] and [`Sync`] pointer type
39	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	/// the amount of threads that should ideally execute an operation with the given parallelism
51	#[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	/// returns the start and length of a subsegment of `0..n`, split between `chunk_count`
61	/// consumers, for the consumer at index `idx`
62	///
63	/// for the same `n` and `chunk_count`, different values of `idx` between in `0..chunk_count`
64	/// will represent distinct subsegments
65	#[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
80/// simd helper utilities based on lifetime-bound indices
81pub mod simd;
82
83/// approximate comparators for testing purposes
84pub mod approx;