1use std::{
4 ops::{Deref, DerefMut, Index, IndexMut},
5 slice,
6};
7
8use binius_field::{
9 Field, PackedField,
10 packed::{get_packed_slice_unchecked, set_packed_slice_unchecked},
11};
12use binius_utils::{
13 checked_arithmetics::{checked_log_2, strict_log_2},
14 rayon::{prelude::*, slice::ParallelSlice},
15};
16use bytemuck::zeroed_vec;
17
18use crate::Error;
19
20#[derive(Debug, Clone, Eq)]
26pub struct FieldBuffer<P: PackedField, Data: Deref<Target = [P]> = Box<[P]>> {
27 log_len: usize,
29 values: Data,
31}
32
33impl<P: PackedField, Data: Deref<Target = [P]>> PartialEq for FieldBuffer<P, Data> {
34 fn eq(&self, other: &Self) -> bool {
35 if self.log_len < P::LOG_WIDTH {
38 let iter_1 = self
39 .values
40 .first()
41 .expect("len >= 1")
42 .iter()
43 .take(1 << self.log_len);
44 let iter_2 = other
45 .values
46 .first()
47 .expect("len >= 1")
48 .iter()
49 .take(1 << self.log_len);
50 iter_1.eq(iter_2)
51 } else {
52 let prefix = 1 << (self.log_len - P::LOG_WIDTH);
53 self.log_len == other.log_len && self.values[..prefix] == other.values[..prefix]
54 }
55 }
56}
57
58impl<P: PackedField> FieldBuffer<P> {
59 pub fn from_values(values: &[P::Scalar]) -> Result<Self, Error> {
65 let Some(log_len) = strict_log_2(values.len()) else {
66 return Err(Error::PowerOfTwoLengthRequired);
67 };
68
69 Self::from_values_truncated(values, log_len)
70 }
71
72 pub fn from_values_truncated(values: &[P::Scalar], log_cap: usize) -> Result<Self, Error> {
81 if !values.len().is_power_of_two() {
82 return Err(Error::PowerOfTwoLengthRequired);
83 }
84
85 let log_len = values.len().ilog2() as usize;
86 if log_len > log_cap {
87 return Err(Error::IncorrectArgumentLength {
88 arg: "values".to_string(),
89 expected: 1 << log_cap,
90 });
91 }
92
93 let packed_cap = 1 << log_cap.saturating_sub(P::LOG_WIDTH);
94 let mut packed_values = Vec::with_capacity(packed_cap);
95 packed_values.extend(
96 values
97 .chunks(P::WIDTH)
98 .map(|chunk| P::from_scalars(chunk.iter().copied())),
99 );
100 packed_values.resize(packed_cap, P::zero());
101
102 Ok(Self {
103 log_len,
104 values: packed_values.into_boxed_slice(),
105 })
106 }
107
108 pub fn zeros(log_len: usize) -> Self {
110 Self::zeros_truncated(log_len, log_len).expect("log_len == log_cap")
111 }
112
113 pub fn zeros_truncated(log_len: usize, log_cap: usize) -> Result<Self, Error> {
117 if log_len > log_cap {
118 return Err(Error::IncorrectArgumentLength {
119 arg: "log_len".to_string(),
120 expected: log_cap,
121 });
122 }
123 let packed_len = 1 << log_cap.saturating_sub(P::LOG_WIDTH);
124 let values = zeroed_vec(packed_len).into_boxed_slice();
125 Ok(Self { log_len, values })
126 }
127}
128
129#[allow(clippy::len_without_is_empty)]
130impl<P: PackedField, Data: Deref<Target = [P]>> FieldBuffer<P, Data> {
131 pub fn new(log_len: usize, values: Data) -> Result<Self, Error> {
138 let expected_packed_len = 1 << log_len.saturating_sub(P::LOG_WIDTH);
139 if values.len() != expected_packed_len {
140 return Err(Error::IncorrectArgumentLength {
141 arg: "values".to_string(),
142 expected: expected_packed_len,
143 });
144 }
145 Self::new_truncated(log_len, values)
146 }
147
148 pub fn new_truncated(log_len: usize, values: Data) -> Result<Self, Error> {
155 let min_packed_len = 1 << log_len.saturating_sub(P::LOG_WIDTH);
156 if values.len() < min_packed_len {
157 return Err(Error::IncorrectArgumentLength {
158 arg: "values".to_string(),
159 expected: min_packed_len,
160 });
161 }
162
163 if !values.len().is_power_of_two() {
164 return Err(Error::PowerOfTwoLengthRequired);
165 }
166
167 Ok(Self { log_len, values })
168 }
169
170 pub fn log_cap(&self) -> usize {
172 checked_log_2(self.values.len()) + P::LOG_WIDTH
173 }
174
175 pub fn cap(&self) -> usize {
177 1 << self.log_cap()
178 }
179
180 pub fn log_len(&self) -> usize {
182 self.log_len
183 }
184
185 pub fn len(&self) -> usize {
187 1 << self.log_len
188 }
189
190 pub fn to_ref(&self) -> FieldSlice<'_, P> {
192 FieldSlice::from_slice(self.log_len, self.as_ref())
193 .expect("log_len matches values.len() by struct invariant")
194 }
195
196 pub fn get(&self, index: usize) -> P::Scalar {
202 self.get_checked(index)
203 .expect("precondition: index is in range")
204 }
205
206 pub fn get_checked(&self, index: usize) -> Result<P::Scalar, Error> {
212 if index >= self.len() {
213 return Err(Error::ArgumentRangeError {
214 arg: "index".to_string(),
215 range: 0..self.len(),
216 });
217 }
218
219 let val = unsafe { get_packed_slice_unchecked(&self.values, index) };
222 Ok(val)
223 }
224
225 pub fn iter_scalars(&self) -> impl Iterator<Item = P::Scalar> + Send + Clone + '_ {
227 P::iter_slice(self.as_ref()).take(self.len())
228 }
229
230 pub fn chunk(
236 &self,
237 log_chunk_size: usize,
238 chunk_index: usize,
239 ) -> Result<FieldSlice<'_, P>, Error> {
240 if log_chunk_size > self.log_len {
241 return Err(Error::ArgumentRangeError {
242 arg: "log_chunk_size".to_string(),
243 range: 0..self.log_len + 1,
244 });
245 }
246
247 let chunk_count = 1 << (self.log_len - log_chunk_size);
248 if chunk_index >= chunk_count {
249 return Err(Error::ArgumentRangeError {
250 arg: "chunk_index".to_string(),
251 range: 0..chunk_count,
252 });
253 }
254
255 let values = if log_chunk_size >= P::LOG_WIDTH {
256 let packed_log_chunk_size = log_chunk_size - P::LOG_WIDTH;
257 let chunk =
258 &self.values[chunk_index << packed_log_chunk_size..][..1 << packed_log_chunk_size];
259 FieldSliceData::Slice(chunk)
260 } else {
261 let packed_log_chunks = P::LOG_WIDTH - log_chunk_size;
262 let packed = self.values[chunk_index >> packed_log_chunks];
263 let chunk_subindex = chunk_index & ((1 << packed_log_chunks) - 1);
264 let chunk = P::from_scalars(
265 (0..1 << log_chunk_size).map(|i| packed.get(chunk_subindex << log_chunk_size | i)),
266 );
267 FieldSliceData::Single(chunk)
268 };
269
270 Ok(FieldBuffer {
271 log_len: log_chunk_size,
272 values,
273 })
274 }
275
276 pub fn chunks(
283 &self,
284 log_chunk_size: usize,
285 ) -> Result<impl Iterator<Item = FieldSlice<'_, P>> + Clone, Error> {
286 if log_chunk_size < P::LOG_WIDTH || log_chunk_size > self.log_len {
287 return Err(Error::ArgumentRangeError {
288 arg: "log_chunk_size".to_string(),
289 range: P::LOG_WIDTH..self.log_len + 1,
290 });
291 }
292
293 let chunk_count = 1 << (self.log_len - log_chunk_size);
294 let packed_chunk_size = 1 << (log_chunk_size - P::LOG_WIDTH);
295 let chunks = self
296 .values
297 .chunks(packed_chunk_size)
298 .take(chunk_count)
299 .map(move |chunk| FieldBuffer {
300 log_len: log_chunk_size,
301 values: FieldSliceData::Slice(chunk),
302 });
303
304 Ok(chunks)
305 }
306
307 pub fn chunks_par(
314 &self,
315 log_chunk_size: usize,
316 ) -> Result<impl IndexedParallelIterator<Item = FieldSlice<'_, P>>, Error> {
317 if log_chunk_size < P::LOG_WIDTH || log_chunk_size > self.log_len {
318 return Err(Error::ArgumentRangeError {
319 arg: "log_chunk_size".to_string(),
320 range: P::LOG_WIDTH..self.log_len + 1,
321 });
322 }
323
324 let log_len = log_chunk_size.min(self.log_len);
325 let packed_chunk_size = 1 << (log_chunk_size - P::LOG_WIDTH);
326 let chunks = self
327 .values
328 .par_chunks(packed_chunk_size)
329 .map(move |chunk| FieldBuffer {
330 log_len,
331 values: FieldSliceData::Slice(chunk),
332 });
333
334 Ok(chunks)
335 }
336
337 pub fn split_half(&self) -> Result<(FieldSlice<'_, P>, FieldSlice<'_, P>), Error> {
343 if self.log_len == 0 {
344 return Err(Error::CannotSplit);
345 }
346
347 let new_log_len = self.log_len - 1;
348 let (first, second) = if new_log_len < P::LOG_WIDTH {
349 let packed = self.values[0];
352 let zeros = P::default();
353
354 let (first_half, second_half) = packed.interleave(zeros, new_log_len);
355
356 let first = FieldBuffer {
357 log_len: new_log_len,
358 values: FieldSliceData::Single(first_half),
359 };
360 let second = FieldBuffer {
361 log_len: new_log_len,
362 values: FieldSliceData::Single(second_half),
363 };
364
365 (first, second)
366 } else {
367 let half_len = 1 << (new_log_len - P::LOG_WIDTH);
369 let (first_half, second_half) = self.values.split_at(half_len);
370 let second_half = &second_half[..half_len];
371
372 let first = FieldBuffer {
373 log_len: new_log_len,
374 values: FieldSliceData::Slice(first_half),
375 };
376 let second = FieldBuffer {
377 log_len: new_log_len,
378 values: FieldSliceData::Slice(second_half),
379 };
380
381 (first, second)
382 };
383
384 Ok((first, second))
385 }
386}
387
388impl<P: PackedField, Data: DerefMut<Target = [P]>> FieldBuffer<P, Data> {
389 pub fn to_mut(&mut self) -> FieldSliceMut<'_, P> {
391 FieldSliceMut::from_slice(self.log_len, self.as_mut())
392 .expect("log_len matches values.len() by struct invariant")
393 }
394
395 pub fn set(&mut self, index: usize, value: P::Scalar) {
401 self.set_checked(index, value)
402 .expect("precondition: index is in range");
403 }
404
405 pub fn set_checked(&mut self, index: usize, value: P::Scalar) -> Result<(), Error> {
411 if index >= self.len() {
412 return Err(Error::ArgumentRangeError {
413 arg: "index".to_string(),
414 range: 0..self.len(),
415 });
416 }
417
418 unsafe { set_packed_slice_unchecked(&mut self.values, index, value) };
421 Ok(())
422 }
423
424 pub fn truncate(&mut self, new_log_len: usize) {
428 self.log_len = self.log_len.min(new_log_len);
429 }
430
431 pub fn zero_extend(&mut self, new_log_len: usize) -> Result<(), Error> {
438 if new_log_len <= self.log_len {
439 return Ok(());
440 }
441
442 if new_log_len > self.log_cap() {
443 return Err(Error::IncorrectArgumentLength {
444 arg: "new_log_len".to_string(),
445 expected: self.log_cap(),
446 });
447 }
448
449 if self.log_len < P::LOG_WIDTH {
450 let first_elem = self.values.first_mut().expect("values.len() >= 1");
451 for i in 1 << self.log_len..(1 << new_log_len).min(P::WIDTH) {
452 first_elem.set(i, P::Scalar::ZERO);
453 }
454 }
455
456 let packed_start = 1 << self.log_len.saturating_sub(P::LOG_WIDTH);
457 let packed_end = 1 << new_log_len.saturating_sub(P::LOG_WIDTH);
458 self.values[packed_start..packed_end].fill(P::zero());
459
460 self.log_len = new_log_len;
461 Ok(())
462 }
463
464 pub fn resize(&mut self, new_log_len: usize) -> Result<(), Error> {
472 if new_log_len > self.log_cap() {
473 return Err(Error::IncorrectArgumentLength {
474 arg: "new_log_len".to_string(),
475 expected: self.log_cap(),
476 });
477 }
478
479 self.log_len = new_log_len;
480 Ok(())
481 }
482
483 pub fn chunks_mut(
490 &mut self,
491 log_chunk_size: usize,
492 ) -> Result<impl Iterator<Item = FieldSliceMut<'_, P>>, Error> {
493 if log_chunk_size < P::LOG_WIDTH || log_chunk_size > self.log_len {
494 return Err(Error::ArgumentRangeError {
495 arg: "log_chunk_size".to_string(),
496 range: P::LOG_WIDTH..self.log_len + 1,
497 });
498 }
499
500 let chunk_count = 1 << (self.log_len - log_chunk_size);
501 let packed_chunk_size = 1 << log_chunk_size.saturating_sub(P::LOG_WIDTH);
502 let chunks = self
503 .values
504 .chunks_mut(packed_chunk_size)
505 .take(chunk_count)
506 .map(move |chunk| FieldBuffer {
507 log_len: log_chunk_size,
508 values: FieldSliceDataMut::Slice(chunk),
509 });
510
511 Ok(chunks)
512 }
513
514 pub fn split_half_mut<F, R>(&mut self, f: F) -> Result<R, Error>
524 where
525 F: FnOnce(&mut FieldSliceMut<'_, P>, &mut FieldSliceMut<'_, P>) -> R,
526 {
527 if self.log_len == 0 {
528 return Err(Error::CannotSplit);
529 }
530
531 let new_log_len = self.log_len - 1;
532
533 if new_log_len < P::LOG_WIDTH {
534 let packed = self.values[0];
536 let zeros = P::default();
537 let (mut first_half, mut second_half) = packed.interleave(zeros, new_log_len);
538
539 let mut first = FieldBuffer {
546 log_len: new_log_len,
547 values: FieldSliceDataMut::Slice(slice::from_mut(&mut first_half)),
548 };
549 let mut second = FieldBuffer {
550 log_len: new_log_len,
551 values: FieldSliceDataMut::Slice(slice::from_mut(&mut second_half)),
552 };
553
554 let result = f(&mut first, &mut second);
556
557 (self.values[0], _) = first_half.interleave(second_half, new_log_len);
560
561 Ok(result)
562 } else {
563 let half_len = 1 << (new_log_len - P::LOG_WIDTH);
565 let (first_half, second_half) = self.values.split_at_mut(half_len);
566 let second_half = &mut second_half[..half_len];
567
568 let mut first = FieldBuffer {
569 log_len: new_log_len,
570 values: FieldSliceDataMut::Slice(first_half),
571 };
572 let mut second = FieldBuffer {
573 log_len: new_log_len,
574 values: FieldSliceDataMut::Slice(second_half),
575 };
576
577 Ok(f(&mut first, &mut second))
578 }
579 }
580
581 pub fn split_half_mut_no_closure(&mut self) -> Result<FieldBufferSplitMut<'_, P>, Error> {
593 if self.log_len == 0 {
594 return Err(Error::CannotSplit);
595 }
596
597 let new_log_len = self.log_len - 1;
598 if new_log_len < P::LOG_WIDTH {
599 let packed = self.values[0];
601 let zeros = P::default();
602 let (lo_half, hi_half) = packed.interleave(zeros, new_log_len);
603
604 Ok(FieldBufferSplitMut(FieldBufferSplitMutInner::Singles {
605 log_len: new_log_len,
606 lo_half,
607 hi_half,
608 parent: &mut self.values[0],
609 }))
610 } else {
611 let half_len = 1 << (new_log_len - P::LOG_WIDTH);
613 let (lo_half, hi_half) = self.values.split_at_mut(half_len);
614 let hi_half = &mut hi_half[..half_len];
615
616 Ok(FieldBufferSplitMut(FieldBufferSplitMutInner::Slices {
617 log_len: new_log_len,
618 lo_half,
619 hi_half,
620 }))
621 }
622 }
623}
624
625impl<P: PackedField, Data: Deref<Target = [P]>> AsRef<[P]> for FieldBuffer<P, Data> {
626 #[inline]
627 fn as_ref(&self) -> &[P] {
628 &self.values[..1 << self.log_len.saturating_sub(P::LOG_WIDTH)]
629 }
630}
631
632impl<P: PackedField, Data: DerefMut<Target = [P]>> AsMut<[P]> for FieldBuffer<P, Data> {
633 #[inline]
634 fn as_mut(&mut self) -> &mut [P] {
635 &mut self.values[..1 << self.log_len.saturating_sub(P::LOG_WIDTH)]
636 }
637}
638
639impl<F: Field, Data: Deref<Target = [F]>> Index<usize> for FieldBuffer<F, Data> {
640 type Output = F;
641
642 fn index(&self, index: usize) -> &Self::Output {
643 &self.values[index]
644 }
645}
646
647impl<F: Field, Data: DerefMut<Target = [F]>> IndexMut<usize> for FieldBuffer<F, Data> {
648 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
649 &mut self.values[index]
650 }
651}
652
653pub type FieldSlice<'a, P> = FieldBuffer<P, FieldSliceData<'a, P>>;
655
656pub type FieldSliceMut<'a, P> = FieldBuffer<P, FieldSliceDataMut<'a, P>>;
658
659impl<'a, P: PackedField> FieldSlice<'a, P> {
660 pub fn from_slice(log_len: usize, slice: &'a [P]) -> Result<Self, Error> {
667 FieldBuffer::new(log_len, FieldSliceData::Slice(slice))
668 }
669}
670
671impl<'a, P: PackedField, Data: Deref<Target = [P]>> From<&'a FieldBuffer<P, Data>>
672 for FieldSlice<'a, P>
673{
674 fn from(buffer: &'a FieldBuffer<P, Data>) -> Self {
675 buffer.to_ref()
676 }
677}
678
679impl<'a, P: PackedField> FieldSliceMut<'a, P> {
680 pub fn from_slice(log_len: usize, slice: &'a mut [P]) -> Result<Self, Error> {
687 FieldBuffer::new(log_len, FieldSliceDataMut::Slice(slice))
688 }
689}
690
691impl<'a, P: PackedField, Data: DerefMut<Target = [P]>> From<&'a mut FieldBuffer<P, Data>>
692 for FieldSliceMut<'a, P>
693{
694 fn from(buffer: &'a mut FieldBuffer<P, Data>) -> Self {
695 buffer.to_mut()
696 }
697}
698
699#[derive(Debug)]
700pub enum FieldSliceData<'a, P> {
701 Single(P),
702 Slice(&'a [P]),
703}
704
705impl<'a, P> Deref for FieldSliceData<'a, P> {
706 type Target = [P];
707
708 fn deref(&self) -> &Self::Target {
709 match self {
710 FieldSliceData::Single(val) => slice::from_ref(val),
711 FieldSliceData::Slice(slice) => slice,
712 }
713 }
714}
715
716#[derive(Debug)]
717pub enum FieldSliceDataMut<'a, P> {
718 Single(P),
719 Slice(&'a mut [P]),
720}
721
722impl<'a, P> Deref for FieldSliceDataMut<'a, P> {
723 type Target = [P];
724
725 fn deref(&self) -> &Self::Target {
726 match self {
727 FieldSliceDataMut::Single(val) => slice::from_ref(val),
728 FieldSliceDataMut::Slice(slice) => slice,
729 }
730 }
731}
732
733impl<'a, P> DerefMut for FieldSliceDataMut<'a, P> {
734 fn deref_mut(&mut self) -> &mut Self::Target {
735 match self {
736 FieldSliceDataMut::Single(val) => slice::from_mut(val),
737 FieldSliceDataMut::Slice(slice) => slice,
738 }
739 }
740}
741
742#[derive(Debug)]
744pub struct FieldBufferSplitMut<'a, P: PackedField>(FieldBufferSplitMutInner<'a, P>);
745
746impl<'a, P: PackedField> FieldBufferSplitMut<'a, P> {
747 pub fn halves(&mut self) -> (FieldSliceMut<'_, P>, FieldSliceMut<'_, P>) {
748 match &mut self.0 {
749 FieldBufferSplitMutInner::Singles {
750 log_len,
751 lo_half,
752 hi_half,
753 parent: _,
754 } => (
755 FieldBuffer {
756 log_len: *log_len,
757 values: FieldSliceDataMut::Slice(slice::from_mut(lo_half)),
758 },
759 FieldBuffer {
760 log_len: *log_len,
761 values: FieldSliceDataMut::Slice(slice::from_mut(hi_half)),
762 },
763 ),
764 FieldBufferSplitMutInner::Slices {
765 log_len,
766 lo_half,
767 hi_half,
768 } => (
769 FieldBuffer {
770 log_len: *log_len,
771 values: FieldSliceDataMut::Slice(lo_half),
772 },
773 FieldBuffer {
774 log_len: *log_len,
775 values: FieldSliceDataMut::Slice(hi_half),
776 },
777 ),
778 }
779 }
780}
781
782#[derive(Debug)]
783enum FieldBufferSplitMutInner<'a, P: PackedField> {
784 Singles {
785 log_len: usize,
786 lo_half: P,
787 hi_half: P,
788 parent: &'a mut P,
789 },
790 Slices {
791 log_len: usize,
792 lo_half: &'a mut [P],
793 hi_half: &'a mut [P],
794 },
795}
796
797impl<'a, P: PackedField> Drop for FieldBufferSplitMutInner<'a, P> {
798 fn drop(&mut self) {
799 match self {
800 Self::Singles {
801 log_len,
802 lo_half,
803 hi_half,
804 parent,
805 } => {
806 (**parent, _) = (*lo_half).interleave(*hi_half, *log_len);
809 }
810 Self::Slices { .. } => {}
811 }
812 }
813}
814
815#[cfg(test)]
816mod tests {
817 use super::*;
818 use crate::test_utils::{B128, Packed128b};
819
820 type P = Packed128b;
821 type F = B128;
822
823 #[test]
824 fn test_zeros() {
825 let buffer = FieldBuffer::<P>::zeros(6); assert_eq!(buffer.log_len(), 6);
829 assert_eq!(buffer.len(), 64);
830
831 for i in 0..64 {
833 assert_eq!(buffer.get_checked(i).unwrap(), F::ZERO);
834 }
835
836 let buffer = FieldBuffer::<P>::zeros(1); assert_eq!(buffer.log_len(), 1);
839 assert_eq!(buffer.len(), 2);
840
841 for i in 0..2 {
843 assert_eq!(buffer.get_checked(i).unwrap(), F::ZERO);
844 }
845 }
846
847 #[test]
848 fn test_from_values_below_packing_width() {
849 let values = vec![F::new(1), F::new(2)]; let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
854
855 assert_eq!(buffer.log_len(), 1); assert_eq!(buffer.len(), 2);
857
858 assert_eq!(buffer.get_checked(0).unwrap(), F::new(1));
860 assert_eq!(buffer.get_checked(1).unwrap(), F::new(2));
861 }
862
863 #[test]
864 fn test_from_values_above_packing_width() {
865 let values: Vec<F> = (0..16).map(F::new).collect(); let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
870
871 assert_eq!(buffer.log_len(), 4); assert_eq!(buffer.len(), 16);
873
874 for i in 0..16 {
876 assert_eq!(buffer.get_checked(i).unwrap(), F::new(i as u128));
877 }
878 }
879
880 #[test]
881 fn test_from_values_non_power_of_two() {
882 let values: Vec<F> = (0..7).map(F::new).collect(); let result = FieldBuffer::<P>::from_values(&values);
886
887 assert!(matches!(result, Err(Error::PowerOfTwoLengthRequired)));
888
889 let values: Vec<F> = vec![];
891 let result = FieldBuffer::<P>::from_values(&values);
892 assert!(matches!(result, Err(Error::PowerOfTwoLengthRequired)));
893 }
894
895 #[test]
896 fn test_new_below_packing_width() {
897 let mut packed_values = vec![P::default()];
902 let mut buffer = FieldBuffer::new(1, packed_values.as_mut_slice()).unwrap();
903
904 assert_eq!(buffer.log_len(), 1);
905 assert_eq!(buffer.len(), 2);
906
907 buffer.set_checked(0, F::new(10)).unwrap();
909 buffer.set_checked(1, F::new(20)).unwrap();
910 assert_eq!(buffer.get_checked(0).unwrap(), F::new(10));
911 assert_eq!(buffer.get_checked(1).unwrap(), F::new(20));
912 }
913
914 #[test]
915 fn test_new_above_packing_width() {
916 let mut packed_values = vec![P::default(); 4];
921 let mut buffer = FieldBuffer::new(4, packed_values.as_mut_slice()).unwrap();
922
923 assert_eq!(buffer.log_len(), 4);
924 assert_eq!(buffer.len(), 16);
925
926 for i in 0..16 {
928 buffer.set_checked(i, F::new(i as u128 * 10)).unwrap();
929 }
930 for i in 0..16 {
931 assert_eq!(buffer.get_checked(i).unwrap(), F::new(i as u128 * 10));
932 }
933 }
934
935 #[test]
936 fn test_new_non_power_of_two() {
937 let packed_values = vec![P::default(); 3]; let result = FieldBuffer::new(4, packed_values.as_slice());
942
943 assert!(matches!(result, Err(Error::IncorrectArgumentLength { .. })));
944
945 let packed_values = vec![P::default(); 5]; let result = FieldBuffer::new(4, packed_values.as_slice());
948
949 assert!(matches!(result, Err(Error::IncorrectArgumentLength { .. })));
950 }
951
952 #[test]
953 fn test_get_set() {
954 let mut buffer = FieldBuffer::<P>::zeros(3); for i in 0..8 {
958 buffer.set_checked(i, F::new(i as u128)).unwrap();
959 }
960
961 for i in 0..8 {
963 assert_eq!(buffer.get_checked(i).unwrap(), F::new(i as u128));
964 }
965
966 assert!(buffer.get_checked(8).is_err());
968 assert!(buffer.set_checked(8, F::new(0)).is_err());
969 }
970
971 #[test]
972 fn test_chunk() {
973 let log_len = 8;
974 let values: Vec<F> = (0..1 << log_len).map(F::new).collect();
975 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
976
977 assert!(buffer.chunk(log_len + 1, 0).is_err());
979
980 for log_chunk_size in 0..=log_len {
981 let chunk_count = 1 << (log_len - log_chunk_size);
982
983 assert!(buffer.chunk(log_chunk_size, chunk_count).is_err());
985
986 for chunk_index in 0..chunk_count {
987 let chunk = buffer.chunk(log_chunk_size, chunk_index).unwrap();
988 for i in 0..1 << log_chunk_size {
989 assert_eq!(
990 chunk.get_checked(i).unwrap(),
991 buffer
992 .get_checked(chunk_index << log_chunk_size | i)
993 .unwrap()
994 );
995 }
996 }
997 }
998 }
999
1000 #[test]
1001 fn test_chunks() {
1002 let values: Vec<F> = (0..16).map(F::new).collect();
1003 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1004
1005 let chunks: Vec<_> = buffer.chunks(2).unwrap().collect();
1007 assert_eq!(chunks.len(), 4);
1008
1009 for (chunk_idx, chunk) in chunks.into_iter().enumerate() {
1010 assert_eq!(chunk.len(), 4);
1011 for i in 0..4 {
1012 let expected = F::new((chunk_idx * 4 + i) as u128);
1013 assert_eq!(chunk.get_checked(i).unwrap(), expected);
1014 }
1015 }
1016
1017 assert!(buffer.chunks(5).is_err());
1019
1020 assert!(buffer.chunks(0).is_err());
1023 assert!(buffer.chunks(1).is_err());
1024 }
1025
1026 #[test]
1027 fn test_chunks_par() {
1028 let values: Vec<F> = (0..16).map(F::new).collect();
1029 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1030
1031 let chunks: Vec<_> = buffer.chunks_par(2).unwrap().collect();
1033 assert_eq!(chunks.len(), 4);
1034
1035 for (chunk_idx, chunk) in chunks.into_iter().enumerate() {
1036 assert_eq!(chunk.len(), 4);
1037 for i in 0..4 {
1038 let expected = F::new((chunk_idx * 4 + i) as u128);
1039 assert_eq!(chunk.get_checked(i).unwrap(), expected);
1040 }
1041 }
1042
1043 assert!(buffer.chunks_par(5).is_err());
1045
1046 assert!(buffer.chunks_par(0).is_err());
1049 assert!(buffer.chunks_par(1).is_err());
1050 }
1051
1052 #[test]
1053 fn test_chunks_mut() {
1054 let mut buffer = FieldBuffer::<P>::zeros(4); let mut chunks: Vec<_> = buffer.chunks_mut(2).unwrap().collect();
1058 assert_eq!(chunks.len(), 4);
1059
1060 for (chunk_idx, chunk) in chunks.iter_mut().enumerate() {
1061 for i in 0..chunk.len() {
1062 chunk
1063 .set_checked(i, F::new((chunk_idx * 10 + i) as u128))
1064 .unwrap();
1065 }
1066 }
1067
1068 for chunk_idx in 0..4 {
1070 for i in 0..4 {
1071 let expected = F::new((chunk_idx * 10 + i) as u128);
1072 assert_eq!(buffer.get_checked(chunk_idx * 4 + i).unwrap(), expected);
1073 }
1074 }
1075
1076 assert!(buffer.chunks_mut(0).is_err());
1078 assert!(buffer.chunks_mut(1).is_err());
1079 }
1080
1081 #[test]
1082 fn test_to_ref_to_mut() {
1083 let mut buffer = FieldBuffer::<P>::zeros_truncated(3, 5).unwrap();
1084
1085 let slice_ref = buffer.to_ref();
1087 assert_eq!(slice_ref.len(), buffer.len());
1088 assert_eq!(slice_ref.log_len(), buffer.log_len());
1089 assert_eq!(slice_ref.as_ref().len(), 1 << slice_ref.log_len().saturating_sub(P::LOG_WIDTH));
1090
1091 let mut slice_mut = buffer.to_mut();
1093 slice_mut.set_checked(0, F::new(123)).unwrap();
1094 assert_eq!(slice_mut.as_mut().len(), 1 << slice_mut.log_len().saturating_sub(P::LOG_WIDTH));
1095 assert_eq!(buffer.get_checked(0).unwrap(), F::new(123));
1096 }
1097
1098 #[test]
1099 fn test_split_half() {
1100 let values: Vec<F> = (0..16).map(F::new).collect();
1102 let buffer = FieldBuffer::<P>::from_values_truncated(&values, 5).unwrap();
1104
1105 let (first, second) = buffer.split_half().unwrap();
1106 assert_eq!(first.len(), 8);
1107 assert_eq!(second.len(), 8);
1108
1109 for i in 0..8 {
1111 assert_eq!(first.get_checked(i).unwrap(), F::new(i as u128));
1112 assert_eq!(second.get_checked(i).unwrap(), F::new((i + 8) as u128));
1113 }
1114
1115 let values: Vec<F> = (0..4).map(F::new).collect();
1119 let buffer = FieldBuffer::<P>::from_values_truncated(&values, 3).unwrap();
1120
1121 let (first, second) = buffer.split_half().unwrap();
1122 assert_eq!(first.len(), 2);
1123 assert_eq!(second.len(), 2);
1124
1125 match &first.values {
1127 FieldSliceData::Single(_) => {}
1128 _ => panic!("Expected Single variant for first half"),
1129 }
1130 match &second.values {
1131 FieldSliceData::Single(_) => {}
1132 _ => panic!("Expected Single variant for second half"),
1133 }
1134
1135 assert_eq!(first.get_checked(0).unwrap(), F::new(0));
1137 assert_eq!(first.get_checked(1).unwrap(), F::new(1));
1138 assert_eq!(second.get_checked(0).unwrap(), F::new(2));
1139 assert_eq!(second.get_checked(1).unwrap(), F::new(3));
1140
1141 let values: Vec<F> = vec![F::new(10), F::new(20)];
1143 let buffer = FieldBuffer::<P>::from_values_truncated(&values, 3).unwrap();
1144
1145 let (first, second) = buffer.split_half().unwrap();
1146 assert_eq!(first.len(), 1);
1147 assert_eq!(second.len(), 1);
1148
1149 match &first.values {
1151 FieldSliceData::Single(_) => {}
1152 _ => panic!("Expected Single variant for first half"),
1153 }
1154 match &second.values {
1155 FieldSliceData::Single(_) => {}
1156 _ => panic!("Expected Single variant for second half"),
1157 }
1158
1159 assert_eq!(first.get_checked(0).unwrap(), F::new(10));
1160 assert_eq!(second.get_checked(0).unwrap(), F::new(20));
1161
1162 let values = vec![F::new(42)];
1164 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1165
1166 let result = buffer.split_half();
1167 assert!(matches!(result, Err(Error::CannotSplit)));
1168 }
1169
1170 #[test]
1171 fn test_split_half_mut() {
1172 let mut buffer = FieldBuffer::<P>::zeros_truncated(4, 5).unwrap(); for i in 0..16 {
1177 buffer.set_checked(i, F::new(i as u128)).unwrap();
1178 }
1179
1180 buffer
1181 .split_half_mut(|first, second| {
1182 assert_eq!(first.len(), 8);
1183 assert_eq!(second.len(), 8);
1184
1185 for i in 0..8 {
1187 first.set_checked(i, F::new((i * 10) as u128)).unwrap();
1188 second.set_checked(i, F::new((i * 20) as u128)).unwrap();
1189 }
1190 })
1191 .unwrap();
1192
1193 for i in 0..8 {
1195 assert_eq!(buffer.get_checked(i).unwrap(), F::new((i * 10) as u128));
1196 assert_eq!(buffer.get_checked(i + 8).unwrap(), F::new((i * 20) as u128));
1197 }
1198
1199 let mut buffer = FieldBuffer::<P>::zeros_truncated(2, 4).unwrap(); for i in 0..4 {
1205 buffer.set_checked(i, F::new(i as u128)).unwrap();
1206 }
1207
1208 buffer
1209 .split_half_mut(|first, second| {
1210 assert_eq!(first.len(), 2);
1211 assert_eq!(second.len(), 2);
1212
1213 first.set_checked(0, F::new(100)).unwrap();
1215 first.set_checked(1, F::new(101)).unwrap();
1216 second.set_checked(0, F::new(200)).unwrap();
1217 second.set_checked(1, F::new(201)).unwrap();
1218 })
1219 .unwrap();
1220
1221 assert_eq!(buffer.get_checked(0).unwrap(), F::new(100));
1223 assert_eq!(buffer.get_checked(1).unwrap(), F::new(101));
1224 assert_eq!(buffer.get_checked(2).unwrap(), F::new(200));
1225 assert_eq!(buffer.get_checked(3).unwrap(), F::new(201));
1226
1227 let mut buffer = FieldBuffer::<P>::zeros_truncated(1, 4).unwrap(); buffer.set_checked(0, F::new(10)).unwrap();
1231 buffer.set_checked(1, F::new(20)).unwrap();
1232
1233 buffer
1234 .split_half_mut(|first, second| {
1235 assert_eq!(first.len(), 1);
1236 assert_eq!(second.len(), 1);
1237
1238 first.set_checked(0, F::new(30)).unwrap();
1240 second.set_checked(0, F::new(40)).unwrap();
1241 })
1242 .unwrap();
1243
1244 assert_eq!(buffer.get_checked(0).unwrap(), F::new(30));
1246 assert_eq!(buffer.get_checked(1).unwrap(), F::new(40));
1247
1248 let mut buffer = FieldBuffer::<P>::zeros(0); let result = buffer.split_half_mut(|_, _| {});
1252 assert!(matches!(result, Err(Error::CannotSplit)));
1253 }
1254
1255 #[test]
1256 fn test_zero_extend() {
1257 let log_len = 10;
1258 let nonzero_scalars = (0..1 << log_len).map(|i| F::new(i + 1)).collect::<Vec<_>>();
1259 let mut buffer = FieldBuffer::<P>::from_values(&nonzero_scalars).unwrap();
1260 buffer.truncate(0);
1261
1262 for i in 0..log_len {
1263 buffer.zero_extend(i + 1).unwrap();
1264
1265 for j in 1 << i..1 << (i + 1) {
1266 assert!(buffer.get_checked(j).unwrap().is_zero());
1267 }
1268 }
1269 }
1270
1271 #[test]
1272 fn test_resize() {
1273 let mut buffer = FieldBuffer::<P>::zeros(4); for i in 0..16 {
1277 buffer.set_checked(i, F::new(i as u128)).unwrap();
1278 }
1279
1280 buffer.resize(3).unwrap();
1281 assert_eq!(buffer.log_len(), 3);
1282 assert_eq!(buffer.get_checked(7).unwrap(), F::new(7));
1283
1284 buffer.resize(4).unwrap();
1285 assert_eq!(buffer.log_len(), 4);
1286 assert_eq!(buffer.get_checked(15).unwrap(), F::new(15));
1287
1288 assert!(
1289 matches!(buffer.resize(5), Err(Error::IncorrectArgumentLength { arg, expected }) if arg == "new_log_len" && expected == 4)
1290 );
1291
1292 buffer.resize(2).unwrap();
1293 assert_eq!(buffer.log_len(), 2);
1294 }
1295
1296 #[test]
1297 fn test_iter_scalars() {
1298 let values = vec![F::new(10), F::new(20)]; let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1302
1303 let collected: Vec<F> = buffer.iter_scalars().collect();
1304 assert_eq!(collected, values);
1305
1306 for (i, &val) in collected.iter().enumerate() {
1308 assert_eq!(val, buffer.get(i));
1309 }
1310
1311 let values = vec![F::new(1), F::new(2), F::new(3), F::new(4)]; let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1314
1315 let collected: Vec<F> = buffer.iter_scalars().collect();
1316 assert_eq!(collected, values);
1317
1318 let values: Vec<F> = (0..16).map(F::new).collect(); let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1321
1322 let collected: Vec<F> = buffer.iter_scalars().collect();
1323 assert_eq!(collected, values);
1324
1325 for (i, &val) in collected.iter().enumerate() {
1327 assert_eq!(val, buffer.get(i));
1328 }
1329
1330 let values = vec![F::new(42)];
1332 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1333
1334 let collected: Vec<F> = buffer.iter_scalars().collect();
1335 assert_eq!(collected, values);
1336
1337 let values: Vec<F> = (0..256).map(F::new).collect();
1339 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1340
1341 let collected: Vec<F> = buffer.iter_scalars().collect();
1342 assert_eq!(collected, values);
1343
1344 let values: Vec<F> = (0..8).map(F::new).collect();
1346 let buffer = FieldBuffer::<P>::from_values(&values).unwrap();
1347
1348 let iter1 = buffer.iter_scalars();
1349 let iter2 = iter1.clone();
1350
1351 let collected1: Vec<F> = iter1.collect();
1352 let collected2: Vec<F> = iter2.collect();
1353 assert_eq!(collected1, collected2);
1354 assert_eq!(collected1, values);
1355
1356 let values: Vec<F> = (0..8).map(F::new).collect();
1358 let buffer = FieldBuffer::<P>::from_values_truncated(&values, 5).unwrap(); let collected: Vec<F> = buffer.iter_scalars().collect();
1361 assert_eq!(collected, values);
1362 assert_eq!(collected.len(), 8); }
1364
1365 #[test]
1366 fn test_split_half_mut_no_closure() {
1367 let mut buffer = FieldBuffer::<P>::zeros(4); for i in 0..16 {
1372 buffer.set_checked(i, F::new(i as u128)).unwrap();
1373 }
1374
1375 {
1376 let mut split = buffer.split_half_mut_no_closure().unwrap();
1377 let (mut first, mut second) = split.halves();
1378
1379 assert_eq!(first.len(), 8);
1380 assert_eq!(second.len(), 8);
1381
1382 for i in 0..8 {
1384 first.set_checked(i, F::new((i * 10) as u128)).unwrap();
1385 second.set_checked(i, F::new((i * 20) as u128)).unwrap();
1386 }
1387 }
1389
1390 for i in 0..8 {
1392 assert_eq!(buffer.get_checked(i).unwrap(), F::new((i * 10) as u128));
1393 assert_eq!(buffer.get_checked(i + 8).unwrap(), F::new((i * 20) as u128));
1394 }
1395
1396 let mut buffer = FieldBuffer::<P>::zeros(2); for i in 0..4 {
1402 buffer.set_checked(i, F::new(i as u128)).unwrap();
1403 }
1404
1405 {
1406 let mut split = buffer.split_half_mut_no_closure().unwrap();
1407 let (mut first, mut second) = split.halves();
1408
1409 assert_eq!(first.len(), 2);
1410 assert_eq!(second.len(), 2);
1411
1412 first.set_checked(0, F::new(100)).unwrap();
1414 first.set_checked(1, F::new(101)).unwrap();
1415 second.set_checked(0, F::new(200)).unwrap();
1416 second.set_checked(1, F::new(201)).unwrap();
1417 }
1419
1420 assert_eq!(buffer.get_checked(0).unwrap(), F::new(100));
1422 assert_eq!(buffer.get_checked(1).unwrap(), F::new(101));
1423 assert_eq!(buffer.get_checked(2).unwrap(), F::new(200));
1424 assert_eq!(buffer.get_checked(3).unwrap(), F::new(201));
1425
1426 let mut buffer = FieldBuffer::<P>::zeros(1); buffer.set_checked(0, F::new(10)).unwrap();
1430 buffer.set_checked(1, F::new(20)).unwrap();
1431
1432 {
1433 let mut split = buffer.split_half_mut_no_closure().unwrap();
1434 let (mut first, mut second) = split.halves();
1435
1436 assert_eq!(first.len(), 1);
1437 assert_eq!(second.len(), 1);
1438
1439 first.set_checked(0, F::new(30)).unwrap();
1441 second.set_checked(0, F::new(40)).unwrap();
1442 }
1444
1445 assert_eq!(buffer.get_checked(0).unwrap(), F::new(30));
1447 assert_eq!(buffer.get_checked(1).unwrap(), F::new(40));
1448
1449 let mut buffer = FieldBuffer::<P>::zeros(0); let result = buffer.split_half_mut_no_closure();
1453 assert!(matches!(result, Err(Error::CannotSplit)));
1454 }
1455}