1#[cfg(any(feature = "native", feature = "wasm"))]
8pub fn is_parallel_available() -> bool {
9 true
10}
11
12#[cfg(not(any(feature = "native", feature = "wasm")))]
14pub fn is_parallel_available() -> bool {
15 false
16}
17
18#[cfg(any(feature = "native", feature = "wasm"))]
20pub fn parallel_map<T, U, F>(data: &[T], f: F) -> Vec<U>
21where
22 T: Sync,
23 U: Send,
24 F: Fn(&T) -> U + Sync + Send,
25{
26 use rayon::prelude::*;
27 data.par_iter().map(f).collect()
28}
29
30#[cfg(not(any(feature = "native", feature = "wasm")))]
32pub fn parallel_map<T, U, F>(data: &[T], f: F) -> Vec<U>
33where
34 F: Fn(&T) -> U,
35{
36 data.iter().map(f).collect()
37}
38
39#[cfg(any(feature = "native", feature = "wasm"))]
41pub fn parallel_map_indexed<U, F>(count: usize, f: F) -> Vec<U>
42where
43 U: Send,
44 F: Fn(usize) -> U + Sync + Send,
45{
46 use rayon::prelude::*;
47 (0..count).into_par_iter().map(f).collect()
48}
49
50#[cfg(not(any(feature = "native", feature = "wasm")))]
52pub fn parallel_map_indexed<U, F>(count: usize, f: F) -> Vec<U>
53where
54 F: Fn(usize) -> U,
55{
56 (0..count).map(f).collect()
57}
58
59#[cfg(any(feature = "native", feature = "wasm"))]
61pub fn parallel_for_each<T, F>(data: &[T], f: F)
62where
63 T: Sync,
64 F: Fn(&T) + Sync + Send,
65{
66 use rayon::prelude::*;
67 data.par_iter().for_each(f);
68}
69
70#[cfg(not(any(feature = "native", feature = "wasm")))]
72pub fn parallel_for_each<T, F>(data: &[T], f: F)
73where
74 F: Fn(&T),
75{
76 data.iter().for_each(f);
77}
78
79#[cfg(any(feature = "native", feature = "wasm"))]
81pub fn parallel_enumerate_map<T, U, F>(data: &[T], f: F) -> Vec<U>
82where
83 T: Sync,
84 U: Send,
85 F: Fn(usize, &T) -> U + Sync + Send,
86{
87 use rayon::prelude::*;
88 data.par_iter().enumerate().map(|(i, x)| f(i, x)).collect()
89}
90
91#[cfg(not(any(feature = "native", feature = "wasm")))]
93pub fn parallel_enumerate_map<T, U, F>(data: &[T], f: F) -> Vec<U>
94where
95 F: Fn(usize, &T) -> U,
96{
97 data.iter().enumerate().map(|(i, x)| f(i, x)).collect()
98}
99
100#[cfg(any(feature = "native", feature = "wasm"))]
102pub fn parallel_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
103where
104 T: Sync,
105 U: Send,
106 F: Fn(&T) -> Option<U> + Sync + Send,
107{
108 use rayon::prelude::*;
109 data.par_iter().filter_map(f).collect()
110}
111
112#[cfg(not(any(feature = "native", feature = "wasm")))]
114pub fn parallel_filter_map<T, U, F>(data: &[T], f: F) -> Vec<U>
115where
116 F: Fn(&T) -> Option<U>,
117{
118 data.iter().filter_map(f).collect()
119}
120
121#[cfg(any(feature = "native", feature = "wasm"))]
123pub fn parallel_flat_map<T, U, I, F>(data: &[T], f: F) -> Vec<U>
124where
125 T: Sync,
126 U: Send,
127 I: rayon::iter::IntoParallelIterator<Item = U>,
128 F: Fn(&T) -> I + Sync + Send,
129{
130 use rayon::prelude::*;
131 data.par_iter().flat_map(f).collect()
132}
133
134#[cfg(not(any(feature = "native", feature = "wasm")))]
136pub fn parallel_flat_map<T, U, I, F>(data: &[T], f: F) -> Vec<U>
137where
138 I: IntoIterator<Item = U>,
139 F: Fn(&T) -> I,
140{
141 data.iter().flat_map(f).collect()
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_parallel_map() {
150 let data = vec![1, 2, 3, 4, 5];
151 let result = parallel_map(&data, |x| x * 2);
152 assert_eq!(result, vec![2, 4, 6, 8, 10]);
153 }
154
155 #[test]
156 fn test_parallel_map_indexed() {
157 let result = parallel_map_indexed(5, |i| i * 2);
158 assert_eq!(result, vec![0, 2, 4, 6, 8]);
159 }
160
161 #[test]
162 fn test_parallel_enumerate_map() {
163 let data = vec![10, 20, 30];
164 let result = parallel_enumerate_map(&data, |i, x| (i, *x));
165 assert_eq!(result, vec![(0, 10), (1, 20), (2, 30)]);
166 }
167}