vortex_array/optimizer/
mod.rs1use vortex_error::VortexResult;
5use vortex_error::vortex_bail;
6
7use crate::Array;
8use crate::array::ArrayRef;
9
10pub mod rules;
11
12pub trait ArrayOptimizer {
13 fn optimize(&self) -> VortexResult<ArrayRef>;
15
16 fn optimize_recursive(&self) -> VortexResult<ArrayRef>;
18}
19
20impl ArrayOptimizer for ArrayRef {
21 fn optimize(&self) -> VortexResult<ArrayRef> {
22 Ok(try_optimize(self)?.unwrap_or_else(|| self.clone()))
23 }
24
25 fn optimize_recursive(&self) -> VortexResult<ArrayRef> {
26 Ok(try_optimize_recursive(self)?.unwrap_or_else(|| self.clone()))
27 }
28}
29
30fn try_optimize(array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
31 let mut current_array = array.clone();
32 let mut any_optimizations = false;
33
34 let mut loop_counter = 0;
36 'outer: loop {
37 if loop_counter > 100 {
38 vortex_bail!("Exceeded maximum optimization iterations (possible infinite loop)");
39 }
40 loop_counter += 1;
41
42 if let Some(new_array) = current_array.vtable().reduce(¤t_array)? {
43 current_array = new_array;
44 any_optimizations = true;
45 continue;
46 }
47
48 for (idx, child) in current_array.children().iter().enumerate() {
51 if let Some(new_array) = child.vtable().reduce_parent(child, ¤t_array, idx)? {
52 current_array = new_array;
54 any_optimizations = true;
55
56 continue 'outer;
58 }
59 }
60
61 break;
63 }
64
65 if any_optimizations {
66 Ok(Some(current_array))
67 } else {
68 Ok(None)
69 }
70}
71
72fn try_optimize_recursive(array: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
73 let mut current_array = array.clone();
74 let mut any_optimizations = false;
75
76 if let Some(new_array) = try_optimize(¤t_array)? {
77 current_array = new_array;
78 any_optimizations = true;
79 }
80
81 let mut new_children = Vec::with_capacity(current_array.nchildren());
82 let mut any_child_optimized = false;
83 for child in current_array.children() {
84 if let Some(new_child) = try_optimize_recursive(&child)? {
85 new_children.push(new_child);
86 any_child_optimized = true;
87 } else {
88 new_children.push(child.clone());
89 }
90 }
91
92 if any_child_optimized {
93 current_array = current_array.with_children(new_children)?;
94 any_optimizations = true;
95 }
96
97 if any_optimizations {
98 Ok(Some(current_array))
99 } else {
100 Ok(None)
101 }
102}