1use alloc::borrow::Cow;
2use alloc::vec;
3use alloc::vec::Vec;
4use core::borrow::{Borrow, BorrowMut};
5use core::marker::PhantomData;
6use core::ops::Deref;
7
8use p3_field::{
9 ExtensionField, Field, PackedValue, par_scale_slice_in_place, scale_slice_in_place_single_core,
10};
11use p3_maybe_rayon::prelude::*;
12use rand::distr::{Distribution, StandardUniform};
13use rand::{Rng, RngExt};
14use serde::{Deserialize, Serialize};
15use tracing::instrument;
16
17use crate::Matrix;
18
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
23pub struct DenseMatrix<T, V = Vec<T>> {
24 pub values: V,
26 pub width: usize,
30 _phantom: PhantomData<T>,
34}
35
36pub type RowMajorMatrix<T> = DenseMatrix<T>;
37pub type RowMajorMatrixView<'a, T> = DenseMatrix<T, &'a [T]>;
38pub type RowMajorMatrixViewMut<'a, T> = DenseMatrix<T, &'a mut [T]>;
39pub type RowMajorMatrixCow<'a, T> = DenseMatrix<T, Cow<'a, [T]>>;
40
41pub trait DenseStorage<T>: Borrow<[T]> + Send + Sync {
42 fn to_vec(self) -> Vec<T>;
43}
44
45impl<T: Clone + Send + Sync> DenseStorage<T> for Vec<T> {
47 fn to_vec(self) -> Self {
48 self
49 }
50}
51
52impl<T: Clone + Send + Sync> DenseStorage<T> for &[T] {
53 fn to_vec(self) -> Vec<T> {
54 <[T]>::to_vec(self)
55 }
56}
57
58impl<T: Clone + Send + Sync> DenseStorage<T> for &mut [T] {
59 fn to_vec(self) -> Vec<T> {
60 <[T]>::to_vec(self)
61 }
62}
63
64impl<T: Clone + Send + Sync> DenseStorage<T> for Cow<'_, [T]> {
65 fn to_vec(self) -> Vec<T> {
66 self.into_owned()
67 }
68}
69
70impl<T: Clone + Send + Sync + Default> DenseMatrix<T> {
71 #[must_use]
74 pub fn default(width: usize, height: usize) -> Self {
75 Self::new(vec![T::default(); width * height], width)
76 }
77}
78
79impl<T: Clone + Send + Sync, S: DenseStorage<T>> DenseMatrix<T, S> {
80 #[must_use]
87 pub fn new(values: S, width: usize) -> Self {
88 debug_assert!(values.borrow().len().is_multiple_of(width));
89 Self {
90 values,
91 width,
92 _phantom: PhantomData,
93 }
94 }
95
96 #[must_use]
98 pub fn new_row(values: S) -> Self {
99 let width = values.borrow().len();
100 Self::new(values, width)
101 }
102
103 #[must_use]
105 pub fn new_col(values: S) -> Self {
106 Self::new(values, 1)
107 }
108
109 pub fn as_view(&self) -> RowMajorMatrixView<'_, T> {
111 RowMajorMatrixView::new(self.values.borrow(), self.width)
112 }
113
114 pub fn as_view_mut(&mut self) -> RowMajorMatrixViewMut<'_, T>
116 where
117 S: BorrowMut<[T]>,
118 {
119 RowMajorMatrixViewMut::new(self.values.borrow_mut(), self.width)
120 }
121
122 pub fn copy_from<S2>(&mut self, source: &DenseMatrix<T, S2>)
124 where
125 T: Copy,
126 S: BorrowMut<[T]>,
127 S2: DenseStorage<T>,
128 {
129 assert_eq!(self.dimensions(), source.dimensions());
130 self.par_rows_mut()
133 .zip(source.par_row_slices())
134 .for_each(|(dst, src)| {
135 dst.copy_from_slice(src);
136 });
137 }
138
139 pub fn flatten_to_base<F: Field>(self) -> RowMajorMatrix<F>
141 where
142 T: ExtensionField<F>,
143 {
144 let width = self.width * T::DIMENSION;
145 let values = T::flatten_to_base(self.values.to_vec());
146 RowMajorMatrix::new(values, width)
147 }
148
149 pub fn row_slices(&self) -> impl DoubleEndedIterator<Item = &[T]> {
151 self.values.borrow().chunks_exact(self.width)
152 }
153
154 pub fn par_row_slices(&self) -> impl IndexedParallelIterator<Item = &[T]>
156 where
157 T: Sync,
158 {
159 self.values.borrow().par_chunks_exact(self.width)
160 }
161
162 pub fn row_mut(&mut self, r: usize) -> &mut [T]
167 where
168 S: BorrowMut<[T]>,
169 {
170 &mut self.values.borrow_mut()[r * self.width..(r + 1) * self.width]
171 }
172
173 pub fn rows_mut(&mut self) -> impl Iterator<Item = &mut [T]>
175 where
176 S: BorrowMut<[T]>,
177 {
178 self.values.borrow_mut().chunks_exact_mut(self.width)
179 }
180
181 pub fn par_rows_mut<'a>(&'a mut self) -> impl IndexedParallelIterator<Item = &'a mut [T]>
183 where
184 T: 'a + Send,
185 S: BorrowMut<[T]>,
186 {
187 self.values.borrow_mut().par_chunks_exact_mut(self.width)
188 }
189
190 pub fn horizontally_packed_row_mut<P>(&mut self, r: usize) -> (&mut [P], &mut [T])
195 where
196 P: PackedValue<Value = T>,
197 S: BorrowMut<[T]>,
198 {
199 P::pack_slice_with_suffix_mut(self.row_mut(r))
200 }
201
202 pub fn scale_row(&mut self, r: usize, scale: T)
207 where
208 T: Field,
209 S: BorrowMut<[T]>,
210 {
211 scale_slice_in_place_single_core(self.row_mut(r), scale);
212 }
213
214 pub fn par_scale_row(&mut self, r: usize, scale: T)
223 where
224 T: Field,
225 S: BorrowMut<[T]>,
226 {
227 par_scale_slice_in_place(self.row_mut(r), scale);
228 }
229
230 pub fn scale(&mut self, scale: T)
232 where
233 T: Field,
234 S: BorrowMut<[T]>,
235 {
236 par_scale_slice_in_place(self.values.borrow_mut(), scale);
237 }
238
239 pub fn split_rows(&self, r: usize) -> (RowMajorMatrixView<'_, T>, RowMajorMatrixView<'_, T>) {
244 let (lo, hi) = self.values.borrow().split_at(r * self.width);
245 (
246 DenseMatrix::new(lo, self.width),
247 DenseMatrix::new(hi, self.width),
248 )
249 }
250
251 pub fn split_rows_mut(
256 &mut self,
257 r: usize,
258 ) -> (RowMajorMatrixViewMut<'_, T>, RowMajorMatrixViewMut<'_, T>)
259 where
260 S: BorrowMut<[T]>,
261 {
262 let (lo, hi) = self.values.borrow_mut().split_at_mut(r * self.width);
263 (
264 DenseMatrix::new(lo, self.width),
265 DenseMatrix::new(hi, self.width),
266 )
267 }
268
269 pub fn par_row_chunks(
273 &self,
274 chunk_rows: usize,
275 ) -> impl IndexedParallelIterator<Item = RowMajorMatrixView<'_, T>>
276 where
277 T: Send,
278 {
279 self.values
280 .borrow()
281 .par_chunks(self.width * chunk_rows)
282 .map(|slice| RowMajorMatrixView::new(slice, self.width))
283 }
284
285 pub fn par_row_chunks_exact(
289 &self,
290 chunk_rows: usize,
291 ) -> impl IndexedParallelIterator<Item = RowMajorMatrixView<'_, T>>
292 where
293 T: Send,
294 {
295 self.values
296 .borrow()
297 .par_chunks_exact(self.width * chunk_rows)
298 .map(|slice| RowMajorMatrixView::new(slice, self.width))
299 }
300
301 pub fn par_row_chunks_mut(
305 &mut self,
306 chunk_rows: usize,
307 ) -> impl IndexedParallelIterator<Item = RowMajorMatrixViewMut<'_, T>>
308 where
309 T: Send,
310 S: BorrowMut<[T]>,
311 {
312 self.values
313 .borrow_mut()
314 .par_chunks_mut(self.width * chunk_rows)
315 .map(|slice| RowMajorMatrixViewMut::new(slice, self.width))
316 }
317
318 pub fn row_chunks_exact_mut(
323 &mut self,
324 chunk_rows: usize,
325 ) -> impl Iterator<Item = RowMajorMatrixViewMut<'_, T>>
326 where
327 T: Send,
328 S: BorrowMut<[T]>,
329 {
330 self.values
331 .borrow_mut()
332 .chunks_exact_mut(self.width * chunk_rows)
333 .map(|slice| RowMajorMatrixViewMut::new(slice, self.width))
334 }
335
336 pub fn par_row_chunks_exact_mut(
341 &mut self,
342 chunk_rows: usize,
343 ) -> impl IndexedParallelIterator<Item = RowMajorMatrixViewMut<'_, T>>
344 where
345 T: Send,
346 S: BorrowMut<[T]>,
347 {
348 self.values
349 .borrow_mut()
350 .par_chunks_exact_mut(self.width * chunk_rows)
351 .map(|slice| RowMajorMatrixViewMut::new(slice, self.width))
352 }
353
354 pub fn row_pair_mut(&mut self, row_1: usize, row_2: usize) -> (&mut [T], &mut [T])
359 where
360 S: BorrowMut<[T]>,
361 {
362 debug_assert_ne!(row_1, row_2);
363 let start_1 = row_1 * self.width;
364 let start_2 = row_2 * self.width;
365 let (lo, hi) = self.values.borrow_mut().split_at_mut(start_2);
366 (&mut lo[start_1..][..self.width], &mut hi[..self.width])
367 }
368
369 #[allow(clippy::type_complexity)]
376 pub fn packed_row_pair_mut<P>(
377 &mut self,
378 row_1: usize,
379 row_2: usize,
380 ) -> ((&mut [P], &mut [T]), (&mut [P], &mut [T]))
381 where
382 S: BorrowMut<[T]>,
383 P: PackedValue<Value = T>,
384 {
385 let (slice_1, slice_2) = self.row_pair_mut(row_1, row_2);
386 (
387 P::pack_slice_with_suffix_mut(slice_1),
388 P::pack_slice_with_suffix_mut(slice_2),
389 )
390 }
391
392 #[instrument(level = "debug", skip_all)]
395 pub fn bit_reversed_zero_pad(self, added_bits: usize) -> RowMajorMatrix<T>
396 where
397 T: Field,
398 {
399 if added_bits == 0 {
400 return self.to_row_major_matrix();
401 }
402
403 let w = self.width;
413 let mut padded =
414 RowMajorMatrix::new(T::zero_vec(self.values.borrow().len() << added_bits), w);
415 padded
416 .par_row_chunks_exact_mut(1 << added_bits)
417 .zip(self.par_row_slices())
418 .for_each(|(mut ch, r)| ch.row_mut(0).copy_from_slice(r));
419
420 padded
421 }
422}
423
424impl<T: Clone + Send + Sync, S: DenseStorage<T>> Matrix<T> for DenseMatrix<T, S> {
425 #[inline]
426 fn width(&self) -> usize {
427 self.width
428 }
429
430 #[inline]
431 fn height(&self) -> usize {
432 self.values
433 .borrow()
434 .len()
435 .checked_div(self.width)
436 .unwrap_or(0)
437 }
438
439 #[inline]
440 unsafe fn get_unchecked(&self, r: usize, c: usize) -> T {
441 unsafe {
442 self.values
444 .borrow()
445 .get_unchecked(r * self.width + c)
446 .clone()
447 }
448 }
449
450 #[inline]
451 unsafe fn row_subseq_unchecked(
452 &self,
453 r: usize,
454 start: usize,
455 end: usize,
456 ) -> impl IntoIterator<Item = T, IntoIter = impl Iterator<Item = T> + Send + Sync> {
457 unsafe {
458 self.values
460 .borrow()
461 .get_unchecked(r * self.width + start..r * self.width + end)
462 .iter()
463 .cloned()
464 }
465 }
466
467 #[inline]
468 unsafe fn row_subslice_unchecked(
469 &self,
470 r: usize,
471 start: usize,
472 end: usize,
473 ) -> impl Deref<Target = [T]> {
474 unsafe {
475 self.values
477 .borrow()
478 .get_unchecked(r * self.width + start..r * self.width + end)
479 }
480 }
481
482 fn to_row_major_matrix(self) -> RowMajorMatrix<T>
483 where
484 Self: Sized,
485 T: Clone,
486 {
487 RowMajorMatrix::new(self.values.to_vec(), self.width)
488 }
489
490 #[inline]
491 fn horizontally_packed_row<'a, P>(
492 &'a self,
493 r: usize,
494 ) -> (
495 impl Iterator<Item = P> + Send + Sync,
496 impl Iterator<Item = T> + Send + Sync,
497 )
498 where
499 P: PackedValue<Value = T>,
500 T: Clone + 'a,
501 {
502 let buf = &self.values.borrow()[r * self.width..(r + 1) * self.width];
503 let (packed, sfx) = P::pack_slice_with_suffix(buf);
504 (packed.iter().copied(), sfx.iter().cloned())
505 }
506
507 #[inline]
508 fn padded_horizontally_packed_row<'a, P>(
509 &'a self,
510 r: usize,
511 ) -> impl Iterator<Item = P> + Send + Sync
512 where
513 P: PackedValue<Value = T>,
514 T: Clone + Default + 'a,
515 {
516 let buf = &self.values.borrow()[r * self.width..(r + 1) * self.width];
517 let (packed, sfx) = P::pack_slice_with_suffix(buf);
518 packed.iter().copied().chain(
519 (!sfx.is_empty()).then(|| P::from_fn(|i| sfx.get(i).cloned().unwrap_or_default())),
520 )
521 }
522
523 #[inline]
524 fn vertically_packed_row<P>(&self, r: usize) -> impl Iterator<Item = P>
525 where
526 T: Copy,
527 P: PackedValue<Value = T>,
528 {
529 let values = self.values.borrow();
530 let width = self.width;
531 let height = self.height();
532 let row = r % height;
533 let no_wrap = P::WIDTH != 1 && r + P::WIDTH <= height;
534 let rows = (!no_wrap && P::WIDTH != 1).then(|| self.wrapping_row_slices(r, P::WIDTH));
535
536 (0..width).map(move |c| {
537 if P::WIDTH == 1 {
538 unsafe { P::broadcast(*values.get_unchecked(row * width + c)) }
540 } else if no_wrap {
541 P::from_fn(|i| unsafe { *values.get_unchecked((r + i) * width + c) })
543 } else {
544 let rows = rows.as_ref().unwrap();
545 P::from_fn(|i| rows[i][c])
546 }
547 })
548 }
549
550 #[inline]
551 fn vertically_packed_row_pair<P>(&self, r: usize, step: usize) -> Vec<P>
552 where
553 T: Copy,
554 P: PackedValue<Value = T>,
555 {
556 let values = self.values.borrow();
557 let width = self.width;
558 let height = self.height();
559
560 if P::WIDTH == 1 {
561 let row = r % height;
562 let next_row = (r + step) % height;
563 let mut out = Vec::with_capacity(width * 2);
564 out.extend(
565 (0..width).map(|c| unsafe { P::broadcast(*values.get_unchecked(row * width + c)) }),
567 );
568 out.extend(
569 (0..width)
571 .map(|c| unsafe { P::broadcast(*values.get_unchecked(next_row * width + c)) }),
572 );
573 out
574 } else if r + P::WIDTH <= height && r + step + P::WIDTH <= height {
575 (0..width)
578 .map(|c| P::from_fn(|i| unsafe { *values.get_unchecked((r + i) * width + c) }))
579 .chain((0..width).map(|c| {
580 P::from_fn(|i| unsafe { *values.get_unchecked((r + step + i) * width + c) })
581 }))
582 .collect::<Vec<_>>()
583 } else {
584 let rows = self.wrapping_row_slices(r, P::WIDTH);
585 let next_rows = self.wrapping_row_slices(r + step, P::WIDTH);
586 (0..width)
587 .map(|c| P::from_fn(|i| rows[i][c]))
588 .chain((0..width).map(|c| P::from_fn(|i| next_rows[i][c])))
589 .collect::<Vec<_>>()
590 }
591 }
592}
593
594impl<T: Clone + Default + Send + Sync> DenseMatrix<T> {
595 pub fn as_cow<'a>(self) -> RowMajorMatrixCow<'a, T> {
596 RowMajorMatrixCow::new(Cow::Owned(self.values), self.width)
597 }
598
599 pub fn rand<R: Rng>(rng: &mut R, rows: usize, cols: usize) -> Self
600 where
601 StandardUniform: Distribution<T>,
602 {
603 let values = rng.sample_iter(StandardUniform).take(rows * cols).collect();
604 Self::new(values, cols)
605 }
606
607 pub fn rand_nonzero<R: Rng>(rng: &mut R, rows: usize, cols: usize) -> Self
608 where
609 T: Field,
610 StandardUniform: Distribution<T>,
611 {
612 let values = rng
613 .sample_iter(StandardUniform)
614 .filter(|x| !x.is_zero())
615 .take(rows * cols)
616 .collect();
617 Self::new(values, cols)
618 }
619
620 #[instrument(level = "debug", skip_all)]
645 pub fn with_random_cols<R>(&self, num_cols: usize, mut rng: R) -> Self
646 where
647 T: Field,
648 R: Rng + Send + Sync,
649 StandardUniform: Distribution<T>,
650 {
651 let old_w = self.width();
653 let new_w = old_w + num_cols;
654
655 let new_values = T::zero_vec(new_w * self.height());
657 let mut result = Self::new(new_values, new_w);
658
659 result
662 .par_rows_mut()
663 .zip(self.par_row_slices())
664 .for_each(|(new_row, old_row)| {
665 new_row[..old_w].copy_from_slice(old_row);
666 });
667
668 result.rows_mut().for_each(|new_row| {
671 new_row[old_w..].iter_mut().for_each(|v| *v = rng.random());
672 });
673
674 result
675 }
676
677 #[instrument(level = "debug", skip_all)]
700 pub fn with_zero_cols(&self, num_cols: usize) -> Self
701 where
702 T: Field,
703 {
704 let mut result = self.clone();
706 result.widen_right(num_cols, T::ZERO);
707 result
708 }
709
710 pub fn pad_to_height(&mut self, new_height: usize, fill: T) {
711 assert!(new_height >= self.height());
712 self.values.resize(self.width * new_height, fill);
713 }
714
715 pub fn pad_to_power_of_two_height(&mut self, fill: T) {
725 let target_height = self.height().next_power_of_two();
727
728 self.values.resize(self.width * target_height, fill);
731 }
732
733 pub fn pad_to_min_power_of_two_height(&mut self, min_height: usize, fill: T) {
751 let target_height = self
753 .height()
754 .next_power_of_two()
755 .max(min_height.next_power_of_two());
756
757 self.values.resize(self.width * target_height, fill);
759 }
760
761 #[must_use]
781 pub fn from_flat_padded(mut values: Vec<T>, width: usize, fill: T) -> Self {
782 assert!(width > 0, "width must be positive");
784
785 let len = values.len();
787 let rem = len % width;
788
789 if rem != 0 {
794 values.resize(len + (width - rem), fill.clone());
795 }
796
797 if values.is_empty() {
799 values.resize(width, fill);
800 }
801
802 Self::new(values, width)
803 }
804
805 pub fn widen_right(&mut self, extra_cols: usize, fill: T)
834 where
835 T: Copy,
836 {
837 if extra_cols == 0 {
839 return;
840 }
841
842 let old_w = self.width;
843 let new_w = old_w + extra_cols;
844 let h = self.height();
845
846 self.values.resize(h * new_w, fill);
851
852 for r in (1..h).rev() {
857 let src_start = r * old_w;
859
860 let dst_start = r * new_w;
862
863 self.values
865 .copy_within(src_start..src_start + old_w, dst_start);
866
867 self.values[dst_start - extra_cols..dst_start].fill(fill);
869 }
870
871 if h == 1 {
875 self.values[old_w..new_w].fill(fill);
876 }
877
878 self.width = new_w;
880 }
881}
882
883impl<T: Copy + Default + Send + Sync, V: DenseStorage<T>> DenseMatrix<T, V> {
884 pub fn transpose(&self) -> RowMajorMatrix<T> {
886 let nelts = self.height() * self.width();
887 let mut values = vec![T::default(); nelts];
888 p3_util::transpose::transpose(
889 self.values.borrow(),
890 &mut values,
891 self.width(),
892 self.height(),
893 );
894 RowMajorMatrix::new(values, self.height())
895 }
896
897 pub fn transpose_into<W: DenseStorage<T> + BorrowMut<[T]>>(
899 &self,
900 other: &mut DenseMatrix<T, W>,
901 ) {
902 assert_eq!(self.height(), other.width());
903 assert_eq!(other.height(), self.width());
904 p3_util::transpose::transpose(
905 self.values.borrow(),
906 other.values.borrow_mut(),
907 self.width(),
908 self.height(),
909 );
910 }
911}
912
913impl<'a, T: Clone + Default + Send + Sync> RowMajorMatrixView<'a, T> {
914 pub fn as_cow(self) -> RowMajorMatrixCow<'a, T> {
915 RowMajorMatrixCow::new(Cow::Borrowed(self.values), self.width)
916 }
917}
918
919#[cfg(test)]
920mod tests {
921 use p3_baby_bear::BabyBear;
922 use p3_field::{FieldArray, PrimeCharacteristicRing};
923 use rand::SeedableRng;
924 use rand::rngs::SmallRng;
925
926 use super::*;
927
928 #[test]
929 fn test_new() {
930 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
931 assert_eq!(matrix.width, 2);
932 assert_eq!(matrix.height(), 3);
933 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6]);
934 }
935
936 #[test]
937 fn test_new_row() {
938 let matrix = RowMajorMatrix::new_row(vec![1, 2, 3]);
939 assert_eq!(matrix.width, 3);
940 assert_eq!(matrix.height(), 1);
941 }
942
943 #[test]
944 fn test_new_col() {
945 let matrix = RowMajorMatrix::new_col(vec![1, 2, 3]);
946 assert_eq!(matrix.width, 1);
947 assert_eq!(matrix.height(), 3);
948 }
949
950 #[test]
951 fn test_height_with_zero_width() {
952 let matrix: DenseMatrix<i32> = RowMajorMatrix::new(vec![], 0);
953 assert_eq!(matrix.height(), 0);
954 }
955
956 #[test]
957 fn test_get_methods() {
958 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2); assert_eq!(matrix.get(0, 0), Some(1));
960 assert_eq!(matrix.get(1, 1), Some(4));
961 assert_eq!(matrix.get(2, 0), Some(5));
962 unsafe {
963 assert_eq!(matrix.get_unchecked(0, 1), 2);
964 assert_eq!(matrix.get_unchecked(1, 0), 3);
965 assert_eq!(matrix.get_unchecked(2, 1), 6);
966 }
967 assert_eq!(matrix.get(3, 0), None); assert_eq!(matrix.get(0, 2), None); }
970
971 #[test]
972 fn test_row_methods() {
973 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 4); let row: Vec<_> = matrix.row(1).unwrap().into_iter().collect();
975 assert_eq!(row, vec![5, 6, 7, 8]);
976 unsafe {
977 let row: Vec<_> = matrix.row_unchecked(0).into_iter().collect();
978 assert_eq!(row, vec![1, 2, 3, 4]);
979 let row: Vec<_> = matrix.row_subseq_unchecked(0, 0, 3).into_iter().collect();
980 assert_eq!(row, vec![1, 2, 3]);
981 let row: Vec<_> = matrix.row_subseq_unchecked(0, 1, 3).into_iter().collect();
982 assert_eq!(row, vec![2, 3]);
983 let row: Vec<_> = matrix.row_subseq_unchecked(0, 2, 4).into_iter().collect();
984 assert_eq!(row, vec![3, 4]);
985 }
986 assert!(matrix.row(2).is_none()); }
988
989 #[test]
990 fn test_row_slice_methods() {
991 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], 3); let slice0 = matrix.row_slice(0);
993 let slice2 = matrix.row_slice(2);
994 assert_eq!(slice0.unwrap().deref(), &[1, 2, 3]);
995 assert_eq!(slice2.unwrap().deref(), &[7, 8, 9]);
996 unsafe {
997 assert_eq!(&[1, 2, 3], matrix.row_slice_unchecked(0).deref());
998 assert_eq!(&[7, 8, 9], matrix.row_slice_unchecked(2).deref());
999
1000 assert_eq!(&[1, 2, 3], matrix.row_subslice_unchecked(0, 0, 3).deref());
1001 assert_eq!(&[8], matrix.row_subslice_unchecked(2, 1, 2).deref());
1002 }
1003 assert!(matrix.row_slice(3).is_none()); }
1005
1006 #[test]
1007 fn test_as_view() {
1008 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1009 let view = matrix.as_view();
1010 assert_eq!(view.values, &[1, 2, 3, 4]);
1011 assert_eq!(view.width, 2);
1012 }
1013
1014 #[test]
1015 fn test_as_view_mut() {
1016 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1017 let view = matrix.as_view_mut();
1018 view.values[0] = 10;
1019 assert_eq!(matrix.values, vec![10, 2, 3, 4]);
1020 }
1021
1022 #[test]
1023 fn test_copy_from() {
1024 let mut matrix1 = RowMajorMatrix::new(vec![0, 0, 0, 0], 2);
1025 let matrix2 = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1026 matrix1.copy_from(&matrix2);
1027 assert_eq!(matrix1.values, vec![1, 2, 3, 4]);
1028 }
1029
1030 #[test]
1031 fn test_split_rows() {
1032 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1033 let (top, bottom) = matrix.split_rows(1);
1034 assert_eq!(top.values, vec![1, 2]);
1035 assert_eq!(bottom.values, vec![3, 4, 5, 6]);
1036 }
1037
1038 #[test]
1039 fn test_split_rows_mut() {
1040 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1041 let (top, bottom) = matrix.split_rows_mut(1);
1042 assert_eq!(top.values, vec![1, 2]);
1043 assert_eq!(bottom.values, vec![3, 4, 5, 6]);
1044 }
1045
1046 #[test]
1047 fn test_row_mut() {
1048 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1049 matrix.row_mut(1)[0] = 10;
1050 assert_eq!(matrix.values, vec![1, 2, 10, 4, 5, 6]);
1051 }
1052
1053 #[test]
1054 fn test_bit_reversed_zero_pad() {
1055 let matrix = RowMajorMatrix::new(
1056 vec![
1057 BabyBear::new(1),
1058 BabyBear::new(2),
1059 BabyBear::new(3),
1060 BabyBear::new(4),
1061 ],
1062 2,
1063 );
1064 let padded = matrix.bit_reversed_zero_pad(1);
1065 assert_eq!(padded.width, 2);
1066 assert_eq!(
1067 padded.values,
1068 vec![
1069 BabyBear::new(1),
1070 BabyBear::new(2),
1071 BabyBear::new(0),
1072 BabyBear::new(0),
1073 BabyBear::new(3),
1074 BabyBear::new(4),
1075 BabyBear::new(0),
1076 BabyBear::new(0)
1077 ]
1078 );
1079 }
1080
1081 #[test]
1082 fn test_bit_reversed_zero_pad_no_change() {
1083 let matrix = RowMajorMatrix::new(
1084 vec![
1085 BabyBear::new(1),
1086 BabyBear::new(2),
1087 BabyBear::new(3),
1088 BabyBear::new(4),
1089 ],
1090 2,
1091 );
1092 let padded = matrix.bit_reversed_zero_pad(0);
1093
1094 assert_eq!(padded.width, 2);
1095 assert_eq!(
1096 padded.values,
1097 vec![
1098 BabyBear::new(1),
1099 BabyBear::new(2),
1100 BabyBear::new(3),
1101 BabyBear::new(4),
1102 ]
1103 );
1104 }
1105
1106 #[test]
1107 fn test_scale() {
1108 let mut matrix = RowMajorMatrix::new(
1109 vec![
1110 BabyBear::new(1),
1111 BabyBear::new(2),
1112 BabyBear::new(3),
1113 BabyBear::new(4),
1114 BabyBear::new(5),
1115 BabyBear::new(6),
1116 ],
1117 2,
1118 );
1119 matrix.scale(BabyBear::new(2));
1120 assert_eq!(
1121 matrix.values,
1122 vec![
1123 BabyBear::new(2),
1124 BabyBear::new(4),
1125 BabyBear::new(6),
1126 BabyBear::new(8),
1127 BabyBear::new(10),
1128 BabyBear::new(12)
1129 ]
1130 );
1131 }
1132
1133 #[test]
1134 fn test_scale_row() {
1135 let mut matrix = RowMajorMatrix::new(
1136 vec![
1137 BabyBear::new(1),
1138 BabyBear::new(2),
1139 BabyBear::new(3),
1140 BabyBear::new(4),
1141 BabyBear::new(5),
1142 BabyBear::new(6),
1143 ],
1144 2,
1145 );
1146 matrix.scale_row(1, BabyBear::new(3));
1147 assert_eq!(
1148 matrix.values,
1149 vec![
1150 BabyBear::new(1),
1151 BabyBear::new(2),
1152 BabyBear::new(9),
1153 BabyBear::new(12),
1154 BabyBear::new(5),
1155 BabyBear::new(6),
1156 ]
1157 );
1158 }
1159
1160 #[test]
1161 fn test_to_row_major_matrix() {
1162 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1163 let converted = matrix.to_row_major_matrix();
1164
1165 assert_eq!(converted.width, 2);
1167 assert_eq!(converted.height(), 3);
1168 assert_eq!(converted.values, vec![1, 2, 3, 4, 5, 6]);
1169 }
1170
1171 #[test]
1172 fn test_horizontally_packed_row() {
1173 type Packed = FieldArray<BabyBear, 2>;
1174
1175 let matrix = RowMajorMatrix::new(
1176 vec![
1177 BabyBear::new(1),
1178 BabyBear::new(2),
1179 BabyBear::new(3),
1180 BabyBear::new(4),
1181 BabyBear::new(5),
1182 BabyBear::new(6),
1183 ],
1184 3,
1185 );
1186
1187 let (packed_iter, suffix_iter) = matrix.horizontally_packed_row::<Packed>(1);
1188
1189 let packed: Vec<_> = packed_iter.collect();
1190 let suffix: Vec<_> = suffix_iter.collect();
1191
1192 assert_eq!(
1193 packed,
1194 vec![Packed::from([BabyBear::new(4), BabyBear::new(5)])]
1195 );
1196 assert_eq!(suffix, vec![BabyBear::new(6)]);
1197 }
1198
1199 #[test]
1200 fn test_padded_horizontally_packed_row() {
1201 use p3_baby_bear::BabyBear;
1202
1203 type Packed = FieldArray<BabyBear, 2>;
1204
1205 let matrix = RowMajorMatrix::new(
1206 vec![
1207 BabyBear::new(1),
1208 BabyBear::new(2),
1209 BabyBear::new(3),
1210 BabyBear::new(4),
1211 BabyBear::new(5),
1212 BabyBear::new(6),
1213 ],
1214 3,
1215 );
1216
1217 let packed_iter = matrix.padded_horizontally_packed_row::<Packed>(1);
1218 let packed: Vec<_> = packed_iter.collect();
1219
1220 assert_eq!(
1221 packed,
1222 vec![
1223 Packed::from([BabyBear::new(4), BabyBear::new(5)]),
1224 Packed::from([BabyBear::new(6), BabyBear::new(0)])
1225 ]
1226 );
1227 }
1228
1229 #[test]
1230 fn test_padded_horizontally_packed_row_exact_width() {
1231 type Packed = FieldArray<BabyBear, 2>;
1232
1233 let matrix = RowMajorMatrix::new(
1237 vec![
1238 BabyBear::new(1),
1239 BabyBear::new(2),
1240 BabyBear::new(3),
1241 BabyBear::new(4),
1242 BabyBear::new(5),
1243 BabyBear::new(6),
1244 BabyBear::new(7),
1245 BabyBear::new(8),
1246 ],
1247 4,
1248 );
1249
1250 let packed: Vec<_> = matrix.padded_horizontally_packed_row::<Packed>(1).collect();
1251
1252 assert_eq!(packed.len(), 2);
1253 assert_eq!(
1254 packed,
1255 vec![
1256 Packed::from([BabyBear::new(5), BabyBear::new(6)]),
1257 Packed::from([BabyBear::new(7), BabyBear::new(8)]),
1258 ]
1259 );
1260 }
1261
1262 #[test]
1263 fn test_pad_to_height() {
1264 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 3);
1265
1266 matrix.pad_to_height(4, 9);
1271
1272 assert_eq!(matrix.height(), 4);
1279 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6, 9, 9, 9, 9, 9, 9]);
1280 }
1281
1282 #[test]
1283 fn test_pad_to_power_of_two_height() {
1284 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1289 assert_eq!(matrix.height(), 3);
1290 matrix.pad_to_power_of_two_height(0);
1291 assert_eq!(matrix.height(), 4);
1292 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6, 0, 0]);
1294
1295 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 2);
1300 assert_eq!(matrix.height(), 4);
1301 matrix.pad_to_power_of_two_height(99);
1302 assert_eq!(matrix.height(), 4);
1303 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6, 7, 8]);
1305
1306 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3], 3);
1310 assert_eq!(matrix.height(), 1);
1311 matrix.pad_to_power_of_two_height(42);
1312 assert_eq!(matrix.height(), 1);
1313 assert_eq!(matrix.values, vec![1, 2, 3]);
1314
1315 let mut matrix = RowMajorMatrix::new(vec![1; 10], 2);
1319 assert_eq!(matrix.height(), 5);
1320 matrix.pad_to_power_of_two_height(-1);
1321 assert_eq!(matrix.height(), 8);
1322 assert_eq!(matrix.values.len(), 16);
1324 assert!(matrix.values[..10].iter().all(|&v| v == 1));
1325 assert!(matrix.values[10..].iter().all(|&v| v == -1));
1326 }
1327
1328 #[test]
1329 fn test_pad_to_power_of_two_height_empty_matrix() {
1330 let mut matrix: RowMajorMatrix<i32> = RowMajorMatrix::new(vec![], 3);
1333 assert_eq!(matrix.height(), 0);
1334 assert_eq!(matrix.width, 3);
1335 matrix.pad_to_power_of_two_height(7);
1336 assert_eq!(matrix.height(), 1);
1338 assert_eq!(matrix.values, vec![7, 7, 7]);
1339 }
1340
1341 #[test]
1342 fn test_pad_to_min_power_of_two_height() {
1343 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1349 assert_eq!(matrix.height(), 3);
1350 matrix.pad_to_min_power_of_two_height(5, 0);
1351 assert_eq!(matrix.height(), 8);
1352 assert_eq!(matrix.values[..6], [1, 2, 3, 4, 5, 6]);
1353 assert!(matrix.values[6..].iter().all(|&v| v == 0));
1354
1355 let mut matrix = RowMajorMatrix::new(vec![1; 10], 2);
1361 assert_eq!(matrix.height(), 5);
1362 matrix.pad_to_min_power_of_two_height(2, -1);
1363 assert_eq!(matrix.height(), 8);
1364 assert!(matrix.values[..10].iter().all(|&v| v == 1));
1365 assert!(matrix.values[10..].iter().all(|&v| v == -1));
1366
1367 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 2);
1373 assert_eq!(matrix.height(), 4);
1374 matrix.pad_to_min_power_of_two_height(3, 99);
1375 assert_eq!(matrix.height(), 4);
1376 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6, 7, 8]);
1377
1378 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1384 assert_eq!(matrix.height(), 3);
1385 matrix.pad_to_min_power_of_two_height(0, 0);
1386 assert_eq!(matrix.height(), 4);
1387 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6, 0, 0]);
1388
1389 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 3);
1391 assert_eq!(matrix.height(), 2);
1392 matrix.pad_to_min_power_of_two_height(8, 7);
1393 assert_eq!(matrix.height(), 8);
1394 assert_eq!(matrix.values[..6], [1, 2, 3, 4, 5, 6]);
1395 assert!(matrix.values[6..].iter().all(|&v| v == 7));
1396 assert_eq!(matrix.values.len(), 24); }
1398
1399 #[test]
1400 fn test_pad_to_min_power_of_two_height_empty_matrix() {
1401 let mut matrix: RowMajorMatrix<i32> = RowMajorMatrix::new(vec![], 3);
1403 assert_eq!(matrix.height(), 0);
1404 matrix.pad_to_min_power_of_two_height(5, 7);
1405 assert_eq!(matrix.height(), 8);
1406 assert_eq!(matrix.values.len(), 24);
1407 assert!(matrix.values.iter().all(|&v| v == 7));
1408 }
1409
1410 #[test]
1411 fn test_from_flat_padded() {
1412 let matrix = RowMajorMatrix::from_flat_padded(vec![1, 2, 3, 4, 5, 6], 3, 0);
1416 assert_eq!(matrix.height(), 2);
1417 assert_eq!(matrix.width, 3);
1418 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 6]);
1419
1420 let matrix = RowMajorMatrix::from_flat_padded(vec![1, 2, 3, 4, 5], 3, 99);
1424 assert_eq!(matrix.height(), 2);
1425 assert_eq!(matrix.width, 3);
1426 assert_eq!(matrix.values, vec![1, 2, 3, 4, 5, 99]);
1427
1428 let matrix = RowMajorMatrix::from_flat_padded(vec![42], 3, 0);
1430 assert_eq!(matrix.height(), 1);
1431 assert_eq!(matrix.values, vec![42, 0, 0]);
1432
1433 let matrix = RowMajorMatrix::from_flat_padded(vec![], 4, 7);
1435 assert_eq!(matrix.height(), 1);
1436 assert_eq!(matrix.width, 4);
1437 assert_eq!(matrix.values, vec![7, 7, 7, 7]);
1438
1439 let matrix = RowMajorMatrix::from_flat_padded(vec![10, 20, 30], 1, 0);
1441 assert_eq!(matrix.height(), 3);
1442 assert_eq!(matrix.values, vec![10, 20, 30]);
1443 }
1444
1445 #[test]
1446 #[should_panic(expected = "width must be positive")]
1447 fn test_from_flat_padded_zero_width_panics() {
1448 let _ = RowMajorMatrix::from_flat_padded(vec![1, 2, 3], 0, 0);
1449 }
1450
1451 #[test]
1452 fn test_widen_right() {
1453 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1459 matrix.widen_right(1, 0);
1460 assert_eq!(matrix.width, 3);
1461 assert_eq!(matrix.height(), 2);
1462 assert_eq!(matrix.values, vec![1, 2, 0, 3, 4, 0]);
1463
1464 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1470 matrix.widen_right(3, -1);
1471 assert_eq!(matrix.width, 5);
1472 assert_eq!(matrix.height(), 2);
1473 assert_eq!(matrix.values, vec![1, 2, -1, -1, -1, 3, 4, -1, -1, -1]);
1474
1475 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4], 2);
1477 matrix.widen_right(0, 99);
1478 assert_eq!(matrix.width, 2);
1479 assert_eq!(matrix.values, vec![1, 2, 3, 4]);
1480
1481 let mut matrix = RowMajorMatrix::new(vec![10, 20, 30], 3);
1483 matrix.widen_right(2, 0);
1484 assert_eq!(matrix.width, 5);
1485 assert_eq!(matrix.height(), 1);
1486 assert_eq!(matrix.values, vec![10, 20, 30, 0, 0]);
1487
1488 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3], 1);
1495 matrix.widen_right(2, 0);
1496 assert_eq!(matrix.width, 3);
1497 assert_eq!(matrix.height(), 3);
1498 assert_eq!(matrix.values, vec![1, 0, 0, 2, 0, 0, 3, 0, 0]);
1499 }
1500
1501 #[test]
1502 fn test_widen_right_empty_matrix() {
1503 let mut matrix: RowMajorMatrix<i32> = RowMajorMatrix::new(vec![], 3);
1505 matrix.widen_right(2, 0);
1506 assert_eq!(matrix.width, 5);
1507 assert_eq!(matrix.height(), 0);
1508 assert!(matrix.values.is_empty());
1509 }
1510
1511 #[test]
1512 fn test_transpose_into() {
1513 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 3);
1514
1515 let mut transposed = RowMajorMatrix::new(vec![0; 6], 2);
1520
1521 matrix.transpose_into(&mut transposed);
1522
1523 assert_eq!(transposed.width, 2);
1529 assert_eq!(transposed.height(), 3);
1530 assert_eq!(transposed.values, vec![1, 4, 2, 5, 3, 6]);
1531 }
1532
1533 #[test]
1534 fn test_flatten_to_base() {
1535 let matrix = RowMajorMatrix::new(
1536 vec![
1537 BabyBear::new(2),
1538 BabyBear::new(3),
1539 BabyBear::new(4),
1540 BabyBear::new(5),
1541 ],
1542 2,
1543 );
1544
1545 let flattened: RowMajorMatrix<BabyBear> = matrix.flatten_to_base();
1546
1547 assert_eq!(flattened.width, 2);
1548 assert_eq!(
1549 flattened.values,
1550 vec![
1551 BabyBear::new(2),
1552 BabyBear::new(3),
1553 BabyBear::new(4),
1554 BabyBear::new(5),
1555 ]
1556 );
1557 }
1558
1559 #[test]
1560 fn test_horizontally_packed_row_mut() {
1561 type Packed = FieldArray<BabyBear, 2>;
1562
1563 let mut matrix = RowMajorMatrix::new(
1564 vec![
1565 BabyBear::new(1),
1566 BabyBear::new(2),
1567 BabyBear::new(3),
1568 BabyBear::new(4),
1569 BabyBear::new(5),
1570 BabyBear::new(6),
1571 ],
1572 3,
1573 );
1574
1575 let (packed, suffix) = matrix.horizontally_packed_row_mut::<Packed>(1);
1576 packed[0] = Packed::from([BabyBear::new(9), BabyBear::new(10)]);
1577 suffix[0] = BabyBear::new(11);
1578
1579 assert_eq!(
1580 matrix.values,
1581 vec![
1582 BabyBear::new(1),
1583 BabyBear::new(2),
1584 BabyBear::new(3),
1585 BabyBear::new(9),
1586 BabyBear::new(10),
1587 BabyBear::new(11),
1588 ]
1589 );
1590 }
1591
1592 #[test]
1593 fn test_par_row_chunks() {
1594 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 2);
1595
1596 let chunks: Vec<_> = matrix.par_row_chunks(2).collect();
1597
1598 assert_eq!(chunks.len(), 2);
1599 assert_eq!(chunks[0].values, vec![1, 2, 3, 4]);
1600 assert_eq!(chunks[1].values, vec![5, 6, 7, 8]);
1601 }
1602
1603 #[test]
1604 fn test_par_row_chunks_exact() {
1605 let matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1606
1607 let chunks: Vec<_> = matrix.par_row_chunks_exact(1).collect();
1608
1609 assert_eq!(chunks.len(), 3);
1610 assert_eq!(chunks[0].values, vec![1, 2]);
1611 assert_eq!(chunks[1].values, vec![3, 4]);
1612 assert_eq!(chunks[2].values, vec![5, 6]);
1613 }
1614
1615 #[test]
1616 fn test_par_row_chunks_mut() {
1617 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 2);
1618
1619 matrix
1620 .par_row_chunks_mut(2)
1621 .for_each(|chunk| chunk.values.iter_mut().for_each(|x| *x += 10));
1622
1623 assert_eq!(matrix.values, vec![11, 12, 13, 14, 15, 16, 17, 18]);
1624 }
1625
1626 #[test]
1627 fn test_row_chunks_exact_mut() {
1628 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1629
1630 for chunk in matrix.row_chunks_exact_mut(1) {
1631 chunk.values.iter_mut().for_each(|x| *x *= 2);
1632 }
1633
1634 assert_eq!(matrix.values, vec![2, 4, 6, 8, 10, 12]);
1635 }
1636
1637 #[test]
1638 fn test_par_row_chunks_exact_mut() {
1639 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1640
1641 matrix
1642 .par_row_chunks_exact_mut(1)
1643 .for_each(|chunk| chunk.values.iter_mut().for_each(|x| *x += 5));
1644
1645 assert_eq!(matrix.values, vec![6, 7, 8, 9, 10, 11]);
1646 }
1647
1648 #[test]
1649 fn test_row_pair_mut() {
1650 let mut matrix = RowMajorMatrix::new(vec![1, 2, 3, 4, 5, 6], 2);
1651
1652 let (row1, row2) = matrix.row_pair_mut(0, 2);
1653 row1[0] = 9;
1654 row2[1] = 10;
1655
1656 assert_eq!(matrix.values, vec![9, 2, 3, 4, 5, 10]);
1657 }
1658
1659 #[test]
1660 fn test_packed_row_pair_mut() {
1661 type Packed = FieldArray<BabyBear, 2>;
1662
1663 let mut matrix = RowMajorMatrix::new(
1664 vec![
1665 BabyBear::new(1),
1666 BabyBear::new(2),
1667 BabyBear::new(3),
1668 BabyBear::new(4),
1669 BabyBear::new(5),
1670 BabyBear::new(6),
1671 ],
1672 3,
1673 );
1674
1675 let ((packed1, sfx1), (packed2, sfx2)) = matrix.packed_row_pair_mut::<Packed>(0, 1);
1676 packed1[0] = Packed::from([BabyBear::new(7), BabyBear::new(8)]);
1677 packed2[0] = Packed::from([BabyBear::new(33), BabyBear::new(44)]);
1678 sfx1[0] = BabyBear::new(99);
1679 sfx2[0] = BabyBear::new(9);
1680
1681 assert_eq!(
1682 matrix.values,
1683 vec![
1684 BabyBear::new(7),
1685 BabyBear::new(8),
1686 BabyBear::new(99),
1687 BabyBear::new(33),
1688 BabyBear::new(44),
1689 BabyBear::new(9),
1690 ]
1691 );
1692 }
1693
1694 #[test]
1695 fn test_transpose_square_matrix() {
1696 const START_INDEX: usize = 1;
1697 const VALUE_LEN: usize = 9;
1698 const WIDTH: usize = 3;
1699 const HEIGHT: usize = 3;
1700
1701 let matrix_values = (START_INDEX..=VALUE_LEN).collect::<Vec<_>>();
1702 let matrix = RowMajorMatrix::new(matrix_values, WIDTH);
1703 let transposed = matrix.transpose();
1704 let should_be_transposed_values = vec![1, 4, 7, 2, 5, 8, 3, 6, 9];
1705 let should_be_transposed = RowMajorMatrix::new(should_be_transposed_values, HEIGHT);
1706 assert_eq!(transposed, should_be_transposed);
1707 }
1708
1709 #[test]
1710 fn test_transpose_row_matrix() {
1711 const START_INDEX: usize = 1;
1712 const VALUE_LEN: usize = 30;
1713 const WIDTH: usize = 1;
1714 const HEIGHT: usize = 30;
1715
1716 let matrix_values = (START_INDEX..=VALUE_LEN).collect::<Vec<_>>();
1717 let matrix = RowMajorMatrix::new(matrix_values.clone(), WIDTH);
1718 let transposed = matrix.transpose();
1719 let should_be_transposed = RowMajorMatrix::new(matrix_values, HEIGHT);
1720 assert_eq!(transposed, should_be_transposed);
1721 }
1722
1723 #[test]
1724 fn test_transpose_rectangular_matrix() {
1725 const START_INDEX: usize = 1;
1726 const VALUE_LEN: usize = 30;
1727 const WIDTH: usize = 5;
1728 const HEIGHT: usize = 6;
1729
1730 let matrix_values = (START_INDEX..=VALUE_LEN).collect::<Vec<_>>();
1731 let matrix = RowMajorMatrix::new(matrix_values, WIDTH);
1732 let transposed = matrix.transpose();
1733 let should_be_transposed_values = vec![
1734 1, 6, 11, 16, 21, 26, 2, 7, 12, 17, 22, 27, 3, 8, 13, 18, 23, 28, 4, 9, 14, 19, 24, 29,
1735 5, 10, 15, 20, 25, 30,
1736 ];
1737 let should_be_transposed = RowMajorMatrix::new(should_be_transposed_values, HEIGHT);
1738 assert_eq!(transposed, should_be_transposed);
1739 }
1740
1741 #[test]
1742 fn test_transpose_larger_rectangular_matrix() {
1743 const START_INDEX: usize = 1;
1744 const VALUE_LEN: usize = 131072; const WIDTH: usize = 256;
1746 const HEIGHT: usize = 512;
1747
1748 let matrix_values = (START_INDEX..=VALUE_LEN).collect::<Vec<_>>();
1749 let matrix = RowMajorMatrix::new(matrix_values, WIDTH);
1750 let transposed = matrix.transpose();
1751
1752 assert_eq!(transposed.width(), HEIGHT);
1753 assert_eq!(transposed.height(), WIDTH);
1754
1755 for col_index in 0..WIDTH {
1756 for row_index in 0..HEIGHT {
1757 assert_eq!(
1758 matrix.values[row_index * WIDTH + col_index],
1759 transposed.values[col_index * HEIGHT + row_index]
1760 );
1761 }
1762 }
1763 }
1764
1765 #[test]
1766 fn test_transpose_very_large_rectangular_matrix() {
1767 const START_INDEX: usize = 1;
1768 const VALUE_LEN: usize = 1048576; const WIDTH: usize = 1024;
1770 const HEIGHT: usize = 1024;
1771
1772 let matrix_values = (START_INDEX..=VALUE_LEN).collect::<Vec<_>>();
1773 let matrix = RowMajorMatrix::new(matrix_values, WIDTH);
1774 let transposed = matrix.transpose();
1775
1776 assert_eq!(transposed.width(), HEIGHT);
1777 assert_eq!(transposed.height(), WIDTH);
1778
1779 for col_index in 0..WIDTH {
1780 for row_index in 0..HEIGHT {
1781 assert_eq!(
1782 matrix.values[row_index * WIDTH + col_index],
1783 transposed.values[col_index * HEIGHT + row_index]
1784 );
1785 }
1786 }
1787 }
1788
1789 #[test]
1790 fn test_vertically_packed_row_scalar_width_1() {
1791 type Packed = BabyBear;
1792
1793 let matrix = RowMajorMatrix::new((1..17).map(BabyBear::new).collect::<Vec<_>>(), 4);
1794 let packed = matrix
1795 .vertically_packed_row::<Packed>(2)
1796 .collect::<Vec<_>>();
1797
1798 assert_eq!(
1799 packed,
1800 vec![
1801 BabyBear::new(9),
1802 BabyBear::new(10),
1803 BabyBear::new(11),
1804 BabyBear::new(12),
1805 ]
1806 );
1807 }
1808
1809 #[test]
1810 fn test_vertically_packed_row_pair() {
1811 type Packed = FieldArray<BabyBear, 2>;
1812
1813 let matrix = RowMajorMatrix::new((1..17).map(BabyBear::new).collect::<Vec<_>>(), 4);
1814
1815 let packed = matrix.vertically_packed_row_pair::<Packed>(0, 2);
1817
1818 assert_eq!(
1834 packed,
1835 (1..5)
1836 .chain(9..13)
1837 .map(|i| [BabyBear::new(i), BabyBear::new(i + 4)].into())
1838 .collect::<Vec<_>>(),
1839 );
1840 }
1841
1842 #[test]
1843 fn test_vertically_packed_row_pair_scalar_width_1() {
1844 type Packed = BabyBear;
1845
1846 let matrix = RowMajorMatrix::new((1..17).map(BabyBear::new).collect::<Vec<_>>(), 4);
1847 let packed = matrix.vertically_packed_row_pair::<Packed>(1, 2);
1848
1849 assert_eq!(
1850 packed,
1851 vec![
1852 BabyBear::new(5),
1853 BabyBear::new(6),
1854 BabyBear::new(7),
1855 BabyBear::new(8),
1856 BabyBear::new(13),
1857 BabyBear::new(14),
1858 BabyBear::new(15),
1859 BabyBear::new(16),
1860 ]
1861 );
1862 }
1863
1864 #[test]
1865 fn test_vertically_packed_row_pair_overlap() {
1866 type Packed = FieldArray<BabyBear, 2>;
1867
1868 let matrix = RowMajorMatrix::new((1..17).map(BabyBear::new).collect::<Vec<_>>(), 4);
1869
1870 let packed = matrix.vertically_packed_row_pair::<Packed>(0, 1);
1887
1888 assert_eq!(
1889 packed,
1890 (1..5)
1891 .chain(5..9)
1892 .map(|i| [BabyBear::new(i), BabyBear::new(i + 4)].into())
1893 .collect::<Vec<_>>(),
1894 );
1895 }
1896
1897 #[test]
1898 fn test_vertically_packed_row_pair_wraparound_start_1() {
1899 use p3_baby_bear::BabyBear;
1900 use p3_field::FieldArray;
1901
1902 type Packed = FieldArray<BabyBear, 2>;
1903
1904 let matrix = RowMajorMatrix::new((1..17).map(BabyBear::new).collect::<Vec<_>>(), 4);
1905
1906 let packed = matrix.vertically_packed_row_pair::<Packed>(1, 2);
1925
1926 assert_eq!(
1927 packed,
1928 vec![
1929 Packed::from([BabyBear::new(5), BabyBear::new(9)]),
1930 Packed::from([BabyBear::new(6), BabyBear::new(10)]),
1931 Packed::from([BabyBear::new(7), BabyBear::new(11)]),
1932 Packed::from([BabyBear::new(8), BabyBear::new(12)]),
1933 Packed::from([BabyBear::new(13), BabyBear::new(1)]),
1934 Packed::from([BabyBear::new(14), BabyBear::new(2)]),
1935 Packed::from([BabyBear::new(15), BabyBear::new(3)]),
1936 Packed::from([BabyBear::new(16), BabyBear::new(4)]),
1937 ]
1938 );
1939 }
1940
1941 #[test]
1942 fn test_with_zero_cols() {
1943 let mat: RowMajorMatrix<BabyBear> =
1949 RowMajorMatrix::new((1..=6).map(BabyBear::new).collect(), 3);
1950 let widened = mat.with_zero_cols(2);
1951
1952 assert_eq!(widened.width(), 5);
1954 assert_eq!(widened.height(), 2);
1955
1956 assert_eq!(
1958 widened.row_slices().next().unwrap(),
1959 &[
1960 BabyBear::new(1),
1961 BabyBear::new(2),
1962 BabyBear::new(3),
1963 BabyBear::ZERO,
1964 BabyBear::ZERO,
1965 ]
1966 );
1967
1968 assert_eq!(
1970 widened.row_slices().nth(1).unwrap(),
1971 &[
1972 BabyBear::new(4),
1973 BabyBear::new(5),
1974 BabyBear::new(6),
1975 BabyBear::ZERO,
1976 BabyBear::ZERO,
1977 ]
1978 );
1979
1980 let same = mat.with_zero_cols(0);
1982 assert_eq!(same.width(), mat.width());
1983 assert_eq!(same.values, mat.values);
1984
1985 let single_row: RowMajorMatrix<BabyBear> =
1989 RowMajorMatrix::new(vec![BabyBear::new(7), BabyBear::new(8)], 2);
1990 let widened = single_row.with_zero_cols(3);
1991 assert_eq!(widened.width(), 5);
1992 assert_eq!(widened.height(), 1);
1993 assert_eq!(
1994 widened.row_slices().next().unwrap(),
1995 &[
1996 BabyBear::new(7),
1997 BabyBear::new(8),
1998 BabyBear::ZERO,
1999 BabyBear::ZERO,
2000 BabyBear::ZERO,
2001 ]
2002 );
2003
2004 let single_col: RowMajorMatrix<BabyBear> = RowMajorMatrix::new(
2010 vec![BabyBear::new(1), BabyBear::new(2), BabyBear::new(3)],
2011 1,
2012 );
2013 let widened = single_col.with_zero_cols(2);
2014 assert_eq!(widened.width(), 3);
2015 assert_eq!(widened.height(), 3);
2016 for (i, row) in widened.row_slices().enumerate() {
2017 assert_eq!(row[0], BabyBear::new((i + 1) as u32));
2019 assert_eq!(row[1], BabyBear::ZERO);
2020 assert_eq!(row[2], BabyBear::ZERO);
2021 }
2022
2023 let empty: RowMajorMatrix<BabyBear> = RowMajorMatrix::new(vec![], 3);
2025 let widened = empty.with_zero_cols(2);
2026 assert_eq!(widened.width(), 5);
2027 assert_eq!(widened.height(), 0);
2028 assert!(widened.values.is_empty());
2029 }
2030
2031 #[test]
2032 fn test_with_zero_cols_matches_widen_right() {
2033 let mat: RowMajorMatrix<BabyBear> =
2041 RowMajorMatrix::new((1..=12).map(BabyBear::new).collect(), 4);
2042
2043 let via_method = mat.with_zero_cols(3);
2045
2046 let mut via_widen = mat;
2048 via_widen.widen_right(3, BabyBear::ZERO);
2049
2050 assert_eq!(via_method.width(), via_widen.width());
2052 assert_eq!(via_method.height(), via_widen.height());
2053 assert_eq!(via_method.values, via_widen.values);
2054 }
2055
2056 #[test]
2057 fn test_with_random_cols() {
2058 let mat: RowMajorMatrix<BabyBear> =
2066 RowMajorMatrix::new((1..=4).map(BabyBear::new).collect(), 2);
2067
2068 let seed = 42u64;
2069 let widened = mat.with_random_cols(3, SmallRng::seed_from_u64(seed));
2070
2071 assert_eq!(widened.width(), 5);
2073 assert_eq!(widened.height(), 2);
2074
2075 let mut reference_rng = SmallRng::seed_from_u64(seed);
2079 for (new_row, old_row) in widened.row_slices().zip(mat.row_slices()) {
2080 assert_eq!(&new_row[..2], old_row);
2082
2083 for val in &new_row[2..] {
2085 let expected: BabyBear = reference_rng.random();
2086 assert_eq!(*val, expected);
2087 }
2088 }
2089 }
2090
2091 #[test]
2092 fn test_with_random_cols_zero_extra() {
2093 let mat: RowMajorMatrix<BabyBear> =
2095 RowMajorMatrix::new((1..=6).map(BabyBear::new).collect(), 3);
2096 let same = mat.with_random_cols(0, SmallRng::seed_from_u64(0));
2097 assert_eq!(same.width(), mat.width());
2098 assert_eq!(same.values, mat.values);
2099 }
2100
2101 #[test]
2102 fn test_with_random_cols_empty_matrix() {
2103 let empty: RowMajorMatrix<BabyBear> = RowMajorMatrix::new(vec![], 3);
2105 let widened = empty.with_random_cols(2, SmallRng::seed_from_u64(0));
2106 assert_eq!(widened.width(), 5);
2107 assert_eq!(widened.height(), 0);
2108 assert!(widened.values.is_empty());
2109 }
2110
2111 #[test]
2112 fn test_with_random_cols_different_seeds() {
2113 let mat: RowMajorMatrix<BabyBear> =
2116 RowMajorMatrix::new((1..=4).map(BabyBear::new).collect(), 2);
2117
2118 let num_random = 4;
2119 let seed_a = 1u64;
2120 let seed_b = 2u64;
2121
2122 let result_a = mat.with_random_cols(num_random, SmallRng::seed_from_u64(seed_a));
2123 let result_b = mat.with_random_cols(num_random, SmallRng::seed_from_u64(seed_b));
2124
2125 for (seed, result) in [(seed_a, &result_a), (seed_b, &result_b)] {
2127 let mut reference_rng = SmallRng::seed_from_u64(seed);
2128 for (new_row, old_row) in result.row_slices().zip(mat.row_slices()) {
2129 assert_eq!(&new_row[..2], old_row);
2131
2132 for val in &new_row[2..] {
2134 let expected: BabyBear = reference_rng.random();
2135 assert_eq!(*val, expected);
2136 }
2137 }
2138 }
2139 }
2140}