petaplot_core/compute/
simd.rs1use bytemuck::{Pod, Zeroable};
2use rayon::prelude::*;
3
4#[repr(C)]
7#[derive(Debug, Clone, Copy, PartialEq, Pod, Zeroable)]
8pub struct MinMaxPair {
9 pub min: f32,
10 pub max: f32,
11}
12
13impl MinMaxPair {
14 #[inline]
15 pub fn new(min: f32, max: f32) -> Self {
16 Self { min, max }
17 }
18
19 #[inline]
20 pub fn identity() -> Self {
21 Self {
22 min: f32::MAX,
23 max: f32::MIN,
24 }
25 }
26
27 #[inline]
28 pub fn combine(&self, other: &Self) -> Self {
29 Self {
30 min: self.min.min(other.min),
31 max: self.max.max(other.max),
32 }
33 }
34}
35
36pub fn reduce_min_max_chunk(data: &[f32], bin_size: usize) -> Vec<MinMaxPair> {
40 if data.is_empty() || bin_size == 0 {
41 return Vec::new();
42 }
43
44 data.par_chunks(bin_size)
45 .map(|chunk| {
46 let mut min_val = f32::MAX;
47 let mut max_val = f32::MIN;
48
49 for &val in chunk {
51 if val < min_val {
52 min_val = val;
53 }
54 if val > max_val {
55 max_val = val;
56 }
57 }
58
59 MinMaxPair {
60 min: min_val,
61 max: max_val,
62 }
63 })
64 .collect()
65}
66
67pub fn reduce_min_max_pairs(pairs: &[MinMaxPair], bin_size: usize) -> Vec<MinMaxPair> {
69 if pairs.is_empty() || bin_size == 0 {
70 return Vec::new();
71 }
72
73 pairs
74 .par_chunks(bin_size)
75 .map(|chunk| {
76 let mut combined = MinMaxPair::identity();
77 for pair in chunk {
78 combined = combined.combine(pair);
79 }
80 combined
81 })
82 .collect()
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_reduce_min_max_chunk_simple() {
91 let data = vec![1.0, 5.0, 2.0, 8.0, 3.0, 0.5, -4.0, 10.0, 7.0];
92 let bin_size = 3;
93
94 let result = reduce_min_max_chunk(&data, bin_size);
95 assert_eq!(result.len(), 3);
96 assert_eq!(result[0], MinMaxPair::new(1.0, 5.0));
97 assert_eq!(result[1], MinMaxPair::new(0.5, 8.0));
98 assert_eq!(result[2], MinMaxPair::new(-4.0, 10.0));
99 }
100
101 #[test]
102 fn test_reduce_min_max_pairs_hierarchical() {
103 let pairs = vec![
104 MinMaxPair::new(1.0, 5.0),
105 MinMaxPair::new(-2.0, 3.0),
106 MinMaxPair::new(0.0, 10.0),
107 MinMaxPair::new(4.0, 6.0),
108 ];
109
110 let result = reduce_min_max_pairs(&pairs, 2);
111 assert_eq!(result.len(), 2);
112 assert_eq!(result[0], MinMaxPair::new(-2.0, 5.0));
113 assert_eq!(result[1], MinMaxPair::new(0.0, 10.0));
114 }
115}