fdars_core/parallel.rs
1//! Parallel iteration abstraction for WASM compatibility.
2//!
3//! This module provides conditional parallel/sequential iteration based on
4//! the `parallel` feature flag. On native targets with the `parallel` feature,
5//! uses rayon for multi-threaded execution. On WASM or without the feature,
6//! falls back to sequential iteration.
7//!
8//! # Usage
9//!
10//! Use the `iter_maybe_parallel!` macro to conditionally parallelize iteration:
11//!
12//! ```ignore
13//! use crate::parallel::iter_maybe_parallel;
14//!
15//! let results: Vec<_> = iter_maybe_parallel!((0..n))
16//! .map(|i| expensive_computation(i))
17//! .collect();
18//! ```
19
20/// Macro for conditionally parallel iteration over ranges.
21///
22/// When the `parallel` feature is enabled, uses `into_par_iter()`.
23/// Otherwise, uses `into_iter()` for sequential execution.
24///
25/// # Examples
26///
27/// ```ignore
28/// use crate::iter_maybe_parallel;
29///
30/// // Range iteration
31/// let results: Vec<_> = iter_maybe_parallel!((0..100))
32/// .map(|i| i * 2)
33/// .collect();
34///
35/// // Vec iteration (consuming)
36/// let vec = vec![1, 2, 3];
37/// let results: Vec<_> = iter_maybe_parallel!(vec)
38/// .map(|x| x * 2)
39/// .collect();
40/// ```
41#[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 for conditionally parallel reference iteration over slices.
58///
59/// When the `parallel` feature is enabled, uses `par_iter()`.
60/// Otherwise, uses `iter()` for sequential execution.
61#[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 for conditionally parallel mutable iteration over slices.
77///
78/// When the `parallel` feature is enabled, uses `par_iter_mut()`.
79/// Otherwise, uses `iter_mut()` for sequential execution.
80#[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 for parallel/sequential chunks iteration on mutable slices.
96///
97/// # Example
98/// ```ignore
99/// use crate::maybe_par_chunks_mut;
100///
101/// maybe_par_chunks_mut!(data, chunk_size, |chunk| {
102/// // process chunk
103/// });
104/// ```
105#[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 for enumerated parallel/sequential chunks iteration.
121///
122/// # Example
123/// ```ignore
124/// use crate::maybe_par_chunks_mut_enumerate;
125///
126/// maybe_par_chunks_mut_enumerate!(data, chunk_size, |(idx, chunk)| {
127/// // process chunk at index idx
128/// });
129/// ```
130#[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
151// Re-export macros at module level
152pub 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;