1use crate::{
12 error::MathError,
13 rational::{MatQ, Q},
14 traits::{MatrixDimensions, MatrixSetEntry, MatrixSetSubmatrix, MatrixSwaps},
15 utils::index::{evaluate_index_for_vector, evaluate_indices_for_matrix},
16};
17use flint_sys::{
18 fmpq::{fmpq_set, fmpq_swap},
19 fmpq_mat::{
20 fmpq_mat_entry, fmpq_mat_invert_cols, fmpq_mat_invert_rows, fmpq_mat_set,
21 fmpq_mat_swap_cols, fmpq_mat_swap_rows, fmpq_mat_window_clear, fmpq_mat_window_init,
22 },
23};
24use std::{
25 fmt::Display,
26 mem::MaybeUninit,
27 ptr::{null, null_mut},
28};
29
30impl<Rational: Into<Q>> MatrixSetEntry<Rational> for MatQ {
31 unsafe fn set_entry_unchecked(&mut self, row: i64, column: i64, value: Rational) {
62 let value: Q = value.into();
63
64 unsafe {
65 let entry = fmpq_mat_entry(&self.matrix, row, column);
66 fmpq_set(entry, &value.value)
67 };
68 }
69}
70
71impl MatrixSetSubmatrix for MatQ {
72 unsafe fn set_submatrix_unchecked(
109 &mut self,
110 row_self_start: i64,
111 col_self_start: i64,
112 row_self_end: i64,
113 col_self_end: i64,
114 other: &Self,
115 row_other_start: i64,
116 col_other_start: i64,
117 row_other_end: i64,
118 col_other_end: i64,
119 ) {
120 let mut window_self = MaybeUninit::uninit();
121 unsafe {
123 fmpq_mat_window_init(
124 window_self.as_mut_ptr(),
125 &self.matrix,
126 row_self_start,
127 col_self_start,
128 row_self_end,
129 col_self_end,
130 )
131 };
132 let mut window_other = MaybeUninit::uninit();
133 unsafe {
135 fmpq_mat_window_init(
136 window_other.as_mut_ptr(),
137 &other.matrix,
138 row_other_start,
139 col_other_start,
140 row_other_end,
141 col_other_end,
142 )
143 };
144 unsafe {
145 fmpq_mat_set(window_self.as_mut_ptr(), window_other.as_mut_ptr());
147
148 fmpq_mat_window_clear(window_self.as_mut_ptr());
151 fmpq_mat_window_clear(window_other.as_mut_ptr());
152 }
153 }
154}
155
156impl MatrixSwaps for MatQ {
157 fn swap_entries(
184 &mut self,
185 row_0: impl TryInto<i64> + Display,
186 col_0: impl TryInto<i64> + Display,
187 row_1: impl TryInto<i64> + Display,
188 col_1: impl TryInto<i64> + Display,
189 ) -> Result<(), MathError> {
190 let (row_0, col_0) = evaluate_indices_for_matrix(self, row_0, col_0)?;
191 let (row_1, col_1) = evaluate_indices_for_matrix(self, row_1, col_1)?;
192
193 unsafe {
194 fmpq_swap(
195 fmpq_mat_entry(&self.matrix, row_0, col_0),
196 fmpq_mat_entry(&self.matrix, row_1, col_1),
197 )
198 };
199 Ok(())
200 }
201
202 fn swap_columns(
226 &mut self,
227 col_0: impl TryInto<i64> + Display,
228 col_1: impl TryInto<i64> + Display,
229 ) -> Result<(), MathError> {
230 let num_cols = self.get_num_columns();
231 let col_0 = evaluate_index_for_vector(col_0, num_cols)?;
232 let col_1 = evaluate_index_for_vector(col_1, num_cols)?;
233
234 if col_0 >= num_cols || col_1 >= num_cols {
235 return Err(MathError::OutOfBounds(
236 format!("smaller than {num_cols}"),
237 if col_0 > col_1 {
238 col_0.to_string()
239 } else {
240 col_1.to_string()
241 },
242 ));
243 }
244 unsafe { fmpq_mat_swap_cols(&mut self.matrix, null(), col_0, col_1) }
245 Ok(())
246 }
247
248 fn swap_rows(
272 &mut self,
273 row_0: impl TryInto<i64> + Display,
274 row_1: impl TryInto<i64> + Display,
275 ) -> Result<(), MathError> {
276 let num_rows = self.get_num_rows();
277 let row_0 = evaluate_index_for_vector(row_0, num_rows)?;
278 let row_1 = evaluate_index_for_vector(row_1, num_rows)?;
279
280 if row_0 >= num_rows || row_1 >= num_rows {
281 return Err(MathError::OutOfBounds(
282 format!("smaller than {num_rows}"),
283 if row_0 > row_1 {
284 row_0.to_string()
285 } else {
286 row_1.to_string()
287 },
288 ));
289 }
290 unsafe { fmpq_mat_swap_rows(&mut self.matrix, null(), row_0, row_1) }
291 Ok(())
292 }
293}
294
295impl MatQ {
296 pub fn reverse_columns(&mut self) {
307 unsafe { fmpq_mat_invert_cols(&mut self.matrix, null_mut()) }
311 }
312
313 pub fn reverse_rows(&mut self) {
324 unsafe { fmpq_mat_invert_rows(&mut self.matrix, null_mut()) }
328 }
329}
330
331#[cfg(test)]
332mod test_setter {
333 use super::Q;
334 use crate::{
335 integer::Z,
336 integer_mod_q::Modulus,
337 rational::MatQ,
338 traits::{MatrixGetEntry, MatrixSetEntry, MatrixSetSubmatrix},
339 };
340 use std::str::FromStr;
341
342 #[test]
344 fn availability() {
345 let mut matrix = MatQ::new(1, 1);
346
347 matrix.set_entry(0, 0, (1, 2)).unwrap();
349 matrix.set_entry(0, 0, (1i16, 2u64)).unwrap();
350 matrix.set_entry(0, 0, Q::from((1, 2))).unwrap();
351 matrix.set_entry(0, 0, &Q::from((1, 2))).unwrap();
352
353 matrix.set_entry(0, 0, 1u8).unwrap();
355 matrix.set_entry(0, 0, 1i8).unwrap();
356 matrix.set_entry(0, 0, 1u16).unwrap();
357 matrix.set_entry(0, 0, 1i16).unwrap();
358 matrix.set_entry(0, 0, 1u32).unwrap();
359 matrix.set_entry(0, 0, 1i32).unwrap();
360 matrix.set_entry(0, 0, 1u64).unwrap();
361 matrix.set_entry(0, 0, 1i64).unwrap();
362 matrix.set_entry(0, 0, Z::from(1)).unwrap();
363 matrix.set_entry(0, 0, &Z::from(1)).unwrap();
364 matrix.set_entry(0, 0, Modulus::from(3)).unwrap();
365 matrix.set_entry(0, 0, &Modulus::from(3)).unwrap();
366 }
367
368 #[test]
370 fn standard_value() {
371 let mut matrix = MatQ::new(5, 10);
372 let value = Q::from(869);
373 matrix.set_entry(4, 7, &value).unwrap();
374
375 let entry = matrix.get_entry(4, 7).unwrap();
376
377 assert_eq!(Q::from(869), entry);
378 }
379
380 #[test]
382 fn max_int_positive() {
383 let mut matrix = MatQ::new(5, 10);
384 let value_1 = Q::from(i64::MAX);
385 let value_2 = Q::from((1, i64::MAX));
386 matrix.set_entry(0, 0, value_1).unwrap();
387 matrix.set_entry(1, 1, value_2).unwrap();
388
389 let entry_1 = matrix.get_entry(0, 0).unwrap();
390 let entry_2 = matrix.get_entry(1, 1).unwrap();
391
392 assert_eq!(Q::from(i64::MAX), entry_1);
393 assert_eq!(Q::from((1, i64::MAX)), entry_2);
394 }
395
396 #[test]
398 fn large_positive() {
399 let mut matrix = MatQ::new(5, 10);
400 let value_1 = Q::from(u64::MAX);
401 let value_2 = Q::from((1, u64::MAX));
402 matrix.set_entry(0, 0, value_1).unwrap();
403 matrix.set_entry(1, 1, value_2).unwrap();
404
405 let entry_1 = matrix.get_entry(0, 0).unwrap();
406 let entry_2 = matrix.get_entry(1, 1).unwrap();
407
408 assert_eq!(Q::from(u64::MAX), entry_1);
409 assert_eq!(Q::from((1, u64::MAX)), entry_2);
410 }
411
412 #[test]
414 fn max_int_negative() {
415 let mut matrix = MatQ::new(5, 10);
416 let value_1 = Q::from(i64::MIN);
417 let value_2 = Q::from((1, i64::MIN));
418 matrix.set_entry(0, 0, value_1).unwrap();
419 matrix.set_entry(1, 1, value_2).unwrap();
420
421 let entry_1 = matrix.get_entry(0, 0).unwrap();
422 let entry_2 = matrix.get_entry(1, 1).unwrap();
423
424 assert_eq!(Q::from(i64::MIN), entry_1);
425 assert_eq!(Q::from((1, i64::MIN)), entry_2);
426 }
427
428 #[test]
430 fn large_negative() {
431 let mut matrix = MatQ::new(5, 10);
432 let value_1 = format!("-{}", u64::MAX);
433 let value_2 = format!("1/-{}", u64::MAX);
434 matrix
435 .set_entry(0, 0, Q::from_str(&value_1).unwrap())
436 .unwrap();
437 matrix
438 .set_entry(1, 1, Q::from_str(&value_2).unwrap())
439 .unwrap();
440
441 let entry_1 = matrix.get_entry(0, 0).unwrap();
442 let entry_2 = matrix.get_entry(1, 1).unwrap();
443
444 assert_eq!(Q::from_str(&format!("-{}", u64::MAX)).unwrap(), entry_1);
445 assert_eq!(Q::from_str(&format!("1/-{}", u64::MAX)).unwrap(), entry_2);
446 }
447
448 #[test]
450 fn getting_at_zero() {
451 let mut matrix = MatQ::new(5, 10);
452 let value = Q::from(i64::MIN);
453 matrix.set_entry(0, 0, value).unwrap();
454
455 let entry = matrix.get_entry(0, 0).unwrap();
456
457 assert_eq!(entry, Q::from(i64::MIN));
458 }
459
460 #[test]
462 fn error_wrong_row() {
463 let matrix = MatQ::new(5, 10);
464
465 assert!(matrix.get_entry(5, 1).is_err());
466 assert!(matrix.get_entry(-6, 1).is_err());
467 }
468
469 #[test]
471 fn error_wrong_column() {
472 let matrix = MatQ::new(5, 10);
473
474 assert!(matrix.get_entry(1, 100).is_err());
475 assert!(matrix.get_entry(1, -11).is_err());
476 }
477
478 #[test]
480 fn negative_indexing() {
481 let mut matrix = MatQ::new(3, 3);
482
483 matrix.set_entry(-1, -1, 9).unwrap();
484 matrix.set_entry(-1, -2, 8).unwrap();
485 matrix.set_entry(-3, -3, 1).unwrap();
486
487 let matrix_cmp = MatQ::from_str("[[1, 0, 0],[0, 0, 0],[0, 8, 9]]").unwrap();
488 assert_eq!(matrix_cmp, matrix);
489 }
490
491 #[test]
493 fn column_small_entries() {
494 let mut mat_1 = MatQ::from_str("[[1, 2, 3/-1],[-4/3, 5, 6]]").unwrap();
495 let mat_2 = MatQ::from_str("[[0],[-1]]").unwrap();
496 let cmp = MatQ::from_str("[[1, 0, -3],[4/-3, -1, 6]]").unwrap();
497
498 mat_1.set_column(1, &mat_2, 0).unwrap();
499
500 assert_eq!(cmp, mat_1);
501 }
502
503 #[test]
505 fn column_large_entries() {
506 let mut mat_1 = MatQ::from_str(&format!(
507 "[[{}/1, 1, 3, 4],[{}/-1, 4, -1/{}, 5],[7, 6, 8, 9]]",
508 i64::MIN,
509 i64::MAX,
510 u64::MAX
511 ))
512 .unwrap();
513 let mat_2 =
514 MatQ::from_str(&format!("[[1, -2/{}],[{}, 0],[7, -1]]", i64::MIN, i64::MAX)).unwrap();
515 let cmp = MatQ::from_str(&format!(
516 "[[-2/{}, 1, 3, 4],[0, 4, -1/{}, 5],[-1, 6, 8, 9]]",
517 i64::MIN,
518 u64::MAX
519 ))
520 .unwrap();
521
522 mat_1.set_column(0, &mat_2, 1).unwrap();
523
524 assert_eq!(cmp, mat_1);
525 }
526
527 #[test]
529 fn column_swap_same_entry() {
530 let mut mat_1 = MatQ::from_str(&format!(
531 "[[{}/-3, 1, 3, 4],[{}/-1, 4, -{}/2, 5],[7, 6, 8, 9]]",
532 i64::MIN,
533 i64::MAX,
534 u64::MAX
535 ))
536 .unwrap();
537 let cmp = mat_1.clone();
538
539 mat_1.set_column(0, &cmp, 0).unwrap();
540 mat_1.set_column(1, &cmp, 1).unwrap();
541
542 assert_eq!(cmp, mat_1);
543 }
544
545 #[test]
547 fn column_out_of_bounds() {
548 let mut mat_1 = MatQ::new(5, 2);
549 let mat_2 = mat_1.clone();
550
551 assert!(mat_1.set_column(-3, &mat_2, 0).is_err());
552 assert!(mat_1.set_column(2, &mat_2, 0).is_err());
553 assert!(mat_1.set_column(1, &mat_2, -3).is_err());
554 assert!(mat_1.set_column(1, &mat_2, 2).is_err());
555 }
556
557 #[test]
559 fn column_mismatching_columns() {
560 let mut mat_1 = MatQ::new(5, 2);
561 let mat_2 = MatQ::new(2, 2);
562
563 assert!(mat_1.set_column(0, &mat_2, 0).is_err());
564 assert!(mat_1.set_column(1, &mat_2, 1).is_err());
565 }
566
567 #[test]
569 fn row_small_entries() {
570 let mut mat_1 = MatQ::from_str("[[1, 2, 3/-1],[-4/3, 5, 6]]").unwrap();
571 let mat_2 = MatQ::from_str("[[0, -1/2, 2]]").unwrap();
572 let cmp = MatQ::from_str("[[1, 2, -3],[0, -1/2, 2]]").unwrap();
573
574 let _ = mat_1.set_row(1, &mat_2, 0);
575
576 assert_eq!(cmp, mat_1);
577 }
578
579 #[test]
581 fn row_large_entries() {
582 let mut mat_1 = MatQ::from_str(&format!(
583 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]]",
584 i64::MIN,
585 i64::MAX,
586 u64::MAX
587 ))
588 .unwrap();
589 let mat_2 = MatQ::from_str(&format!(
590 "[[0, 0, 0, 0],[1/{}, 0, {}/3, 0]]",
591 i64::MIN,
592 i64::MAX
593 ))
594 .unwrap();
595 let cmp = MatQ::from_str(&format!(
596 "[[1/{}, 0, {}/3, 0],[{}, 4, {}, 5],[7, 6, 8, 9]]",
597 i64::MIN,
598 i64::MAX,
599 i64::MAX,
600 u64::MAX
601 ))
602 .unwrap();
603
604 let _ = mat_1.set_row(0, &mat_2, 1);
605
606 assert_eq!(cmp, mat_1);
607 }
608
609 #[test]
611 fn row_swap_same_entry() {
612 let mut mat_1 = MatQ::from_str(&format!(
613 "[[{}, 1, 3, 4],[-{}/-1, 4, {}/-3, 5],[7, 6, 8, 9]]",
614 i64::MIN,
615 i64::MAX,
616 u64::MAX
617 ))
618 .unwrap();
619 let cmp = mat_1.clone();
620
621 let _ = mat_1.set_row(0, &cmp, 0);
622 let _ = mat_1.set_row(1, &cmp, 1);
623
624 assert_eq!(cmp, mat_1);
625 }
626
627 #[test]
629 fn row_out_of_bounds() {
630 let mut mat_1 = MatQ::new(5, 2);
631 let mat_2 = mat_1.clone();
632
633 assert!(mat_1.set_row(-6, &mat_2, 0).is_err());
634 assert!(mat_1.set_row(5, &mat_2, 0).is_err());
635 assert!(mat_1.set_row(2, &mat_2, -6).is_err());
636 assert!(mat_1.set_row(2, &mat_2, 5).is_err());
637 }
638
639 #[test]
641 fn row_mismatching_columns() {
642 let mut mat_1 = MatQ::new(3, 2);
643 let mat_2 = MatQ::new(3, 3);
644
645 assert!(mat_1.set_row(0, &mat_2, 0).is_err());
646 assert!(mat_1.set_row(1, &mat_2, 1).is_err());
647 }
648
649 #[test]
651 fn negative_indexing_row_column() {
652 let mut matrix = MatQ::identity(3, 3);
653 let matrix2 = MatQ::identity(3, 3);
654
655 matrix.set_column(-1, &matrix2, -2).unwrap();
656 matrix.set_row(-1, &matrix2, -2).unwrap();
657
658 let matrix_cmp = MatQ::from_str("[[1, 0, 0],[0, 1, 1],[0, 1, 0]]").unwrap();
659 assert_eq!(matrix_cmp, matrix);
660 }
661}
662
663#[cfg(test)]
664mod test_swaps {
665 use super::MatQ;
666 use crate::traits::{MatrixGetSubmatrix, MatrixSwaps};
667 use std::str::FromStr;
668
669 #[test]
671 fn entries_small_entries() {
672 let mut matrix = MatQ::from_str("[[1, 1/2, 3/-5],[-4/3, -5, 6]]").unwrap();
673 let cmp = MatQ::from_str("[[1, -5, 3/-5],[-4/3, 1/2, 6]]").unwrap();
674
675 let _ = matrix.swap_entries(1, 1, 0, 1);
676
677 assert_eq!(cmp, matrix);
678 }
679
680 #[test]
682 fn entries_large_entries() {
683 let mut matrix = MatQ::from_str(&format!(
684 "[[{}/2, 1, 3, 4],[{}, 4, -1/{}, 5],[7, 6, 8, 9]]",
685 i64::MIN,
686 i64::MAX,
687 u64::MAX
688 ))
689 .unwrap();
690 let cmp = MatQ::from_str(&format!(
691 "[[-1/{}, 1, 3, 4],[{}, 4, {}/2, 5],[7, 6, 8, 9]]",
692 u64::MAX,
693 i64::MAX,
694 i64::MIN
695 ))
696 .unwrap();
697
698 let _ = matrix.swap_entries(0, 0, 1, 2);
699
700 assert_eq!(cmp, matrix);
701 }
702
703 #[test]
705 fn entries_swap_same_entry() {
706 let mut matrix = MatQ::from_str(&format!(
707 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]]",
708 i64::MIN,
709 i64::MAX,
710 u64::MAX
711 ))
712 .unwrap();
713 let cmp = matrix.clone();
714
715 let _ = matrix.swap_entries(0, 0, 0, 0);
716 let _ = matrix.swap_entries(1, 1, 1, 1);
717
718 assert_eq!(cmp, matrix);
719 }
720
721 #[test]
723 fn entries_out_of_bounds() {
724 let mut matrix = MatQ::new(5, 2);
725
726 assert!(matrix.swap_entries(-6, 0, 0, 0).is_err());
727 assert!(matrix.swap_entries(0, -3, 0, 0).is_err());
728 assert!(matrix.swap_entries(0, 0, 5, 0).is_err());
729 assert!(matrix.swap_entries(0, 5, 0, 0).is_err());
730 }
731
732 #[test]
734 fn columns_small_entries() {
735 let mut matrix = MatQ::from_str("[[1, 2/-1, -3/1],[1/4, 5/7, 6]]").unwrap();
736 let cmp_vec_0 = MatQ::from_str("[[1],[1/4]]").unwrap();
737 let cmp_vec_1 = MatQ::from_str("[[-3],[6]]").unwrap();
738 let cmp_vec_2 = MatQ::from_str("[[-2],[5/7]]").unwrap();
739
740 let _ = matrix.swap_columns(1, 2);
741
742 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
743 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
744 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
745 }
746
747 #[test]
749 fn columns_large_entries() {
750 let mut matrix = MatQ::from_str(&format!(
751 "[[{}, 1, 3, 4/-3],[{}/2, 4, -1/{}, 5],[7, 6, 8/9, 9]]",
752 i64::MIN,
753 i64::MAX,
754 u64::MAX
755 ))
756 .unwrap();
757 let cmp_vec_0 = MatQ::from_str(&format!("[[3],[-1/{}],[8/9]]", u64::MAX)).unwrap();
758 let cmp_vec_1 = MatQ::from_str("[[1],[4],[6]]").unwrap();
759 let cmp_vec_2 = MatQ::from_str(&format!("[[{}],[{}/2],[7]]", i64::MIN, i64::MAX)).unwrap();
760 let cmp_vec_3 = MatQ::from_str("[[4/-3],[5],[9]]").unwrap();
761
762 let _ = matrix.swap_columns(0, 2);
763
764 assert_eq!(cmp_vec_0, matrix.get_column(0).unwrap());
765 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
766 assert_eq!(cmp_vec_2, matrix.get_column(2).unwrap());
767 assert_eq!(cmp_vec_3, matrix.get_column(3).unwrap());
768 }
769
770 #[test]
772 fn columns_swap_same_col() {
773 let mut matrix = MatQ::from_str(&format!(
774 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]]",
775 i64::MIN,
776 i64::MAX,
777 u64::MAX
778 ))
779 .unwrap();
780 let cmp = matrix.clone();
781
782 let _ = matrix.swap_columns(0, 0);
783
784 assert_eq!(cmp, matrix);
785 }
786
787 #[test]
789 fn column_out_of_bounds() {
790 let mut matrix = MatQ::new(5, 2);
791
792 assert!(matrix.swap_columns(-6, 0).is_err());
793 assert!(matrix.swap_columns(0, -6).is_err());
794 assert!(matrix.swap_columns(5, 0).is_err());
795 assert!(matrix.swap_columns(0, 5).is_err());
796 }
797
798 #[test]
800 fn rows_small_entries() {
801 let mut matrix = MatQ::from_str("[[1, 2/-3],[3, -4/3]]").unwrap();
802 let cmp_vec_0 = MatQ::from_str("[[3, -4/3]]").unwrap();
803 let cmp_vec_1 = MatQ::from_str("[[1, 2/-3]]").unwrap();
804
805 let _ = matrix.swap_rows(1, 0);
806
807 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
808 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
809 }
810
811 #[test]
813 fn rows_large_entries() {
814 let mut matrix = MatQ::from_str(&format!(
815 "[[{}, 1, 3, 4],[7, 6/-1, 8, 9/4],[1/{}, 4, -2/{}, 5/3]]",
816 i64::MIN,
817 i64::MAX,
818 u64::MAX
819 ))
820 .unwrap();
821 let cmp_vec_0 =
822 MatQ::from_str(&format!("[[1/{}, 4, -2/{}, 5/3]]", i64::MAX, u64::MAX)).unwrap();
823 let cmp_vec_1 = MatQ::from_str("[[7, 6/-1, 8, 9/4]]").unwrap();
824 let cmp_vec_2 = MatQ::from_str(&format!("[[{}, 1, 3, 4]]", i64::MIN)).unwrap();
825
826 let _ = matrix.swap_rows(0, 2);
827
828 assert_eq!(cmp_vec_0, matrix.get_row(0).unwrap());
829 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
830 assert_eq!(cmp_vec_2, matrix.get_row(2).unwrap());
831 }
832
833 #[test]
835 fn rows_swap_same_row() {
836 let mut matrix = MatQ::from_str(&format!(
837 "[[{}, 1, 3, 4],[{}, 4, {}, 5],[7, 6, 8, 9]]",
838 i64::MIN,
839 i64::MAX,
840 u64::MAX
841 ))
842 .unwrap();
843 let cmp = matrix.clone();
844
845 let _ = matrix.swap_rows(1, 1);
846
847 assert_eq!(cmp, matrix);
848 }
849
850 #[test]
852 fn row_out_of_bounds() {
853 let mut matrix = MatQ::new(2, 4);
854
855 assert!(matrix.swap_rows(-3, 0).is_err());
856 assert!(matrix.swap_rows(0, -3).is_err());
857 assert!(matrix.swap_rows(4, 0).is_err());
858 assert!(matrix.swap_rows(0, 4).is_err());
859 }
860
861 #[test]
863 fn negative_indexing_row_column() {
864 let mut matrix = MatQ::identity(3, 3);
865 let mut matrix2 = MatQ::identity(3, 3);
866
867 matrix.swap_columns(-1, -2).unwrap();
868 matrix2.swap_rows(-1, -2).unwrap();
869
870 let matrix_cmp = MatQ::from_str("[[1, 0, 0],[0, 0, 1],[0, 1, 0]]").unwrap();
871 assert_eq!(matrix_cmp, matrix);
872 assert_eq!(matrix_cmp, matrix2);
873 }
874}
875
876#[cfg(test)]
877mod test_reverses {
878 use super::MatQ;
879 use crate::traits::MatrixGetSubmatrix;
880 use std::str::FromStr;
881
882 #[test]
884 fn columns_small_entries() {
885 let mut matrix = MatQ::from_str("[[1, 2/-1, -3/1],[4, 5/6, 6]]").unwrap();
886 let cmp_vec_0 = MatQ::from_str("[[1],[4]]").unwrap();
887 let cmp_vec_1 = MatQ::from_str("[[-2],[5/6]]").unwrap();
888 let cmp_vec_2 = MatQ::from_str("[[-3],[6]]").unwrap();
889
890 matrix.reverse_columns();
891
892 assert_eq!(cmp_vec_2, matrix.get_column(0).unwrap());
893 assert_eq!(cmp_vec_1, matrix.get_column(1).unwrap());
894 assert_eq!(cmp_vec_0, matrix.get_column(2).unwrap());
895 }
896
897 #[test]
899 fn columns_large_entries() {
900 let mut matrix = MatQ::from_str(&format!(
901 "[[1/{}, 1, 3, 4],[-1/{}, 4, {}, 5],[7, 6, 8/9, 9]]",
902 i64::MIN,
903 i64::MAX,
904 u64::MAX
905 ))
906 .unwrap();
907 let cmp_vec_0 =
908 MatQ::from_str(&format!("[[1/{}],[-1/{}],[7]]", i64::MIN, i64::MAX)).unwrap();
909 let cmp_vec_1 = MatQ::from_str("[[1],[4],[6]]").unwrap();
910 let cmp_vec_2 = MatQ::from_str(&format!("[[3],[{}],[8/9]]", u64::MAX)).unwrap();
911 let cmp_vec_3 = MatQ::from_str("[[4],[5],[9]]").unwrap();
912
913 matrix.reverse_columns();
914
915 assert_eq!(cmp_vec_3, matrix.get_column(0).unwrap());
916 assert_eq!(cmp_vec_2, matrix.get_column(1).unwrap());
917 assert_eq!(cmp_vec_1, matrix.get_column(2).unwrap());
918 assert_eq!(cmp_vec_0, matrix.get_column(3).unwrap());
919 }
920
921 #[test]
923 fn rows_small_entries() {
924 let mut matrix = MatQ::from_str("[[1, 2/-1],[-3/1, 4]]").unwrap();
925 let cmp_vec_0 = MatQ::from_str("[[1, -2]]").unwrap();
926 let cmp_vec_1 = MatQ::from_str("[[-3, 4]]").unwrap();
927
928 matrix.reverse_rows();
929
930 assert_eq!(cmp_vec_1, matrix.get_row(0).unwrap());
931 assert_eq!(cmp_vec_0, matrix.get_row(1).unwrap());
932 }
933
934 #[test]
936 fn rows_large_entries() {
937 let mut matrix = MatQ::from_str(&format!(
938 "[[{}, 1, 3, 4],[7, 6, 8, 9],[{}, 4, -2/{}, 5]]",
939 i64::MIN,
940 i64::MAX,
941 u64::MAX
942 ))
943 .unwrap();
944 let cmp_vec_0 = MatQ::from_str(&format!("[[{}, 1, 3, 4]]", i64::MIN)).unwrap();
945 let cmp_vec_1 = MatQ::from_str("[[7, 6, 8, 9]]").unwrap();
946 let cmp_vec_2 =
947 MatQ::from_str(&format!("[[{}, 4, -2/{}, 5]]", i64::MAX, u64::MAX)).unwrap();
948
949 matrix.reverse_rows();
950
951 assert_eq!(cmp_vec_2, matrix.get_row(0).unwrap());
952 assert_eq!(cmp_vec_1, matrix.get_row(1).unwrap());
953 assert_eq!(cmp_vec_0, matrix.get_row(2).unwrap());
954 }
955}
956
957#[cfg(test)]
958mod test_set_submatrix {
959 use crate::{rational::MatQ, traits::MatrixSetSubmatrix};
960 use std::str::FromStr;
961
962 #[test]
964 fn entire_matrix() {
965 let mut mat = MatQ::new(10, 10);
966 let identity = MatQ::identity(10, 10);
967
968 mat.set_submatrix(0, 0, &identity, 0, 0, 9, 9).unwrap();
969
970 assert_eq!(identity, mat);
971 }
972
973 #[test]
975 fn out_of_bounds() {
976 let mut mat = MatQ::identity(10, 10);
977
978 assert!(mat.set_submatrix(10, 0, &mat.clone(), 0, 0, 9, 9).is_err());
979 assert!(mat.set_submatrix(0, 10, &mat.clone(), 0, 0, 9, 9).is_err());
980 assert!(mat.set_submatrix(0, 0, &mat.clone(), 10, 0, 9, 9).is_err());
981 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 10, 9, 9).is_err());
982 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 10, 9).is_err());
983 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, 10).is_err());
984 assert!(mat.set_submatrix(-11, 0, &mat.clone(), 0, 0, 9, 9).is_err());
985 assert!(mat.set_submatrix(0, -11, &mat.clone(), 0, 0, 9, 9).is_err());
986 assert!(mat.set_submatrix(0, 0, &mat.clone(), -11, 0, 9, 9).is_err());
987 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, -11, 9, 9).is_err());
988 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, -11, 9).is_err());
989 assert!(mat.set_submatrix(0, 0, &mat.clone(), 0, 0, 9, -11).is_err());
990 }
991
992 #[test]
995 fn submatrix_too_large() {
996 let mut mat = MatQ::new(10, 10);
997
998 assert!(
999 mat.set_submatrix(0, 0, &MatQ::identity(11, 11), 0, 0, 10, 10)
1000 .is_err()
1001 );
1002 assert!(mat.set_submatrix(1, 2, &mat.clone(), 0, 0, 9, 9).is_err());
1003 }
1004
1005 #[test]
1007 fn large_values() {
1008 let mut mat = MatQ::from_str(&format!("[[1, {}],[-{}/3, 0]]", u64::MAX, u64::MAX)).unwrap();
1009 let cmp_mat =
1010 MatQ::from_str(&format!("[[-{}/3, 0],[-{}/3, 0]]", u64::MAX, u64::MAX)).unwrap();
1011
1012 mat.set_submatrix(0, 0, &mat.clone(), 1, 0, 1, 1).unwrap();
1013 assert_eq!(cmp_mat, mat);
1014 }
1015
1016 #[test]
1018 #[should_panic]
1019 fn submatrix_negative() {
1020 let mut mat = MatQ::identity(10, 10);
1021
1022 let _ = mat.set_submatrix(0, 0, &mat.clone(), 0, 9, 9, 5);
1023 }
1024}