11use std:: num:: NonZeroUsize ;
2+ use std:: sync:: Arc ;
23
34use 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