1use super::MatZ;
12use crate::{
13 integer::Z,
14 traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
15};
16use flint_sys::{
17 fmpz::{fmpz, fmpz_init_set},
18 fmpz_mat::{fmpz_mat_entry, fmpz_mat_init_set, fmpz_mat_window_clear, fmpz_mat_window_init},
19};
20use std::mem::MaybeUninit;
21
22impl MatrixDimensions for MatZ {
23 fn get_num_rows(&self) -> i64 {
34 self.matrix.r
35 }
36
37 fn get_num_columns(&self) -> i64 {
48 self.matrix.c
49 }
50}
51
52impl MatrixGetEntry<Z> for MatZ {
53 unsafe fn get_entry_unchecked(&self, row: i64, column: i64) -> Z {
81 let mut copy = fmpz(0);
82 let entry = unsafe { fmpz_mat_entry(&self.matrix, row, column) };
83 unsafe { fmpz_init_set(&mut copy, entry) };
84
85 Z { value: copy }
86 }
87}
88
89impl MatrixGetSubmatrix for MatZ {
90 unsafe fn get_submatrix_unchecked(
124 &self,
125 row_1: i64,
126 row_2: i64,
127 col_1: i64,
128 col_2: i64,
129 ) -> Self {
130 let mut window = MaybeUninit::uninit();
131 unsafe {
133 fmpz_mat_window_init(
134 window.as_mut_ptr(),
135 &self.matrix,
136 row_1,
137 col_1,
138 row_2,
139 col_2,
140 )
141 };
142 let mut window_copy = MaybeUninit::uninit();
143 unsafe {
144 fmpz_mat_init_set(window_copy.as_mut_ptr(), window.as_ptr());
146 fmpz_mat_window_clear(window.as_mut_ptr());
149 }
150 MatZ {
151 matrix: unsafe { window_copy.assume_init() },
152 }
153 }
154}
155
156impl MatZ {
157 pub(crate) fn collect_entries(&self) -> Vec<fmpz> {
173 let mut entries: Vec<fmpz> =
174 Vec::with_capacity((self.get_num_rows() * self.get_num_columns()) as usize);
175
176 for row in 0..self.get_num_rows() {
177 for col in 0..self.get_num_columns() {
178 let entry = unsafe { *fmpz_mat_entry(&self.matrix, row, col) };
180 entries.push(entry);
181 }
182 }
183
184 entries
185 }
186}
187
188#[cfg(test)]
189mod test_get_entry {
190 use super::Z;
191 use crate::{
192 integer::MatZ,
193 traits::{MatrixGetEntry, MatrixSetEntry},
194 };
195 use std::str::FromStr;
196
197 #[test]
199 fn max_int_positive() {
200 let mut matrix = MatZ::new(5, 10);
201 let value = Z::from(i64::MAX);
202 matrix.set_entry(1, 1, value).unwrap();
203
204 let entry = matrix.get_entry(1, 1).unwrap();
205
206 assert_eq!(Z::from(i64::MAX), entry);
207 }
208
209 #[test]
211 fn large_positive() {
212 let mut matrix = MatZ::new(5, 10);
213 let value = Z::from(u64::MAX);
214 matrix.set_entry(1, 1, value).unwrap();
215
216 let entry = matrix.get_entry(1, 1).unwrap();
217
218 assert_eq!(Z::from(u64::MAX), entry);
219 }
220
221 #[test]
223 fn max_int_negative() {
224 let mut matrix = MatZ::new(5, 10);
225 let value = Z::from(i64::MIN);
226 matrix.set_entry(1, 1, value).unwrap();
227
228 let entry = matrix.get_entry(1, 1).unwrap();
229
230 assert_eq!(Z::from(i64::MIN), entry);
231 }
232
233 #[test]
235 fn large_negative() {
236 let mut matrix = MatZ::new(5, 10);
237 let value_str = &format!("-{}", u64::MAX);
238 matrix
239 .set_entry(1, 1, Z::from_str(value_str).unwrap())
240 .unwrap();
241
242 let entry = matrix.get_entry(1, 1).unwrap();
243
244 assert_eq!(Z::from_str(value_str).unwrap(), entry);
245 }
246
247 #[test]
249 fn getting_at_zero() {
250 let mut matrix = MatZ::new(5, 10);
251 let value = Z::from(i64::MIN);
252 matrix.set_entry(0, 0, value).unwrap();
253
254 let entry = matrix.get_entry(0, 0).unwrap();
255
256 assert_eq!(entry, Z::from(i64::MIN));
257 }
258
259 #[test]
261 fn error_wrong_row() {
262 let matrix = MatZ::new(5, 10);
263
264 assert!(matrix.get_entry(5, 1).is_err());
265 assert!(matrix.get_entry(-6, 1).is_err());
266 }
267
268 #[test]
270 fn error_wrong_column() {
271 let matrix = MatZ::new(5, 10);
272
273 assert!(matrix.get_entry(1, 100).is_err());
274 assert!(matrix.get_entry(1, -11).is_err());
275 }
276
277 #[test]
279 fn negative_indexing() {
280 let matrix = MatZ::from_str("[[1, 2, 3],[4, 5, 6],[7, 8, 9]]").unwrap();
281
282 assert_eq!(matrix.get_entry(-1, -1).unwrap(), Z::from(9));
283 assert_eq!(matrix.get_entry(-1, -2).unwrap(), Z::from(8));
284 assert_eq!(matrix.get_entry(-3, -3).unwrap(), Z::from(1));
285 }
286
287 #[test]
289 fn memory_test() {
290 let mut matrix = MatZ::new(5, 10);
291 let value = Z::from(u64::MAX);
292 matrix.set_entry(1, 1, value).unwrap();
293 let entry = matrix.get_entry(1, 1).unwrap();
294 matrix.set_entry(1, 1, Z::from(0)).unwrap();
295
296 assert_eq!(Z::from(u64::MAX), entry);
297 }
298
299 #[test]
303 fn get_entries() {
304 let matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
305
306 let entries = matrix.get_entries();
307 let mut added_entries = Z::default();
308 for row in entries {
309 for entry in row {
310 added_entries += entry;
311 }
312 }
313 }
314
315 #[test]
317 fn get_entries_correct() {
318 let matrix = MatZ::from_str("[[2, 3, 4],[5, 6, 7]]").unwrap();
319
320 let entries = matrix.get_entries();
321
322 assert_eq!(2, entries[0][0]);
323 assert_eq!(3, entries[0][1]);
324 assert_eq!(4, entries[0][2]);
325 assert_eq!(5, entries[1][0]);
326 assert_eq!(6, entries[1][1]);
327 assert_eq!(7, entries[1][2]);
328
329 assert_eq!(2, entries.len());
330 assert_eq!(3, entries[0].len());
331 assert_eq!(3, entries[1].len());
332 }
333
334 #[test]
336 fn get_entries_rowwise() {
337 let matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
338
339 let entries = matrix.get_entries_rowwise();
340 let mut added_entries = Z::default();
341 for entry in entries {
342 added_entries += entry;
343 }
344 }
345
346 #[test]
348 fn get_entries_rowwise_correct() {
349 let matrix = MatZ::from_str("[[2, 3, 4],[5, 6, 7]]").unwrap();
350
351 let entries = matrix.get_entries_rowwise();
352
353 assert_eq!(2, entries[0]);
354 assert_eq!(3, entries[1]);
355 assert_eq!(4, entries[2]);
356 assert_eq!(5, entries[3]);
357 assert_eq!(6, entries[4]);
358 assert_eq!(7, entries[5]);
359 assert_eq!(6, entries.len());
360 }
361
362 #[test]
364 fn get_entries_columnwise() {
365 let matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
366
367 let entries = matrix.get_entries_columnwise();
368 let mut added_entries = Z::default();
369 for entry in entries {
370 added_entries += entry;
371 }
372 }
373
374 #[test]
376 fn get_entries_columnwise_correct() {
377 let matrix = MatZ::from_str("[[2, 3, 4],[5, 6, 7]]").unwrap();
378
379 let entries = matrix.get_entries_columnwise();
380
381 assert_eq!(2, entries[0]);
382 assert_eq!(5, entries[1]);
383 assert_eq!(3, entries[2]);
384 assert_eq!(6, entries[3]);
385 assert_eq!(4, entries[4]);
386 assert_eq!(7, entries[5]);
387 assert_eq!(6, entries.len());
388 }
389}
390
391#[cfg(test)]
392mod test_get_num {
393 use crate::{integer::MatZ, traits::MatrixDimensions};
394
395 #[test]
397 fn num_rows() {
398 let matrix = MatZ::new(5, 10);
399
400 assert_eq!(matrix.get_num_rows(), 5);
401 }
402
403 #[test]
405 fn num_columns() {
406 let matrix = MatZ::new(5, 10);
407
408 assert_eq!(matrix.get_num_columns(), 10);
409 }
410}
411
412#[cfg(test)]
413mod test_get_vec {
414 use crate::{integer::MatZ, traits::MatrixGetSubmatrix};
415 use std::str::FromStr;
416
417 #[test]
419 fn get_row_works() {
420 let matrix =
421 MatZ::from_str(&format!("[[0, 0, 0],[4, {}, {}]]", i64::MAX, i64::MIN)).unwrap();
422 let row_1 = matrix.get_row(0).unwrap();
423 let row_2 = matrix.get_row(1).unwrap();
424
425 let cmp_1 = MatZ::from_str("[[0, 0, 0]]").unwrap();
426 let cmp_2 = MatZ::from_str(&format!("[[4, {}, {}]]", i64::MAX, i64::MIN)).unwrap();
427
428 assert_eq!(cmp_1, row_1);
429 assert_eq!(cmp_2, row_2);
430 }
431
432 #[test]
434 fn get_row_negative_indexing_works() {
435 let matrix =
436 MatZ::from_str(&format!("[[0, 0, 0],[42, {}, {}]]", i64::MAX, i64::MIN)).unwrap();
437 let row_1 = matrix.get_row(-2).unwrap();
438 let row_2 = matrix.get_row(-1).unwrap();
439
440 let cmp_1 = MatZ::from_str("[[0, 0, 0]]").unwrap();
441 let cmp_2 = MatZ::from_str(&format!("[[42, {}, {}]]", i64::MAX, i64::MIN)).unwrap();
442
443 assert_eq!(cmp_1, row_1);
444 assert_eq!(cmp_2, row_2);
445 }
446
447 #[test]
449 fn get_column_works() {
450 let matrix = MatZ::from_str(&format!(
451 "[[1, 0, 3],[{}, 0, 5],[{}, 0, 7]]",
452 i64::MAX,
453 i64::MIN
454 ))
455 .unwrap();
456 let column_1 = matrix.get_column(0).unwrap();
457 let column_2 = matrix.get_column(1).unwrap();
458 let column_3 = matrix.get_column(2).unwrap();
459
460 let cmp_1 = MatZ::from_str(&format!("[[1],[{}],[{}]]", i64::MAX, i64::MIN)).unwrap();
461 let cmp_2 = MatZ::from_str("[[0],[0],[0]]").unwrap();
462 let cmp_3 = MatZ::from_str("[[3],[5],[7]]").unwrap();
463
464 assert_eq!(cmp_1, column_1);
465 assert_eq!(cmp_2, column_2);
466 assert_eq!(cmp_3, column_3);
467 }
468
469 #[test]
471 fn get_column_negative_indexing_works() {
472 let matrix = MatZ::from_str(&format!(
473 "[[42, 0, 42],[{}, 0, 17],[{}, 0, 42]]",
474 i64::MAX,
475 i64::MIN
476 ))
477 .unwrap();
478 let column_1 = matrix.get_column(-3).unwrap();
479 let column_2 = matrix.get_column(-2).unwrap();
480 let column_3 = matrix.get_column(-1).unwrap();
481
482 let cmp_1 = MatZ::from_str(&format!("[[42],[{}],[{}]]", i64::MAX, i64::MIN)).unwrap();
483 let cmp_2 = MatZ::from_str("[[0],[0],[0]]").unwrap();
484 let cmp_3 = MatZ::from_str("[[42],[17],[42]]").unwrap();
485
486 assert_eq!(cmp_1, column_1);
487 assert_eq!(cmp_2, column_2);
488 assert_eq!(cmp_3, column_3);
489 }
490
491 #[test]
493 fn wrong_dim_error() {
494 let matrix = MatZ::from_str(&format!(
495 "[[1, 2, 3],[{}, 4, 5],[{}, 6, 7]]",
496 i64::MAX,
497 i64::MIN
498 ))
499 .unwrap();
500 let row_1 = matrix.get_row(-4);
501 let row_2 = matrix.get_row(4);
502 let column_1 = matrix.get_column(-4);
503 let column_2 = matrix.get_column(4);
504
505 assert!(row_1.is_err());
506 assert!(row_2.is_err());
507 assert!(column_1.is_err());
508 assert!(column_2.is_err());
509 }
510}
511
512#[cfg(test)]
513mod test_get_submatrix {
514 use crate::{
515 integer::{MatZ, Z},
516 traits::{MatrixDimensions, MatrixGetSubmatrix, MatrixSetSubmatrix},
517 };
518 use std::str::FromStr;
519
520 #[test]
522 fn entire_matrix() {
523 let mat = MatZ::identity(5, 5);
524
525 let sub_mat = mat.get_submatrix(0, 4, 0, 4).unwrap();
526
527 assert_eq!(mat, sub_mat);
528 }
529
530 #[test]
532 fn matrix_single_entry() {
533 let mat = MatZ::identity(5, 5);
534
535 let sub_mat = mat.get_submatrix(0, 0, 0, 0).unwrap();
536
537 let cmp_mat = MatZ::identity(1, 1);
538 assert_eq!(cmp_mat, sub_mat);
539 }
540
541 #[test]
543 fn correct_dimensions() {
544 let mat = MatZ::identity(100, 100);
545
546 let sub_mat = mat.get_submatrix(1, 37, 0, 29).unwrap();
547
548 assert_eq!(37, sub_mat.get_num_rows());
549 assert_eq!(30, sub_mat.get_num_columns());
550 }
551
552 #[test]
555 fn large_entries() {
556 let mat = MatZ::from_str(&format!("[[{}, 2, 3],[1, {}, 3]]", u64::MAX, i64::MIN)).unwrap();
557
558 let sub_mat = mat.get_submatrix(0, 1, 0, 1).unwrap();
559
560 let cmp_mat = MatZ::from_str(&format!("[[{}, 2],[1, {}]]", u64::MAX, i64::MIN)).unwrap();
561 assert_eq!(cmp_mat, sub_mat);
562 }
563
564 #[test]
567 fn invalid_coordinates() {
568 let mat = MatZ::identity(10, 10);
569
570 assert!(mat.get_submatrix(0, 0, 0, 10).is_err());
571 assert!(mat.get_submatrix(0, 10, 0, 0).is_err());
572 assert!(mat.get_submatrix(0, 0, -11, 0).is_err());
573 assert!(mat.get_submatrix(-11, 0, 0, 0).is_err());
574 }
575
576 #[test]
578 fn negative_indexing() {
579 let matrix = MatZ::from_str("[[1, 2, 3],[4, 5, 6],[7, 8, 9]]").unwrap();
580
581 assert_eq!(matrix, matrix.get_submatrix(0, -1, 0, -1).unwrap());
582 assert_eq!(matrix, matrix.get_submatrix(-3, -1, -3, -1).unwrap());
583 assert_eq!(
584 matrix.get_row(0).unwrap(),
585 matrix.get_submatrix(0, -3, -3, -1).unwrap()
586 );
587 }
588
589 #[test]
591 #[should_panic]
592 fn no_columns() {
593 let mat = MatZ::identity(10, 10);
594
595 let _ = mat.get_submatrix(0, 0, 6, 5);
596 }
597
598 #[test]
600 #[should_panic]
601 fn no_rows() {
602 let mat = MatZ::identity(10, 10);
603
604 let _ = mat.get_submatrix(5, 4, 0, 0);
605 }
606
607 #[test]
609 fn availability() {
610 let mat = MatZ::identity(10, 10);
611
612 let _ = mat.get_submatrix(0_i8, 0_i8, 0_i8, 0_i8);
613 let _ = mat.get_submatrix(0_i16, 0_i16, 0_i16, 0_i16);
614 let _ = mat.get_submatrix(0_i32, 0_i32, 0_i32, 0_i32);
615 let _ = mat.get_submatrix(0_i64, 0_i64, 0_i64, 0_i64);
616 let _ = mat.get_submatrix(0_u8, 0_u8, 0_u8, 0_u8);
617 let _ = mat.get_submatrix(0_u16, 0_i16, 0_u16, 0_u16);
618 let _ = mat.get_submatrix(0_u32, 0_i32, 0_u32, 0_u32);
619 let _ = mat.get_submatrix(0_u64, 0_i64, 0_u64, 0_u64);
620 let _ = mat.get_submatrix(&Z::ZERO, &Z::ZERO, &Z::ZERO, &Z::ZERO);
621 }
622
623 #[test]
627 fn get_rows_1() {
628 let matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
629
630 let mut added_rows = MatZ::new(1, 3);
631 for row in matrix.get_rows() {
632 added_rows += row;
633 }
634 }
635
636 #[test]
638 fn get_rows_2() {
639 let mut matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
640
641 let mut added_rows = MatZ::new(1, 3);
642 for (i, row) in matrix.get_rows().iter().enumerate() {
643 added_rows += row;
644 matrix.set_row(i, &added_rows, 0).unwrap();
645 }
646 }
647
648 #[test]
650 fn get_columns_1() {
651 let matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
652
653 let mut added_columns = MatZ::new(3, 1);
654 for column in matrix.get_columns() {
655 added_columns += column;
656 }
657 }
658
659 #[test]
661 fn get_columns_2() {
662 let mut matrix = MatZ::sample_uniform(3, 3, 0, 16).unwrap();
663
664 let mut added_columns = MatZ::new(3, 1);
665 for (i, column) in matrix.get_columns().iter().enumerate() {
666 added_columns += column;
667 matrix.set_column(i, &added_columns, 0).unwrap();
668 }
669 }
670}
671
672#[cfg(test)]
673mod test_collect_entries {
674 use super::MatZ;
675 use std::str::FromStr;
676
677 #[test]
679 fn all_entries_collected() {
680 let mat_1 =
681 MatZ::from_str(&format!("[[1, 2],[{}, {}],[3, 4]]", i64::MAX, i64::MIN)).unwrap();
682 let mat_2 = MatZ::from_str("[[-1, 2]]").unwrap();
683
684 let entries_1 = mat_1.collect_entries();
685 let entries_2 = mat_2.collect_entries();
686
687 assert_eq!(entries_1.len(), 6);
688 assert_eq!(entries_1[0].0, 1);
689 assert_eq!(entries_1[1].0, 2);
690 assert!(entries_1[2].0 >= 2_i64.pow(62));
691 assert!(entries_1[3].0 >= 2_i64.pow(62));
692 assert_eq!(entries_1[4].0, 3);
693 assert_eq!(entries_1[5].0, 4);
694
695 assert_eq!(entries_2.len(), 2);
696 assert_eq!(entries_2[0].0, -1);
697 assert_eq!(entries_2[1].0, 2);
698 }
699}