1#[inline]
22pub fn is_parallel_available() -> bool {
23 cfg!(any(feature = "native", feature = "wasm"))
24}
25
26#[cfg(any(feature = "native", feature = "wasm"))]
31pub fn parallel_map<T, U, F>(data: &[T], f: F) -> Vec<U>
32where
33 T: Sync,
34 U: Send,
35 F: Fn(&T) -> U + Sync + Send,
36{
37 use rayon::prelude::*;
38 data.par_iter().map(f).collect()
39}
40
41#[cfg(not(any(feature = "native", feature = "wasm")))]
42pub fn parallel_map<T, U, F>(data: &[T], f: F) -> Vec<U>
43where
44 F: Fn(&T) -> U,
45{
46 data.iter().map(f).collect()
47}
48
49#[cfg(any(feature = "native", feature = "wasm"))]
54pub fn parallel_map_indexed<U, F>(count: usize, f: F) -> Vec<U>
55where
56 U: Send,
57 F: Fn(usize) -> U + Sync + Send,
58{
59 use rayon::prelude::*;
60 (0..count).into_par_iter().map(f).collect()
61}
62
63#[cfg(not(any(feature = "native", feature = "wasm")))]
64pub fn parallel_map_indexed<U, F>(count: usize, f: F) -> Vec<U>
65where
66 F: Fn(usize) -> U,
67{
68 (0..count).map(f).collect()
69}
70
71#[cfg(any(feature = "native", feature = "wasm"))]
73pub fn parallel_flat_map<T, U, I, F>(data: &[T], f: F) -> Vec<U>
74where
75 T: Sync,
76 U: Send,
77 I: rayon::iter::IntoParallelIterator<Item = U>,
78 F: Fn(&T) -> I + Sync + Send,
79{
80 use rayon::prelude::*;
81 data.par_iter().flat_map(f).collect()
82}
83
84#[cfg(not(any(feature = "native", feature = "wasm")))]
85pub fn parallel_flat_map<T, U, I, F>(data: &[T], f: F) -> Vec<U>
86where
87 I: IntoIterator<Item = U>,
88 F: Fn(&T) -> I,
89{
90 data.iter().flat_map(f).collect()
91}
92
93#[cfg(any(feature = "native", feature = "wasm"))]
95pub fn parallel_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
96where
97 T: Sync,
98 U: Send,
99 F: Fn(&T) -> Option<U> + Sync + Send,
100{
101 use rayon::prelude::*;
102 data.par_iter().filter_map(f).collect()
103}
104
105#[cfg(not(any(feature = "native", feature = "wasm")))]
106pub fn parallel_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
107where
108 F: Fn(&T) -> Option<U>,
109{
110 data.iter().filter_map(f).collect()
111}
112
113#[cfg(any(feature = "native", feature = "wasm"))]
115pub fn parallel_for_each<T, F>(data: &[T], f: F)
116where
117 T: Sync,
118 F: Fn(&T) + Sync + Send,
119{
120 use rayon::prelude::*;
121 data.par_iter().for_each(f);
122}
123
124#[cfg(not(any(feature = "native", feature = "wasm")))]
125pub fn parallel_for_each<T, F>(data: &[T], f: F)
126where
127 F: Fn(&T),
128{
129 data.iter().for_each(f);
130}
131
132#[cfg(any(feature = "native", feature = "wasm"))]
134pub fn parallel_enumerate_map<T, U, F>(data: &[T], f: F) -> Vec<U>
135where
136 T: Sync,
137 U: Send,
138 F: Fn(usize, &T) -> U + Sync + Send,
139{
140 use rayon::prelude::*;
141 data.par_iter().enumerate().map(|(i, x)| f(i, x)).collect()
142}
143
144#[cfg(not(any(feature = "native", feature = "wasm")))]
145pub fn parallel_enumerate_map<T, U, F>(data: &[T], f: F) -> Vec<U>
146where
147 F: Fn(usize, &T) -> U,
148{
149 data.iter().enumerate().map(|(i, x)| f(i, x)).collect()
150}
151
152#[cfg(any(feature = "native", feature = "wasm"))]
154pub fn parallel_enumerate_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
155where
156 T: Sync,
157 U: Send,
158 F: Fn(usize, &T) -> Option<U> + Sync + Send,
159{
160 use rayon::prelude::*;
161 data.par_iter()
162 .enumerate()
163 .filter_map(|(i, x)| f(i, x))
164 .collect()
165}
166
167#[cfg(not(any(feature = "native", feature = "wasm")))]
168pub fn parallel_enumerate_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
169where
170 F: Fn(usize, &T) -> Option<U>,
171{
172 data.iter()
173 .enumerate()
174 .filter_map(|(i, x)| f(i, x))
175 .collect()
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_parallel_map() {
184 let data = vec![1, 2, 3, 4, 5];
185 let result = parallel_map(&data, |x| x * 2);
186 assert_eq!(result, vec![2, 4, 6, 8, 10]);
187 }
188
189 #[test]
190 fn test_parallel_map_indexed() {
191 let result = parallel_map_indexed(5, |i| i * 2);
192 assert_eq!(result, vec![0, 2, 4, 6, 8]);
193 }
194
195 #[test]
196 fn test_parallel_filter_map() {
197 let data = vec![1, 2, 3, 4, 5];
198 let result = parallel_filter_map(&data, |x| if *x % 2 == 0 { Some(*x) } else { None });
199 assert_eq!(result, vec![2, 4]);
200 }
201
202 #[test]
203 fn test_parallel_enumerate_map() {
204 let data = vec![10, 20, 30];
205 let result = parallel_enumerate_map(&data, |i, x| i + *x);
206 assert_eq!(result, vec![10, 21, 32]);
207 }
208}