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