1use super::MatPolynomialRingZq;
12use crate::integer_mod_q::PolynomialRingZq;
13use crate::macros::for_others::implement_for_owned;
14use crate::traits::{MatrixSetSubmatrix, MatrixSwaps};
15use crate::{error::MathError, integer::PolyOverZ, traits::MatrixSetEntry};
16use flint_sys::fmpz_poly_mat::{
17 fmpz_poly_mat_set, fmpz_poly_mat_window_clear, fmpz_poly_mat_window_init,
18};
19use flint_sys::{fmpz_poly::fmpz_poly_set, fmpz_poly_mat::fmpz_poly_mat_entry};
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
386#[cfg(test)]
387mod test_setter {
388 use crate::{
389 integer::{MatPolyOverZ, PolyOverZ},
390 integer_mod_q::{
391 MatPolynomialRingZq, ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq,
392 },
393 traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
394 };
395 use std::str::FromStr;
396
397 const LARGE_PRIME: u64 = u64::MAX - 58;
398
399 #[test]
401 fn standard_value() {
402 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
403 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
404 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
405 let value = PolyOverZ::default();
406
407 poly_ring_mat.set_entry(1, 1, value).unwrap();
408
409 let entry_z: PolyOverZ = poly_ring_mat.get_entry(1, 1).unwrap();
410 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(1, 1).unwrap();
411
412 assert_eq!("0", entry_z.to_string());
413 assert_eq!("0", entry_zq.poly.to_string());
414 assert_eq!("4 1 0 0 1 mod 17", entry_zq.modulus.to_string());
415 }
416
417 #[test]
420 fn set_entry_reduced() {
421 let id_mat = MatPolyOverZ::identity(2, 2);
422 let modulus = PolyOverZq::from_str("5 1 0 0 0 1 mod 17").unwrap();
423 let poly_mod = ModulusPolynomialRingZq::from(modulus);
424
425 let mut poly_mat = MatPolynomialRingZq::from((id_mat, &poly_mod));
426
427 poly_mat
428 .set_entry(0, 0, PolyOverZ::from_str("5 -1 0 0 0 16").unwrap())
429 .unwrap();
430
431 let entry: PolyOverZ = poly_mat.get_entry(0, 0).unwrap();
432 assert!(entry.is_zero());
433 }
434
435 #[test]
437 fn large_positive() {
438 let modulus =
439 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
440 let poly_mat =
441 MatPolyOverZ::from_str(&format!("[[2 1 1, 1 42],[0, 2 {} 2]]", i64::MAX)).unwrap();
442 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
443 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MAX)).unwrap();
444
445 poly_ring_mat.set_entry(0, 0, value).unwrap();
446
447 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 0).unwrap();
448 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 0).unwrap();
449
450 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_z.to_string());
451 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_zq.poly.to_string());
452 assert_eq!(
453 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
454 entry_zq.modulus.to_string()
455 );
456 }
457
458 #[test]
460 fn large_positive_ref() {
461 let modulus =
462 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
463 let poly_mat = MatPolyOverZ::from_str(&format!(
464 "[[2 1 1, 1 42, 0],[0, 2 {} 2, 1 1]]",
465 i64::MAX
466 ))
467 .unwrap();
468 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
469 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MAX)).unwrap();
470
471 poly_ring_mat.set_entry(0, 0, &value).unwrap();
472
473 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 0).unwrap();
474 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 0).unwrap();
475
476 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_z.to_string());
477 assert_eq!(format!("3 1 {} 1", i64::MAX), entry_zq.poly.to_string());
478 assert_eq!(
479 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
480 entry_zq.modulus.to_string()
481 );
482 }
483
484 #[test]
486 fn large_negative() {
487 let modulus =
488 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {LARGE_PRIME}")).unwrap();
489 let poly_mat = MatPolyOverZ::from_str(&format!(
490 "[[2 1 1, 1 42],[0, 2 {} 2],[1 2, 0]]",
491 i64::MAX
492 ))
493 .unwrap();
494 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
495 let value = PolyOverZ::from_str(&format!("3 1 {} 1", i64::MIN)).unwrap();
496
497 poly_ring_mat.set_entry(0, 1, value).unwrap();
498
499 let entry_z: PolyOverZ = poly_ring_mat.get_entry(0, 1).unwrap();
500 let entry_zq: PolynomialRingZq = poly_ring_mat.get_entry(0, 1).unwrap();
501
502 assert_eq!(
503 format!("3 1 {} 1", LARGE_PRIME - i64::MIN as u64),
504 entry_z.to_string()
505 );
506 assert_eq!(
507 format!("3 1 {} 1", LARGE_PRIME - i64::MIN as u64),
508 entry_zq.poly.to_string()
509 );
510 assert_eq!(
511 format!("4 1 0 0 1 mod {LARGE_PRIME}"),
512 entry_zq.modulus.to_string()
513 );
514 }
515
516 #[test]
518 fn error_wrong_row() {
519 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
520 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
521 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
522 let value = PolyOverZ::default();
523
524 assert!(poly_ring_mat.set_entry(2, 0, &value).is_err());
525 assert!(poly_ring_mat.set_entry(-3, 0, value).is_err());
526 }
527
528 #[test]
530 fn error_wrong_column() {
531 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
532 let poly_mat =
533 MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42, 0],[0, 2 1 2, 1 17]]").unwrap();
534 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus));
535 let value = PolyOverZ::default();
536
537 assert!(poly_ring_mat.set_entry(0, 3, &value).is_err());
538 assert!(poly_ring_mat.set_entry(0, -4, value).is_err());
539 }
540
541 #[test]
543 fn modulus_error() {
544 let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
545 let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap();
546 let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap();
547 let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus_1));
548 let value = PolynomialRingZq::from((&PolyOverZ::default(), &modulus_2));
549
550 assert!(poly_ring_mat.set_entry(1, 1, value).is_err());
551 }
552
553 #[test]
555 fn column_small_entries() {
556 let mut mat_1 =
557 MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 1 5, 1 6]] / 2 1 1 mod 6").unwrap();
558 let mat_2 = MatPolynomialRingZq::from_str("[[0],[1 -1]] / 2 1 1 mod 6").unwrap();
559 let cmp =
560 MatPolynomialRingZq::from_str("[[0, 0, 0],[0, 1 -1, 1 6]] / 2 1 1 mod 6").unwrap();
561
562 mat_1.set_column(1, &mat_2, 0).unwrap();
563
564 assert_eq!(cmp, mat_1);
565 }
566
567 #[test]
569 fn column_large_entries() {
570 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
571 "[[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 {}",
572 i64::MIN,
573 i64::MAX,
574 u64::MAX-1,
575 u64::MAX
576 ))
577 .unwrap();
578 let mat_2 = MatPolynomialRingZq::from_str(&format!(
579 "[[1 1, 1 {}],[1 {}, 0],[1 7, 1 -1]] / 2 1 1 mod {}",
580 i64::MIN,
581 i64::MAX,
582 u64::MAX
583 ))
584 .unwrap();
585 let cmp = MatPolynomialRingZq::from_str(&format!(
586 "[[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 {}",
587 i64::MIN,
588 u64::MAX-1,
589 u64::MAX
590 ))
591 .unwrap();
592
593 mat_1.set_column(0, &mat_2, 1).unwrap();
594
595 assert_eq!(cmp, mat_1);
596 }
597
598 #[test]
600 fn column_swap_same_entry() {
601 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
602 "[[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 {}",
603 i64::MIN,
604 i64::MAX,
605 u64::MAX-1,
606 u64::MAX
607 ))
608 .unwrap();
609 let cmp = mat_1.clone();
610
611 mat_1.set_column(0, &cmp, 0).unwrap();
612 mat_1.set_column(1, &cmp, 1).unwrap();
613
614 assert_eq!(cmp, mat_1);
615 }
616
617 #[test]
619 fn column_out_of_bounds() {
620 let mut mat_1 =
621 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
622 .unwrap();
623 let mat_2 = mat_1.clone();
624
625 assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
626 assert!(mat_1.set_column(2, &mat_2, 0).is_err());
627 assert!(mat_1.set_column(1, &mat_2, -3).is_err());
628 assert!(mat_1.set_column(1, &mat_2, 2).is_err());
629 }
630
631 #[test]
633 fn column_mismatching_columns() {
634 let mut mat_1 =
635 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
636 .unwrap();
637 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
638
639 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
640 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
641 }
642
643 #[test]
645 fn column_mismatching_moduli() {
646 let mut mat_1 =
647 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
648 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 7").unwrap();
649
650 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
651 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
652 }
653
654 #[test]
656 fn row_small_entries() {
657 let mut mat_1 =
658 MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 2 5 6, 0]] / 2 1 1 mod 6").unwrap();
659 let mat_2 = MatPolynomialRingZq::from_str("[[0, 1 -1, 1 2]] / 2 1 1 mod 6").unwrap();
660 let cmp = MatPolynomialRingZq::from_str("[[0, 1 2, 0],[0, 1 -1, 1 2]] / 2 1 1 mod 6")
661 .unwrap();
662
663 let _ = mat_1.set_row(1, &mat_2, 0);
664
665 assert_eq!(cmp, mat_1);
666 }
667
668 #[test]
670 fn row_large_entries() {
671 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
672 "[[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 {}",
673 i64::MIN,
674 i64::MAX,
675 u64::MAX-1,
676 u64::MAX
677 ))
678 .unwrap();
679 let mat_2 = MatPolynomialRingZq::from_str(&format!(
680 "[[0, 0, 0, 0],[1 {}, 0, 1 {}, 0]] / 2 1 1 mod {}",
681 i64::MIN,
682 i64::MAX,
683 u64::MAX
684 ))
685 .unwrap();
686 let cmp = MatPolynomialRingZq::from_str(&format!(
687 "[[1 {}, 0, 1 {}, 0],[1 {}, 1 4, 1 {}, 1 5],[1 7, 1 6, 2 8 9, 0]] / 2 1 1 mod {}",
688 i64::MIN,
689 i64::MAX,
690 i64::MAX,
691 u64::MAX-1,
692 u64::MAX
693 ))
694 .unwrap();
695
696 let _ = mat_1.set_row(0, &mat_2, 1);
697
698 assert_eq!(cmp, mat_1);
699 }
700
701 #[test]
703 fn row_swap_same_entry() {
704 let mut mat_1 = MatPolynomialRingZq::from_str(&format!(
705 "[[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 {}",
706 i64::MIN,
707 i64::MAX,
708 u64::MAX-1,
709 u64::MAX
710 ))
711 .unwrap();
712 let cmp = mat_1.clone();
713
714 let _ = mat_1.set_row(0, &cmp, 0);
715 let _ = mat_1.set_row(1, &cmp, 1);
716
717 assert_eq!(cmp, mat_1);
718 }
719
720 #[test]
722 fn row_out_of_bounds() {
723 let mut mat_1 =
724 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6")
725 .unwrap();
726 let mat_2 = mat_1.clone();
727
728 assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
729 assert!(mat_1.set_row(5, &mat_2, 0).is_err());
730 assert!(mat_1.set_row(2, &mat_2, -6).is_err());
731 assert!(mat_1.set_row(2, &mat_2, 5).is_err());
732 }
733
734 #[test]
736 fn row_mismatching_columns() {
737 let mut mat_1 =
738 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
739 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0, 0],[0, 0, 0],[0, 0, 0]] / 2 1 1 mod 6")
740 .unwrap();
741
742 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
743 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
744 }
745
746 #[test]
748 fn row_mismatching_moduli() {
749 let mut mat_1 =
750 MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 6").unwrap();
751 let mat_2 = MatPolynomialRingZq::from_str("[[0, 0],[0, 0],[0, 0]] / 2 1 1 mod 7").unwrap();
752
753 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
754 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
755 }
756}
757
758#[cfg(test)]
759mod test_swaps {
760 use super::MatPolynomialRingZq;
761 use crate::{
762 integer_mod_q::ModulusPolynomialRingZq,
763 traits::{MatrixGetSubmatrix, MatrixSwaps},
764 };
765 use std::str::FromStr;
766
767 #[test]
772 fn entries_swapping() {
773 let mut matrix = MatPolynomialRingZq::from_str(
774 "[[1 1, 1 2, 1 3],[1 4, 2 5 6, 0]] / 3 1 2 1 mod 17",
775 )
776 .unwrap();
777 let cmp = MatPolynomialRingZq::from_str(
778 "[[1 1, 2 5 6, 1 3],[1 4, 1 2, 0]] / 3 1 2 1 mod 17",
779 )
780 .unwrap();
781
782 let _ = matrix.swap_entries(1, 1, 0, 1);
783
784 assert_eq!(cmp, matrix);
785 }
786
787 #[test]
789 fn entries_out_of_bounds() {
790 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
791 let mut matrix = MatPolynomialRingZq::new(5, 2, modulus);
792
793 assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
794 assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
795 assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
796 assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
797 }
798
799 #[test]
801 fn entries_negative_indexing() {
802 let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
803 let mut matrix = MatPolynomialRingZq::identity(2, 2, modulus);
804
805 matrix.swap_entries(-2, -2, -2, -1).unwrap();
806 assert_eq!(
807 "[[0, 1 1],[0, 1 1]] / 3 1 0 1 mod 17",
808 matrix.to_string()
809 );
810 }
811
812 #[test]
814 fn columns_swapping() {
815 let mut matrix = MatPolynomialRingZq::from_str(
816 "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 3 1 2 1 mod 17",
817 )
818 .unwrap();
819 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[1 4]] / 3 1 2 1 mod 17").unwrap();
820 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 3],[1 6]] / 3 1 2 1 mod 17").unwrap();
821 let cmp_vec_2 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap();
822
823 let _ = matrix.swap_columns(1, 2);
824
825 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
826 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
827 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
828 }
829
830 #[test]
832 fn column_out_of_bounds() {
833 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
834 let mut matrix = MatPolynomialRingZq::new(5, 2, modulus);
835
836 assert!(matrix.swap_columns(-6, 0).is_err());
837 assert!(matrix.swap_columns(0, -6).is_err());
838 assert!(matrix.swap_columns(5, 0).is_err());
839 assert!(matrix.swap_columns(0, 5).is_err());
840 }
841
842 #[test]
844 fn rows_swapping() {
845 let mut matrix =
846 MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 2 4 5]] / 3 1 2 1 mod 17")
847 .unwrap();
848 let cmp_vec_0 =
849 MatPolynomialRingZq::from_str("[[1 3, 2 4 5]] / 3 1 2 1 mod 17").unwrap();
850 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap();
851
852 let _ = matrix.swap_rows(1, 0);
853
854 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
855 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
856 }
857
858 #[test]
860 fn row_out_of_bounds() {
861 let modulus = ModulusPolynomialRingZq::from_str("3 3 0 1 mod 17").unwrap();
862 let mut matrix = MatPolynomialRingZq::new(2, 4, modulus);
863
864 assert!(matrix.swap_rows(-3, 0).is_err());
865 assert!(matrix.swap_rows(0, -3).is_err());
866 assert!(matrix.swap_rows(4, 0).is_err());
867 assert!(matrix.swap_rows(0, 4).is_err());
868 }
869}
870
871#[cfg(test)]
872mod test_reverses {
873 use super::MatPolynomialRingZq;
874 use crate::traits::MatrixGetSubmatrix;
875 use std::str::FromStr;
876
877 #[test]
882 fn columns_reversing() {
883 let mut matrix = MatPolynomialRingZq::from_str(
884 "[[1 1, 1 2, 2 3 4],[0, 1 5, 1 6]] / 3 1 2 1 mod 17",
885 )
886 .unwrap();
887 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[0]] / 3 1 2 1 mod 17").unwrap();
888 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap();
889 let cmp_vec_2 =
890 MatPolynomialRingZq::from_str("[[2 3 4],[1 6]] / 3 1 2 1 mod 17").unwrap();
891
892 matrix.reverse_columns();
893
894 assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
895 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
896 assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
897 }
898
899 #[test]
901 fn rows_reversing() {
902 let mut matrix =
903 MatPolynomialRingZq::from_str("[[1 1, 1 2],[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap();
904 let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap();
905 let cmp_vec_1 = MatPolynomialRingZq::from_str("[[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap();
906
907 matrix.reverse_rows();
908
909 assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
910 assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
911 }
912}
913
914#[cfg(test)]
915mod test_set_submatrix {
916 use crate::{
917 integer::MatPolyOverZ,
918 integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
919 traits::MatrixSetSubmatrix,
920 };
921 use std::str::FromStr;
922
923 #[test]
925 fn entire_matrix() {
926 let modulus =
927 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
928 let mut mat = MatPolynomialRingZq::from((
929 &MatPolyOverZ::sample_uniform(10, 10, 5, -100, 100).unwrap(),
930 &modulus,
931 ));
932 let identity = MatPolynomialRingZq::identity(10, 10, &modulus);
933
934 mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
935
936 assert_eq!(identity, mat);
937 }
938
939 #[test]
941 fn out_of_bounds() {
942 let modulus =
943 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
944 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
945
946 assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
947 assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
948 assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
949 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
950 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
951 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
952 assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
953 assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
954 assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
955 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
956 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
957 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
958 }
959
960 #[test]
963 fn submatrix_too_large() {
964 let modulus =
965 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
966 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
967
968 assert!(
969 mat.set_submatrix(
970 0,
971 0,
972 &MatPolynomialRingZq::identity(11, 11, &modulus),
973 0,
974 0,
975 10,
976 10
977 )
978 .is_err()
979 );
980 assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
981 }
982
983 #[test]
985 fn large_values() {
986 let modulus =
987 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
988 let mut mat = MatPolynomialRingZq::from((
989 &MatPolyOverZ::from_str(&format!(
990 "[[1 1, 2 1 {}],[1 -{}, 0]]",
991 u64::MAX,
992 u64::MAX
993 ))
994 .unwrap(),
995 &modulus,
996 ));
997 let cmp_mat = MatPolynomialRingZq::from((
998 &MatPolyOverZ::from_str(&format!("[[1 -{}, 0],[1 -{}, 0]]", u64::MAX, u64::MAX))
999 .unwrap(),
1000 &modulus,
1001 ));
1002
1003 mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
1004 assert_eq!(cmp_mat, mat);
1005 }
1006
1007 #[test]
1009 #[should_panic]
1010 fn submatrix_negative() {
1011 let modulus =
1012 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1013 let mut mat = MatPolynomialRingZq::identity(10, 10, &modulus);
1014
1015 let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
1016 }
1017
1018 #[test]
1020 fn different_moduli() {
1021 let modulus1 =
1022 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
1023 let mut mat1 = MatPolynomialRingZq::identity(10, 10, &modulus1);
1024
1025 let modulus2 =
1026 ModulusPolynomialRingZq::from_str(&format!("4 2 0 0 1 mod {}", u64::MAX - 1)).unwrap();
1027 let mat2 = MatPolynomialRingZq::identity(10, 10, &modulus2);
1028
1029 assert!(mat1.set_submatrix(0, 0, &mat2.clone(), 0, 9, 0, 9).is_err());
1030 }
1031}