qfall_math/integer/mat_z/
get.rs

1// Copyright © 2023 Marcel Luca Schmidt, Marvin Beckmann
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementations to get information about a [`MatZ`] matrix.
10
11use 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    /// Returns the number of rows of the matrix as a [`i64`].
24    ///
25    /// # Examples
26    /// ```
27    /// use qfall_math::integer::MatZ;
28    /// use qfall_math::traits::*;
29    ///
30    /// let matrix = MatZ::new(5, 6);
31    /// let rows = matrix.get_num_rows();
32    /// ```
33    fn get_num_rows(&self) -> i64 {
34        self.matrix.r
35    }
36
37    /// Returns the number of columns of the matrix as a [`i64`].
38    ///
39    /// # Examples
40    /// ```
41    /// use qfall_math::integer::MatZ;
42    /// use qfall_math::traits::*;
43    ///
44    /// let matrix = MatZ::new(5, 6);
45    /// let columns = matrix.get_num_columns();
46    /// ```
47    fn get_num_columns(&self) -> i64 {
48        self.matrix.c
49    }
50}
51
52impl MatrixGetEntry<Z> for MatZ {
53    /// Outputs the [`Z`] value of a specific matrix entry without checking
54    /// whether it's part of the matrix.
55    ///
56    /// Parameters:
57    /// - `row`: specifies the row in which the entry is located
58    /// - `column`: specifies the column in which the entry is located
59    ///
60    /// Returns the [`Z`] value of the matrix at the position of the given
61    /// row and column.
62    ///
63    /// # Safety
64    /// To use this function safely, make sure that the selected entry is part
65    /// of the matrix. If it is not, memory leaks, unexpected panics, etc. might
66    /// occur.
67    ///
68    /// # Examples
69    /// ```
70    /// use qfall_math::integer::{MatZ, Z};
71    /// use qfall_math::traits::MatrixGetEntry;
72    /// use std::str::FromStr;
73    ///
74    /// let matrix = MatZ::from_str("[[1, 2, 3],[4, 5, 6],[7, 8, 9]]").unwrap();
75    ///
76    /// assert_eq!(unsafe { matrix.get_entry_unchecked(0, 2) }, Z::from(3));
77    /// assert_eq!(unsafe { matrix.get_entry_unchecked(2, 1) }, Z::from(8));
78    /// assert_eq!(unsafe { matrix.get_entry_unchecked(2, 1) }, Z::from(8));
79    /// ```
80    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    /// Returns a deep copy of the submatrix defined by the given parameters
91    /// and does not check the provided dimensions.
92    /// There is also a safe version of this function that checks the input.
93    ///
94    /// Parameters:
95    /// `row_1`: the starting row of the submatrix
96    /// `row_2`: the ending row of the submatrix
97    /// `col_1`: the starting column of the submatrix
98    /// `col_2`: the ending column of the submatrix
99    ///
100    /// Returns the submatrix from `(row_1, col_1)` to `(row_2, col_2)`(exclusively).
101    ///
102    /// # Examples
103    /// ```
104    /// use qfall_math::{integer::MatZ, traits::MatrixGetSubmatrix};
105    /// use std::str::FromStr;
106    ///
107    /// let mat = MatZ::identity(3, 3);
108    ///
109    /// let sub_mat_1 = mat.get_submatrix(0, 2, 1, 1).unwrap();
110    /// let sub_mat_2 = mat.get_submatrix(0, -1, 1, -2).unwrap();
111    /// let sub_mat_3 = unsafe{mat.get_submatrix_unchecked(0, 3, 1, 2)};
112    ///
113    /// let e_2 = MatZ::from_str("[[0],[1],[0]]").unwrap();
114    /// assert_eq!(e_2, sub_mat_1);
115    /// assert_eq!(e_2, sub_mat_2);
116    /// assert_eq!(e_2, sub_mat_3);
117    /// ```
118    ///
119    /// # Safety
120    /// To use this function safely, make sure that the selected submatrix is part
121    /// of the matrix. If it is not, memory leaks, unexpected panics, etc. might
122    /// occur.
123    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        // The memory for the elements of window is shared with self.
132        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            // Deep clone of the content of the window
145            fmpz_mat_init_set(window_copy.as_mut_ptr(), window.as_ptr());
146            // Clears the matrix window and releases any memory that it uses. Note that
147            // the memory to the underlying matrix that window points to is not freed
148            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    /// Efficiently collects all [`fmpz`]s in a [`MatZ`] without cloning them.
158    ///
159    /// Hence, the values on the returned [`Vec`] are intended for short-term use
160    /// as the access to [`fmpz`] values could lead to memory leaks or modified values
161    /// once the [`MatZ`] instance was modified or dropped.
162    ///
163    /// # Examples
164    /// ```compile_fail
165    /// use qfall_math::integer::MatZ;
166    /// use std::str::FromStr;
167    ///
168    /// let mat = MatZ::from_str("[[1, 2],[3, 4],[5, 6]]").unwrap();
169    ///
170    /// let fmpz_entries = mat.collect_entries();
171    /// ```
172    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                // efficiently get entry without cloning the entry itself
179                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    /// Ensure that getting entries works with large numbers.
198    #[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    /// Ensure that getting entries works with large numbers (larger than i64).
210    #[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    /// Ensure that getting entries works with large negative numbers.
222    #[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    /// Ensure that getting entries works with large negative numbers (larger than i64).
234    #[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    /// Ensure that getting entries at (0, 0) works.
248    #[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    /// Ensure that a wrong number of rows yields an Error.
260    #[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    /// Ensure that a wrong number of columns yields an Error.
269    #[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    /// Ensure that negative indices return the correct values.
278    #[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    /// Ensure that the entry is a deep copy and not just a clone of the reference.
288    #[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    // *** Doc-tests of automatically implemented functions by `MatrixGetEntry`
300
301    /// Ensures that the doc-test of [`MatZ::get_entries`] works.
302    #[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    /// Ensures that [`MatZ::get_entries`] returns all entries in the correct order.
316    #[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    /// Ensures that the doc-test of [`MatZ::get_entries_rowwise`] works.
335    #[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    /// Ensures that [`MatZ::get_entries_rowwise`] returns all entries in the correct order.
347    #[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    /// Ensures that the doc-test of [`MatZ::get_entries_columnwise`] works.
363    #[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    /// Ensures that [`MatZ::get_entries_columnwise`] returns all entries in the correct order.
375    #[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    /// Ensure that the getter for number of rows works correctly.
396    #[test]
397    fn num_rows() {
398        let matrix = MatZ::new(5, 10);
399
400        assert_eq!(matrix.get_num_rows(), 5);
401    }
402
403    /// Ensure that the getter for number of columns works correctly.
404    #[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    /// Ensure that getting a row works
418    #[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    /// Ensure that getting a row with a negative index works
433    #[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    /// Ensure that getting a column works
448    #[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    /// Ensure that getting a column with a negative index works
470    #[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    /// Ensure that wrong row and column dimensions yields an error
492    #[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    /// Ensures that getting the entire matrix as a submatrix works.
521    #[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    /// Ensures that a single matrix entry can be retrieved.
531    #[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    /// Ensures that the dimensions of the submatrix are correct.
542    #[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    /// Ensures that a submatrix can be correctly retrieved for a matrix with large
553    /// entries.
554    #[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    /// Ensures that an error is returned if coordinates are addressed that are not
565    /// within the matrix.
566    #[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    /// Ensure that negative indices return the correct submatrix.
577    #[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    /// Ensures that the function panics if no columns of the matrix are addressed.
590    #[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    /// Ensures that the function panics if no rows of the matrix are addressed.
599    #[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    /// Ensure that the submatrix function can be called with several types.
608    #[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    // *** Doc-tests of automatically implemented functions by `MatrixGetSubmatrix`
624
625    /// Ensures that the first doc-test of [`MatZ::get_rows`] works.
626    #[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    /// Ensures that the second doc-test of [`MatZ::get_rows`] works.
637    #[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    /// Ensures that the first doc-test of [`MatZ::get_columns`] works.
649    #[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    /// Ensures that the second doc-test of [`MatZ::get_columns`] works.
660    #[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    /// Ensures that all entries from the matrices are actually collected in the vector.
678    #[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}