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