1#[macro_export]
42macro_rules! iter_maybe_parallel {
43 ($expr:expr) => {{
44 #[cfg(feature = "parallel")]
45 {
46 use rayon::iter::IntoParallelIterator;
47
48 IntoParallelIterator::into_par_iter($expr)
49 }
50 #[cfg(not(feature = "parallel"))]
51 {
52 IntoIterator::into_iter($expr)
53 }
54 }};
55}
56
57#[macro_export]
62macro_rules! slice_maybe_parallel {
63 ($expr:expr) => {{
64 #[cfg(feature = "parallel")]
65 {
66 use rayon::prelude::*;
67 $expr.par_iter()
68 }
69 #[cfg(not(feature = "parallel"))]
70 {
71 $expr.iter()
72 }
73 }};
74}
75
76#[macro_export]
81macro_rules! slice_maybe_parallel_mut {
82 ($expr:expr) => {{
83 #[cfg(feature = "parallel")]
84 {
85 use rayon::prelude::*;
86 $expr.par_iter_mut()
87 }
88 #[cfg(not(feature = "parallel"))]
89 {
90 $expr.iter_mut()
91 }
92 }};
93}
94
95#[macro_export]
106macro_rules! maybe_par_chunks_mut {
107 ($slice:expr, $chunk_size:expr, $closure:expr) => {{
108 #[cfg(feature = "parallel")]
109 {
110 use rayon::prelude::*;
111 $slice.par_chunks_mut($chunk_size).for_each($closure);
112 }
113 #[cfg(not(feature = "parallel"))]
114 {
115 $slice.chunks_mut($chunk_size).for_each($closure);
116 }
117 }};
118}
119
120#[macro_export]
131macro_rules! maybe_par_chunks_mut_enumerate {
132 ($slice:expr, $chunk_size:expr, $closure:expr) => {{
133 #[cfg(feature = "parallel")]
134 {
135 use rayon::prelude::*;
136 $slice
137 .par_chunks_mut($chunk_size)
138 .enumerate()
139 .for_each($closure);
140 }
141 #[cfg(not(feature = "parallel"))]
142 {
143 $slice
144 .chunks_mut($chunk_size)
145 .enumerate()
146 .for_each($closure);
147 }
148 }};
149}
150
151pub use iter_maybe_parallel;
153pub use maybe_par_chunks_mut;
154pub use maybe_par_chunks_mut_enumerate;
155pub use slice_maybe_parallel;
156pub use slice_maybe_parallel_mut;
157
158#[cfg(test)]
159mod tests {
160 #[cfg(feature = "parallel")]
161 use rayon::iter::ParallelIterator;
162
163 #[test]
164 fn test_iter_maybe_parallel_range() {
165 let mut result: Vec<usize> = iter_maybe_parallel!(0..10).map(|i| i * 2).collect();
166 result.sort(); assert_eq!(result, vec![0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
168 }
169
170 #[test]
171 fn test_slice_maybe_parallel_map() {
172 let vec = vec![1.0_f64, 2.0, 3.0, 4.0, 5.0];
173 let mut result: Vec<f64> = slice_maybe_parallel!(vec).map(|&x| x * x).collect();
174 result.sort_by(|a, b| a.partial_cmp(b).unwrap());
175 assert_eq!(result, vec![1.0, 4.0, 9.0, 16.0, 25.0]);
176 }
177
178 #[test]
179 fn test_slice_maybe_parallel_mut() {
180 let mut vec = vec![1.0_f64, 2.0, 3.0, 4.0];
181 slice_maybe_parallel_mut!(vec).for_each(|x| *x *= 3.0);
182 assert_eq!(vec, vec![3.0, 6.0, 9.0, 12.0]);
183 }
184
185 #[test]
186 fn test_maybe_par_chunks_mut() {
187 let mut vec = vec![0.0_f64; 12];
188 maybe_par_chunks_mut!(vec, 4, |chunk: &mut [f64]| {
189 for x in chunk.iter_mut() {
190 *x = 1.0;
191 }
192 });
193 assert!(vec.iter().all(|&x| x == 1.0));
194 }
195
196 #[test]
197 fn test_maybe_par_chunks_mut_enumerate() {
198 let mut vec = vec![0.0_f64; 12];
199 maybe_par_chunks_mut_enumerate!(vec, 4, |(idx, chunk): (usize, &mut [f64])| {
200 for x in chunk.iter_mut() {
201 *x = idx as f64;
202 }
203 });
204 assert_eq!(
205 vec,
206 vec![0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0]
207 );
208 }
209}