1use super::MatPolynomialRingZq;
12use crate::integer_mod_q::{Modulus, ModulusPolynomialRingZq, PolynomialRingZq};
13use crate::macros::for_others::implement_for_owned;
14use crate::traits::{MatrixSetSubmatrix, MatrixSwaps};
15use crate::{error::MathError, integer::PolyOverZ, traits::MatrixSetEntry};
16use flint3_sys::{
17 fmpz_poly_mat_entry, fmpz_poly_mat_set, fmpz_poly_mat_window_clear, fmpz_poly_mat_window_init,
18 fmpz_poly_set,
19};
20use std::fmt::Display;
21use std::mem::MaybeUninit;
22
23impl MatrixSetEntry<&PolyOverZ> for MatPolynomialRingZq {
24 fn set_entry(
61 &mut self,
62 row: impl TryInto<i64> + Display,
63 column: impl TryInto<i64> + Display,
64 value: &PolyOverZ,
65 ) -> Result<(), MathError> {
66 let value = PolynomialRingZq::from((value, self.get_mod()));
67
68 self.set_entry(row, column, value)
69 }
70
71 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: &PolyOverZ) {
106 unsafe {
107 let entry = fmpz_poly_mat_entry(&self.matrix.matrix, row, column);
108 fmpz_poly_set(entry, &value.poly)
109 };
110 }
111}
112
113impl MatrixSetEntry<&PolynomialRingZq> for MatPolynomialRingZq {
114 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: &PolynomialRingZq) {
148 unsafe {
149 let entry = fmpz_poly_mat_entry(&self.matrix.matrix, row, column);
150 fmpz_poly_set(entry, &value.poly.poly)
151 };
152 }
153}
154
155implement_for_owned!(PolyOverZ, MatPolynomialRingZq, MatrixSetEntry);
156implement_for_owned!(PolynomialRingZq, MatPolynomialRingZq, MatrixSetEntry);
157
158impl MatrixSetSubmatrix for MatPolynomialRingZq {
159 unsafe fn set_submatrix_unchecked(
200 &mut self,
201 row_self_start: i64,
202 col_self_start: i64,
203 row_self_end: i64,
204 col_self_end: i64,
205 other: &Self,
206 row_other_start: i64,
207 col_other_start: i64,
208 row_other_end: i64,
209 col_other_end: i64,
210 ) {
211 {
212 let mut window_self = MaybeUninit::uninit();
213 unsafe {
215 fmpz_poly_mat_window_init(
216 window_self.as_mut_ptr(),
217 &self.matrix.matrix,
218 row_self_start,
219 col_self_start,
220 row_self_end,
221 col_self_end,
222 )
223 };
224 let mut window_other = MaybeUninit::uninit();
225 unsafe {
227 fmpz_poly_mat_window_init(
228 window_other.as_mut_ptr(),
229 &other.matrix.matrix,
230 row_other_start,
231 col_other_start,
232 row_other_end,
233 col_other_end,
234 )
235 };
236 unsafe {
237 fmpz_poly_mat_set(window_self.as_mut_ptr(), window_other.as_mut_ptr());
239
240 fmpz_poly_mat_window_clear(window_self.as_mut_ptr());
243 fmpz_poly_mat_window_clear(window_other.as_mut_ptr());
244 }
245 }
246 }
247}
248
249impl MatrixSwaps for MatPolynomialRingZq {
250 fn swap_entries(
278 &mut self,
279 row_0: impl TryInto<i64> + Display,
280 col_0: impl TryInto<i64> + Display,
281 row_1: impl TryInto<i64> + Display,
282 col_1: impl TryInto<i64> + Display,
283 ) -> Result<(), MathError> {
284 self.matrix.swap_entries(row_0, col_0, row_1, col_1)
285 }
286
287 fn swap_columns(
313 &mut self,
314 col_0: impl TryInto<i64> + Display,
315 col_1: impl TryInto<i64> + Display,
316 ) -> Result<(), MathError> {
317 self.matrix.swap_columns(col_0, col_1)
318 }
319
320 fn swap_rows(
346 &mut self,
347 row_0: impl TryInto<i64> + Display,
348 row_1: impl TryInto<i64> + Display,
349 ) -> Result<(), MathError> {
350 self.matrix.swap_rows(row_0, row_1)
351 }
352}
353
354impl MatPolynomialRingZq {
355 pub fn reverse_columns(&mut self) {
367 self.matrix.reverse_columns()
368 }
369
370 pub fn reverse_rows(&mut self) {
382 self.matrix.reverse_rows()
383 }
384
385 pub fn change_modulus(&mut self, modulus: impl Into<ModulusPolynomialRingZq>) {
409 self.modulus = modulus.into();
410 self.reduce();
411 }
412
413 pub fn change_q(&mut self, q: impl Into<Modulus>) {
435 self.modulus.change_q(q);
436 self.reduce();
437 }
438}
439
440#[cfg(test)]
441mod test_setter {
442 use crate::{
443 integer::{MatPolyOverZ, PolyOverZ},
444 integer_mod_q::{
445 MatPolynomialRingZq, ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq,
446 },
447 traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
448 };
449 use std::str::FromStr;
450
451 const LARGE_PRIME: u64 = u64::MAX - 58;
452
453 #[test]
455 fn standard_value() {
456 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
457 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
458 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
459 let value = PolyOverZ::default();
460
461 poly_ring_mat.set_entry(1, 1, value).unwrap();
462
463 let entry_z: PolyOverZ = poly_ring_mat.get_entry(1, 1).unwrap();
464 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(1, 1).unwrap();
465
466 assert_eq!("0", entry_z.to_string());
467 assert_eq!("0", entry_zq.poly.to_string());
468 assert_eq!("4 1 0 0 1 mod 17", entry_zq.modulus.to_string());
469 }
470
471 #[test]
474 fn set_entry_reduced() {
475 let id_mat = MatPolyOverZ::identity(2, 2);
476 let modulus = PolyOverZq::from_str("5 1 0 0 0 1 mod 17").unwrap();
477 let poly_mod = ModulusPolynomialRingZq::from(modulus);
478
479 let mut poly_mat = MatPolynomialRingZq::from((id_mat, &poly_mod));
480
481 poly_mat
482 .set_entry(0, 0, PolyOverZ::from_str("5 -1 0 0 0 16").unwrap())
483 .unwrap();
484
485 let entry: PolyOverZ = poly_mat.get_entry(0, 0).unwrap();
486 assert!(entry.is_zero());
487 }
488
489 #[test]
491 fn large_positive() {
492 let modulus =
493 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
494 let poly_mat =
495 MatPolyOverZ::from_str(&format!("[[2 1 1, 1 42],[0, 2 {} 2]]", i64::MAX)).unwrap();
496 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
497 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MAX)).unwrap();
498
499 poly_ring_mat.set_entry(0, 0, value).unwrap();
500
501 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 0).unwrap();
502 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 0).unwrap();
503
504 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_z.to_string());
505 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_zq.poly.to_string());
506 assert_eq!(
507 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
508 entry_zq.modulus.to_string()
509 );
510 }
511
512 #[test]
514 fn large_positive_ref() {
515 let modulus =
516 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
517 let poly_mat = MatPolyOverZ::from_str(&format!(
518 "[[2 1 1, 1 42, 0],[0, 2 {} 2, 1 1]]",
519 i64::MAX
520 ))
521 .unwrap();
522 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
523 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MAX)).unwrap();
524
525 poly_ring_mat.set_entry(0, 0, &value).unwrap();
526
527 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 0).unwrap();
528 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 0).unwrap();
529
530 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_z.to_string());
531 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_zq.poly.to_string());
532 assert_eq!(
533 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
534 entry_zq.modulus.to_string()
535 );
536 }
537
538 #[test]
540 fn large_negative() {
541 let modulus =
542 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
543 let poly_mat = MatPolyOverZ::from_str(&format!(
544 "[[2 1 1, 1 42],[0, 2 {} 2],[1 2, 0]]",
545 i64::MAX
546 ))
547 .unwrap();
548 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
549 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MIN)).unwrap();
550
551 poly_ring_mat.set_entry(0, 1, value).unwrap();
552
553 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 1).unwrap();
554 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 1).unwrap();
555
556 assert_eq!(
557 format!("3 1 {} 1", LARGE_PRIME - i64::MIN as u64),
558 entry_z.to_string()
559 );
560 assert_eq!(
561 format!("3 1 {} 1", LARGE_PRIME - i64::MIN as u64),
562 entry_zq.poly.to_string()
563 );
564 assert_eq!(
565 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
566 entry_zq.modulus.to_string()
567 );
568 }
569
570 #[test]
572 fn error_wrong_row() {
573 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
574 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
575 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
576 let value = PolyOverZ::default();
577
578 assert!(poly_ring_mat.set_entry(2, 0, &value).is_err());
579 assert!(poly_ring_mat.set_entry(-3, 0, value).is_err());
580 }
581
582 #[test]
584 fn error_wrong_column() {
585 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
586 let poly_mat =
587 MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42, 0],[0, 2 1 2, 1 17]]").unwrap();
588 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
589 let value = PolyOverZ::default();
590
591 assert!(poly_ring_mat.set_entry(0, 3, &value).is_err());
592 assert!(poly_ring_mat.set_entry(0, -4, value).is_err());
593 }
594
595 #[test]
597 fn modulus_error() {
598 let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
599 let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap();
600 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
601 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus_1));
602 let value = PolynomialRingZq::from((&PolyOverZ::default(), &modulus_2));
603
604 assert!(poly_ring_mat.set_entry(1, 1, value).is_err());
605 }
606
607 #[test]
609 fn column_small_entries() {
610 let mut mat_1 =
611 MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 1 5, 1 6]] / 2 1 1 mod 6").unwrap();
612 let mat_2 = MatPolynomialRingZq::from_str("[[0],[1 -1]] / 2 1 1 mod 6").unwrap();
613 let cmp =
614 MatPolynomialRingZq::from_str("[[0, 0, 0],[0, 1 -1, 1 6]] / 2 1 1 mod 6").unwrap();
615
616 mat_1.set_column(1, &mat_2, 0).unwrap();
617
618 assert_eq!(cmp, mat_1);
619 }
620
621 #[test]
623 fn column_large_entries() {
624 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
625 "[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
626 i64::MIN,
627 i64::MAX,
628 u64::MAX-1,
629 u64::MAX
630 ))
631 .unwrap();
632 let mat_2 = MatPolynomialRingZq::from_str(&format!(
633 "[[1 1, 1 {}],[1 {}, 0],[1 7, 1 -1]] / 2 1 1 mod {}",
634 i64::MIN,
635 i64::MAX,
636 u64::MAX
637 ))
638 .unwrap();
639 let cmp = MatPolynomialRingZq::from_str(&format!(
640 "[[1 {}, 1 1, 1 3, 1 4],[0, 1 4, 1 {}, 1 5],[1 -1, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
641 i64::MIN,
642 u64::MAX-1,
643 u64::MAX
644 ))
645 .unwrap();
646
647 mat_1.set_column(0, &mat_2, 1).unwrap();
648
649 assert_eq!(cmp, mat_1);
650 }
651
652 #[test]
654 fn column_swap_same_entry() {
655 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
656 "[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
657 i64::MIN,
658 i64::MAX,
659 u64::MAX-1,
660 u64::MAX
661 ))
662 .unwrap();
663 let cmp = mat_1.clone();
664
665 mat_1.set_column(0, &cmp, 0).unwrap();
666 mat_1.set_column(1, &cmp, 1).unwrap();
667
668 assert_eq!(cmp, mat_1);
669 }
670
671 #[test]
673 fn column_out_of_bounds() {
674 let mut mat_1 =
675 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
676 .unwrap();
677 let mat_2 = mat_1.clone();
678
679 assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
680 assert!(mat_1.set_column(2, &mat_2, 0).is_err());
681 assert!(mat_1.set_column(1, &mat_2, -3).is_err());
682 assert!(mat_1.set_column(1, &mat_2, 2).is_err());
683 }
684
685 #[test]
687 fn column_mismatching_columns() {
688 let mut mat_1 =
689 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
690 .unwrap();
691 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
692
693 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
694 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
695 }
696
697 #[test]
699 fn column_mismatching_moduli() {
700 let mut mat_1 =
701 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
702 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 7").unwrap();
703
704 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
705 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
706 }
707
708 #[test]
710 fn row_small_entries() {
711 let mut mat_1 =
712 MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 2 5 6, 0]] / 2 1 1 mod 6").unwrap();
713 let mat_2 = MatPolynomialRingZq::from_str("[[0, 1 -1, 1 2]] / 2 1 1 mod 6").unwrap();
714 let cmp = MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 1 -1, 1 2]] / 2 1 1 mod 6")
715 .unwrap();
716
717 let _ = mat_1.set_row(1, &mat_2, 0);
718
719 assert_eq!(cmp, mat_1);
720 }
721
722 #[test]
724 fn row_large_entries() {
725 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
726 "[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
727 i64::MIN,
728 i64::MAX,
729 u64::MAX-1,
730 u64::MAX
731 ))
732 .unwrap();
733 let mat_2 = MatPolynomialRingZq::from_str(&format!(
734 "[[0, 0, 0, 0],[1 {}, 0, 1 {}, 0]] / 2 1 1 mod {}",
735 i64::MIN,
736 i64::MAX,
737 u64::MAX
738 ))
739 .unwrap();
740 let cmp = MatPolynomialRingZq::from_str(&format!(
741 "[[1 {}, 0, 1 {}, 0],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
742 i64::MIN,
743 i64::MAX,
744 i64::MAX,
745 u64::MAX-1,
746 u64::MAX
747 ))
748 .unwrap();
749
750 let _ = mat_1.set_row(0, &mat_2, 1);
751
752 assert_eq!(cmp, mat_1);
753 }
754
755 #[test]
757 fn row_swap_same_entry() {
758 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
759 "[[1 {}, 1 1, 1 3, 1 4],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
760 i64::MIN,
761 i64::MAX,
762 u64::MAX-1,
763 u64::MAX
764 ))
765 .unwrap();
766 let cmp = mat_1.clone();
767
768 let _ = mat_1.set_row(0, &cmp, 0);
769 let _ = mat_1.set_row(1, &cmp, 1);
770
771 assert_eq!(cmp, mat_1);
772 }
773
774 #[test]
776 fn row_out_of_bounds() {
777 let mut mat_1 =
778 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
779 .unwrap();
780 let mat_2 = mat_1.clone();
781
782 assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
783 assert!(mat_1.set_row(5, &mat_2, 0).is_err());
784 assert!(mat_1.set_row(2, &mat_2, -6).is_err());
785 assert!(mat_1.set_row(2, &mat_2, 5).is_err());
786 }
787
788 #[test]
790 fn row_mismatching_columns() {
791 let mut mat_1 =
792 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
793 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0, 0],[0, 0, 0],[0, 0, 0]] / 2 1 1 mod 6")
794 .unwrap();
795
796 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
797 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
798 }
799
800 #[test]
802 fn row_mismatching_moduli() {
803 let mut mat_1 =
804 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
805 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 7").unwrap();
806
807 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
808 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
809 }
810}
811
812#[cfg(test)]
813mod test_swaps {
814 use super::MatPolynomialRingZq;
815 use crate::{
816 integer_mod_q::ModulusPolynomialRingZq,
817 traits::{MatrixGetSubmatrix, MatrixSwaps},
818 };
819 use std::str::FromStr;
820
821 #[test]
826 fn entries_swapping() {
827 let mut matrix = MatPolynomialRingZq::from_str(
828 "[[1 1, 1 2, 1 3],[1 4, 2 5 6, 0]] / 3 1 2 1 mod 17",
829 )
830 .unwrap();
831 let cmp = MatPolynomialRingZq::from_str(
832 "[[1 1, 2 5 6, 1 3],[1 4, 1 2, 0]] / 3 1 2 1 mod 17",
833 )
834 .unwrap();
835
836 let _ = matrix.swap_entries(1, 1, 0, 1);
837
838 assert_eq!(cmp, matrix);
839 }
840
841 #[test]
843 fn entries_out_of_bounds() {
844 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
845 let mut matrix = MatPolynomialRingZq::new(5, 2, modulus);
846
847 assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
848 assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
849 assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
850 assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
851 }
852
853 #[test]
855 fn entries_negative_indexing() {
856 let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
857 let mut matrix = MatPolynomialRingZq::identity(2, 2, modulus);
858
859 matrix.swap_entries(-2, -2, -2, -1).unwrap();
860 assert_eq!(
861 "[[0, 1 1],[0, 1 1]] / 3 1 0 1 mod 17",
862 matrix.to_string()
863 );
864 }
865
866 #[test]
868 fn columns_swapping() {
869 let mut matrix = MatPolynomialRingZq::from_str(
870 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 3 1 2 1 mod 17",
871 )
872 .unwrap();
873 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[1 4]] / 3 1 2 1 mod 17").unwrap();
874 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 3],[1 6]] / 3 1 2 1 mod 17").unwrap();
875 let cmp_vec_2 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap();
876
877 let _ = matrix.swap_columns(1, 2);
878
879 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
880 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
881 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
882 }
883
884 #[test]
886 fn column_out_of_bounds() {
887 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
888 let mut matrix = MatPolynomialRingZq::new(5, 2, modulus);
889
890 assert!(matrix.swap_columns(-6, 0).is_err());
891 assert!(matrix.swap_columns(0, -6).is_err());
892 assert!(matrix.swap_columns(5, 0).is_err());
893 assert!(matrix.swap_columns(0, 5).is_err());
894 }
895
896 #[test]
898 fn rows_swapping() {
899 let mut matrix =
900 MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 2 4 5]] / 3 1 2 1 mod 17")
901 .unwrap();
902 let cmp_vec_0 =
903 MatPolynomialRingZq::from_str("[[1 3, 2 4 5]] / 3 1 2 1 mod 17").unwrap();
904 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap();
905
906 let _ = matrix.swap_rows(1, 0);
907
908 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
909 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
910 }
911
912 #[test]
914 fn row_out_of_bounds() {
915 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
916 let mut matrix = MatPolynomialRingZq::new(2, 4, modulus);
917
918 assert!(matrix.swap_rows(-3, 0).is_err());
919 assert!(matrix.swap_rows(0, -3).is_err());
920 assert!(matrix.swap_rows(4, 0).is_err());
921 assert!(matrix.swap_rows(0, 4).is_err());
922 }
923}
924
925#[cfg(test)]
926mod test_reverses {
927 use super::MatPolynomialRingZq;
928 use crate::traits::MatrixGetSubmatrix;
929 use std::str::FromStr;
930
931 #[test]
936 fn columns_reversing() {
937 let mut matrix = MatPolynomialRingZq::from_str(
938 "[[1 1, 1 2, 2 3 4],[0, 1 5, 1 6]] / 3 1 2 1 mod 17",
939 )
940 .unwrap();
941 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[0]] / 3 1 2 1 mod 17").unwrap();
942 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap();
943 let cmp_vec_2 =
944 MatPolynomialRingZq::from_str("[[2 3 4],[1 6]] / 3 1 2 1 mod 17").unwrap();
945
946 matrix.reverse_columns();
947
948 assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
949 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
950 assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
951 }
952
953 #[test]
955 fn rows_reversing() {
956 let mut matrix =
957 MatPolynomialRingZq::from_str("[[1 1, 1 2],[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap();
958 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap();
959 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap();
960
961 matrix.reverse_rows();
962
963 assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
964 assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
965 }
966}
967
968#[cfg(test)]
969mod test_set_submatrix {
970 use crate::{
971 integer::MatPolyOverZ,
972 integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
973 traits::MatrixSetSubmatrix,
974 };
975 use std::str::FromStr;
976
977 #[test]
979 fn entire_matrix() {
980 let modulus =
981 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
982 let mut mat = MatPolynomialRingZq::from((
983 &MatPolyOverZ::sample_uniform(10, 10, 5, -100, 100).unwrap(),
984 &modulus,
985 ));
986 let identity = MatPolynomialRingZq::identity(10, 10, &modulus);
987
988 mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
989
990 assert_eq!(identity, mat);
991 }
992
993 #[test]
995 fn out_of_bounds() {
996 let modulus =
997 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
998 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
999
1000 assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1001 assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
1002 assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
1003 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
1004 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
1005 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
1006 assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
1007 assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
1008 assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
1009 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
1010 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
1011 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
1012 }
1013
1014 #[test]
1017 fn submatrix_too_large() {
1018 let modulus =
1019 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1020 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
1021
1022 assert!(
1023 mat.set_submatrix(
1024 0,
1025 0,
1026 &MatPolynomialRingZq::identity(11, 11, &modulus),
1027 0,
1028 0,
1029 10,
1030 10
1031 )
1032 .is_err()
1033 );
1034 assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
1035 }
1036
1037 #[test]
1039 fn large_values() {
1040 let modulus =
1041 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1042 let mut mat = MatPolynomialRingZq::from((
1043 &MatPolyOverZ::from_str(&format!(
1044 "[[1 1, 2 1 {}],[1 -{}, 0]]",
1045 u64::MAX,
1046 u64::MAX
1047 ))
1048 .unwrap(),
1049 &modulus,
1050 ));
1051 let cmp_mat = MatPolynomialRingZq::from((
1052 &MatPolyOverZ::from_str(&format!("[[1 -{}, 0],[1 -{}, 0]]", u64::MAX, u64::MAX))
1053 .unwrap(),
1054 &modulus,
1055 ));
1056
1057 mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
1058 assert_eq!(cmp_mat, mat);
1059 }
1060
1061 #[test]
1063 #[should_panic]
1064 fn submatrix_negative() {
1065 let modulus =
1066 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1067 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
1068
1069 let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
1070 }
1071
1072 #[test]
1074 fn different_moduli() {
1075 let modulus1 =
1076 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1077 let mut mat1 = MatPolynomialRingZq::identity(10, 10, &modulus1);
1078
1079 let modulus2 =
1080 ModulusPolynomialRingZq::from_str(&format!("4 2 0 0 1 mod {}", u64::MAX - 1)).unwrap();
1081 let mat2 = MatPolynomialRingZq::identity(10, 10, &modulus2);
1082
1083 assert!(mat1.set_submatrix(0, 0, &mat2.clone(), 0, 9, 0, 9).is_err());
1084 }
1085}
1086
1087#[cfg(test)]
1088mod test_change_modulus {
1089 use super::MatPolynomialRingZq;
1090 use crate::integer_mod_q::ModulusPolynomialRingZq;
1091 use std::str::FromStr;
1092
1093 #[test]
1095 fn modulus_correct() {
1096 let mut matrix = MatPolynomialRingZq::from_str(
1097 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod 7",
1098 )
1099 .unwrap();
1100 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 8").unwrap();
1101
1102 matrix.change_modulus(&modulus);
1103
1104 assert_eq!(
1105 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod 8",
1106 matrix.to_string()
1107 );
1108 }
1109
1110 #[test]
1112 fn big_modulus_correct() {
1113 let mut matrix = MatPolynomialRingZq::from_str(&format!(
1114 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod {}",
1115 i64::MAX
1116 ))
1117 .unwrap();
1118 let modulus =
1119 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1120
1121 matrix.change_modulus(&modulus);
1122
1123 assert_eq!(
1124 format!(
1125 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod {}",
1126 u64::MAX
1127 ),
1128 matrix.to_string()
1129 );
1130 }
1131
1132 #[test]
1134 fn reduced_correct() {
1135 let mut matrix = MatPolynomialRingZq::from_str(
1136 "[[1 1, 1 2, 1 3],[1 4, 1 5, 4 1 0 0 1]] / 8 1 0 0 0 0 0 0 1 mod 7",
1137 )
1138 .unwrap();
1139 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 2").unwrap();
1140
1141 matrix.change_modulus(&modulus);
1142
1143 assert_eq!(
1144 "[[1 1, 0, 1 1],[0, 1 1, 0]] / 4 1 0 0 1 mod 2",
1145 matrix.to_string()
1146 );
1147 }
1148}
1149
1150#[cfg(test)]
1151mod test_change_q {
1152 use super::MatPolynomialRingZq;
1153 use std::str::FromStr;
1154
1155 #[test]
1157 fn q_correct() {
1158 let mut matrix = MatPolynomialRingZq::from_str(
1159 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod 7",
1160 )
1161 .unwrap();
1162
1163 matrix.change_q(8);
1164
1165 assert_eq!(
1166 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod 8",
1167 matrix.to_string()
1168 );
1169 }
1170
1171 #[test]
1173 fn big_q_correct() {
1174 let mut matrix = MatPolynomialRingZq::from_str(&format!(
1175 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod {}",
1176 i64::MAX
1177 ))
1178 .unwrap();
1179
1180 matrix.change_q(u64::MAX);
1181
1182 assert_eq!(
1183 format!(
1184 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 4 1 0 0 1 mod {}",
1185 u64::MAX
1186 ),
1187 matrix.to_string()
1188 );
1189 }
1190
1191 #[test]
1193 fn reduced_correct() {
1194 let mut matrix = MatPolynomialRingZq::from_str(
1195 "[[1 1, 1 2, 1 3],[1 4, 1 5, 4 1 0 0 1]] / 4 1 0 0 1 mod 7",
1196 )
1197 .unwrap();
1198
1199 matrix.change_q(2);
1200
1201 assert_eq!(
1202 "[[1 1, 0, 1 1],[0, 1 1, 0]] / 4 1 0 0 1 mod 2",
1203 matrix.to_string()
1204 );
1205 }
1206}