1use crate::{
12 error::MathError,
13 integer::Z,
14 integer_mod_q::{MatZq, Modulus, Zq},
15 macros::for_others::implement_for_owned,
16 traits::{AsInteger, MatrixDimensions, MatrixSetEntry, MatrixSetSubmatrix, MatrixSwaps},
17 utils::index::{evaluate_index_for_vector, evaluate_indices_for_matrix},
18};
19use flint_sys::{
20 fmpz::fmpz_swap,
21 fmpz_mat::{
22 fmpz_mat_entry, fmpz_mat_invert_cols, fmpz_mat_invert_rows, fmpz_mat_swap_cols,
23 fmpz_mat_swap_rows,
24 },
25 fmpz_mod_mat::{
26 _fmpz_mod_mat_reduce, _fmpz_mod_mat_set_mod, fmpz_mod_mat_set, fmpz_mod_mat_set_entry,
27 fmpz_mod_mat_window_clear, fmpz_mod_mat_window_init,
28 },
29};
30use std::{
31 fmt::Display,
32 mem::MaybeUninit,
33 ptr::{null, null_mut},
34};
35
36impl<Integer: Into<Z>> MatrixSetEntry<Integer> for MatZq {
37 fn set_entry(
68 &mut self,
69 row: impl TryInto<i64> + Display,
70 column: impl TryInto<i64> + Display,
71 value: Integer,
72 ) -> Result<(), MathError> {
73 let value: Zq = Zq::from((value, &self.modulus));
75
76 self.set_entry(row, column, value)
77 }
78
79 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: Integer) {
108 let value: Z = value.into();
109
110 unsafe {
111 fmpz_mod_mat_set_entry(&mut self.matrix, row, column, &value.value)
113 };
114 }
115}
116
117impl MatrixSetEntry<&Zq> for MatZq {
118 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: &Zq) {
148 unsafe {
149 fmpz_mod_mat_set_entry(&mut self.matrix, row, column, &value.value.value)
151 };
152 }
153}
154
155implement_for_owned!(Zq, MatZq, MatrixSetEntry);
156
157impl MatrixSetSubmatrix for MatZq {
158 unsafe fn set_submatrix_unchecked(
199 &mut self,
200 row_self_start: i64,
201 col_self_start: i64,
202 row_self_end: i64,
203 col_self_end: i64,
204 other: &Self,
205 row_other_start: i64,
206 col_other_start: i64,
207 row_other_end: i64,
208 col_other_end: i64,
209 ) {
210 {
211 let mut window_self = MaybeUninit::uninit();
212 unsafe {
214 fmpz_mod_mat_window_init(
215 window_self.as_mut_ptr(),
216 &self.matrix,
217 row_self_start,
218 col_self_start,
219 row_self_end,
220 col_self_end,
221 )
222 };
223 let mut window_other = MaybeUninit::uninit();
224 unsafe {
226 fmpz_mod_mat_window_init(
227 window_other.as_mut_ptr(),
228 &other.matrix,
229 row_other_start,
230 col_other_start,
231 row_other_end,
232 col_other_end,
233 )
234 };
235 unsafe {
236 fmpz_mod_mat_set(window_self.as_mut_ptr(), window_other.as_ptr());
237
238 fmpz_mod_mat_window_clear(window_self.as_mut_ptr());
241 fmpz_mod_mat_window_clear(window_other.as_mut_ptr());
242 }
243 }
244 }
245}
246
247impl MatrixSwaps for MatZq {
248 fn swap_entries(
274 &mut self,
275 row_0: impl TryInto<i64> + Display,
276 col_0: impl TryInto<i64> + Display,
277 row_1: impl TryInto<i64> + Display,
278 col_1: impl TryInto<i64> + Display,
279 ) -> Result<(), MathError> {
280 let (row_0, col_0) = evaluate_indices_for_matrix(self, row_0, col_0)?;
281 let (row_1, col_1) = evaluate_indices_for_matrix(self, row_1, col_1)?;
282
283 unsafe {
284 fmpz_swap(
285 fmpz_mat_entry(&self.matrix.mat[0], row_0, col_0),
286 fmpz_mat_entry(&self.matrix.mat[0], row_1, col_1),
287 )
288 };
289 Ok(())
290 }
291
292 fn swap_columns(
316 &mut self,
317 col_0: impl TryInto<i64> + Display,
318 col_1: impl TryInto<i64> + Display,
319 ) -> Result<(), MathError> {
320 let num_cols = self.get_num_columns();
321 let col_0 = evaluate_index_for_vector(col_0, num_cols)?;
322 let col_1 = evaluate_index_for_vector(col_1, num_cols)?;
323
324 if col_0 >= num_cols || col_1 >= num_cols {
325 return Err(MathError::OutOfBounds(
326 format!("smaller than {num_cols}"),
327 if col_0 > col_1 {
328 col_0.to_string()
329 } else {
330 col_1.to_string()
331 },
332 ));
333 }
334 unsafe { fmpz_mat_swap_cols(&mut self.matrix.mat[0], null(), col_0, col_1) }
335 Ok(())
336 }
337
338 fn swap_rows(
362 &mut self,
363 row_0: impl TryInto<i64> + Display,
364 row_1: impl TryInto<i64> + Display,
365 ) -> Result<(), MathError> {
366 let num_rows = self.get_num_rows();
367 let row_0 = evaluate_index_for_vector(row_0, num_rows)?;
368 let row_1 = evaluate_index_for_vector(row_1, num_rows)?;
369
370 if row_0 >= num_rows || row_1 >= num_rows {
371 return Err(MathError::OutOfBounds(
372 format!("smaller than {num_rows}"),
373 if row_0 > row_1 {
374 row_0.to_string()
375 } else {
376 row_1.to_string()
377 },
378 ));
379 }
380 unsafe { fmpz_mat_swap_rows(&mut self.matrix.mat[0], null(), row_0, row_1) }
381 Ok(())
382 }
383}
384
385impl MatZq {
386 pub fn reverse_columns(&mut self) {
397 unsafe { fmpz_mat_invert_cols(&mut self.matrix.mat[0], null_mut()) }
401 }
402
403 pub fn reverse_rows(&mut self) {
414 unsafe { fmpz_mat_invert_rows(&mut self.matrix.mat[0], null_mut()) }
418 }
419
420 pub fn change_modulus(&mut self, modulus: impl Into<Modulus>) {
439 self.modulus = modulus.into();
440 unsafe {
441 _fmpz_mod_mat_set_mod(&mut self.matrix, self.modulus.get_fmpz_ref().unwrap());
442 _fmpz_mod_mat_reduce(&mut self.matrix)
443 }
444 }
445}
446
447#[cfg(test)]
448mod test_setter {
449 use crate::{
450 integer::Z,
451 integer_mod_q::{MatZq, Zq},
452 traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
453 };
454 use std::str::FromStr;
455
456 #[test]
458 fn max_int_positive() {
459 let mut matrix = MatZq::new(5, 10, u64::MAX);
460 let value = Z::from(i64::MAX);
461 matrix.set_entry(0, 0, value).unwrap();
462
463 let entry: Z = matrix.get_entry(0, 0).unwrap();
464
465 assert_eq!(Z::from(i64::MAX), entry);
466 }
467
468 #[test]
470 fn large_positive() {
471 let mut matrix = MatZq::new(5, 10, u64::MAX);
472 let value = Z::from(u64::MAX - 1);
473 matrix.set_entry(0, 0, value).unwrap();
474
475 let entry: Z = matrix.get_entry(0, 0).unwrap();
476
477 assert_eq!(u64::MAX - 1, entry);
478 }
479
480 #[test]
482 fn max_int_negative() {
483 let mut matrix = MatZq::new(5, 10, u64::MAX);
484 let value = Z::from(-i64::MAX);
485 matrix.set_entry(0, 0, value).unwrap();
486
487 let entry: Z = matrix.get_entry(0, 0).unwrap();
488
489 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64, entry);
490 }
491
492 #[test]
494 fn large_negative() {
495 let mut matrix = MatZq::new(5, 10, u64::MAX);
496 let value = Z::from(-i64::MAX - 1);
497 matrix.set_entry(0, 0, value).unwrap();
498
499 let entry: Z = matrix.get_entry(0, 0).unwrap();
500
501 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64 - 1, entry);
502 }
503
504 #[test]
506 fn error_wrong_row() {
507 let mut matrix = MatZq::new(5, 10, 7);
508
509 assert!(matrix.set_entry(5, 1, 3).is_err());
510 assert!(matrix.set_entry(-6, 1, 1).is_err());
511 }
512
513 #[test]
515 fn error_wrong_column() {
516 let mut matrix = MatZq::new(5, 10, 7);
517
518 assert!(matrix.set_entry(1, 100, 3).is_err());
519 assert!(matrix.set_entry(1, -11, 1).is_err());
520 }
521
522 #[test]
524 fn diff_types() {
525 let mut matrix = MatZq::new(5, 10, 56);
526
527 matrix.set_entry(0, 0, Z::default()).unwrap();
528 matrix.set_entry(0, 0, Zq::from((12, 56))).unwrap();
529 matrix.set_entry(0, 0, 3).unwrap();
530 matrix.set_entry(0, 0, &Z::default()).unwrap();
531 matrix.set_entry(0, 0, &Zq::from((12, 56))).unwrap();
532 }
533
534 #[test]
536 fn negative_indexing() {
537 let mut matrix = MatZq::new(3, 3, 10);
538
539 matrix.set_entry(-1, -1, 9).unwrap();
540 matrix.set_entry(-1, -2, 8).unwrap();
541 matrix.set_entry(-3, -3, Zq::from((1, 10))).unwrap();
542
543 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 0, 0],[0, 8, 9]] mod 10").unwrap();
544 assert_eq!(matrix_cmp, matrix);
545 }
546
547 #[test]
549 fn set_entry_reduce() {
550 let mut matrix = MatZq::new(5, 10, 3);
551 matrix.set_entry(1, 1, Z::from(u64::MAX)).unwrap();
552
553 let entry: Z = matrix.get_entry(1, 1).unwrap();
554
555 assert_eq!(entry, Z::from(0));
556 }
557
558 #[test]
560 fn modulus_error() {
561 let mut matrix = MatZq::new(5, 10, 3);
562 assert!(matrix.set_entry(1, 1, Zq::from((2, 5))).is_err());
563 }
564
565 #[test]
567 fn column_small_entries() {
568 let mut mat_1 = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 11").unwrap();
569 let mat_2 = MatZq::from_str("[[0],[-1]] mod 11").unwrap();
570
571 let cmp = MatZq::from_str("[[1, 0, 3],[4, -1, 6]] mod 11").unwrap();
572
573 mat_1.set_column(1, &mat_2, 0).unwrap();
574
575 assert_eq!(cmp, mat_1);
576 }
577
578 #[test]
580 fn column_large_entries() {
581 let mut mat_1 = MatZq::from_str(&format!(
582 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
583 i64::MIN,
584 i64::MAX,
585 i64::MAX,
586 u64::MAX
587 ))
588 .unwrap();
589 let mat_2 = MatZq::from_str(&format!(
590 "[[1, {}],[{}, 0],[7, -1]] mod {}",
591 i64::MIN,
592 i64::MAX,
593 u64::MAX
594 ))
595 .unwrap();
596 let cmp = MatZq::from_str(&format!(
597 "[[{}, 1, 3, 4],[0, 4, {}, 5],[-1, 6, 8, 9]] mod {}",
598 i64::MIN,
599 i64::MAX,
600 u64::MAX
601 ))
602 .unwrap();
603
604 mat_1.set_column(0, &mat_2, 1).unwrap();
605
606 assert_eq!(cmp, mat_1);
607 }
608
609 #[test]
611 fn column_swap_same_entry() {
612 let mut mat_1 = MatZq::from_str(&format!(
613 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
614 i64::MIN,
615 i64::MAX,
616 i64::MAX,
617 u64::MAX
618 ))
619 .unwrap();
620 let cmp = mat_1.clone();
621
622 mat_1.set_column(0, &cmp, 0).unwrap();
623 mat_1.set_column(1, &cmp, 1).unwrap();
624
625 assert_eq!(cmp, mat_1);
626 }
627
628 #[test]
630 fn column_out_of_bounds() {
631 let mut mat_1 = MatZq::new(5, 2, 17);
632 let mat_2 = mat_1.clone();
633
634 assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
635 assert!(mat_1.set_column(2, &mat_2, 0).is_err());
636 assert!(mat_1.set_column(1, &mat_2, -3).is_err());
637 assert!(mat_1.set_column(1, &mat_2, 2).is_err());
638 }
639
640 #[test]
642 fn column_mismatching_columns() {
643 let mut mat_1 = MatZq::new(5, 2, 17);
644 let mat_2 = MatZq::new(2, 2, 17);
645
646 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
647 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
648 }
649
650 #[test]
652 fn column_mismatching_moduli() {
653 let mut mat_1 = MatZq::new(3, 3, 19);
654 let mat_2 = MatZq::new(3, 3, 17);
655
656 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
657 }
658
659 #[test]
661 fn row_small_entries() {
662 let mut mat_1 = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 11").unwrap();
663 let mat_2 = MatZq::from_str("[[0, -1, 2]] mod 11").unwrap();
664 let cmp = MatZq::from_str("[[1, 2, 3],[0, -1, 2]] mod 11").unwrap();
665
666 let _ = mat_1.set_row(1, &mat_2, 0);
667
668 assert_eq!(cmp, mat_1);
669 }
670
671 #[test]
673 fn row_large_entries() {
674 let mut mat_1 = MatZq::from_str(&format!(
675 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
676 i64::MIN,
677 i64::MAX,
678 i64::MAX,
679 u64::MAX
680 ))
681 .unwrap();
682 let mat_2 = MatZq::from_str(&format!(
683 "[[0, 0, 0, 0],[{}, 0, {}, 0]] mod {}",
684 i64::MIN,
685 i64::MAX,
686 u64::MAX
687 ))
688 .unwrap();
689 let cmp = MatZq::from_str(&format!(
690 "[[{}, 0, {}, 0],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
691 i64::MIN,
692 i64::MAX,
693 i64::MAX,
694 i64::MAX,
695 u64::MAX
696 ))
697 .unwrap();
698
699 let _ = mat_1.set_row(0, &mat_2, 1);
700
701 assert_eq!(cmp, mat_1);
702 }
703
704 #[test]
706 fn row_swap_same_entry() {
707 let mut mat_1 = MatZq::from_str(&format!(
708 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
709 i64::MIN,
710 i64::MAX,
711 i64::MAX,
712 u64::MAX
713 ))
714 .unwrap();
715 let cmp = mat_1.clone();
716
717 let _ = mat_1.set_row(0, &cmp, 0);
718 let _ = mat_1.set_row(1, &cmp, 1);
719
720 assert_eq!(cmp, mat_1);
721 }
722
723 #[test]
725 fn row_out_of_bounds() {
726 let mut mat_1 = MatZq::new(5, 2, 17);
727 let mat_2 = mat_1.clone();
728
729 assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
730 assert!(mat_1.set_row(5, &mat_2, 0).is_err());
731 assert!(mat_1.set_row(2, &mat_2, -6).is_err());
732 assert!(mat_1.set_row(2, &mat_2, 5).is_err());
733 }
734
735 #[test]
737 fn row_mismatching_columns() {
738 let mut mat_1 = MatZq::new(3, 2, 17);
739 let mat_2 = MatZq::new(3, 3, 17);
740
741 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
742 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
743 }
744
745 #[test]
747 fn row_mismatching_moduli() {
748 let mut mat_1 = MatZq::new(3, 3, 19);
749 let mat_2 = MatZq::new(3, 3, 17);
750
751 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
752 }
753
754 #[test]
756 fn negative_indexing_row_column() {
757 let mut matrix = MatZq::identity(3, 3, 17);
758 let matrix2 = MatZq::identity(3, 3, 17);
759
760 matrix.set_column(-1, &matrix2, -2).unwrap();
761 matrix.set_row(-1, &matrix2, -2).unwrap();
762
763 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 1, 1],[0, 1, 0]] mod 17").unwrap();
764 assert_eq!(matrix_cmp, matrix);
765 }
766}
767
768#[cfg(test)]
769mod test_swaps {
770 use super::MatZq;
771 use crate::traits::{MatrixGetSubmatrix, MatrixSwaps};
772 use std::str::FromStr;
773
774 #[test]
776 fn entries_small_entries() {
777 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
778 let cmp = MatZq::from_str("[[1, 5, 3],[4, 2, 6]] mod 7").unwrap();
779
780 let _ = matrix.swap_entries(1, 1, 0, 1);
781
782 assert_eq!(cmp, matrix);
783 }
784
785 #[test]
787 fn entries_large_entries() {
788 let mut matrix = MatZq::from_str(&format!(
789 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
790 i64::MIN,
791 i64::MAX,
792 i64::MAX,
793 u64::MAX
794 ))
795 .unwrap();
796 let cmp = MatZq::from_str(&format!(
797 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
798 i64::MAX,
799 i64::MAX,
800 i64::MIN,
801 u64::MAX
802 ))
803 .unwrap();
804
805 let _ = matrix.swap_entries(0, 0, 1, 2);
806
807 assert_eq!(cmp, matrix);
808 }
809
810 #[test]
812 fn entries_swap_same_entry() {
813 let mut matrix = MatZq::from_str(&format!(
814 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
815 i64::MIN,
816 i64::MAX,
817 i64::MAX,
818 u64::MAX
819 ))
820 .unwrap();
821 let cmp = matrix.clone();
822
823 let _ = matrix.swap_entries(0, 0, 0, 0);
824 let _ = matrix.swap_entries(1, 1, 1, 1);
825
826 assert_eq!(cmp, matrix);
827 }
828
829 #[test]
831 fn entries_out_of_bounds() {
832 let mut matrix = MatZq::new(5, 2, 5);
833
834 assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
835 assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
836 assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
837 assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
838 }
839
840 #[test]
842 fn entries_negative_indexing() {
843 let mut matrix = MatZq::identity(2, 2, 2);
844
845 matrix.swap_entries(-2, -2, -2, -1).unwrap();
846 assert_eq!("[[0, 1],[0, 1]] mod 2", matrix.to_string());
847 }
848
849 #[test]
851 fn columns_small_entries() {
852 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 17").unwrap();
853 let cmp_vec_0 = MatZq::from_str("[[1],[4]] mod 17").unwrap();
854 let cmp_vec_1 = MatZq::from_str("[[3],[6]] mod 17").unwrap();
855 let cmp_vec_2 = MatZq::from_str("[[2],[5]] mod 17").unwrap();
856
857 let _ = matrix.swap_columns(1, 2);
858
859 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
860 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
861 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
862 }
863
864 #[test]
866 fn columns_large_entries() {
867 let mut matrix = MatZq::from_str(&format!(
868 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
869 i64::MIN,
870 i64::MAX,
871 i64::MAX,
872 u64::MAX
873 ))
874 .unwrap();
875 let cmp_vec_0 =
876 MatZq::from_str(&format!("[[3],[{}],[8]] mod {}", i64::MAX, u64::MAX)).unwrap();
877 let cmp_vec_1 = MatZq::from_str(&format!("[[1],[4],[6]] mod {}", u64::MAX)).unwrap();
878 let cmp_vec_2 = MatZq::from_str(&format!(
879 "[[{}],[{}],[7]] mod {}",
880 i64::MIN,
881 i64::MAX,
882 u64::MAX
883 ))
884 .unwrap();
885 let cmp_vec_3 = MatZq::from_str(&format!("[[4],[5],[9]] mod {}", u64::MAX)).unwrap();
886
887 let _ = matrix.swap_columns(0, 2);
888
889 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
890 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
891 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
892 assert_eq!(cmp_vec_3, matrix.get_column(3).unwrap());
893 }
894
895 #[test]
897 fn columns_swap_same_col() {
898 let mut matrix = MatZq::from_str(&format!(
899 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
900 i64::MIN,
901 i64::MAX,
902 i64::MAX,
903 u64::MAX
904 ))
905 .unwrap();
906 let cmp = matrix.clone();
907
908 let _ = matrix.swap_columns(0, 0);
909
910 assert_eq!(cmp, matrix);
911 }
912
913 #[test]
915 fn column_out_of_bounds() {
916 let mut matrix = MatZq::new(5, 2, 5);
917
918 assert!(matrix.swap_columns(-6, 0).is_err());
919 assert!(matrix.swap_columns(0, -6).is_err());
920 assert!(matrix.swap_columns(5, 0).is_err());
921 assert!(matrix.swap_columns(0, 5).is_err());
922 }
923
924 #[test]
926 fn rows_small_entries() {
927 let mut matrix = MatZq::from_str("[[1, 2],[3, 4]] mod 12").unwrap();
928 let cmp_vec_0 = MatZq::from_str("[[3, 4]] mod 12").unwrap();
929 let cmp_vec_1 = MatZq::from_str("[[1, 2]] mod 12").unwrap();
930
931 let _ = matrix.swap_rows(1, 0);
932
933 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
934 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
935 }
936
937 #[test]
939 fn rows_large_entries() {
940 let mut matrix = MatZq::from_str(&format!(
941 "[[{}, 1, 3, 4],[7, 6, 8, 9],[{}, 4, {}, 5]] mod {}",
942 i64::MIN,
943 i64::MAX,
944 i64::MAX,
945 u64::MAX
946 ))
947 .unwrap();
948 let cmp_vec_0 = MatZq::from_str(&format!(
949 "[[{}, 4, {}, 5]] mod {}",
950 i64::MAX,
951 i64::MAX,
952 u64::MAX
953 ))
954 .unwrap();
955 let cmp_vec_1 = MatZq::from_str(&format!("[[7, 6, 8, 9]] mod {}", u64::MAX)).unwrap();
956 let cmp_vec_2 =
957 MatZq::from_str(&format!("[[{}, 1, 3, 4]] mod {}", i64::MIN, u64::MAX)).unwrap();
958
959 let _ = matrix.swap_rows(0, 2);
960
961 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
962 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
963 assert_eq!(cmp_vec_2, matrix.get_row(2).unwrap());
964 }
965
966 #[test]
968 fn rows_swap_same_row() {
969 let mut matrix = MatZq::from_str(&format!(
970 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
971 i64::MIN,
972 i64::MAX,
973 i64::MAX,
974 u64::MAX
975 ))
976 .unwrap();
977 let cmp = matrix.clone();
978
979 let _ = matrix.swap_rows(1, 1);
980
981 assert_eq!(cmp, matrix);
982 }
983
984 #[test]
986 fn row_out_of_bounds() {
987 let mut matrix = MatZq::new(2, 4, 5);
988
989 assert!(matrix.swap_rows(-3, 0).is_err());
990 assert!(matrix.swap_rows(0, -3).is_err());
991 assert!(matrix.swap_rows(4, 0).is_err());
992 assert!(matrix.swap_rows(0, 4).is_err());
993 }
994
995 #[test]
997 fn negative_indexing_row_column() {
998 let mut matrix = MatZq::identity(3, 3, 17);
999 let mut matrix2 = MatZq::identity(3, 3, 17);
1000
1001 matrix.swap_columns(-1, -2).unwrap();
1002 matrix2.swap_rows(-1, -2).unwrap();
1003
1004 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 0, 1],[0, 1, 0]] mod 17").unwrap();
1005 assert_eq!(matrix_cmp, matrix);
1006 assert_eq!(matrix_cmp, matrix2);
1007 }
1008}
1009
1010#[cfg(test)]
1011mod test_reverses {
1012 use super::MatZq;
1013 use crate::traits::MatrixGetSubmatrix;
1014 use std::str::FromStr;
1015
1016 #[test]
1018 fn columns_small_entries() {
1019 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1020 let cmp_vec_0 = MatZq::from_str("[[1],[4]] mod 7").unwrap();
1021 let cmp_vec_1 = MatZq::from_str("[[2],[5]] mod 7").unwrap();
1022 let cmp_vec_2 = MatZq::from_str("[[3],[6]] mod 7").unwrap();
1023
1024 matrix.reverse_columns();
1025
1026 assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
1027 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
1028 assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
1029 }
1030
1031 #[test]
1033 fn columns_large_entries() {
1034 let mut matrix = MatZq::from_str(&format!(
1035 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
1036 i64::MIN,
1037 i64::MAX,
1038 i64::MAX,
1039 u64::MAX
1040 ))
1041 .unwrap();
1042 let cmp_vec_0 = MatZq::from_str(&format!(
1043 "[[{}],[{}],[7]] mod {}",
1044 i64::MIN,
1045 i64::MAX,
1046 u64::MAX
1047 ))
1048 .unwrap();
1049 let cmp_vec_1 = MatZq::from_str(&format!("[[1],[4],[6]] mod {}", u64::MAX)).unwrap();
1050 let cmp_vec_2 =
1051 MatZq::from_str(&format!("[[3],[{}],[8]] mod {}", i64::MAX, u64::MAX)).unwrap();
1052 let cmp_vec_3 = MatZq::from_str(&format!("[[4],[5],[9]] mod {}", u64::MAX)).unwrap();
1053
1054 matrix.reverse_columns();
1055
1056 assert_eq!(cmp_vec_3, matrix.get_column(0).unwrap());
1057 assert_eq!(cmp_vec_2, matrix.get_column(1).unwrap());
1058 assert_eq!(cmp_vec_1, matrix.get_column(2).unwrap());
1059 assert_eq!(cmp_vec_0, matrix.get_column(3).unwrap());
1060 }
1061
1062 #[test]
1064 fn rows_small_entries() {
1065 let mut matrix = MatZq::from_str("[[1, 2],[3, 4]] mod 6").unwrap();
1066 let cmp_vec_0 = MatZq::from_str("[[1, 2]] mod 6").unwrap();
1067 let cmp_vec_1 = MatZq::from_str("[[3, 4]] mod 6").unwrap();
1068
1069 matrix.reverse_rows();
1070
1071 assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
1072 assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
1073 }
1074
1075 #[test]
1077 fn rows_large_entries() {
1078 let mut matrix = MatZq::from_str(&format!(
1079 "[[{}, 1, 3, 4],[7, 6, 8, 9],[{}, 4, {}, 5]] mod {}",
1080 i64::MIN,
1081 i64::MAX,
1082 i64::MAX,
1083 u64::MAX
1084 ))
1085 .unwrap();
1086 let cmp_vec_0 =
1087 MatZq::from_str(&format!("[[{}, 1, 3, 4]] mod {}", i64::MIN, u64::MAX)).unwrap();
1088 let cmp_vec_1 = MatZq::from_str(&format!("[[7, 6, 8, 9]] mod {}", u64::MAX)).unwrap();
1089 let cmp_vec_2 = MatZq::from_str(&format!(
1090 "[[{}, 4, {}, 5]] mod {}",
1091 i64::MAX,
1092 i64::MAX,
1093 u64::MAX
1094 ))
1095 .unwrap();
1096
1097 matrix.reverse_rows();
1098
1099 assert_eq!(cmp_vec_2, matrix.get_row(0).unwrap());
1100 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
1101 assert_eq!(cmp_vec_0, matrix.get_row(2).unwrap());
1102 }
1103}
1104
1105#[cfg(test)]
1106mod test_change_modulus {
1107 use super::MatZq;
1108 use crate::integer_mod_q::Modulus;
1109 use std::str::FromStr;
1110
1111 #[test]
1113 fn modulus_correct() {
1114 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1115 let modulus = Modulus::from(8);
1116
1117 matrix.change_modulus(&modulus);
1118
1119 assert_eq!("[[1, 2, 3],[4, 5, 6]] mod 8", matrix.to_string());
1120 }
1121
1122 #[test]
1124 fn big_modulus_correct() {
1125 let mut matrix =
1126 MatZq::from_str(&format!("[[1, 2, 3],[4, 5, 6]] mod {}", i64::MAX)).unwrap();
1127 let modulus = Modulus::from(u64::MAX);
1128
1129 matrix.change_modulus(&modulus);
1130
1131 assert_eq!(
1132 format!("[[1, 2, 3],[4, 5, 6]] mod {}", u64::MAX),
1133 matrix.to_string()
1134 );
1135 }
1136
1137 #[test]
1139 fn reduced_correct() {
1140 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1141 let modulus = Modulus::from(2);
1142
1143 matrix.change_modulus(&modulus);
1144
1145 assert_eq!("[[1, 0, 1],[0, 1, 0]] mod 2", matrix.to_string());
1146 }
1147}
1148
1149#[cfg(test)]
1150mod test_set_submatrix {
1151 use crate::{
1152 integer::MatZ,
1153 integer_mod_q::{MatZq, Modulus},
1154 traits::MatrixSetSubmatrix,
1155 };
1156 use std::str::FromStr;
1157
1158 #[test]
1160 fn entire_matrix() {
1161 let modulus = Modulus::from(u64::MAX);
1162 let mut mat = MatZq::from((&MatZ::sample_uniform(10, 10, -100, 100).unwrap(), &modulus));
1163 let identity = MatZq::identity(10, 10, &modulus);
1164
1165 mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
1166
1167 assert_eq!(identity, mat);
1168 }
1169
1170 #[test]
1172 fn out_of_bounds() {
1173 let modulus = Modulus::from(u64::MAX);
1174 let mut mat = MatZq::identity(10, 10, &modulus);
1175
1176 assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1177 assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
1178 assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
1179 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
1180 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
1181 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
1182 assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1183 assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
1184 assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
1185 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
1186 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
1187 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
1188 }
1189
1190 #[test]
1193 fn submatrix_too_large() {
1194 let modulus = Modulus::from(u64::MAX);
1195 let mut mat = MatZq::identity(10, 10, &modulus);
1196
1197 assert!(
1198 mat.set_submatrix(0, 0, &MatZq::identity(11, 11, &modulus), 0, 0, 10, 10)
1199 .is_err()
1200 );
1201 assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
1202 }
1203
1204 #[test]
1206 fn large_values() {
1207 let modulus = Modulus::from(u64::MAX);
1208 let mut mat = MatZq::from((
1209 &MatZ::from_str(&format!("[[1, {}],[-{}, 0]]", u64::MAX, u64::MAX)).unwrap(),
1210 &modulus,
1211 ));
1212 let cmp_mat = MatZq::from((
1213 &MatZ::from_str(&format!("[[-{}, 0],[-{}, 0]]", u64::MAX, u64::MAX)).unwrap(),
1214 &modulus,
1215 ));
1216
1217 mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
1218 assert_eq!(cmp_mat, mat);
1219 }
1220
1221 #[test]
1223 #[should_panic]
1224 fn submatrix_negative() {
1225 let modulus = Modulus::from(u64::MAX);
1226 let mut mat = MatZq::identity(10, 10, &modulus);
1227
1228 let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
1229 }
1230
1231 #[test]
1233 fn different_moduli() {
1234 let modulus1 = Modulus::from(u64::MAX);
1235 let mut mat1 = MatZq::identity(10, 10, &modulus1);
1236
1237 let modulus2 = Modulus::from(u64::MAX - 1);
1238 let mat2 = MatZq::identity(10, 10, &modulus2);
1239
1240 assert!(mat1.set_submatrix(0, 0, &mat2.clone(), 0, 9, 0, 9).is_err());
1241 }
1242}