1use super::MatZq;
12use crate::{
13 integer::{MatZ, Z},
14 integer_mod_q::{Modulus, Zq, fmpz_mod_helpers::length},
15 traits::{AsInteger, MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix, MatrixSetEntry},
16};
17use flint3_sys::{
18 fmpz, fmpz_init_set, fmpz_mat_set, fmpz_mod_mat_entry, fmpz_mod_mat_init_set,
19 fmpz_mod_mat_window_clear, fmpz_mod_mat_window_init,
20};
21use std::mem::MaybeUninit;
22
23impl MatZq {
24 pub fn get_representative_least_nonnegative_residue(&self) -> MatZ {
46 let mut out = MatZ::new(self.get_num_rows(), self.get_num_columns());
47 unsafe { fmpz_mat_set(&mut out.matrix, &self.matrix) };
48 out
49 }
50
51 pub fn get_representative_least_absolute_residue(&self) -> MatZ {
79 let modulus: Z = Z::from(&self.modulus);
80 let modulus_half = modulus.div_floor(2);
81
82 let mut out = MatZ::new(self.get_num_rows(), self.get_num_columns());
83
84 for row in 0..self.get_num_rows() {
85 for column in 0..self.get_num_columns() {
86 let entry: Z = unsafe { self.get_entry_unchecked(row, column) };
87
88 if entry > modulus_half {
90 unsafe { out.set_entry_unchecked(row, column, entry - &modulus) };
91 } else {
92 unsafe { out.set_entry_unchecked(row, column, entry) };
93 }
94 }
95 }
96
97 out
98 }
99
100 pub fn get_mod(&self) -> Modulus {
110 self.modulus.clone()
111 }
112}
113
114impl MatrixGetSubmatrix for MatZq {
115 unsafe fn get_submatrix_unchecked(
149 &self,
150 row_1: i64,
151 row_2: i64,
152 col_1: i64,
153 col_2: i64,
154 ) -> Self {
155 let mut window = MaybeUninit::uninit();
156 unsafe {
158 fmpz_mod_mat_window_init(
159 window.as_mut_ptr(),
160 &self.matrix,
161 row_1,
162 col_1,
163 row_2,
164 col_2,
165 self.modulus.get_fmpz_mod_ctx_struct(),
166 )
167 };
168 let mut window_copy = MaybeUninit::uninit();
169 unsafe {
170 fmpz_mod_mat_init_set(
172 window_copy.as_mut_ptr(),
173 window.as_ptr(),
174 self.modulus.get_fmpz_mod_ctx_struct(),
175 );
176 fmpz_mod_mat_window_clear(window.as_mut_ptr(), self.modulus.get_fmpz_mod_ctx_struct());
179 }
180 MatZq {
181 matrix: unsafe { window_copy.assume_init() },
182 modulus: self.get_mod(),
183 }
184 }
185}
186
187impl MatZq {
188 pub(crate) fn collect_entries(&self) -> Vec<fmpz> {
204 let mut entries: Vec<fmpz> =
205 Vec::with_capacity((self.get_num_rows() * self.get_num_columns()) as usize);
206
207 for row in 0..self.get_num_rows() {
208 for col in 0..self.get_num_columns() {
209 let entry = unsafe { *fmpz_mod_mat_entry(&self.matrix, row, col) };
211 entries.push(entry);
212 }
213 }
214
215 entries
216 }
217
218 pub(crate) fn collect_lengths(&self) -> Vec<Z> {
231 let entries_fmpz = self.collect_entries();
232
233 let modulus_fmpz = unsafe { self.get_mod().into_fmpz() };
234 let mut entry_lengths = Vec::with_capacity(entries_fmpz.len());
235 for value in entries_fmpz {
236 entry_lengths.push(length(&value, &modulus_fmpz));
237 }
238
239 entry_lengths
240 }
241}
242
243impl MatrixDimensions for MatZq {
244 fn get_num_rows(&self) -> i64 {
255 self.matrix.r
256 }
257
258 fn get_num_columns(&self) -> i64 {
269 self.matrix.c
270 }
271}
272
273impl MatrixGetEntry<Z> for MatZq {
274 unsafe fn get_entry_unchecked(&self, row: i64, column: i64) -> Z {
307 let mut out = Z::default();
308 let entry = unsafe { fmpz_mod_mat_entry(&self.matrix, row, column) };
309 unsafe { fmpz_init_set(&mut out.value, entry) };
310
311 out
312 }
313}
314
315impl MatrixGetEntry<Zq> for MatZq {
316 unsafe fn get_entry_unchecked(&self, row: i64, column: i64) -> Zq {
344 let mut out = Zq::from((0, &self.modulus));
345 let entry = unsafe { fmpz_mod_mat_entry(&self.matrix, row, column) };
346 unsafe { fmpz_init_set(&mut out.value.value, entry) };
347
348 out
349 }
350}
351
352#[cfg(test)]
353mod test_get_entry {
354 use super::Zq;
355 use crate::{
356 integer::Z,
357 integer_mod_q::MatZq,
358 traits::{MatrixGetEntry, MatrixSetEntry},
359 };
360 use std::str::FromStr;
361
362 #[test]
364 fn get_edges() {
365 let matrix = MatZq::new(5, 10, u64::MAX);
366
367 let entry_1: Z = matrix.get_entry(0, 0).unwrap();
368 let entry_2: Z = matrix.get_entry(4, 9).unwrap();
369
370 assert_eq!(0, entry_1);
371 assert_eq!(0, entry_2);
372 }
373
374 #[test]
376 fn max_int_positive() {
377 let mut matrix = MatZq::new(5, 10, u64::MAX);
378 let value = Z::from(i64::MAX);
379 matrix.set_entry(0, 0, value).unwrap();
380
381 let entry: Z = matrix.get_entry(0, 0).unwrap();
382
383 assert_eq!(i64::MAX, entry);
384 }
385
386 #[test]
388 fn large_positive() {
389 let mut matrix = MatZq::new(5, 10, u64::MAX);
390 let value = Z::from(u64::MAX - 1);
391 matrix.set_entry(0, 0, value).unwrap();
392
393 let entry: Z = matrix.get_entry(0, 0).unwrap();
394
395 assert_eq!(u64::MAX - 1, entry);
396 }
397
398 #[test]
400 fn max_int_negative() {
401 let mut matrix = MatZq::new(5, 10, u64::MAX);
402 let value = Z::from(-i64::MAX);
403 matrix.set_entry(0, 0, value).unwrap();
404
405 let entry: Z = matrix.get_entry(0, 0).unwrap();
406
407 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64, entry);
408 }
409
410 #[test]
412 fn large_negative() {
413 let mut matrix = MatZq::new(5, 10, u64::MAX);
414 let value = Z::from(-i64::MAX - 1);
415 matrix.set_entry(0, 0, value).unwrap();
416
417 let entry: Z = matrix.get_entry(0, 0).unwrap();
418
419 assert_eq!((u64::MAX as i128 - i64::MAX as i128) as u64 - 1, entry);
420 }
421
422 #[test]
424 fn error_wrong_row() {
425 let matrix: MatZq = MatZq::new(5, 10, 7);
426
427 assert!(MatrixGetEntry::<Z>::get_entry(&matrix, 5, 1).is_err());
428 assert!(MatrixGetEntry::<Z>::get_entry(&matrix, -6, 1).is_err());
429 assert!(MatrixGetEntry::<Zq>::get_entry(&matrix, 5, 1).is_err());
430 assert!(MatrixGetEntry::<Zq>::get_entry(&matrix, -6, 1).is_err());
431 }
432
433 #[test]
435 fn error_wrong_column() {
436 let matrix = MatZq::new(5, 10, 7);
437
438 assert!(MatrixGetEntry::<Z>::get_entry(&matrix, 1, 10).is_err());
439 assert!(MatrixGetEntry::<Z>::get_entry(&matrix, 1, -11).is_err());
440 assert!(MatrixGetEntry::<Zq>::get_entry(&matrix, 1, 10).is_err());
441 assert!(MatrixGetEntry::<Zq>::get_entry(&matrix, 1, -11).is_err());
442 }
443
444 #[test]
446 fn negative_indexing() {
447 let matrix = MatZq::from_str("[[1, 2, 3],[4, 5, 6],[7, 8, 9]] mod 10").unwrap();
448
449 let entry_1: Z = matrix.get_entry(-1, -1).unwrap();
450 let entry_2: Z = matrix.get_entry(-1, -2).unwrap();
451 let entry_3: Z = matrix.get_entry(-3, -3).unwrap();
452 let entry_4: Zq = matrix.get_entry(-1, -1).unwrap();
453 let entry_5: Zq = matrix.get_entry(-1, -2).unwrap();
454 let entry_6: Zq = matrix.get_entry(-3, -3).unwrap();
455
456 assert_eq!(9, entry_1);
457 assert_eq!(8, entry_2);
458 assert_eq!(1, entry_3);
459 assert_eq!(Zq::from((9, 10)), entry_4);
460 assert_eq!(Zq::from((8, 10)), entry_5);
461 assert_eq!(Zq::from((1, 10)), entry_6);
462 }
463
464 #[test]
466 fn memory_test() {
467 let mut matrix = MatZq::new(5, 10, u64::MAX);
468 let value = Zq::from((u64::MAX - 1, u64::MAX));
469 matrix.set_entry(1, 1, value).unwrap();
470 let entry: Z = matrix.get_entry(1, 1).unwrap();
471 matrix.set_entry(1, 1, Z::ONE).unwrap();
472
473 assert_eq!(u64::MAX - 1, entry);
474 }
475
476 #[test]
478 fn get_entry_z_memory() {
479 let mut matrix = MatZq::new(5, 10, u64::MAX);
480 matrix.set_entry(1, 1, Z::from(u64::MAX - 3)).unwrap();
481 let _: Z = matrix.get_entry(1, 1).unwrap();
482 matrix.set_entry(2, 2, Z::from(u64::MAX - 10)).unwrap();
483
484 let entry: Z = matrix.get_entry(1, 1).unwrap();
485 let _z = Z::from(u64::MAX);
486
487 assert_eq!(entry, Z::from(u64::MAX - 3));
488 }
489
490 #[test]
492 fn get_entry_zq_memory() {
493 let mut matrix = MatZq::new(5, 10, u64::MAX);
494 matrix.set_entry(1, 1, Z::from(u64::MAX - 3)).unwrap();
495 let _: Zq = matrix.get_entry(1, 1).unwrap();
496 matrix.set_entry(2, 2, Z::from(u64::MAX - 10)).unwrap();
497
498 let entry: Z = matrix.get_entry(1, 1).unwrap();
499 let _z = Z::from(u64::MAX);
500
501 assert_eq!(entry, Z::from(u64::MAX - 3));
502 }
503
504 #[test]
506 fn diff_types() {
507 let matrix = MatZq::new(5, 10, u64::MAX);
508
509 let _: Z = matrix.get_entry(0, 0).unwrap();
510 let _: Zq = matrix.get_entry(0, 0).unwrap();
511 }
512}
513
514#[cfg(test)]
515mod test_get_num {
516 use crate::{integer_mod_q::MatZq, traits::MatrixDimensions};
517
518 #[test]
520 fn num_rows() {
521 let matrix = MatZq::new(5, 10, 7);
522
523 assert_eq!(matrix.get_num_rows(), 5);
524 }
525
526 #[test]
528 fn num_columns() {
529 let matrix = MatZq::new(5, 10, 7);
530
531 assert_eq!(matrix.get_num_columns(), 10);
532 }
533}
534
535#[cfg(test)]
536mod test_get_representative_least_nonnegative_residue {
537 use crate::{
538 integer::Z,
539 integer_mod_q::MatZq,
540 traits::{MatrixDimensions, MatrixGetEntry, MatrixSetEntry},
541 };
542
543 #[test]
545 fn dimensions() {
546 let matzq = MatZq::new(15, 17, 13);
547
548 let matz_1 = matzq.get_representative_least_nonnegative_residue();
549
550 assert_eq!(15, matz_1.get_num_rows());
551 assert_eq!(17, matz_1.get_num_columns());
552 }
553
554 #[test]
556 fn entries_taken_over_correctly() {
557 let mut matzq = MatZq::new(2, 2, u64::MAX);
558 matzq.set_entry(0, 0, u64::MAX - 58).unwrap();
559 matzq.set_entry(0, 1, -1).unwrap();
560
561 let matz_1 = matzq.get_representative_least_nonnegative_residue();
562
563 assert_eq!(Z::from(u64::MAX - 1), matz_1.get_entry(0, 1).unwrap());
564 assert_eq!(Z::from(u64::MAX - 58), matz_1.get_entry(0, 0).unwrap());
565 }
566}
567
568#[cfg(test)]
569mod test_mod {
570 use crate::integer_mod_q::{MatZq, Modulus};
571
572 #[test]
574 fn get_mod() {
575 let matrix = MatZq::new(5, 10, 7);
576
577 assert_eq!(matrix.get_mod(), Modulus::from(7));
578 }
579
580 #[test]
582 fn get_mod_large() {
583 let matrix = MatZq::new(5, 10, u64::MAX);
584
585 assert_eq!(matrix.get_mod(), Modulus::from(u64::MAX));
586 }
587
588 #[test]
590 fn get_mod_memory() {
591 let matrix = MatZq::new(5, 10, u64::MAX);
592 let _ = matrix.get_mod();
593 let _ = Modulus::from(u64::MAX - 1);
594
595 let modulus = matrix.get_mod();
596
597 assert_eq!(modulus, Modulus::from(u64::MAX));
598 }
599}
600
601#[cfg(test)]
602mod test_get_vec {
603 use crate::{integer_mod_q::MatZq, traits::MatrixGetSubmatrix};
604 use std::str::FromStr;
605
606 #[test]
608 fn get_row_works() {
609 let matrix = MatZq::from_str(&format!(
610 "[[0, 0, 0],[4, {}, {}]] mod {}",
611 i64::MAX,
612 i64::MIN,
613 u64::MAX
614 ))
615 .unwrap();
616 let row_1 = matrix.get_row(0).unwrap();
617 let row_2 = matrix.get_row(1).unwrap();
618
619 let cmp_1 = MatZq::from_str(&format!("[[0, 0, 0]] mod {}", u64::MAX)).unwrap();
620 let cmp_2 = MatZq::from_str(&format!(
621 "[[4, {}, {}]] mod {}",
622 i64::MAX,
623 i64::MIN,
624 u64::MAX
625 ))
626 .unwrap();
627
628 assert_eq!(cmp_1, row_1);
629 assert_eq!(cmp_2, row_2);
630 }
631
632 #[test]
634 fn get_row_negative_indexing_works() {
635 let matrix = MatZq::from_str(&format!(
636 "[[0, 0, 0],[42, {}, {}]] mod {}",
637 i64::MAX,
638 u64::MAX - 1,
639 u64::MAX
640 ))
641 .unwrap();
642 let row_1 = matrix.get_row(-2).unwrap();
643 let row_2 = matrix.get_row(-1).unwrap();
644
645 let cmp_1 = MatZq::from_str(&format!("[[0, 0, 0]] mod {}", u64::MAX)).unwrap();
646 let cmp_2 = MatZq::from_str(&format!(
647 "[[42, {}, {}]] mod {}",
648 i64::MAX,
649 u64::MAX - 1,
650 u64::MAX
651 ))
652 .unwrap();
653
654 assert_eq!(cmp_1, row_1);
655 assert_eq!(cmp_2, row_2);
656 }
657
658 #[test]
660 fn get_column_works() {
661 let matrix = MatZq::from_str(&format!(
662 "[[1, 0, 3],[{}, 0, 5],[{}, 0, 7]] mod {}",
663 i64::MAX,
664 i64::MIN,
665 u64::MAX
666 ))
667 .unwrap();
668 let column_1 = matrix.get_column(0).unwrap();
669 let column_2 = matrix.get_column(1).unwrap();
670 let column_3 = matrix.get_column(2).unwrap();
671
672 let cmp_1 = MatZq::from_str(&format!(
673 "[[1],[{}],[{}]] mod {}",
674 i64::MAX,
675 i64::MIN,
676 u64::MAX
677 ))
678 .unwrap();
679 let cmp_2 = MatZq::from_str(&format!("[[0],[0],[0]] mod {}", u64::MAX)).unwrap();
680 let cmp_3 = MatZq::from_str(&format!("[[3],[5],[7]] mod {}", u64::MAX)).unwrap();
681
682 assert_eq!(cmp_1, column_1);
683 assert_eq!(cmp_2, column_2);
684 assert_eq!(cmp_3, column_3);
685 }
686
687 #[test]
689 fn get_column_negative_indexing_works() {
690 let matrix = MatZq::from_str(&format!(
691 "[[42, 0, 42],[{}, 0, 17],[{}, 0, 42]] mod {}",
692 i64::MAX,
693 u64::MAX - 1,
694 u64::MAX
695 ))
696 .unwrap();
697 let column_1 = matrix.get_column(-3).unwrap();
698 let column_2 = matrix.get_column(-2).unwrap();
699 let column_3 = matrix.get_column(-1).unwrap();
700
701 let cmp_1 = MatZq::from_str(&format!(
702 "[[42],[{}],[{}]] mod {}",
703 i64::MAX,
704 u64::MAX - 1,
705 u64::MAX
706 ))
707 .unwrap();
708 let cmp_2 = MatZq::from_str(&format!("[[0],[0],[0]] mod {}", u64::MAX)).unwrap();
709 let cmp_3 = MatZq::from_str(&format!("[[42],[17],[42]] mod {}", u64::MAX)).unwrap();
710
711 assert_eq!(cmp_1, column_1);
712 assert_eq!(cmp_2, column_2);
713 assert_eq!(cmp_3, column_3);
714 }
715
716 #[test]
718 fn wrong_dim_error() {
719 let matrix = MatZq::from_str(&format!(
720 "[[1, 2, 3],[{}, 4, 5],[{}, 6, 7]] mod {}",
721 i64::MAX,
722 i64::MIN,
723 u64::MAX
724 ))
725 .unwrap();
726 let row_1 = matrix.get_row(-4);
727 let row_2 = matrix.get_row(4);
728 let column_1 = matrix.get_column(-4);
729 let column_2 = matrix.get_column(4);
730
731 assert!(row_1.is_err());
732 assert!(row_2.is_err());
733 assert!(column_1.is_err());
734 assert!(column_2.is_err());
735 }
736}
737
738#[cfg(test)]
739mod test_get_submatrix {
740 use crate::{
741 integer::Z,
742 integer_mod_q::MatZq,
743 traits::{MatrixDimensions, MatrixGetSubmatrix},
744 };
745 use std::str::FromStr;
746
747 #[test]
749 fn entire_matrix() {
750 let mat = MatZq::identity(5, 5, i64::MAX);
751
752 let sub_mat = mat.get_submatrix(0, 4, 0, 4).unwrap();
753
754 assert_eq!(mat, sub_mat);
755 }
756
757 #[test]
759 fn matrix_single_entry() {
760 let mat = MatZq::identity(5, 5, i64::MAX);
761
762 let sub_mat = mat.get_submatrix(0, 0, 0, 0).unwrap();
763
764 let cmp_mat = MatZq::identity(1, 1, i64::MAX);
765 assert_eq!(cmp_mat, sub_mat);
766 }
767
768 #[test]
770 fn correct_dimensions() {
771 let mat = MatZq::identity(100, 100, i64::MAX);
772
773 let sub_mat = mat.get_submatrix(1, 37, 0, 29).unwrap();
774
775 assert_eq!(37, sub_mat.get_num_rows());
776 assert_eq!(30, sub_mat.get_num_columns());
777 }
778
779 #[test]
782 fn large_entries() {
783 let mat = MatZq::from_str(&format!(
784 "[[{}, 2, 3],[1, {}, 3]] mod {}",
785 u64::MAX,
786 i64::MIN,
787 u128::MAX
788 ))
789 .unwrap();
790
791 let sub_mat = mat.get_submatrix(0, 1, 0, 1).unwrap();
792
793 let cmp_mat = MatZq::from_str(&format!(
794 "[[{}, 2],[1, {}]] mod {}",
795 u64::MAX,
796 i64::MIN,
797 u128::MAX
798 ))
799 .unwrap();
800 assert_eq!(cmp_mat, sub_mat);
801 }
802
803 #[test]
806 fn invalid_coordinates() {
807 let mat = MatZq::identity(10, 10, u64::MAX);
808
809 assert!(mat.get_submatrix(0, 0, 0, 10).is_err());
810 assert!(mat.get_submatrix(0, 10, 0, 0).is_err());
811 assert!(mat.get_submatrix(0, 0, -11, 0).is_err());
812 assert!(mat.get_submatrix(-11, 0, 0, 0).is_err());
813 }
814
815 #[test]
817 fn negative_indexing() {
818 let matrix = MatZq::identity(3, 3, u64::MAX);
819
820 assert_eq!(matrix, matrix.get_submatrix(0, -1, 0, -1).unwrap());
821 assert_eq!(matrix, matrix.get_submatrix(-3, -1, -3, -1).unwrap());
822 assert_eq!(
823 matrix.get_row(0).unwrap(),
824 matrix.get_submatrix(0, -3, -3, -1).unwrap()
825 );
826 }
827
828 #[test]
830 #[should_panic]
831 fn no_columns() {
832 let mat = MatZq::identity(10, 10, u64::MAX);
833
834 let _ = mat.get_submatrix(0, 0, 6, 5);
835 }
836
837 #[test]
839 #[should_panic]
840 fn no_rows() {
841 let mat = MatZq::identity(10, 10, u64::MAX);
842
843 let _ = mat.get_submatrix(5, 4, 0, 0);
844 }
845
846 #[test]
848 fn availability() {
849 let mat = MatZq::identity(10, 10, u64::MAX);
850
851 let _ = mat.get_submatrix(0_i8, 0_i8, 0_i8, 0_i8);
852 let _ = mat.get_submatrix(0_i16, 0_i16, 0_i16, 0_i16);
853 let _ = mat.get_submatrix(0_i32, 0_i32, 0_i32, 0_i32);
854 let _ = mat.get_submatrix(0_i64, 0_i64, 0_i64, 0_i64);
855 let _ = mat.get_submatrix(0_u8, 0_u8, 0_u8, 0_u8);
856 let _ = mat.get_submatrix(0_u16, 0_i16, 0_u16, 0_u16);
857 let _ = mat.get_submatrix(0_u32, 0_i32, 0_u32, 0_u32);
858 let _ = mat.get_submatrix(0_u64, 0_i64, 0_u64, 0_u64);
859 let _ = mat.get_submatrix(&Z::ZERO, &Z::ZERO, &Z::ZERO, &Z::ZERO);
860 }
861}
862
863#[cfg(test)]
864mod test_collect_entries {
865 use super::MatZq;
866 use std::str::FromStr;
867
868 #[test]
870 fn all_entries_collected() {
871 let mat_1 = MatZq::from_str(&format!(
872 "[[1, 2],[{}, {}],[3, 4]] mod {}",
873 i64::MAX,
874 i64::MIN,
875 u64::MAX
876 ))
877 .unwrap();
878 let mat_2 = MatZq::from_str("[[-1, 2]] mod 2").unwrap();
879
880 let entries_1 = mat_1.collect_entries();
881 let entries_2 = mat_2.collect_entries();
882
883 assert_eq!(entries_1.len(), 6);
884 assert_eq!(entries_1[0], 1);
885 assert_eq!(entries_1[1], 2);
886 assert!(entries_1[2] >= 2_i64.pow(62));
887 assert!(entries_1[3] >= 2_i64.pow(62));
888 assert_eq!(entries_1[4], 3);
889 assert_eq!(entries_1[5], 4);
890
891 assert_eq!(entries_2.len(), 2);
892 assert_eq!(entries_2[0], 1);
893 assert_eq!(entries_2[1], 0);
894 }
895}
896
897#[cfg(test)]
898mod test_collect_lengths {
899 use super::{MatZq, Z};
900 use std::str::FromStr;
901
902 #[test]
904 fn lengths_correctly_computed() {
905 let mat_1 = MatZq::from_str(&format!(
906 "[[1, 2],[{}, {}],[3, 4]] mod {}",
907 i64::MAX - 2,
908 i64::MIN,
909 i64::MAX - 1
910 ))
911 .unwrap();
912 let mat_2 = MatZq::from_str("[[-1, 2]] mod 2").unwrap();
913
914 let lengths_1 = mat_1.collect_lengths();
915 let lengths_2 = mat_2.collect_lengths();
916
917 assert_eq!(lengths_1.len(), 6);
918 assert_eq!(lengths_1[0], Z::ONE);
919 assert_eq!(lengths_1[1], Z::from(2));
920 assert_eq!(lengths_1[2], Z::ONE);
921 assert_eq!(lengths_1[3], Z::from(2));
922 assert_eq!(lengths_1[4], Z::from(3));
923 assert_eq!(lengths_1[5], Z::from(4));
924
925 assert_eq!(lengths_2.len(), 2);
926 assert_eq!(lengths_2[0], Z::ONE);
927 assert_eq!(lengths_2[1], Z::ZERO);
928 }
929}
930
931#[cfg(test)]
932mod test_get_representative_least_absolute_residue {
933 use super::*;
934 use std::str::FromStr;
935
936 #[test]
938 fn large_modulus() {
939 let mat_zq = MatZq::from_str(&format!("[[1,2],[-1,-2]] mod {}", u64::MAX)).unwrap();
940
941 let mat_z = mat_zq.get_representative_least_absolute_residue();
942
943 let mat_cmp = MatZ::from_str("[[1,2],[-1,-2]]").unwrap();
944 assert_eq!(mat_z.to_string(), mat_cmp.to_string());
945 }
946
947 #[test]
949 fn even_modulus() {
950 let mat_zq = MatZq::from_str("[[0,1,2,3,4,5,6,7,8,9,10]] mod 10").unwrap();
951
952 let mat_z = mat_zq.get_representative_least_absolute_residue();
953
954 let mat_cmp = MatZ::from_str("[[0,1,2,3,4,5,-4,-3,-2,-1,0]]").unwrap();
955 assert_eq!(mat_z.to_string(), mat_cmp.to_string());
956 }
957
958 #[test]
960 fn uneven_modulus() {
961 let mat_zq = MatZq::from_str("[[0,1,2,3,4,5,6,7,8,9,10,11]] mod 11").unwrap();
962
963 let mat_z = mat_zq.get_representative_least_absolute_residue();
964
965 let mat_cmp = MatZ::from_str("[[0,1,2,3,4,5,-5,-4,-3,-2,-1,0]]").unwrap();
966 assert_eq!(mat_z.to_string(), mat_cmp.to_string());
967 }
968
969 #[test]
972 fn consistent_with_zq() {
973 for modulus in [256, 257] {
974 let mut mat_zq = MatZq::new(1, modulus, modulus);
975 for value in 0..modulus {
976 mat_zq.set_entry(0, value, value).unwrap();
977 }
978
979 let mat_z = mat_zq.get_representative_least_absolute_residue();
980
981 for value in 0..modulus {
982 let entry: Z = mat_z.get_entry(0, value).unwrap();
983 let cmp = Zq::from((value, modulus)).get_representative_least_absolute_residue();
984 assert_eq!(cmp, entry);
985 }
986 }
987 }
988}