1use crate::{
12 error::MathError,
13 integer::Z,
14 integer_mod_q::{MatZq, Modulus, Zq},
15 macros::for_others::implement_for_owned,
16 traits::{MatrixDimensions, MatrixSetEntry, MatrixSetSubmatrix, MatrixSwaps},
17 utils::index::{evaluate_index_for_vector, evaluate_indices_for_matrix},
18};
19use flint3_sys::{
20 fmpz_swap,
21 {
22 _fmpz_mod_mat_reduce, fmpz_mod_mat_set, fmpz_mod_mat_set_entry, fmpz_mod_mat_window_clear,
23 fmpz_mod_mat_window_init,
24 },
25 {
26 fmpz_mat_entry, fmpz_mat_invert_cols, fmpz_mat_invert_rows, fmpz_mat_swap_cols,
27 fmpz_mat_swap_rows,
28 },
29};
30use std::{fmt::Display, mem::MaybeUninit, ptr::null_mut};
31
32impl<Integer: Into<Z>> MatrixSetEntry<Integer> for MatZq {
33 fn set_entry(
64 &mut self,
65 row: impl TryInto<i64> + Display,
66 column: impl TryInto<i64> + Display,
67 value: Integer,
68 ) -> Result<(), MathError> {
69 let value: Zq = Zq::from((value, &self.modulus));
71
72 self.set_entry(row, column, value)
73 }
74
75 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: Integer) {
104 let value: Z = value.into();
105
106 unsafe {
107 fmpz_mod_mat_set_entry(
109 &mut self.matrix,
110 row,
111 column,
112 &value.value,
113 self.modulus.get_fmpz_mod_ctx_struct(),
114 )
115 };
116 }
117}
118
119impl MatrixSetEntry<&Zq> for MatZq {
120 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: &Zq) {
150 unsafe {
151 fmpz_mod_mat_set_entry(
153 &mut self.matrix,
154 row,
155 column,
156 &value.value.value,
157 self.modulus.get_fmpz_mod_ctx_struct(),
158 )
159 };
160 }
161}
162
163implement_for_owned!(Zq, MatZq, MatrixSetEntry);
164
165impl MatrixSetSubmatrix for MatZq {
166 unsafe fn set_submatrix_unchecked(
207 &mut self,
208 row_self_start: i64,
209 col_self_start: i64,
210 row_self_end: i64,
211 col_self_end: i64,
212 other: &Self,
213 row_other_start: i64,
214 col_other_start: i64,
215 row_other_end: i64,
216 col_other_end: i64,
217 ) {
218 {
219 let mut window_self = MaybeUninit::uninit();
220 unsafe {
222 fmpz_mod_mat_window_init(
223 window_self.as_mut_ptr(),
224 &self.matrix,
225 row_self_start,
226 col_self_start,
227 row_self_end,
228 col_self_end,
229 self.modulus.get_fmpz_mod_ctx_struct(),
230 )
231 };
232 let mut window_other = MaybeUninit::uninit();
233 unsafe {
235 fmpz_mod_mat_window_init(
236 window_other.as_mut_ptr(),
237 &other.matrix,
238 row_other_start,
239 col_other_start,
240 row_other_end,
241 col_other_end,
242 self.modulus.get_fmpz_mod_ctx_struct(),
243 )
244 };
245 unsafe {
246 fmpz_mod_mat_set(
247 window_self.as_mut_ptr(),
248 window_other.as_ptr(),
249 self.modulus.get_fmpz_mod_ctx_struct(),
250 );
251
252 fmpz_mod_mat_window_clear(
255 window_self.as_mut_ptr(),
256 self.modulus.get_fmpz_mod_ctx_struct(),
257 );
258 fmpz_mod_mat_window_clear(
259 window_other.as_mut_ptr(),
260 self.modulus.get_fmpz_mod_ctx_struct(),
261 );
262 }
263 }
264 }
265}
266
267impl MatrixSwaps for MatZq {
268 fn swap_entries(
294 &mut self,
295 row_0: impl TryInto<i64> + Display,
296 col_0: impl TryInto<i64> + Display,
297 row_1: impl TryInto<i64> + Display,
298 col_1: impl TryInto<i64> + Display,
299 ) -> Result<(), MathError> {
300 let (row_0, col_0) = evaluate_indices_for_matrix(self, row_0, col_0)?;
301 let (row_1, col_1) = evaluate_indices_for_matrix(self, row_1, col_1)?;
302
303 unsafe {
304 fmpz_swap(
305 fmpz_mat_entry(&self.matrix, row_0, col_0),
306 fmpz_mat_entry(&self.matrix, row_1, col_1),
307 )
308 };
309 Ok(())
310 }
311
312 fn swap_columns(
336 &mut self,
337 col_0: impl TryInto<i64> + Display,
338 col_1: impl TryInto<i64> + Display,
339 ) -> Result<(), MathError> {
340 let num_cols = self.get_num_columns();
341 let col_0 = evaluate_index_for_vector(col_0, num_cols)?;
342 let col_1 = evaluate_index_for_vector(col_1, num_cols)?;
343
344 if col_0 >= num_cols || col_1 >= num_cols {
345 return Err(MathError::OutOfBounds(
346 format!("smaller than {num_cols}"),
347 if col_0 > col_1 {
348 col_0.to_string()
349 } else {
350 col_1.to_string()
351 },
352 ));
353 }
354 unsafe { fmpz_mat_swap_cols(&mut self.matrix, null_mut(), col_0, col_1) }
355 Ok(())
356 }
357
358 fn swap_rows(
382 &mut self,
383 row_0: impl TryInto<i64> + Display,
384 row_1: impl TryInto<i64> + Display,
385 ) -> Result<(), MathError> {
386 let num_rows = self.get_num_rows();
387 let row_0 = evaluate_index_for_vector(row_0, num_rows)?;
388 let row_1 = evaluate_index_for_vector(row_1, num_rows)?;
389
390 if row_0 >= num_rows || row_1 >= num_rows {
391 return Err(MathError::OutOfBounds(
392 format!("smaller than {num_rows}"),
393 if row_0 > row_1 {
394 row_0.to_string()
395 } else {
396 row_1.to_string()
397 },
398 ));
399 }
400 unsafe { fmpz_mat_swap_rows(&mut self.matrix, null_mut(), row_0, row_1) }
401 Ok(())
402 }
403}
404
405impl MatZq {
406 pub fn reverse_columns(&mut self) {
417 unsafe { fmpz_mat_invert_cols(&mut self.matrix, null_mut()) }
421 }
422
423 pub fn reverse_rows(&mut self) {
434 unsafe { fmpz_mat_invert_rows(&mut self.matrix, null_mut()) }
438 }
439
440 pub fn change_modulus(&mut self, modulus: impl Into<Modulus>) {
459 self.modulus = modulus.into();
460 unsafe { _fmpz_mod_mat_reduce(&mut self.matrix, self.modulus.get_fmpz_mod_ctx()) }
461 }
462}
463
464#[cfg(test)]
465mod test_setter {
466 use crate::{
467 integer::Z,
468 integer_mod_q::{MatZq, Zq},
469 traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
470 };
471 use std::str::FromStr;
472
473 #[test]
475 fn max_int_positive() {
476 let mut matrix = MatZq::new(5, 10, u64::MAX);
477 let value = Z::from(i64::MAX);
478 matrix.set_entry(0, 0, value).unwrap();
479
480 let entry: Z = matrix.get_entry(0, 0).unwrap();
481
482 assert_eq!(Z::from(i64::MAX), entry);
483 }
484
485 #[test]
487 fn large_positive() {
488 let mut matrix = MatZq::new(5, 10, u64::MAX);
489 let value = Z::from(u64::MAX - 1);
490 matrix.set_entry(0, 0, value).unwrap();
491
492 let entry: Z = matrix.get_entry(0, 0).unwrap();
493
494 assert_eq!(u64::MAX - 1, entry);
495 }
496
497 #[test]
499 fn max_int_negative() {
500 let mut matrix = MatZq::new(5, 10, u64::MAX);
501 let value = Z::from(-i64::MAX);
502 matrix.set_entry(0, 0, value).unwrap();
503
504 let entry: Z = matrix.get_entry(0, 0).unwrap();
505
506 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64, entry);
507 }
508
509 #[test]
511 fn large_negative() {
512 let mut matrix = MatZq::new(5, 10, u64::MAX);
513 let value = Z::from(-i64::MAX - 1);
514 matrix.set_entry(0, 0, value).unwrap();
515
516 let entry: Z = matrix.get_entry(0, 0).unwrap();
517
518 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64 - 1, entry);
519 }
520
521 #[test]
523 fn error_wrong_row() {
524 let mut matrix = MatZq::new(5, 10, 7);
525
526 assert!(matrix.set_entry(5, 1, 3).is_err());
527 assert!(matrix.set_entry(-6, 1, 1).is_err());
528 }
529
530 #[test]
532 fn error_wrong_column() {
533 let mut matrix = MatZq::new(5, 10, 7);
534
535 assert!(matrix.set_entry(1, 100, 3).is_err());
536 assert!(matrix.set_entry(1, -11, 1).is_err());
537 }
538
539 #[test]
541 fn diff_types() {
542 let mut matrix = MatZq::new(5, 10, 56);
543
544 matrix.set_entry(0, 0, Z::default()).unwrap();
545 matrix.set_entry(0, 0, Zq::from((12, 56))).unwrap();
546 matrix.set_entry(0, 0, 3).unwrap();
547 matrix.set_entry(0, 0, &Z::default()).unwrap();
548 matrix.set_entry(0, 0, &Zq::from((12, 56))).unwrap();
549 }
550
551 #[test]
553 fn negative_indexing() {
554 let mut matrix = MatZq::new(3, 3, 10);
555
556 matrix.set_entry(-1, -1, 9).unwrap();
557 matrix.set_entry(-1, -2, 8).unwrap();
558 matrix.set_entry(-3, -3, Zq::from((1, 10))).unwrap();
559
560 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 0, 0],[0, 8, 9]] mod 10").unwrap();
561 assert_eq!(matrix_cmp, matrix);
562 }
563
564 #[test]
566 fn set_entry_reduce() {
567 let mut matrix = MatZq::new(5, 10, 3);
568 matrix.set_entry(1, 1, Z::from(u64::MAX)).unwrap();
569
570 let entry: Z = matrix.get_entry(1, 1).unwrap();
571
572 assert_eq!(entry, Z::from(0));
573 }
574
575 #[test]
577 fn modulus_error() {
578 let mut matrix = MatZq::new(5, 10, 3);
579 assert!(matrix.set_entry(1, 1, Zq::from((2, 5))).is_err());
580 }
581
582 #[test]
584 fn column_small_entries() {
585 let mut mat_1 = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 11").unwrap();
586 let mat_2 = MatZq::from_str("[[0],[-1]] mod 11").unwrap();
587
588 let cmp = MatZq::from_str("[[1, 0, 3],[4, -1, 6]] mod 11").unwrap();
589
590 mat_1.set_column(1, &mat_2, 0).unwrap();
591
592 assert_eq!(cmp, mat_1);
593 }
594
595 #[test]
597 fn column_large_entries() {
598 let mut mat_1 = MatZq::from_str(&format!(
599 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
600 i64::MIN,
601 i64::MAX,
602 i64::MAX,
603 u64::MAX
604 ))
605 .unwrap();
606 let mat_2 = MatZq::from_str(&format!(
607 "[[1, {}],[{}, 0],[7, -1]] mod {}",
608 i64::MIN,
609 i64::MAX,
610 u64::MAX
611 ))
612 .unwrap();
613 let cmp = MatZq::from_str(&format!(
614 "[[{}, 1, 3, 4],[0, 4, {}, 5],[-1, 6, 8, 9]] mod {}",
615 i64::MIN,
616 i64::MAX,
617 u64::MAX
618 ))
619 .unwrap();
620
621 mat_1.set_column(0, &mat_2, 1).unwrap();
622
623 assert_eq!(cmp, mat_1);
624 }
625
626 #[test]
628 fn column_swap_same_entry() {
629 let mut mat_1 = MatZq::from_str(&format!(
630 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
631 i64::MIN,
632 i64::MAX,
633 i64::MAX,
634 u64::MAX
635 ))
636 .unwrap();
637 let cmp = mat_1.clone();
638
639 mat_1.set_column(0, &cmp, 0).unwrap();
640 mat_1.set_column(1, &cmp, 1).unwrap();
641
642 assert_eq!(cmp, mat_1);
643 }
644
645 #[test]
647 fn column_out_of_bounds() {
648 let mut mat_1 = MatZq::new(5, 2, 17);
649 let mat_2 = mat_1.clone();
650
651 assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
652 assert!(mat_1.set_column(2, &mat_2, 0).is_err());
653 assert!(mat_1.set_column(1, &mat_2, -3).is_err());
654 assert!(mat_1.set_column(1, &mat_2, 2).is_err());
655 }
656
657 #[test]
659 fn column_mismatching_columns() {
660 let mut mat_1 = MatZq::new(5, 2, 17);
661 let mat_2 = MatZq::new(2, 2, 17);
662
663 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
664 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
665 }
666
667 #[test]
669 fn column_mismatching_moduli() {
670 let mut mat_1 = MatZq::new(3, 3, 19);
671 let mat_2 = MatZq::new(3, 3, 17);
672
673 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
674 }
675
676 #[test]
678 fn row_small_entries() {
679 let mut mat_1 = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 11").unwrap();
680 let mat_2 = MatZq::from_str("[[0, -1, 2]] mod 11").unwrap();
681 let cmp = MatZq::from_str("[[1, 2, 3],[0, -1, 2]] mod 11").unwrap();
682
683 let _ = mat_1.set_row(1, &mat_2, 0);
684
685 assert_eq!(cmp, mat_1);
686 }
687
688 #[test]
690 fn row_large_entries() {
691 let mut mat_1 = MatZq::from_str(&format!(
692 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
693 i64::MIN,
694 i64::MAX,
695 i64::MAX,
696 u64::MAX
697 ))
698 .unwrap();
699 let mat_2 = MatZq::from_str(&format!(
700 "[[0, 0, 0, 0],[{}, 0, {}, 0]] mod {}",
701 i64::MIN,
702 i64::MAX,
703 u64::MAX
704 ))
705 .unwrap();
706 let cmp = MatZq::from_str(&format!(
707 "[[{}, 0, {}, 0],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
708 i64::MIN,
709 i64::MAX,
710 i64::MAX,
711 i64::MAX,
712 u64::MAX
713 ))
714 .unwrap();
715
716 let _ = mat_1.set_row(0, &mat_2, 1);
717
718 assert_eq!(cmp, mat_1);
719 }
720
721 #[test]
723 fn row_swap_same_entry() {
724 let mut mat_1 = MatZq::from_str(&format!(
725 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
726 i64::MIN,
727 i64::MAX,
728 i64::MAX,
729 u64::MAX
730 ))
731 .unwrap();
732 let cmp = mat_1.clone();
733
734 let _ = mat_1.set_row(0, &cmp, 0);
735 let _ = mat_1.set_row(1, &cmp, 1);
736
737 assert_eq!(cmp, mat_1);
738 }
739
740 #[test]
742 fn row_out_of_bounds() {
743 let mut mat_1 = MatZq::new(5, 2, 17);
744 let mat_2 = mat_1.clone();
745
746 assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
747 assert!(mat_1.set_row(5, &mat_2, 0).is_err());
748 assert!(mat_1.set_row(2, &mat_2, -6).is_err());
749 assert!(mat_1.set_row(2, &mat_2, 5).is_err());
750 }
751
752 #[test]
754 fn row_mismatching_columns() {
755 let mut mat_1 = MatZq::new(3, 2, 17);
756 let mat_2 = MatZq::new(3, 3, 17);
757
758 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
759 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
760 }
761
762 #[test]
764 fn row_mismatching_moduli() {
765 let mut mat_1 = MatZq::new(3, 3, 19);
766 let mat_2 = MatZq::new(3, 3, 17);
767
768 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
769 }
770
771 #[test]
773 fn negative_indexing_row_column() {
774 let mut matrix = MatZq::identity(3, 3, 17);
775 let matrix2 = MatZq::identity(3, 3, 17);
776
777 matrix.set_column(-1, &matrix2, -2).unwrap();
778 matrix.set_row(-1, &matrix2, -2).unwrap();
779
780 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 1, 1],[0, 1, 0]] mod 17").unwrap();
781 assert_eq!(matrix_cmp, matrix);
782 }
783}
784
785#[cfg(test)]
786mod test_swaps {
787 use super::MatZq;
788 use crate::traits::{MatrixGetSubmatrix, MatrixSwaps};
789 use std::str::FromStr;
790
791 #[test]
793 fn entries_small_entries() {
794 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
795 let cmp = MatZq::from_str("[[1, 5, 3],[4, 2, 6]] mod 7").unwrap();
796
797 let _ = matrix.swap_entries(1, 1, 0, 1);
798
799 assert_eq!(cmp, matrix);
800 }
801
802 #[test]
804 fn entries_large_entries() {
805 let mut matrix = MatZq::from_str(&format!(
806 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
807 i64::MIN,
808 i64::MAX,
809 i64::MAX,
810 u64::MAX
811 ))
812 .unwrap();
813 let cmp = MatZq::from_str(&format!(
814 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
815 i64::MAX,
816 i64::MAX,
817 i64::MIN,
818 u64::MAX
819 ))
820 .unwrap();
821
822 let _ = matrix.swap_entries(0, 0, 1, 2);
823
824 assert_eq!(cmp, matrix);
825 }
826
827 #[test]
829 fn entries_swap_same_entry() {
830 let mut matrix = MatZq::from_str(&format!(
831 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
832 i64::MIN,
833 i64::MAX,
834 i64::MAX,
835 u64::MAX
836 ))
837 .unwrap();
838 let cmp = matrix.clone();
839
840 let _ = matrix.swap_entries(0, 0, 0, 0);
841 let _ = matrix.swap_entries(1, 1, 1, 1);
842
843 assert_eq!(cmp, matrix);
844 }
845
846 #[test]
848 fn entries_out_of_bounds() {
849 let mut matrix = MatZq::new(5, 2, 5);
850
851 assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
852 assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
853 assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
854 assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
855 }
856
857 #[test]
859 fn entries_negative_indexing() {
860 let mut matrix = MatZq::identity(2, 2, 2);
861
862 matrix.swap_entries(-2, -2, -2, -1).unwrap();
863 assert_eq!("[[0, 1],[0, 1]] mod 2", matrix.to_string());
864 }
865
866 #[test]
868 fn columns_small_entries() {
869 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 17").unwrap();
870 let cmp_vec_0 = MatZq::from_str("[[1],[4]] mod 17").unwrap();
871 let cmp_vec_1 = MatZq::from_str("[[3],[6]] mod 17").unwrap();
872 let cmp_vec_2 = MatZq::from_str("[[2],[5]] mod 17").unwrap();
873
874 let _ = matrix.swap_columns(1, 2);
875
876 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
877 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
878 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
879 }
880
881 #[test]
883 fn columns_large_entries() {
884 let mut matrix = MatZq::from_str(&format!(
885 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
886 i64::MIN,
887 i64::MAX,
888 i64::MAX,
889 u64::MAX
890 ))
891 .unwrap();
892 let cmp_vec_0 =
893 MatZq::from_str(&format!("[[3],[{}],[8]] mod {}", i64::MAX, u64::MAX)).unwrap();
894 let cmp_vec_1 = MatZq::from_str(&format!("[[1],[4],[6]] mod {}", u64::MAX)).unwrap();
895 let cmp_vec_2 = MatZq::from_str(&format!(
896 "[[{}],[{}],[7]] mod {}",
897 i64::MIN,
898 i64::MAX,
899 u64::MAX
900 ))
901 .unwrap();
902 let cmp_vec_3 = MatZq::from_str(&format!("[[4],[5],[9]] mod {}", u64::MAX)).unwrap();
903
904 let _ = matrix.swap_columns(0, 2);
905
906 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
907 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
908 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
909 assert_eq!(cmp_vec_3, matrix.get_column(3).unwrap());
910 }
911
912 #[test]
914 fn columns_swap_same_col() {
915 let mut matrix = MatZq::from_str(&format!(
916 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
917 i64::MIN,
918 i64::MAX,
919 i64::MAX,
920 u64::MAX
921 ))
922 .unwrap();
923 let cmp = matrix.clone();
924
925 let _ = matrix.swap_columns(0, 0);
926
927 assert_eq!(cmp, matrix);
928 }
929
930 #[test]
932 fn column_out_of_bounds() {
933 let mut matrix = MatZq::new(5, 2, 5);
934
935 assert!(matrix.swap_columns(-6, 0).is_err());
936 assert!(matrix.swap_columns(0, -6).is_err());
937 assert!(matrix.swap_columns(5, 0).is_err());
938 assert!(matrix.swap_columns(0, 5).is_err());
939 }
940
941 #[test]
943 fn rows_small_entries() {
944 let mut matrix = MatZq::from_str("[[1, 2],[3, 4]] mod 12").unwrap();
945 let cmp_vec_0 = MatZq::from_str("[[3, 4]] mod 12").unwrap();
946 let cmp_vec_1 = MatZq::from_str("[[1, 2]] mod 12").unwrap();
947
948 let _ = matrix.swap_rows(1, 0);
949
950 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
951 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
952 }
953
954 #[test]
956 fn rows_large_entries() {
957 let mut matrix = MatZq::from_str(&format!(
958 "[[{}, 1, 3, 4],[7, 6, 8, 9],[{}, 4, {}, 5]] mod {}",
959 i64::MIN,
960 i64::MAX,
961 i64::MAX,
962 u64::MAX
963 ))
964 .unwrap();
965 let cmp_vec_0 = MatZq::from_str(&format!(
966 "[[{}, 4, {}, 5]] mod {}",
967 i64::MAX,
968 i64::MAX,
969 u64::MAX
970 ))
971 .unwrap();
972 let cmp_vec_1 = MatZq::from_str(&format!("[[7, 6, 8, 9]] mod {}", u64::MAX)).unwrap();
973 let cmp_vec_2 =
974 MatZq::from_str(&format!("[[{}, 1, 3, 4]] mod {}", i64::MIN, u64::MAX)).unwrap();
975
976 let _ = matrix.swap_rows(0, 2);
977
978 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
979 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
980 assert_eq!(cmp_vec_2, matrix.get_row(2).unwrap());
981 }
982
983 #[test]
985 fn rows_swap_same_row() {
986 let mut matrix = MatZq::from_str(&format!(
987 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
988 i64::MIN,
989 i64::MAX,
990 i64::MAX,
991 u64::MAX
992 ))
993 .unwrap();
994 let cmp = matrix.clone();
995
996 let _ = matrix.swap_rows(1, 1);
997
998 assert_eq!(cmp, matrix);
999 }
1000
1001 #[test]
1003 fn row_out_of_bounds() {
1004 let mut matrix = MatZq::new(2, 4, 5);
1005
1006 assert!(matrix.swap_rows(-3, 0).is_err());
1007 assert!(matrix.swap_rows(0, -3).is_err());
1008 assert!(matrix.swap_rows(4, 0).is_err());
1009 assert!(matrix.swap_rows(0, 4).is_err());
1010 }
1011
1012 #[test]
1014 fn negative_indexing_row_column() {
1015 let mut matrix = MatZq::identity(3, 3, 17);
1016 let mut matrix2 = MatZq::identity(3, 3, 17);
1017
1018 matrix.swap_columns(-1, -2).unwrap();
1019 matrix2.swap_rows(-1, -2).unwrap();
1020
1021 let matrix_cmp = MatZq::from_str("[[1, 0, 0],[0, 0, 1],[0, 1, 0]] mod 17").unwrap();
1022 assert_eq!(matrix_cmp, matrix);
1023 assert_eq!(matrix_cmp, matrix2);
1024 }
1025}
1026
1027#[cfg(test)]
1028mod test_reverses {
1029 use super::MatZq;
1030 use crate::traits::MatrixGetSubmatrix;
1031 use std::str::FromStr;
1032
1033 #[test]
1035 fn columns_small_entries() {
1036 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1037 let cmp_vec_0 = MatZq::from_str("[[1],[4]] mod 7").unwrap();
1038 let cmp_vec_1 = MatZq::from_str("[[2],[5]] mod 7").unwrap();
1039 let cmp_vec_2 = MatZq::from_str("[[3],[6]] mod 7").unwrap();
1040
1041 matrix.reverse_columns();
1042
1043 assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
1044 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
1045 assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
1046 }
1047
1048 #[test]
1050 fn columns_large_entries() {
1051 let mut matrix = MatZq::from_str(&format!(
1052 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]] mod {}",
1053 i64::MIN,
1054 i64::MAX,
1055 i64::MAX,
1056 u64::MAX
1057 ))
1058 .unwrap();
1059 let cmp_vec_0 = MatZq::from_str(&format!(
1060 "[[{}],[{}],[7]] mod {}",
1061 i64::MIN,
1062 i64::MAX,
1063 u64::MAX
1064 ))
1065 .unwrap();
1066 let cmp_vec_1 = MatZq::from_str(&format!("[[1],[4],[6]] mod {}", u64::MAX)).unwrap();
1067 let cmp_vec_2 =
1068 MatZq::from_str(&format!("[[3],[{}],[8]] mod {}", i64::MAX, u64::MAX)).unwrap();
1069 let cmp_vec_3 = MatZq::from_str(&format!("[[4],[5],[9]] mod {}", u64::MAX)).unwrap();
1070
1071 matrix.reverse_columns();
1072
1073 assert_eq!(cmp_vec_3, matrix.get_column(0).unwrap());
1074 assert_eq!(cmp_vec_2, matrix.get_column(1).unwrap());
1075 assert_eq!(cmp_vec_1, matrix.get_column(2).unwrap());
1076 assert_eq!(cmp_vec_0, matrix.get_column(3).unwrap());
1077 }
1078
1079 #[test]
1081 fn rows_small_entries() {
1082 let mut matrix = MatZq::from_str("[[1, 2],[3, 4]] mod 6").unwrap();
1083 let cmp_vec_0 = MatZq::from_str("[[1, 2]] mod 6").unwrap();
1084 let cmp_vec_1 = MatZq::from_str("[[3, 4]] mod 6").unwrap();
1085
1086 matrix.reverse_rows();
1087
1088 assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
1089 assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
1090 }
1091
1092 #[test]
1094 fn rows_large_entries() {
1095 let mut matrix = MatZq::from_str(&format!(
1096 "[[{}, 1, 3, 4],[7, 6, 8, 9],[{}, 4, {}, 5]] mod {}",
1097 i64::MIN,
1098 i64::MAX,
1099 i64::MAX,
1100 u64::MAX
1101 ))
1102 .unwrap();
1103 let cmp_vec_0 =
1104 MatZq::from_str(&format!("[[{}, 1, 3, 4]] mod {}", i64::MIN, u64::MAX)).unwrap();
1105 let cmp_vec_1 = MatZq::from_str(&format!("[[7, 6, 8, 9]] mod {}", u64::MAX)).unwrap();
1106 let cmp_vec_2 = MatZq::from_str(&format!(
1107 "[[{}, 4, {}, 5]] mod {}",
1108 i64::MAX,
1109 i64::MAX,
1110 u64::MAX
1111 ))
1112 .unwrap();
1113
1114 matrix.reverse_rows();
1115
1116 assert_eq!(cmp_vec_2, matrix.get_row(0).unwrap());
1117 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
1118 assert_eq!(cmp_vec_0, matrix.get_row(2).unwrap());
1119 }
1120}
1121
1122#[cfg(test)]
1123mod test_change_modulus {
1124 use super::MatZq;
1125 use crate::integer_mod_q::Modulus;
1126 use std::str::FromStr;
1127
1128 #[test]
1130 fn modulus_correct() {
1131 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1132 let modulus = Modulus::from(8);
1133
1134 matrix.change_modulus(&modulus);
1135
1136 println!("{}", matrix);
1137
1138 assert_eq!("[[1, 2, 3],[4, 5, 6]] mod 8", matrix.to_string());
1139 }
1140
1141 #[test]
1143 fn big_modulus_correct() {
1144 let mut matrix =
1145 MatZq::from_str(&format!("[[1, 2, 3],[4, 5, 6]] mod {}", i64::MAX)).unwrap();
1146 let modulus = Modulus::from(u64::MAX);
1147
1148 matrix.change_modulus(&modulus);
1149
1150 assert_eq!(
1151 format!("[[1, 2, 3],[4, 5, 6]] mod {}", u64::MAX),
1152 matrix.to_string()
1153 );
1154 }
1155
1156 #[test]
1158 fn reduced_correct() {
1159 let mut matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6]] mod 7").unwrap();
1160 let modulus = Modulus::from(2);
1161
1162 matrix.change_modulus(&modulus);
1163
1164 assert_eq!("[[1, 0, 1],[0, 1, 0]] mod 2", matrix.to_string());
1165 }
1166}
1167
1168#[cfg(test)]
1169mod test_set_submatrix {
1170 use crate::{
1171 integer::MatZ,
1172 integer_mod_q::{MatZq, Modulus},
1173 traits::MatrixSetSubmatrix,
1174 };
1175 use std::str::FromStr;
1176
1177 #[test]
1179 fn entire_matrix() {
1180 let modulus = Modulus::from(u64::MAX);
1181 let mut mat = MatZq::from((&MatZ::sample_uniform(10, 10, -100, 100).unwrap(), &modulus));
1182 let identity = MatZq::identity(10, 10, &modulus);
1183
1184 mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
1185
1186 assert_eq!(identity, mat);
1187 }
1188
1189 #[test]
1191 fn out_of_bounds() {
1192 let modulus = Modulus::from(u64::MAX);
1193 let mut mat = MatZq::identity(10, 10, &modulus);
1194
1195 assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1196 assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
1197 assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
1198 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
1199 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
1200 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
1201 assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1202 assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
1203 assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
1204 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
1205 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
1206 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
1207 }
1208
1209 #[test]
1212 fn submatrix_too_large() {
1213 let modulus = Modulus::from(u64::MAX);
1214 let mut mat = MatZq::identity(10, 10, &modulus);
1215
1216 assert!(
1217 mat.set_submatrix(0, 0, &MatZq::identity(11, 11, &modulus), 0, 0, 10, 10)
1218 .is_err()
1219 );
1220 assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
1221 }
1222
1223 #[test]
1225 fn large_values() {
1226 let modulus = Modulus::from(u64::MAX);
1227 let mut mat = MatZq::from((
1228 &MatZ::from_str(&format!("[[1, {}],[-{}, 0]]", u64::MAX, u64::MAX)).unwrap(),
1229 &modulus,
1230 ));
1231 let cmp_mat = MatZq::from((
1232 &MatZ::from_str(&format!("[[-{}, 0],[-{}, 0]]", u64::MAX, u64::MAX)).unwrap(),
1233 &modulus,
1234 ));
1235
1236 mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
1237 assert_eq!(cmp_mat, mat);
1238 }
1239
1240 #[test]
1242 #[should_panic]
1243 fn submatrix_negative() {
1244 let modulus = Modulus::from(u64::MAX);
1245 let mut mat = MatZq::identity(10, 10, &modulus);
1246
1247 let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
1248 }
1249
1250 #[test]
1252 fn different_moduli() {
1253 let modulus1 = Modulus::from(u64::MAX);
1254 let mut mat1 = MatZq::identity(10, 10, &modulus1);
1255
1256 let modulus2 = Modulus::from(u64::MAX - 1);
1257 let mat2 = MatZq::identity(10, 10, &modulus2);
1258
1259 assert!(mat1.set_submatrix(0, 0, &mat2.clone(), 0, 9, 0, 9).is_err());
1260 }
1261}