1pub fn vec_to_boxed_array<T, const N: usize>(vec: Vec<T>) -> Box<[T; N]> {
13 vec.into_boxed_slice()
14 .try_into()
15 .unwrap_or_else(|_| panic!("vec_to_boxed_array: length mismatch, expected {}", N))
16}
17
18pub fn vec_to_boxed_array2<T: Clone, const N: usize, const M: usize>(
21 vec: Vec<Vec<T>>,
22) -> Box<[[T; N]; M]> {
23 let mut vec_of_slices2: Vec<[T; N]> = vec![];
24 vec.into_iter().for_each(|x: Vec<T>| {
25 let y: Box<[T]> = x.into_boxed_slice();
26 let z: Box<[T; N]> = y
27 .try_into()
28 .unwrap_or_else(|_| panic!("vec_to_boxed_array2: length mismatch inner array"));
29 let zz: &[[T; N]] = std::slice::from_ref(z.as_ref());
30 vec_of_slices2.extend_from_slice(zz);
31 });
32
33 vec_of_slices2
34 .into_boxed_slice()
35 .try_into()
36 .unwrap_or_else(|_| panic!("vec_to_boxed_array2: length mismatch outer array"))
37}
38
39pub fn vec_to_boxed_array3<T: Clone, const N: usize, const M: usize, const K: usize>(
41 vec: Vec<Vec<Vec<T>>>,
42) -> Box<[[[T; N]; M]; K]> {
43 let mut vec_of_slices2: Vec<[[T; N]; M]> = vec![];
44 vec.into_iter().for_each(|x| {
45 let r: Box<[[T; N]; M]> = vec_to_boxed_array2(x);
46 let zz: &[[[T; N]; M]] = std::slice::from_ref(r.as_ref());
47 vec_of_slices2.extend_from_slice(zz);
48 });
49
50 vec_of_slices2
51 .into_boxed_slice()
52 .try_into()
53 .unwrap_or_else(|_| panic!("vec_to_boxed_array3: length mismatch outer array"))
54}
55
56#[macro_export]
66macro_rules! box_array {
67 ($val:expr ; $len:expr) => {{
68 fn vec_to_boxed_array<T>(vec: Vec<T>) -> Box<[T; $len]> {
70 (vec.into_boxed_slice())
71 .try_into()
72 .unwrap_or_else(|_| panic!("box_array: length mismatch"))
73 }
74
75 vec_to_boxed_array(vec![$val; $len])
76 }};
77}
78
79#[macro_export]
88macro_rules! box_array2 {
89 ($val:expr; $len1:expr; $len2:expr) => {{
90 fn vec_to_boxed_array2<T: Clone, const N: usize, const M: usize>(
91 vec: Vec<Vec<T>>,
92 ) -> Box<[[T; N]; M]> {
93 let mut vec_of_slices2: Vec<[T; N]> = vec![];
94 vec.into_iter().for_each(|x: Vec<T>| {
95 let y: Box<[T]> = x.into_boxed_slice();
96 let z: Box<[T; N]> = y
97 .try_into()
98 .unwrap_or_else(|_| panic!("vec_to_boxed_array2: length mismatch inner array"));
99 let zz: &[[T; N]] = std::slice::from_ref(z.as_ref());
100 vec_of_slices2.extend_from_slice(zz);
101 });
102
103 vec_of_slices2
104 .into_boxed_slice()
105 .try_into()
106 .unwrap_or_else(|_| panic!("vec_to_boxed_array2: length mismatch outer array"))
107 }
108
109 vec_to_boxed_array2(vec![vec![$val; $len1]; $len2])
110 }};
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 use ark_ec::AffineRepr;
118 use ark_ff::{UniformRand, Zero};
119 use mina_curves::pasta::Pallas as CurvePoint;
120
121 pub type BaseField = <CurvePoint as AffineRepr>::BaseField;
122
123 #[test]
124 fn test_boxed_stack_overflow() {
127 let _boxed: Box<[[BaseField; 1000000]; 1]> =
131 vec_to_boxed_array2(vec![vec![BaseField::zero(); 1000000]; 1]);
132 let _boxed: Box<[[BaseField; 250000]; 4]> =
133 vec_to_boxed_array2(vec![vec![BaseField::zero(); 250000]; 4]);
134 let _boxed: Box<[BaseField; 1000000]> = box_array![BaseField::zero(); 1000000];
135 let _boxed: Box<[[BaseField; 250000]; 4]> = box_array2![BaseField::zero(); 250000; 4];
136 }
137
138 #[test]
139 fn test_boxed_stack_completeness() {
141 let mut rng = crate::tests::make_test_rng(None);
142
143 const ARR_SIZE: usize = 100;
144
145 let vector1: Vec<usize> = (0..ARR_SIZE).map(|i| i * i).collect();
146 let boxed1: Box<[usize; ARR_SIZE]> = vec_to_boxed_array(vector1);
147 assert!(boxed1[0] == 0);
148 assert!(boxed1[ARR_SIZE - 1] == (ARR_SIZE - 1) * (ARR_SIZE - 1));
149 let n_queries = ARR_SIZE;
150 for _ in 0..n_queries {
151 let index = usize::rand(&mut rng) % ARR_SIZE;
152 assert!(boxed1[index] == index * index);
153 }
154
155 let vector2: Vec<Vec<usize>> = (0..ARR_SIZE)
156 .map(|i| (0..ARR_SIZE).map(|j| i * j).collect())
157 .collect();
158 let boxed2: Box<[[usize; ARR_SIZE]; ARR_SIZE]> = vec_to_boxed_array2(vector2);
159 assert!(boxed2[0][0] == 0);
160 assert!(boxed2[ARR_SIZE - 1][ARR_SIZE - 1] == (ARR_SIZE - 1) * (ARR_SIZE - 1));
161 let n_queries = ARR_SIZE;
162 for _ in 0..n_queries {
163 let index1 = usize::rand(&mut rng) % ARR_SIZE;
164 let index2 = usize::rand(&mut rng) % ARR_SIZE;
165 assert!(boxed2[index1][index2] == index1 * index2);
166 }
167
168 let vector3: Vec<Vec<Vec<usize>>> = (0..ARR_SIZE)
169 .map(|i| {
170 (0..ARR_SIZE)
171 .map(|j| (0..ARR_SIZE).map(|k| i * j + k).collect())
172 .collect()
173 })
174 .collect();
175 let boxed3: Box<[[[usize; ARR_SIZE]; ARR_SIZE]; ARR_SIZE]> = vec_to_boxed_array3(vector3);
176 assert!(boxed3[0][0][0] == 0);
177 assert!(
178 boxed3[ARR_SIZE - 1][ARR_SIZE - 1][ARR_SIZE - 1]
179 == (ARR_SIZE - 1) * (ARR_SIZE - 1) + (ARR_SIZE - 1)
180 );
181 let n_queries = ARR_SIZE;
182 for _ in 0..n_queries {
183 let index1 = usize::rand(&mut rng) % ARR_SIZE;
184 let index2 = usize::rand(&mut rng) % ARR_SIZE;
185 let index3 = usize::rand(&mut rng) % ARR_SIZE;
186 assert!(boxed3[index1][index2][index3] == index1 * index2 + index3);
187 }
188 }
189}