binius_field/
tower_levels.rs1use std::{
4 array,
5 ops::{Add, AddAssign, Index, IndexMut},
6};
7
8pub trait TowerLevel: 'static {
20 const WIDTH: usize;
22
23 type Data<T>: AsMut<[T]>
25 + AsRef<[T]>
26 + Sized
27 + Index<usize, Output = T>
28 + IndexMut<usize, Output = T>;
29 type Base: TowerLevel;
30
31 #[allow(clippy::type_complexity)]
33 fn split<T>(
34 data: &Self::Data<T>,
35 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>);
36
37 #[allow(clippy::type_complexity)]
39 fn split_mut<T>(
40 data: &mut Self::Data<T>,
41 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>);
42
43 #[allow(clippy::type_complexity)]
45 fn join<T: Copy + Default>(
46 first: &<Self::Base as TowerLevel>::Data<T>,
47 second: &<Self::Base as TowerLevel>::Data<T>,
48 ) -> Self::Data<T>;
49
50 fn from_fn<T: Copy>(f: impl FnMut(usize) -> T) -> Self::Data<T>;
52
53 fn default<T: Copy + Default>() -> Self::Data<T> {
55 Self::from_fn(|_| T::default())
56 }
57}
58
59pub trait TowerLevelWithArithOps: TowerLevel {
60 #[inline(always)]
61 fn add_into<T: AddAssign + Copy>(
62 field_element: &Self::Data<T>,
63 destination: &mut Self::Data<T>,
64 ) {
65 for i in 0..Self::WIDTH {
66 destination[i] += field_element[i];
67 }
68 }
69
70 #[inline(always)]
71 fn copy_into<T: Copy>(field_element: &Self::Data<T>, destination: &mut Self::Data<T>) {
72 for i in 0..Self::WIDTH {
73 destination[i] = field_element[i];
74 }
75 }
76
77 #[inline(always)]
78 fn sum<T: Copy + Add<Output = T>>(
79 field_element_a: &Self::Data<T>,
80 field_element_b: &Self::Data<T>,
81 ) -> Self::Data<T> {
82 Self::from_fn(|i| field_element_a[i] + field_element_b[i])
83 }
84}
85
86impl<T: TowerLevel> TowerLevelWithArithOps for T {}
87
88pub struct TowerLevel64;
89
90impl TowerLevel for TowerLevel64 {
91 const WIDTH: usize = 64;
92
93 type Data<T> = [T; 64];
94 type Base = TowerLevel32;
95
96 #[inline(always)]
97 fn split<T>(
98 data: &Self::Data<T>,
99 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
100 ((data[0..32].try_into().unwrap()), (data[32..64].try_into().unwrap()))
101 }
102
103 #[inline(always)]
104 fn split_mut<T>(
105 data: &mut Self::Data<T>,
106 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
107 let (chunk_1, chunk_2) = data.split_at_mut(32);
108
109 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
110 }
111
112 #[inline(always)]
113 fn join<T: Copy + Default>(
114 left: &<Self::Base as TowerLevel>::Data<T>,
115 right: &<Self::Base as TowerLevel>::Data<T>,
116 ) -> Self::Data<T> {
117 let mut result = [T::default(); 64];
118 result[..32].copy_from_slice(left);
119 result[32..].copy_from_slice(right);
120 result
121 }
122
123 #[inline(always)]
124 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
125 array::from_fn(f)
126 }
127}
128
129pub struct TowerLevel32;
130
131impl TowerLevel for TowerLevel32 {
132 const WIDTH: usize = 32;
133
134 type Data<T> = [T; 32];
135 type Base = TowerLevel16;
136
137 #[inline(always)]
138 fn split<T>(
139 data: &Self::Data<T>,
140 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
141 ((data[0..16].try_into().unwrap()), (data[16..32].try_into().unwrap()))
142 }
143
144 #[inline(always)]
145 fn split_mut<T>(
146 data: &mut Self::Data<T>,
147 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
148 let (chunk_1, chunk_2) = data.split_at_mut(16);
149
150 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
151 }
152
153 #[inline(always)]
154 fn join<T: Copy + Default>(
155 left: &<Self::Base as TowerLevel>::Data<T>,
156 right: &<Self::Base as TowerLevel>::Data<T>,
157 ) -> Self::Data<T> {
158 let mut result = [T::default(); 32];
159 result[..16].copy_from_slice(left);
160 result[16..].copy_from_slice(right);
161 result
162 }
163
164 #[inline(always)]
165 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
166 array::from_fn(f)
167 }
168}
169
170pub struct TowerLevel16;
171
172impl TowerLevel for TowerLevel16 {
173 const WIDTH: usize = 16;
174
175 type Data<T> = [T; 16];
176 type Base = TowerLevel8;
177
178 #[inline(always)]
179 fn split<T>(
180 data: &Self::Data<T>,
181 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
182 ((data[0..8].try_into().unwrap()), (data[8..16].try_into().unwrap()))
183 }
184
185 #[inline(always)]
186 fn split_mut<T>(
187 data: &mut Self::Data<T>,
188 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
189 let (chunk_1, chunk_2) = data.split_at_mut(8);
190
191 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
192 }
193
194 #[inline(always)]
195 fn join<T: Copy + Default>(
196 left: &<Self::Base as TowerLevel>::Data<T>,
197 right: &<Self::Base as TowerLevel>::Data<T>,
198 ) -> Self::Data<T> {
199 let mut result = [T::default(); 16];
200 result[..8].copy_from_slice(left);
201 result[8..].copy_from_slice(right);
202 result
203 }
204
205 #[inline(always)]
206 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
207 array::from_fn(f)
208 }
209}
210
211pub struct TowerLevel8;
212
213impl TowerLevel for TowerLevel8 {
214 const WIDTH: usize = 8;
215
216 type Data<T> = [T; 8];
217 type Base = TowerLevel4;
218
219 #[inline(always)]
220 fn split<T>(
221 data: &Self::Data<T>,
222 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
223 ((data[0..4].try_into().unwrap()), (data[4..8].try_into().unwrap()))
224 }
225
226 #[inline(always)]
227 fn split_mut<T>(
228 data: &mut Self::Data<T>,
229 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
230 let (chunk_1, chunk_2) = data.split_at_mut(4);
231
232 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
233 }
234
235 #[inline(always)]
236 fn join<T: Copy + Default>(
237 left: &<Self::Base as TowerLevel>::Data<T>,
238 right: &<Self::Base as TowerLevel>::Data<T>,
239 ) -> Self::Data<T> {
240 let mut result = [T::default(); 8];
241 result[..4].copy_from_slice(left);
242 result[4..].copy_from_slice(right);
243 result
244 }
245
246 #[inline(always)]
247 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
248 array::from_fn(f)
249 }
250}
251
252pub struct TowerLevel4;
253
254impl TowerLevel for TowerLevel4 {
255 const WIDTH: usize = 4;
256
257 type Data<T> = [T; 4];
258 type Base = TowerLevel2;
259
260 #[inline(always)]
261 fn split<T>(
262 data: &Self::Data<T>,
263 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
264 ((data[0..2].try_into().unwrap()), (data[2..4].try_into().unwrap()))
265 }
266
267 #[inline(always)]
268 fn split_mut<T>(
269 data: &mut Self::Data<T>,
270 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
271 let (chunk_1, chunk_2) = data.split_at_mut(2);
272
273 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
274 }
275
276 #[inline(always)]
277 fn join<T: Copy + Default>(
278 left: &<Self::Base as TowerLevel>::Data<T>,
279 right: &<Self::Base as TowerLevel>::Data<T>,
280 ) -> Self::Data<T> {
281 let mut result = [T::default(); 4];
282 result[..2].copy_from_slice(left);
283 result[2..].copy_from_slice(right);
284 result
285 }
286
287 #[inline(always)]
288 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
289 array::from_fn(f)
290 }
291}
292
293pub struct TowerLevel2;
294
295impl TowerLevel for TowerLevel2 {
296 const WIDTH: usize = 2;
297
298 type Data<T> = [T; 2];
299 type Base = TowerLevel1;
300
301 #[inline(always)]
302 fn split<T>(
303 data: &Self::Data<T>,
304 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
305 ((data[0..1].try_into().unwrap()), (data[1..2].try_into().unwrap()))
306 }
307
308 #[inline(always)]
309 fn split_mut<T>(
310 data: &mut Self::Data<T>,
311 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
312 let (chunk_1, chunk_2) = data.split_at_mut(1);
313
314 ((chunk_1.try_into().unwrap()), (chunk_2.try_into().unwrap()))
315 }
316
317 #[inline(always)]
318 fn join<T: Copy + Default>(
319 left: &<Self::Base as TowerLevel>::Data<T>,
320 right: &<Self::Base as TowerLevel>::Data<T>,
321 ) -> Self::Data<T> {
322 let mut result = [T::default(); 2];
323 result[..1].copy_from_slice(left);
324 result[1..].copy_from_slice(right);
325 result
326 }
327
328 #[inline(always)]
329 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
330 array::from_fn(f)
331 }
332}
333
334pub struct TowerLevel1;
335
336impl TowerLevel for TowerLevel1 {
337 const WIDTH: usize = 1;
338
339 type Data<T> = [T; 1];
340 type Base = Self;
341
342 #[inline(always)]
345 fn split<T>(
346 _data: &Self::Data<T>,
347 ) -> (&<Self::Base as TowerLevel>::Data<T>, &<Self::Base as TowerLevel>::Data<T>) {
348 unreachable!()
349 }
350
351 #[inline(always)]
352 fn split_mut<T>(
353 _data: &mut Self::Data<T>,
354 ) -> (&mut <Self::Base as TowerLevel>::Data<T>, &mut <Self::Base as TowerLevel>::Data<T>) {
355 unreachable!()
356 }
357
358 #[inline(always)]
359 fn join<T: Copy + Default>(
360 _left: &<Self::Base as TowerLevel>::Data<T>,
361 _right: &<Self::Base as TowerLevel>::Data<T>,
362 ) -> Self::Data<T> {
363 unreachable!()
364 }
365
366 #[inline(always)]
367 fn from_fn<T>(f: impl FnMut(usize) -> T) -> Self::Data<T> {
368 array::from_fn(f)
369 }
370}