Skip to content

Commit f64ba1f

Browse files
committed
array_fold: a few minor cleanups
Just things that were bugging me.
1 parent 75b93b0 commit f64ba1f

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

src/compile/builtins.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::num::NonZeroUsize;
2+
use std::sync::Arc;
23

34
use simplicity::node::CoreConstructible;
45

@@ -18,16 +19,20 @@ pub fn array_fold(size: NonZeroUsize, f: &ProgNode) -> Result<ProgNode, simplici
1819
/// Recursively fold the array using the precomputed folding functions.
1920
fn tree_fold(
2021
n: usize,
21-
f_powers_of_two: &Vec<ProgNode>,
22+
f_powers_of_two: &[ProgNode],
2223
) -> Result<ProgNode, simplicity::types::Error> {
23-
if n.is_power_of_two() {
24-
return Ok(f_powers_of_two[n.ilog2() as usize].clone());
25-
}
26-
// For n > 1 the next largest power is always >= 0
24+
// Array is a left-balanced (right-associative) binary tree.
2725
let max_pow2 = n.ilog2() as usize;
26+
debug_assert!(max_pow2 < f_powers_of_two.len());
27+
let f_right = &f_powers_of_two[max_pow2];
28+
29+
// If the tree is balanced, return precomputed solution.
2830
let size_right = 1 << max_pow2;
29-
// Array is a left-balanced (right-associative) binary tree.
30-
let f_right = f_powers_of_two.get(max_pow2).expect("max_pow2 OOB");
31+
if n == size_right {
32+
return Ok(Arc::clone(f_right));
33+
}
34+
debug_assert!(size_right < n);
35+
3136
let f_left = tree_fold(n - size_right, f_powers_of_two)?;
3237
f_array_fold(&f_left, f_right)
3338
}
@@ -51,7 +56,7 @@ pub fn array_fold(size: NonZeroUsize, f: &ProgNode) -> Result<ProgNode, simplici
5156

5257
// Precompute the folding functions for arrays of size 2^i where i < n.
5358
let n = size.get();
54-
let mut f_powers_of_two: Vec<ProgNode> = Vec::with_capacity(n.ilog2() as usize);
59+
let mut f_powers_of_two: Vec<ProgNode> = Vec::with_capacity(1 + n.ilog2() as usize);
5560

5661
// An array of size 1 is just the element itself, so f_array_fold_1 is the same as the folding function.
5762
let mut f_prev = f.clone();
@@ -60,7 +65,7 @@ pub fn array_fold(size: NonZeroUsize, f: &ProgNode) -> Result<ProgNode, simplici
6065
let mut i = 1;
6166
while i < n {
6267
f_prev = f_array_fold(&f_prev, &f_prev)?;
63-
f_powers_of_two.push(f_prev.clone());
68+
f_powers_of_two.push(Arc::clone(&f_prev));
6469
i *= 2;
6570
}
6671

0 commit comments

Comments
 (0)