easy_ml/matrices/
mod.rs

1/*!
2 * Generic matrix type.
3 *
4 * Matrices are generic over some type `T`. If `T` is [Numeric](super::numeric) then
5 * the matrix can be used in a mathematical way.
6 */
7
8#[cfg(feature = "serde")]
9use serde::Serialize;
10
11mod errors;
12pub mod iterators;
13pub mod operations;
14pub mod slices;
15pub mod views;
16
17pub use errors::ScalarConversionError;
18
19use crate::linear_algebra;
20use crate::matrices::iterators::*;
21use crate::matrices::slices::Slice2D;
22use crate::matrices::views::{
23    IndexRange, MatrixMask, MatrixPart, MatrixQuadrants, MatrixRange, MatrixReverse, MatrixView,
24    Reverse,
25};
26use crate::numeric::extra::{Real, RealRef};
27use crate::numeric::{Numeric, NumericRef};
28
29use std::num::NonZeroUsize;
30
31/**
32 * A general purpose matrix of some type. This type may implement
33 * no traits, in which case the matrix will be rather useless. If the
34 * type implements [`Clone`] most storage and accessor methods are defined and if the type
35 * implements [`Numeric`](super::numeric) then the matrix can be used in
36 * a mathematical way.
37 *
38 * When doing numeric operations with Matrices you should be careful to not
39 * consume a matrix by accidentally using it by value. All the operations are
40 * also defined on references to matrices so you should favor `&x * &y` style
41 * notation for matrices you intend to continue using. There are also convenience
42 * operations defined for a matrix and a scalar.
43 *
44 * # Matrix size invariants
45 *
46 * Matrices must always be at least 1x1. You cannot construct a matrix with no rows or
47 * no columns, and any function that resizes matrices will error if you try to use it
48 * in a way that would construct a 0x1, 1x0, or 0x0 matrix. The maximum size of a matrix
49 * is dependent on the platform's `std::isize::MAX` value. Matrices with dimensions NxM
50 * such that N * M < `std::isize::MAX` should not cause any errors in this library, but
51 * attempting to expand their size further may cause panics and or errors. At the time of
52 * writing it is no longer possible to construct or use matrices where the product of their
53 * number of rows and columns exceed `std::isize::MAX`, but some constructor methods may be used
54 * to attempt this. Concerned readers should note that on a 64 bit computer this maximum
55 * value is 9,223,372,036,854,775,807 so running out of memory is likely to occur first.
56 *
57 * # Matrix layout and iterator performance
58 *
59 * [See iterators submodule for Matrix layout and iterator performance](iterators#matrix-layout-and-iterator-performance)
60 *
61 * # Matrix operations
62 *
63 * [See operations submodule](operations)
64 */
65#[derive(Debug)]
66#[cfg_attr(feature = "serde", derive(Serialize))]
67pub struct Matrix<T> {
68    data: Vec<T>,
69    rows: Row,
70    columns: Column,
71}
72
73/// The maximum row and column lengths are usize, due to the internal storage being backed by Vec
74pub type Row = usize;
75/// The maximum row and column lengths are usize, due to the internal storage being backed by Vec
76pub type Column = usize;
77
78/**
79 * Methods for matrices of any type, including non numerical types such as bool.
80 */
81impl<T> Matrix<T> {
82    /**
83     * Creates a 1x1 matrix from some scalar
84     */
85    pub fn from_scalar(value: T) -> Matrix<T> {
86        Matrix {
87            data: vec![value],
88            rows: 1,
89            columns: 1,
90        }
91    }
92
93    /**
94     * Creates a row vector (1xN) from a list
95     *
96     * # Panics
97     *
98     * Panics if no values are provided. Note: this method erroneously did not validate its inputs
99     * in Easy ML versions up to and including 1.7.0
100     */
101    #[track_caller]
102    pub fn row(values: Vec<T>) -> Matrix<T> {
103        assert!(!values.is_empty(), "No values provided");
104        Matrix {
105            columns: values.len(),
106            data: values,
107            rows: 1,
108        }
109    }
110
111    /**
112     * Creates a column vector (Nx1) from a list
113     *
114     * # Panics
115     *
116     * Panics if no values are provided. Note: this method erroneously did not validate its inputs
117     * in Easy ML versions up to and including 1.7.0
118     */
119    #[track_caller]
120    pub fn column(values: Vec<T>) -> Matrix<T> {
121        assert!(!values.is_empty(), "No values provided");
122        Matrix {
123            rows: values.len(),
124            data: values,
125            columns: 1,
126        }
127    }
128
129    /**
130     * Creates a matrix from a nested array of values, each inner vector
131     * being a row, and hence the outer vector containing all rows in sequence, the
132     * same way as when writing matrices in mathematics.
133     *
134     * Example of a 2 x 3 matrix in both notations:
135     * ```ignore
136     *   [
137     *      1, 2, 4
138     *      8, 9, 3
139     *   ]
140     * ```
141     * ```
142     * use easy_ml::matrices::Matrix;
143     * Matrix::from(vec![
144     *     vec![ 1, 2, 4 ],
145     *     vec![ 8, 9, 3 ]
146     * ]);
147     * ```
148     *
149     * # Panics
150     *
151     * Panics if the input is jagged or rows or column length is 0.
152     */
153    #[track_caller]
154    pub fn from(mut values: Vec<Vec<T>>) -> Matrix<T> {
155        assert!(!values.is_empty(), "No rows defined");
156        // check length of first row is > 1
157        assert!(!values[0].is_empty(), "No column defined");
158        // check length of each row is the same
159        assert!(
160            values.iter().map(|x| x.len()).all(|x| x == values[0].len()),
161            "Inconsistent size"
162        );
163        // flatten the data into a row major layout
164        let rows = values.len();
165        let columns = values[0].len();
166        let mut data = Vec::with_capacity(rows * columns);
167        let mut value_stream = values.drain(..);
168        for _ in 0..rows {
169            let mut value_row_stream = value_stream.next().unwrap();
170            let mut row_of_values = value_row_stream.drain(..);
171            for _ in 0..columns {
172                data.push(row_of_values.next().unwrap());
173            }
174        }
175        Matrix {
176            data,
177            rows,
178            columns,
179        }
180    }
181
182    /**
183     * Creates a matrix with the specified size from a row major vec of data.
184     * The length of the vec must match the size of the matrix or the constructor
185     * will panic.
186     *
187     * Example of a 2 x 3 matrix in both notations:
188     * ```ignore
189     *   [
190     *      1, 2, 4
191     *      8, 9, 3
192     *   ]
193     * ```
194     * ```
195     * use easy_ml::matrices::Matrix;
196     * Matrix::from_flat_row_major((2, 3), vec![
197     *     1, 2, 4,
198     *     8, 9, 3
199     * ]);
200     * ```
201     *
202     * This method is more efficient than [`Matrix::from`](Matrix::from())
203     * but requires specifying the size explicitly and manually keeping track of where rows
204     * start and stop.
205     *
206     * # Panics
207     *
208     * Panics if the length of the vec does not match the size of the matrix, or no values are
209     * provided. Note: this method erroneously did not validate its inputs were not empty in
210     * Easy ML versions up to and including 1.7.0
211     */
212    #[track_caller]
213    pub fn from_flat_row_major(size: (Row, Column), values: Vec<T>) -> Matrix<T> {
214        assert!(
215            size.0 * size.1 == values.len(),
216            "Inconsistent size, attempted to construct a {}x{} matrix but provided with {} elements.",
217            size.0,
218            size.1,
219            values.len()
220        );
221        assert!(!values.is_empty(), "No values provided");
222        Matrix {
223            data: values,
224            rows: size.0,
225            columns: size.1,
226        }
227    }
228
229    /**
230     * Creates a matrix with the specified size initalised from a function.
231     *
232     * ```
233     * use easy_ml::matrices::Matrix;
234     * let matrix = Matrix::from_fn((4, 4), |(r, c)| r * c);
235     * assert_eq!(
236     *     matrix,
237     *     Matrix::from(vec![
238     *         vec![ 0, 0, 0, 0 ],
239     *         vec![ 0, 1, 2, 3 ],
240     *         vec![ 0, 2, 4, 6 ],
241     *         vec![ 0, 3, 6, 9 ],
242     *     ])
243     * );
244     * ```
245     *
246     * # Panics
247     *
248     * Panics if the size has 0 rows or columns.
249     */
250    #[track_caller]
251    pub fn from_fn<F>(size: (Row, Column), mut producer: F) -> Matrix<T>
252    where
253        F: FnMut((Row, Column)) -> T,
254    {
255        use crate::tensors::indexing::ShapeIterator;
256        let length = size.0 * size.1;
257        let mut data = Vec::with_capacity(length);
258        let iterator = ShapeIterator::from([("row", size.0), ("column", size.1)]);
259        for [r, c] in iterator {
260            data.push(producer((r, c)));
261        }
262        Matrix::from_flat_row_major(size, data)
263    }
264
265    #[deprecated(
266        since = "1.1.0",
267        note = "Incorrect use of terminology, a unit matrix is another term for an identity matrix, please use `from_scalar` instead"
268    )]
269    pub fn unit(value: T) -> Matrix<T> {
270        Matrix::from_scalar(value)
271    }
272
273    /**
274     * Returns the dimensionality of this matrix in Row, Column format
275     */
276    pub fn size(&self) -> (Row, Column) {
277        (self.rows, self.columns)
278    }
279
280    /**
281     * Gets the number of rows in this matrix.
282     */
283    pub fn rows(&self) -> Row {
284        self.rows
285    }
286
287    /**
288     * Gets the number of columns in this matrix.
289     */
290    pub fn columns(&self) -> Column {
291        self.columns
292    }
293
294    /**
295     * Matrix data is stored as row major, so each row is stored as
296     * adjacent items going through the different columns. Therefore,
297     * to index this flattened representation we jump down in row sized
298     * blocks to reach the correct row, and then jump further equal to
299     * the column. The confusing thing is that the number of columns
300     * this matrix has is the length of each of the rows in this matrix,
301     * and vice versa.
302     */
303    fn get_index(&self, row: Row, column: Column) -> usize {
304        column + (row * self.columns())
305    }
306
307    /**
308     * The reverse of [get_index], converts from the flattened storage
309     * in memory into the row and column to index at this position.
310     *
311     * Matrix data is stored as row major, so each multiple of the number
312     * of columns starts a new row, and each index modulo the columns
313     * gives the column.
314     */
315    #[allow(dead_code)]
316    fn get_row_column(&self, index: usize) -> (Row, Column) {
317        (index / self.columns(), index % self.columns())
318    }
319
320    /**
321     * Gets a reference to the value at this row and column. Rows and Columns are 0 indexed.
322     *
323     * # Panics
324     *
325     * Panics if the index is out of range.
326     */
327    #[track_caller]
328    pub fn get_reference(&self, row: Row, column: Column) -> &T {
329        assert!(row < self.rows(), "Row out of index");
330        assert!(column < self.columns(), "Column out of index");
331        &self.data[self.get_index(row, column)]
332    }
333
334    /**
335     * Gets a mutable reference to the value at this row and column.
336     * Rows and Columns are 0 indexed.
337     *
338     * # Panics
339     *
340     * Panics if the index is out of range.
341     */
342    #[track_caller]
343    pub fn get_reference_mut(&mut self, row: Row, column: Column) -> &mut T {
344        assert!(row < self.rows(), "Row out of index");
345        assert!(column < self.columns(), "Column out of index");
346        let index = self.get_index(row, column);
347        // borrow for get_index ends
348        &mut self.data[index]
349    }
350
351    /**
352     * Not public API because don't want to name clash with the method on MatrixRef
353     * that calls this.
354     */
355    pub(crate) fn _try_get_reference(&self, row: Row, column: Column) -> Option<&T> {
356        if row < self.rows() && column < self.columns() {
357            Some(&self.data[self.get_index(row, column)])
358        } else {
359            None
360        }
361    }
362
363    /**
364     * Not public API because don't want to name clash with the method on MatrixRef
365     * that calls this.
366     */
367    pub(crate) unsafe fn _get_reference_unchecked(&self, row: Row, column: Column) -> &T {
368        unsafe { self.data.get_unchecked(self.get_index(row, column)) }
369    }
370
371    /**
372     * Sets a new value to this row and column. Rows and Columns are 0 indexed.
373     *
374     * # Panics
375     *
376     * Panics if the index is out of range.
377     */
378    #[track_caller]
379    pub fn set(&mut self, row: Row, column: Column, value: T) {
380        assert!(row < self.rows(), "Row out of index");
381        assert!(column < self.columns(), "Column out of index");
382        let index = self.get_index(row, column);
383        // borrow for get_index ends
384        self.data[index] = value;
385    }
386
387    /**
388     * Not public API because don't want to name clash with the method on MatrixMut
389     * that calls this.
390     */
391    pub(crate) fn _try_get_reference_mut(&mut self, row: Row, column: Column) -> Option<&mut T> {
392        if row < self.rows() && column < self.columns() {
393            let index = self.get_index(row, column);
394            // borrow for get_index ends
395            Some(&mut self.data[index])
396        } else {
397            None
398        }
399    }
400
401    /**
402     * Not public API because don't want to name clash with the method on MatrixMut
403     * that calls this.
404     */
405    pub(crate) unsafe fn _get_reference_unchecked_mut(
406        &mut self,
407        row: Row,
408        column: Column,
409    ) -> &mut T {
410        unsafe {
411            let index = self.get_index(row, column);
412            // borrow for get_index ends
413            self.data.get_unchecked_mut(index)
414        }
415    }
416
417    /**
418     * Removes a row from this Matrix, shifting all other rows to the left.
419     * Rows are 0 indexed.
420     *
421     * # Panics
422     *
423     * This will panic if the row does not exist or the matrix only has one row.
424     */
425    #[track_caller]
426    pub fn remove_row(&mut self, row: Row) {
427        assert!(self.rows() > 1);
428        let mut r = 0;
429        let mut c = 0;
430        // drop the values at the specified row
431        let columns = self.columns();
432        self.data.retain(|_| {
433            let keep = r != row;
434            if c < (columns - 1) {
435                c += 1;
436            } else {
437                r += 1;
438                c = 0;
439            }
440            keep
441        });
442        self.rows -= 1;
443    }
444
445    /**
446     * Removes a column from this Matrix, shifting all other columns to the left.
447     * Columns are 0 indexed.
448     *
449     * # Panics
450     *
451     * This will panic if the column does not exist or the matrix only has one column.
452     */
453    #[track_caller]
454    pub fn remove_column(&mut self, column: Column) {
455        assert!(self.columns() > 1);
456        let mut r = 0;
457        let mut c = 0;
458        // drop the values at the specified column
459        let columns = self.columns();
460        self.data.retain(|_| {
461            let keep = c != column;
462            if c < (columns - 1) {
463                c += 1;
464            } else {
465                r += 1;
466                c = 0;
467            }
468            keep
469        });
470        self.columns -= 1;
471    }
472
473    /**
474     * Returns an iterator over references to a column vector in this matrix.
475     * Columns are 0 indexed.
476     *
477     * # Panics
478     *
479     * Panics if the column does not exist in this matrix.
480     */
481    #[track_caller]
482    pub fn column_reference_iter(&self, column: Column) -> ColumnReferenceIterator<'_, T> {
483        ColumnReferenceIterator::new(self, column)
484    }
485
486    /**
487     * Returns an iterator over references to a row vector in this matrix.
488     * Rows are 0 indexed.
489     *
490     * # Panics
491     *
492     * Panics if the row does not exist in this matrix.
493     */
494    #[track_caller]
495    pub fn row_reference_iter(&self, row: Row) -> RowReferenceIterator<'_, T> {
496        RowReferenceIterator::new(self, row)
497    }
498
499    /**
500     * Returns an iterator over mutable references to a column vector in this matrix.
501     * Columns are 0 indexed.
502     *
503     * # Panics
504     *
505     * Panics if the column does not exist in this matrix.
506     */
507    #[track_caller]
508    pub fn column_reference_mut_iter(
509        &mut self,
510        column: Column,
511    ) -> ColumnReferenceMutIterator<'_, T> {
512        ColumnReferenceMutIterator::new(self, column)
513    }
514
515    /**
516     * Returns an iterator over mutable references to a row vector in this matrix.
517     * Rows are 0 indexed.
518     *
519     * # Panics
520     *
521     * Panics if the row does not exist in this matrix.
522     */
523    #[track_caller]
524    pub fn row_reference_mut_iter(&mut self, row: Row) -> RowReferenceMutIterator<'_, T> {
525        RowReferenceMutIterator::new(self, row)
526    }
527
528    /**
529     * Returns a column major iterator over references to all values in this matrix,
530     * proceeding through each column in order.
531     */
532    pub fn column_major_reference_iter(&self) -> ColumnMajorReferenceIterator<'_, T> {
533        ColumnMajorReferenceIterator::new(self)
534    }
535
536    /**
537     * Returns a row major iterator over references to all values in this matrix,
538     * proceeding through each row in order.
539     */
540    pub fn row_major_reference_iter(&self) -> RowMajorReferenceIterator<'_, T> {
541        RowMajorReferenceIterator::new(self)
542    }
543
544    // Non public row major reference iterator since we don't want to expose our implementation
545    // details to public API since then we could never change them.
546    pub(crate) fn direct_row_major_reference_iter(&self) -> std::slice::Iter<'_, T> {
547        self.data.iter()
548    }
549
550    // Non public row major reference iterator since we don't want to expose our implementation
551    // details to public API since then we could never change them.
552    pub(crate) fn direct_row_major_reference_iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
553        self.data.iter_mut()
554    }
555
556    /**
557     * Returns a column major iterator over mutable references to all values in this matrix,
558     * proceeding through each column in order.
559     */
560    pub fn column_major_reference_mut_iter(&mut self) -> ColumnMajorReferenceMutIterator<'_, T> {
561        ColumnMajorReferenceMutIterator::new(self)
562    }
563
564    /**
565     * Returns a row major iterator over mutable references to all values in this matrix,
566     * proceeding through each row in order.
567     */
568    pub fn row_major_reference_mut_iter(&mut self) -> RowMajorReferenceMutIterator<'_, T> {
569        RowMajorReferenceMutIterator::new(self)
570    }
571
572    /**
573     * Creates a column major iterator over all values in this matrix,
574     * proceeding through each column in order.
575     */
576    pub fn column_major_owned_iter(self) -> ColumnMajorOwnedIterator<T>
577    where
578        T: Default,
579    {
580        ColumnMajorOwnedIterator::new(self)
581    }
582
583    /**
584     * Creates a row major iterator over all values in this matrix,
585     * proceeding through each row in order.
586     */
587    pub fn row_major_owned_iter(self) -> RowMajorOwnedIterator<T>
588    where
589        T: Default,
590    {
591        RowMajorOwnedIterator::new(self)
592    }
593
594    /**
595     * Returns an iterator over references to the main diagonal in this matrix.
596     */
597    pub fn diagonal_reference_iter(&self) -> DiagonalReferenceIterator<'_, T> {
598        DiagonalReferenceIterator::new(self)
599    }
600
601    /**
602     * Returns an iterator over mutable references to the main diagonal in this matrix.
603     */
604    pub fn diagonal_reference_mut_iter(&mut self) -> DiagonalReferenceMutIterator<'_, T> {
605        DiagonalReferenceMutIterator::new(self)
606    }
607
608    /**
609     * Shrinks this matrix down from its current MxN size down to
610     * some new size OxP where O and P are determined by the kind of
611     * slice given and 1 <= O <= M and 1 <= P <= N.
612     *
613     * Only rows and columns specified by the slice will be retained, so for
614     * instance if the Slice is constructed by
615     * `Slice2D::new().rows(Slice::Range(0..2)).columns(Slice::Range(0..3))` then the
616     * modified matrix will be no bigger than 2x3 and contain up to the first two
617     * rows and first three columns that it previously had.
618     *
619     * See [Slice](slices::Slice) for constructing slices.
620     *
621     * # Panics
622     *
623     * This function will panic if the slice would delete all rows or all columns
624     * from this matrix, ie the resulting matrix must be at least 1x1.
625     */
626    #[track_caller]
627    pub fn retain_mut(&mut self, slice: Slice2D) {
628        let mut r = 0;
629        let mut c = 0;
630        // drop the values rejected by the slice
631        let columns = self.columns();
632        self.data.retain(|_| {
633            let keep = slice.accepts(r, c);
634            if c < (columns - 1) {
635                c += 1;
636            } else {
637                r += 1;
638                c = 0;
639            }
640            keep
641        });
642        // work out the resulting size of this matrix by using the non
643        // public fields of the Slice2D to handle each row and column
644        // seperately.
645        let remaining_rows = {
646            let mut accepted = 0;
647            for i in 0..self.rows() {
648                if slice.rows.accepts(i) {
649                    accepted += 1;
650                }
651            }
652            accepted
653        };
654        let remaining_columns = {
655            let mut accepted = 0;
656            for i in 0..self.columns() {
657                if slice.columns.accepts(i) {
658                    accepted += 1;
659                }
660            }
661            accepted
662        };
663        assert!(
664            remaining_rows > 0,
665            "Provided slice must leave at least 1 row in the retained matrix"
666        );
667        assert!(
668            remaining_columns > 0,
669            "Provided slice must leave at least 1 column in the retained matrix"
670        );
671        assert!(
672            !self.data.is_empty(),
673            "Provided slice must leave at least 1 row and 1 column in the retained matrix"
674        );
675        self.rows = remaining_rows;
676        self.columns = remaining_columns
677        // By construction jagged slices should be impossible, if this
678        // invariant later changes by accident it would be possible to break the
679        // rectangle shape invariant on a matrix object
680        // As Slice2D should prevent the construction of jagged slices no
681        // check is here to detect if all rows are still the same length
682    }
683
684    /**
685     * Consumes a 1x1 matrix and converts it into a scalar without copying the data.
686     *
687     * # Example
688     *
689     * ```
690     * use easy_ml::matrices::Matrix;
691     * # fn main() -> Result<(), Box<dyn std::error::Error>> {
692     * let x = Matrix::column(vec![ 1.0, 2.0, 3.0 ]);
693     * let sum_of_squares: f64 = (x.transpose() * x).try_into_scalar()?;
694     * # Ok(())
695     * # }
696     * ```
697     */
698    pub fn try_into_scalar(self) -> Result<T, ScalarConversionError> {
699        if self.size() == (1, 1) {
700            Ok(self.data.into_iter().next().unwrap())
701        } else {
702            Err(ScalarConversionError {})
703        }
704    }
705
706    /**
707     * Partition a matrix into an arbitary number of non overlapping parts.
708     *
709     * **This function is much like a hammer you should be careful to not overuse. If you don't need
710     * to mutate the parts of the matrix data individually it will be much easier and less error
711     * prone to create immutable views into the matrix using [MatrixRange] instead.**
712     *
713     * Parts are returned in row major order, forming a grid of slices into the Matrix data that
714     * can be mutated independently.
715     *
716     * # Panics
717     *
718     * Panics if any row or column index is greater than the number of rows or columns in the
719     * matrix. Each list of row partitions and column partitions must also be in ascending order.
720     *
721     * # Further Info
722     *
723     * The partitions form the boundries between each slice of matrix data. Hence, for each
724     * dimension, each partition may range between 0 and the length of the dimension inclusive.
725     *
726     * For one dimension of length 5, you can supply 0 up to 6 partitions,
727     * `[0,1,2,3,4,5]` would split that dimension into 7, 0 to 0, 0 to 1, 1 to 2,
728     * 2 to 3, 3 to 4, 4 to 5 and 5 to 5. 0 to 0 and 5 to 5 would of course be empty and the
729     * 5 parts in between would each be of length 1 along that dimension.
730     * `[2,4]` would instead split that dimension into three parts of 0 to 2, 2 to 4, and 4 to 5.
731     * `[]` would not split that dimension at all, and give a single part of 0 to 5.
732     *
733     * `partition` does this along both dimensions, and returns the parts in row major order, so
734     * you will receive a list of R+1 * C+1 length where R is the length of the row partitions
735     * provided and C is the length of the column partitions provided. If you just want to split
736     * a matrix into a 2x2 grid see [`partition_quadrants`](Matrix::partition_quadrants) which
737     * provides a dedicated API with more ergonomics for extracting the parts.
738     */
739    #[track_caller]
740    pub fn partition(
741        &mut self,
742        row_partitions: &[Row],
743        column_partitions: &[Column],
744    ) -> Vec<MatrixView<T, MatrixPart<'_, T>>> {
745        let rows = self.rows();
746        let columns = self.columns();
747        fn check_axis(partitions: &[usize], length: usize) {
748            let mut previous: Option<usize> = None;
749            for &index in partitions {
750                assert!(index <= length);
751                previous = match previous {
752                    None => Some(index),
753                    Some(i) => {
754                        assert!(index > i, "{:?} must be ascending", partitions);
755                        Some(i)
756                    }
757                }
758            }
759        }
760        check_axis(row_partitions, rows);
761        check_axis(column_partitions, columns);
762
763        // There will be one more slice than partitions, since partitions are the boundries
764        // between slices.
765        let row_slices = row_partitions.len() + 1;
766        let column_slices = column_partitions.len() + 1;
767        let total_slices = row_slices * column_slices;
768        let mut slices: Vec<Vec<&mut [T]>> = Vec::with_capacity(total_slices);
769        let (_, mut data) = self.data.split_at_mut(0);
770
771        let mut index = 0;
772        for r in 0..row_slices {
773            let row_index = row_partitions.get(r).cloned().unwrap_or(rows);
774            // Determine how many rows of our matrix we need for the next set of row slices
775            let rows_included = row_index - index;
776            for _ in 0..column_slices {
777                slices.push(Vec::with_capacity(rows_included));
778            }
779            index = row_index;
780
781            for _ in 0..rows_included {
782                // Partition the next row of our matrix along the columns
783                let mut index = 0;
784                for c in 0..column_slices {
785                    let column_index = column_partitions.get(c).cloned().unwrap_or(columns);
786                    let columns_included = column_index - index;
787                    index = column_index;
788                    // Split off as many elements as included in this column slice
789                    let (slice, rest) = data.split_at_mut(columns_included);
790                    // Insert the slice into the slices, we'll push `rows_included` times into
791                    // each slice Vec.
792                    slices[(r * column_slices) + c].push(slice);
793                    data = rest;
794                }
795            }
796        }
797        // rest is now empty, so we can ignore it.
798
799        slices
800            .into_iter()
801            .map(|slices| {
802                let rows = slices.len();
803                let columns = slices.first().map(|columns| columns.len()).unwrap_or(0);
804                if columns == 0 {
805                    // We may have allocated N rows but if each column in that row has no size
806                    // our actual size is 0x0
807                    MatrixView::from(MatrixPart::new(slices, 0, 0))
808                } else {
809                    MatrixView::from(MatrixPart::new(slices, rows, columns))
810                }
811            })
812            .collect()
813    }
814
815    /**
816     * Partition a matrix into 4 non overlapping quadrants. Top left starts at 0,0 until
817     * exclusive of row and column, bottom right starts at row and column to the end of the matrix.
818     *
819     * # Panics
820     *
821     * Panics if the row or column are greater than the number of rows or columns in the matrix.
822     *
823     * # Examples
824     *
825     * ```
826     * use easy_ml::matrices::Matrix;
827     * let mut matrix = Matrix::from(vec![
828     *     vec![ 0, 1, 2 ],
829     *     vec![ 3, 4, 5 ],
830     *     vec![ 6, 7, 8 ]
831     * ]);
832     * // Split the matrix at the second row and first column giving 2x1, 2x2, 1x1 and 2x1
833     * // quadrants.
834     * // 0 | 1 2
835     * // 3 | 4 5
836     * // -------
837     * // 6 | 7 8
838     * let mut parts = matrix.partition_quadrants(2, 1);
839     * assert_eq!(parts.top_left, Matrix::column(vec![ 0, 3 ]));
840     * assert_eq!(parts.top_right, Matrix::from(vec![vec![ 1, 2 ], vec![ 4, 5 ]]));
841     * assert_eq!(parts.bottom_left, Matrix::column(vec![ 6 ]));
842     * assert_eq!(parts.bottom_right, Matrix::row(vec![ 7, 8 ]));
843     * // Modify the matrix data independently without worrying about the borrow checker
844     * parts.top_right.map_mut(|x| x + 10);
845     * parts.bottom_left.map_mut(|x| x - 10);
846     * // Drop MatrixQuadrants so we can use the matrix directly again
847     * std::mem::drop(parts);
848     * assert_eq!(matrix, Matrix::from(vec![
849     *     vec![ 0, 11, 12 ],
850     *     vec![ 3, 14, 15 ],
851     *     vec![ -4, 7, 8 ]
852     * ]));
853     * ```
854     */
855    #[track_caller]
856    #[allow(clippy::needless_lifetimes)] // false positive?
857    pub fn partition_quadrants<'a>(
858        &'a mut self,
859        row: Row,
860        column: Column,
861    ) -> MatrixQuadrants<'a, T> {
862        let mut parts = self.partition(&[row], &[column]).into_iter();
863        // We know there will be exactly 4 parts returned by the partition since we provided
864        // 1 row and 1 column to partition ourself into 4 with.
865        MatrixQuadrants {
866            top_left: parts.next().unwrap(),
867            top_right: parts.next().unwrap(),
868            bottom_left: parts.next().unwrap(),
869            bottom_right: parts.next().unwrap(),
870        }
871    }
872
873    /**
874     * Returns a MatrixView giving a view of only the data within the row and column
875     * [IndexRange]s.
876     *
877     * This is a shorthand for constructing the MatrixView from this Matrix.
878     *
879     * ```
880     * use easy_ml::matrices::Matrix;
881     * use easy_ml::matrices::views::{MatrixView, MatrixRange, IndexRange};
882     * let ab = Matrix::from(vec![
883     *     vec![ 0, 1, 2, 0 ],
884     *     vec![ 3, 4, 5, 1 ]
885     * ]);
886     * let shorter = ab.range(0..2, 1..3);
887     * assert_eq!(
888     *     shorter,
889     *     Matrix::from(vec![
890     *        vec![ 1, 2 ],
891     *        vec![ 4, 5 ]
892     *     ])
893     * );
894     * ```
895     */
896    pub fn range<R>(&self, rows: R, columns: R) -> MatrixView<T, MatrixRange<T, &Matrix<T>>>
897    where
898        R: Into<IndexRange>,
899    {
900        MatrixView::from(MatrixRange::from(self, rows, columns))
901    }
902
903    /**
904     * Returns a MatrixView giving a view of only the data within the row and column
905     * [IndexRange]s. The MatrixRange mutably borrows this Matrix, and can
906     * therefore mutate it.
907     *
908     * This is a shorthand for constructing the MatrixView from this Matrix.
909     */
910    pub fn range_mut<R>(
911        &mut self,
912        rows: R,
913        columns: R,
914    ) -> MatrixView<T, MatrixRange<T, &mut Matrix<T>>>
915    where
916        R: Into<IndexRange>,
917    {
918        MatrixView::from(MatrixRange::from(self, rows, columns))
919    }
920
921    /**
922     * Returns a MatrixView giving a view of only the data within the row and column
923     * [IndexRange]s. The MatrixRange takes ownership of this Matrix, and can
924     * therefore mutate it.
925     *
926     * This is a shorthand for constructing the MatrixView from this Matrix.
927     */
928    pub fn range_owned<R>(self, rows: R, columns: R) -> MatrixView<T, MatrixRange<T, Matrix<T>>>
929    where
930        R: Into<IndexRange>,
931    {
932        MatrixView::from(MatrixRange::from(self, rows, columns))
933    }
934
935    /**
936     * Returns a MatrixView giving a view of only the data outside the row and column
937     * [IndexRange]s.
938     *
939     * This is a shorthand for constructing the MatrixView from this Matrix.
940     *
941     * ```
942     * use easy_ml::matrices::Matrix;
943     * use easy_ml::matrices::views::{MatrixView, MatrixMask, IndexRange};
944     * let ab = Matrix::from(vec![
945     *     vec![ 0, 1, 2, 0 ],
946     *     vec![ 3, 4, 5, 1 ]
947     * ]);
948     * let shorter = ab.mask(0..1, 1..3);
949     * assert_eq!(
950     *     shorter,
951     *     Matrix::from(vec![
952     *        vec![ 3, 1 ]
953     *     ])
954     * );
955     * ```
956     */
957    pub fn mask<R>(&self, rows: R, columns: R) -> MatrixView<T, MatrixMask<T, &Matrix<T>>>
958    where
959        R: Into<IndexRange>,
960    {
961        MatrixView::from(MatrixMask::from(self, rows, columns))
962    }
963
964    /**
965     * Returns a MatrixView giving a view of only the data outside the row and column
966     * [IndexRange]s. The MatrixMask mutably borrows this Matrix, and can
967     * therefore mutate it.
968     *
969     * This is a shorthand for constructing the MatrixView from this Matrix.
970     */
971    pub fn mask_mut<R>(
972        &mut self,
973        rows: R,
974        columns: R,
975    ) -> MatrixView<T, MatrixMask<T, &mut Matrix<T>>>
976    where
977        R: Into<IndexRange>,
978    {
979        MatrixView::from(MatrixMask::from(self, rows, columns))
980    }
981
982    /**
983     * Returns a MatrixView giving a view of only the data outside the row and column
984     * [IndexRange]s. The MatrixMask takes ownership of this Matrix, and can
985     * therefore mutate it.
986     *
987     * This is a shorthand for constructing the MatrixView from this Matrix.
988     */
989    pub fn mask_owned<R>(self, rows: R, columns: R) -> MatrixView<T, MatrixMask<T, Matrix<T>>>
990    where
991        R: Into<IndexRange>,
992    {
993        MatrixView::from(MatrixMask::from(self, rows, columns))
994    }
995
996    /**
997     * Returns a MatrixView giving a view of only the data within the provided
998     * number of elements to retain at the start and end of the rows in the
999     * matrix.
1000     *
1001     * This is a shorthand for constructing the MatrixView from this Matrix.
1002     *
1003     * ```
1004     * use easy_ml::matrices::Matrix;
1005     * use easy_ml::matrices::views::{MatrixView, MatrixMask};
1006     * let ab = Matrix::from(vec![
1007     *     vec![ 0, 1, 2, 0 ],
1008     *     vec![ 3, 4, 5, 1 ],
1009     *     vec![ 9, 2, 0, 2 ]
1010     * ]);
1011     * let shorter = ab.start_and_end_of_rows(1);
1012     * assert_eq!(
1013     *     shorter,
1014     *     Matrix::from(vec![
1015     *        vec![ 0, 1, 2, 0 ],
1016     *        vec![ 9, 2, 0, 2 ]
1017     *     ])
1018     * );
1019     * ```
1020     *
1021     * # Panics
1022     *
1023     * - If the number of elements to retain at the start and end are 0
1024     */
1025    #[track_caller]
1026    pub fn start_and_end_of_rows(&self, retain: usize) -> MatrixView<T, MatrixMask<T, &Matrix<T>>> {
1027        match NonZeroUsize::new(retain) {
1028            None => panic!(
1029                "Number of rows to retain at start and end of matrix must be at least 1, 0 rows retained would remove all elements"
1030            ),
1031            Some(retain) => MatrixView::from(MatrixMask::start_and_end_of_rows(self, Some(retain))),
1032        }
1033    }
1034
1035    /**
1036     * Returns a MatrixView giving a view of only the data within the provided
1037     * number of elements to retain at the start and end of the rows in the
1038     * matrix. The MatrixMask mutably borrows this Matrix, and can
1039     * therefore mutate it.
1040     *
1041     * This is a shorthand for constructing the MatrixView from this Matrix.
1042     *
1043     * # Panics
1044     *
1045     * - If the number of elements to retain at the start and end are 0
1046     */
1047    #[track_caller]
1048    pub fn start_and_end_of_rows_mut(
1049        &mut self,
1050        retain: usize,
1051    ) -> MatrixView<T, MatrixMask<T, &mut Matrix<T>>> {
1052        match NonZeroUsize::new(retain) {
1053            None => panic!(
1054                "Number of rows to retain at start and end of matrix must be at least 1, 0 rows retained would remove all elements"
1055            ),
1056            Some(retain) => MatrixView::from(MatrixMask::start_and_end_of_rows(self, Some(retain))),
1057        }
1058    }
1059
1060    /**
1061     * Returns a MatrixView giving a view of only the data within the provided
1062     * number of elements to retain at the start and end of the rows in the
1063     * matrix. The MatrixMask takes ownership of this Matrix, and can
1064     * therefore mutate it.
1065     *
1066     * This is a shorthand for constructing the MatrixView from this Matrix.
1067     *
1068     * # Panics
1069     *
1070     * - If the number of elements to retain at the start and end are 0
1071     */
1072    #[track_caller]
1073    pub fn start_and_end_of_rows_owned(
1074        self,
1075        retain: usize,
1076    ) -> MatrixView<T, MatrixMask<T, Matrix<T>>> {
1077        match NonZeroUsize::new(retain) {
1078            None => panic!(
1079                "Number of rows to retain at start and end of matrix must be at least 1, 0 rows retained would remove all elements"
1080            ),
1081            Some(retain) => MatrixView::from(MatrixMask::start_and_end_of_rows(self, Some(retain))),
1082        }
1083    }
1084
1085    /**
1086     * Returns a MatrixView giving a view of only the data within the provided
1087     * number of elements to retain at the start and end of the columns in the
1088     * matrix.
1089     *
1090     * This is a shorthand for constructing the MatrixView from this Matrix.
1091     *
1092     * ```
1093     * use easy_ml::matrices::Matrix;
1094     * use easy_ml::matrices::views::{MatrixView, MatrixMask};
1095     * let ab = Matrix::from(vec![
1096     *     vec![ 0, 1, 2, 0 ],
1097     *     vec![ 3, 4, 5, 1 ],
1098     *     vec![ 9, 2, 0, 2 ]
1099     * ]);
1100     * let shorter = ab.start_and_end_of_columns(1);
1101     * assert_eq!(
1102     *     shorter,
1103     *     Matrix::from(vec![
1104     *        vec![ 0, 0 ],
1105     *        vec![ 3, 1 ],
1106     *        vec![ 9, 2 ]
1107     *     ])
1108     * );
1109     * ```
1110     *
1111     * # Panics
1112     *
1113     * - If the number of elements to retain at the start and end are 0
1114     */
1115    #[track_caller]
1116    pub fn start_and_end_of_columns(
1117        &self,
1118        retain: usize,
1119    ) -> MatrixView<T, MatrixMask<T, &Matrix<T>>> {
1120        match NonZeroUsize::new(retain) {
1121            None => panic!(
1122                "Number of columns to retain at start and end of matrix must be at least 1, 0 columns retained would remove all elements"
1123            ),
1124            Some(retain) => {
1125                MatrixView::from(MatrixMask::start_and_end_of_columns(self, Some(retain)))
1126            }
1127        }
1128    }
1129
1130    /**
1131     * Returns a MatrixView giving a view of only the data within the provided
1132     * number of elements to retain at the start and end of the columns in the
1133     * matrix. The MatrixMask mutably borrows this Matrix, and can
1134     * therefore mutate it.
1135     *
1136     * This is a shorthand for constructing the MatrixView from this Matrix.
1137     *
1138     * # Panics
1139     *
1140     * - If the number of elements to retain at the start and end are 0
1141     */
1142    #[track_caller]
1143    pub fn start_and_end_of_columns_mut(
1144        &mut self,
1145        retain: usize,
1146    ) -> MatrixView<T, MatrixMask<T, &mut Matrix<T>>> {
1147        match NonZeroUsize::new(retain) {
1148            None => panic!(
1149                "Number of columns to retain at start and end of matrix must be at least 1, 0 columns retained would remove all elements"
1150            ),
1151            Some(retain) => {
1152                MatrixView::from(MatrixMask::start_and_end_of_columns(self, Some(retain)))
1153            }
1154        }
1155    }
1156
1157    /**
1158     * Returns a MatrixView giving a view of only the data within the provided
1159     * number of elements to retain at the start and end of the columns in the
1160     * matrix. The MatrixMask takes ownership of this Matrix, and can
1161     * therefore mutate it.
1162     *
1163     * This is a shorthand for constructing the MatrixView from this Matrix.
1164     *
1165     * # Panics
1166     *
1167     * - If the number of elements to retain at the start and end are 0
1168     */
1169    #[track_caller]
1170    pub fn start_and_end_of_columns_owned(
1171        self,
1172        retain: usize,
1173    ) -> MatrixView<T, MatrixMask<T, Matrix<T>>> {
1174        match NonZeroUsize::new(retain) {
1175            None => panic!(
1176                "Number of columns to retain at start and end of matrix must be at least 1, 0 columns retained would remove all elements"
1177            ),
1178            Some(retain) => {
1179                MatrixView::from(MatrixMask::start_and_end_of_columns(self, Some(retain)))
1180            }
1181        }
1182    }
1183
1184    /**
1185     * Returns a MatrixView with the rows and columns specified reversed in iteration
1186     * order. The data of this matrix and the dimension lengths remain unchanged.
1187     *
1188     * This is a shorthand for constructing the MatrixView from this Matrix.
1189     *
1190     * ```
1191     * use easy_ml::matrices::Matrix;
1192     * use easy_ml::matrices::views::{MatrixView, MatrixReverse, Reverse};
1193     * let ab = Matrix::from(vec![
1194     *     vec![ 0, 1, 2 ],
1195     *     vec![ 3, 4, 5 ]
1196     * ]);
1197     * let reversed = ab.reverse(Reverse { rows: true, ..Default::default() });
1198     * let also_reversed = MatrixView::from(
1199     *     MatrixReverse::from(&ab, Reverse { rows: true, columns: false })
1200     * );
1201     * assert_eq!(reversed, also_reversed);
1202     * assert_eq!(
1203     *     reversed,
1204     *     Matrix::from(vec![
1205     *         vec![ 3, 4, 5 ],
1206     *         vec![ 0, 1, 2 ]
1207     *     ])
1208     * );
1209     * ```
1210     */
1211    pub fn reverse(&self, reverse: Reverse) -> MatrixView<T, MatrixReverse<T, &Matrix<T>>> {
1212        MatrixView::from(MatrixReverse::from(self, reverse))
1213    }
1214
1215    /**
1216     * Returns a MatrixView with the rows and columns specified reversed in iteration
1217     * order. The data of this matrix and the dimension lengths remain unchanged. The MatrixReverse
1218     * mutably borrows this Matrix, and can therefore mutate it
1219     *
1220     * This is a shorthand for constructing the MatrixView from this Matrix.
1221     */
1222    pub fn reverse_mut(
1223        &mut self,
1224        reverse: Reverse,
1225    ) -> MatrixView<T, MatrixReverse<T, &mut Matrix<T>>> {
1226        MatrixView::from(MatrixReverse::from(self, reverse))
1227    }
1228
1229    /**
1230     * Returns a MatrixView with the rows and columns specified reversed in iteration
1231     * order. The data of this matrix and the dimension lengths remain unchanged. The MatrixReverse
1232     * takes ownership of this Matrix, and can therefore mutate it
1233     *
1234     * This is a shorthand for constructing the MatrixView from this Matrix.
1235     */
1236    pub fn reverse_owned(self, reverse: Reverse) -> MatrixView<T, MatrixReverse<T, Matrix<T>>> {
1237        MatrixView::from(MatrixReverse::from(self, reverse))
1238    }
1239
1240    /**
1241     * Converts this Matrix into a 2 dimensional Tensor with the provided dimension names.
1242     *
1243     * This is a wrapper around the `TryFrom<(Matrix<T>, [Dimension; 2])>` implementation.
1244     *
1245     * The Tensor will have the data in the same order, a shape with lengths of `self.rows()` then
1246     * `self.columns()` and the provided dimension names respectively.
1247     *
1248     * Result::Err is returned if the `rows` and `columns` dimension names are the same.
1249     */
1250    pub fn into_tensor(
1251        self,
1252        rows: crate::tensors::Dimension,
1253        columns: crate::tensors::Dimension,
1254    ) -> Result<crate::tensors::Tensor<T, 2>, crate::tensors::InvalidShapeError<2>> {
1255        (self, [rows, columns]).try_into()
1256    }
1257}
1258
1259/**
1260 * Methods for matrices with types that can be copied, but still not neccessarily numerical.
1261 */
1262impl<T: Clone> Matrix<T> {
1263    /**
1264     * Computes and returns the transpose of this matrix
1265     *
1266     * ```
1267     * use easy_ml::matrices::Matrix;
1268     * let x = Matrix::from(vec![
1269     *    vec![ 1, 2 ],
1270     *    vec![ 3, 4 ]]);
1271     * let y = Matrix::from(vec![
1272     *    vec![ 1, 3 ],
1273     *    vec![ 2, 4 ]]);
1274     * assert_eq!(x.transpose(), y);
1275     * ```
1276     */
1277    pub fn transpose(&self) -> Matrix<T> {
1278        Matrix::from_fn((self.columns(), self.rows()), |(column, row)| {
1279            self.get(row, column)
1280        })
1281    }
1282
1283    /**
1284     * Transposes the matrix in place (if it is square).
1285     *
1286     * ```
1287     * use easy_ml::matrices::Matrix;
1288     * let mut x = Matrix::from(vec![
1289     *    vec![ 1, 2 ],
1290     *    vec![ 3, 4 ]]);
1291     * x.transpose_mut();
1292     * let y = Matrix::from(vec![
1293     *    vec![ 1, 3 ],
1294     *    vec![ 2, 4 ]]);
1295     * assert_eq!(x, y);
1296     * ```
1297     *
1298     * Note: None square matrices were erroneously not supported in previous versions (<=1.8.0) and
1299     * could be incorrectly mutated. This method will now correctly transpose non square matrices
1300     * by not attempting to transpose them in place.
1301     */
1302    pub fn transpose_mut(&mut self) {
1303        if self.rows() != self.columns() {
1304            let transposed = self.transpose();
1305            self.data = transposed.data;
1306            self.rows = transposed.rows;
1307            self.columns = transposed.columns;
1308        } else {
1309            for i in 0..self.rows() {
1310                for j in 0..self.columns() {
1311                    if i > j {
1312                        continue;
1313                    }
1314                    let temp = self.get(i, j);
1315                    self.set(i, j, self.get(j, i));
1316                    self.set(j, i, temp);
1317                }
1318            }
1319        }
1320    }
1321
1322    /**
1323     * Returns an iterator over a column vector in this matrix. Columns are 0 indexed.
1324     *
1325     * If you have a matrix such as:
1326     * ```ignore
1327     * [
1328     *    1, 2, 3
1329     *    4, 5, 6
1330     *    7, 8, 9
1331     * ]
1332     * ```
1333     * then a column of 0, 1, and 2 will yield [1, 4, 7], [2, 5, 8] and [3, 6, 9]
1334     * respectively. If you do not need to copy the elements use
1335     * [`column_reference_iter`](Matrix::column_reference_iter) instead.
1336     *
1337     * # Panics
1338     *
1339     * Panics if the column does not exist in this matrix.
1340     */
1341    #[track_caller]
1342    pub fn column_iter(&self, column: Column) -> ColumnIterator<'_, T> {
1343        ColumnIterator::new(self, column)
1344    }
1345
1346    /**
1347     * Returns an iterator over a row vector in this matrix. Rows are 0 indexed.
1348     *
1349     * If you have a matrix such as:
1350     * ```ignore
1351     * [
1352     *    1, 2, 3
1353     *    4, 5, 6
1354     *    7, 8, 9
1355     * ]
1356     * ```
1357     * then a row of 0, 1, and 2 will yield [1, 2, 3], [4, 5, 6] and [7, 8, 9]
1358     * respectively. If you do not need to copy the elements use
1359     * [`row_reference_iter`](Matrix::row_reference_iter) instead.
1360     *
1361     * # Panics
1362     *
1363     * Panics if the row does not exist in this matrix.
1364     */
1365    #[track_caller]
1366    pub fn row_iter(&self, row: Row) -> RowIterator<'_, T> {
1367        RowIterator::new(self, row)
1368    }
1369
1370    /**
1371     * Returns a column major iterator over all values in this matrix, proceeding through each
1372     * column in order.
1373     *
1374     * If you have a matrix such as:
1375     * ```ignore
1376     * [
1377     *    1, 2
1378     *    3, 4
1379     * ]
1380     * ```
1381     * then the iterator will yield [1, 3, 2, 4]. If you do not need to copy the
1382     * elements use [`column_major_reference_iter`](Matrix::column_major_reference_iter) instead.
1383     */
1384    pub fn column_major_iter(&self) -> ColumnMajorIterator<'_, T> {
1385        ColumnMajorIterator::new(self)
1386    }
1387
1388    /**
1389     * Returns a row major iterator over all values in this matrix, proceeding through each
1390     * row in order.
1391     *
1392     * If you have a matrix such as:
1393     * ```ignore
1394     * [
1395     *    1, 2
1396     *    3, 4
1397     * ]
1398     * ```
1399     * then the iterator will yield [1, 2, 3, 4]. If you do not need to copy the
1400     * elements use [`row_major_reference_iter`](Matrix::row_major_reference_iter) instead.
1401     */
1402    pub fn row_major_iter(&self) -> RowMajorIterator<'_, T> {
1403        RowMajorIterator::new(self)
1404    }
1405
1406    /**
1407     * Returns a iterator over the main diagonal of this matrix.
1408     *
1409     * If you have a matrix such as:
1410     * ```ignore
1411     * [
1412     *    1, 2
1413     *    3, 4
1414     * ]
1415     * ```
1416     * then the iterator will yield [1, 4]. If you do not need to copy the
1417     * elements use [`diagonal_reference_iter`](Matrix::diagonal_reference_iter) instead.
1418     *
1419     * # Examples
1420     *
1421     * Computing a [trace](https://en.wikipedia.org/wiki/Trace_(linear_algebra))
1422     * ```
1423     * use easy_ml::matrices::Matrix;
1424     * let matrix = Matrix::from(vec![
1425     *     vec![ 1, 2, 3 ],
1426     *     vec![ 4, 5, 6 ],
1427     *     vec![ 7, 8, 9 ],
1428     * ]);
1429     * let trace: i32 = matrix.diagonal_iter().sum();
1430     * assert_eq!(trace, 1 + 5 + 9);
1431     * ```
1432     */
1433    pub fn diagonal_iter(&self) -> DiagonalIterator<'_, T> {
1434        DiagonalIterator::new(self)
1435    }
1436
1437    /**
1438     * Creates a matrix of the provided size with all elements initialised to the provided value
1439     *
1440     * # Panics
1441     *
1442     * Panics if no values are provided. Note: this method erroneously did not validate its inputs
1443     * in Easy ML versions up to and including 1.7.0
1444     */
1445    #[track_caller]
1446    pub fn empty(value: T, size: (Row, Column)) -> Matrix<T> {
1447        assert!(size.0 > 0 && size.1 > 0, "Size must be at least 1x1");
1448        Matrix {
1449            data: vec![value; size.0 * size.1],
1450            rows: size.0,
1451            columns: size.1,
1452        }
1453    }
1454
1455    /**
1456     * Gets a copy of the value at this row and column. Rows and Columns are 0 indexed.
1457     *
1458     * # Panics
1459     *
1460     * Panics if the index is out of range.
1461     */
1462    #[track_caller]
1463    pub fn get(&self, row: Row, column: Column) -> T {
1464        assert!(
1465            row < self.rows(),
1466            "Row out of index, only have {} rows",
1467            self.rows()
1468        );
1469        assert!(
1470            column < self.columns(),
1471            "Column out of index, only have {} columns",
1472            self.columns()
1473        );
1474        self.data[self.get_index(row, column)].clone()
1475    }
1476
1477    /**
1478     * Similar to matrix.get(0, 0) in that this returns the element in the first
1479     * row and first column, except that this method will panic if the matrix is
1480     * not 1x1.
1481     *
1482     * This is provided as a convenience function when you want to convert a unit matrix
1483     * to a scalar, such as after taking a dot product of two vectors.
1484     *
1485     * # Example
1486     *
1487     * ```
1488     * use easy_ml::matrices::Matrix;
1489     * let x = Matrix::column(vec![ 1.0, 2.0, 3.0 ]);
1490     * let sum_of_squares: f64 = (x.transpose() * x).scalar();
1491     * ```
1492     *
1493     * # Panics
1494     *
1495     * Panics if the matrix is not 1x1
1496     */
1497    #[track_caller]
1498    pub fn scalar(&self) -> T {
1499        assert!(
1500            self.rows() == 1,
1501            "Cannot treat matrix as scalar as it has more than one row"
1502        );
1503        assert!(
1504            self.columns() == 1,
1505            "Cannot treat matrix as scalar as it has more than one column"
1506        );
1507        self.get(0, 0)
1508    }
1509
1510    /**
1511     * Applies a function to all values in the matrix, modifying
1512     * the matrix in place.
1513     */
1514    pub fn map_mut(&mut self, mapping_function: impl Fn(T) -> T) {
1515        for value in self.data.iter_mut() {
1516            *value = mapping_function(value.clone());
1517        }
1518    }
1519
1520    /**
1521     * Applies a function to all values and each value's index in the
1522     * matrix, modifying the matrix in place.
1523     */
1524    pub fn map_mut_with_index(&mut self, mapping_function: impl Fn(T, Row, Column) -> T) {
1525        self.row_major_reference_mut_iter()
1526            .with_index()
1527            .for_each(|((i, j), x)| {
1528                *x = mapping_function(x.clone(), i, j);
1529            });
1530    }
1531
1532    /**
1533     * Creates and returns a new matrix with all values from the original with the
1534     * function applied to each. This can be used to change the type of the matrix
1535     * such as creating a mask:
1536     * ```
1537     * use easy_ml::matrices::Matrix;
1538     * let x = Matrix::from(vec![
1539     *    vec![ 0.0, 1.2 ],
1540     *    vec![ 5.8, 6.9 ]]);
1541     * let y = x.map(|element| element > 2.0);
1542     * let result = Matrix::from(vec![
1543     *    vec![ false, false ],
1544     *    vec![ true, true ]]);
1545     * assert_eq!(&y, &result);
1546     * ```
1547     */
1548    pub fn map<U>(&self, mapping_function: impl Fn(T) -> U) -> Matrix<U>
1549    where
1550        U: Clone,
1551    {
1552        let mapped = self
1553            .data
1554            .iter()
1555            .map(|x| mapping_function(x.clone()))
1556            .collect();
1557        Matrix::from_flat_row_major(self.size(), mapped)
1558    }
1559
1560    /**
1561     * Creates and returns a new matrix with all values from the original
1562     * and the index of each value mapped by a function. This can be used
1563     * to perform elementwise operations that are not defined on the
1564     * Matrix type itself.
1565     *
1566     * # Exmples
1567     *
1568     * Matrix elementwise division:
1569     *
1570     * ```
1571     * use easy_ml::matrices::Matrix;
1572     * let x = Matrix::from(vec![
1573     *     vec![ 9.0, 2.0 ],
1574     *     vec![ 4.0, 3.0 ]]);
1575     * let y = Matrix::from(vec![
1576     *     vec![ 3.0, 2.0 ],
1577     *     vec![ 1.0, 3.0 ]]);
1578     * let z = x.map_with_index(|x, row, column| x / y.get(row, column));
1579     * let result = Matrix::from(vec![
1580     *     vec![ 3.0, 1.0 ],
1581     *     vec![ 4.0, 1.0 ]]);
1582     * assert_eq!(&z, &result);
1583     * ```
1584     */
1585    pub fn map_with_index<U>(&self, mapping_function: impl Fn(T, Row, Column) -> U) -> Matrix<U>
1586    where
1587        U: Clone,
1588    {
1589        let mapped = self
1590            .row_major_iter()
1591            .with_index()
1592            .map(|((i, j), x)| mapping_function(x, i, j))
1593            .collect();
1594        Matrix::from_flat_row_major(self.size(), mapped)
1595    }
1596
1597    /**
1598     * Inserts a new row into the Matrix at the provided index,
1599     * shifting other rows to the right and filling all entries with the
1600     * provided value. Rows are 0 indexed.
1601     *
1602     * # Panics
1603     *
1604     * This will panic if the row is greater than the number of rows in the matrix.
1605     */
1606    #[track_caller]
1607    pub fn insert_row(&mut self, row: Row, value: T) {
1608        assert!(
1609            row <= self.rows(),
1610            "Row to insert must be <= to {}",
1611            self.rows()
1612        );
1613        for column in 0..self.columns() {
1614            self.data.insert(self.get_index(row, column), value.clone());
1615        }
1616        self.rows += 1;
1617    }
1618
1619    /**
1620     * Inserts a new row into the Matrix at the provided index, shifting other rows
1621     * to the right and filling all entries with the values from the iterator in sequence.
1622     * Rows are 0 indexed.
1623     *
1624     * # Panics
1625     *
1626     * This will panic if the row is greater than the number of rows in the matrix,
1627     * or if the iterator has fewer elements than `self.columns()`.
1628     *
1629     * Example of duplicating a row:
1630     * ```
1631     * use easy_ml::matrices::Matrix;
1632     * let x: Matrix<u8> = Matrix::row(vec![ 1, 2, 3 ]);
1633     * let mut y = x.clone();
1634     * // duplicate the first row as the second row
1635     * y.insert_row_with(1, x.row_iter(0));
1636     * assert_eq!((2, 3), y.size());
1637     * let mut values = y.column_major_iter();
1638     * assert_eq!(Some(1), values.next());
1639     * assert_eq!(Some(1), values.next());
1640     * assert_eq!(Some(2), values.next());
1641     * assert_eq!(Some(2), values.next());
1642     * assert_eq!(Some(3), values.next());
1643     * assert_eq!(Some(3), values.next());
1644     * assert_eq!(None, values.next());
1645     * ```
1646     */
1647    #[track_caller]
1648    pub fn insert_row_with<I>(&mut self, row: Row, mut values: I)
1649    where
1650        I: Iterator<Item = T>,
1651    {
1652        assert!(
1653            row <= self.rows(),
1654            "Row to insert must be <= to {}",
1655            self.rows()
1656        );
1657        for column in 0..self.columns() {
1658            self.data.insert(
1659                self.get_index(row, column),
1660                values.next().unwrap_or_else(|| {
1661                    panic!("At least {} values must be provided", self.columns())
1662                }),
1663            );
1664        }
1665        self.rows += 1;
1666    }
1667
1668    /**
1669     * Inserts a new column into the Matrix at the provided index, shifting other
1670     * columns to the right and filling all entries with the provided value.
1671     * Columns are 0 indexed.
1672     *
1673     * # Panics
1674     *
1675     * This will panic if the column is greater than the number of columns in the matrix.
1676     */
1677    #[track_caller]
1678    pub fn insert_column(&mut self, column: Column, value: T) {
1679        assert!(
1680            column <= self.columns(),
1681            "Column to insert must be <= to {}",
1682            self.columns()
1683        );
1684        for row in (0..self.rows()).rev() {
1685            self.data.insert(self.get_index(row, column), value.clone());
1686        }
1687        self.columns += 1;
1688    }
1689
1690    /**
1691     * Inserts a new column into the Matrix at the provided index, shifting other columns
1692     * to the right and filling all entries with the values from the iterator in sequence.
1693     * Columns are 0 indexed.
1694     *
1695     * # Panics
1696     *
1697     * This will panic if the column is greater than the number of columns in the matrix,
1698     * or if the iterator has fewer elements than `self.rows()`.
1699     *
1700     * Example of duplicating a column:
1701     * ```
1702     * use easy_ml::matrices::Matrix;
1703     * let x: Matrix<u8> = Matrix::column(vec![ 1, 2, 3 ]);
1704     * let mut y = x.clone();
1705     * // duplicate the first column as the second column
1706     * y.insert_column_with(1, x.column_iter(0));
1707     * assert_eq!((3, 2), y.size());
1708     * let mut values = y.column_major_iter();
1709     * assert_eq!(Some(1), values.next());
1710     * assert_eq!(Some(2), values.next());
1711     * assert_eq!(Some(3), values.next());
1712     * assert_eq!(Some(1), values.next());
1713     * assert_eq!(Some(2), values.next());
1714     * assert_eq!(Some(3), values.next());
1715     * assert_eq!(None, values.next());
1716     * ```
1717     */
1718    #[track_caller]
1719    pub fn insert_column_with<I>(&mut self, column: Column, values: I)
1720    where
1721        I: Iterator<Item = T>,
1722    {
1723        assert!(
1724            column <= self.columns(),
1725            "Column to insert must be <= to {}",
1726            self.columns()
1727        );
1728        let mut array_values = values.collect::<Vec<T>>();
1729        assert!(
1730            array_values.len() >= self.rows(),
1731            "At least {} values must be provided",
1732            self.rows()
1733        );
1734        for row in (0..self.rows()).rev() {
1735            self.data
1736                .insert(self.get_index(row, column), array_values.pop().unwrap());
1737        }
1738        self.columns += 1;
1739    }
1740
1741    /**
1742     * Makes a copy of this matrix shrunk down in size according to the slice. See
1743     * [retain_mut](Matrix::retain_mut()).
1744     */
1745    pub fn retain(&self, slice: Slice2D) -> Matrix<T> {
1746        let mut retained = self.clone();
1747        retained.retain_mut(slice);
1748        retained
1749    }
1750}
1751
1752/**
1753 * Any matrix of a Cloneable type implements Clone.
1754 */
1755impl<T: Clone> Clone for Matrix<T> {
1756    fn clone(&self) -> Self {
1757        self.map(|element| element)
1758    }
1759}
1760
1761/**
1762 * Any matrix of a Displayable type implements Display
1763 *
1764 * You can control the precision of the formatting using format arguments, i.e.
1765 * `format!("{:.3}", matrix)`
1766 */
1767impl<T: std::fmt::Display> std::fmt::Display for Matrix<T> {
1768    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1769        crate::matrices::views::format_view(self, f)
1770    }
1771}
1772
1773/**
1774 * Any matrix and two different dimension names can be converted to a 2 dimensional tensor with
1775 * the same number of rows and columns.
1776 *
1777 * Conversion will fail if the dimension names for `self.rows()` and `self.columns()` respectively
1778 * are the same.
1779 */
1780impl<T> TryFrom<(Matrix<T>, [crate::tensors::Dimension; 2])> for crate::tensors::Tensor<T, 2> {
1781    type Error = crate::tensors::InvalidShapeError<2>;
1782
1783    fn try_from(value: (Matrix<T>, [crate::tensors::Dimension; 2])) -> Result<Self, Self::Error> {
1784        let (matrix, [row_name, column_name]) = value;
1785        let shape = [(row_name, matrix.rows), (column_name, matrix.columns)];
1786        let check = crate::tensors::InvalidShapeError::new(shape);
1787        if !check.is_valid() {
1788            return Err(check);
1789        }
1790        // Now we know the shape is valid, we can call the standard Tensor constructor knowing
1791        // it won't fail since our data length will match the size of our shape.
1792        Ok(crate::tensors::Tensor::from(shape, matrix.data))
1793    }
1794}
1795
1796/**
1797 * Methods for matrices with numerical types, such as f32 or f64.
1798 *
1799 * Note that unsigned integers are not Numeric because they do not
1800 * implement [Neg](std::ops::Neg). You must first
1801 * wrap unsigned integers via [Wrapping](std::num::Wrapping) or [Saturating](std::num::Saturating).
1802 *
1803 * While these methods will all be defined on signed integer types as well, such as i16 or i32,
1804 * in many cases integers cannot be used sensibly in these computations. If you
1805 * have a matrix of type i8 for example, you should consider mapping it into a floating
1806 * type before doing heavy linear algebra maths on it.
1807 *
1808 * Determinants can be computed without loss of precision using sufficiently large signed
1809 * integers because the only operations performed on the elements are addition, subtraction
1810 * and mulitplication. However the inverse of a matrix such as
1811 *
1812 * ```ignore
1813 * [
1814 *   4, 7
1815 *   2, 8
1816 * ]
1817 * ```
1818 *
1819 * is
1820 *
1821 * ```ignore
1822 * [
1823 *   0.6, -0.7,
1824 *  -0.2, 0.4
1825 * ]
1826 * ```
1827 *
1828 * which requires a type that supports decimals to accurately represent.
1829 *
1830 * Mapping matrix type example:
1831 * ```
1832 * use easy_ml::matrices::Matrix;
1833 * use std::num::Wrapping;
1834 *
1835 * let matrix: Matrix<u8> = Matrix::from(vec![
1836 *     vec![ 2, 3 ],
1837 *     vec![ 6, 0 ]
1838 * ]);
1839 * // determinant is not defined on this matrix because u8 is not Numeric
1840 * // println!("{:?}", matrix.determinant()); // won't compile
1841 * // however Wrapping<u8> is numeric
1842 * let matrix = matrix.map(|element| Wrapping(element));
1843 * println!("{:?}", matrix.determinant()); // -> 238 (overflow)
1844 * println!("{:?}", matrix.map(|element| element.0 as i16).determinant()); // -> -18
1845 * println!("{:?}", matrix.map(|element| element.0 as f32).determinant()); // -> -18.0
1846 * ```
1847 */
1848impl<T: Numeric> Matrix<T>
1849where
1850    for<'a> &'a T: NumericRef<T>,
1851{
1852    /**
1853     * Returns the determinant of this square matrix, or None if the matrix
1854     * does not have a determinant. See [`linear_algebra`](super::linear_algebra::determinant())
1855     */
1856    pub fn determinant(&self) -> Option<T> {
1857        linear_algebra::determinant::<T>(self)
1858    }
1859
1860    /**
1861     * Computes the inverse of a matrix provided that it exists. To have an inverse a
1862     * matrix must be square (same number of rows and columns) and it must also have a
1863     * non zero determinant. See [`linear_algebra`](super::linear_algebra::inverse())
1864     */
1865    pub fn inverse(&self) -> Option<Matrix<T>> {
1866        linear_algebra::inverse::<T>(self)
1867    }
1868
1869    /**
1870     * Computes the covariance matrix for this NxM feature matrix, in which
1871     * each N'th row has M features to find the covariance and variance of. See
1872     * [`linear_algebra`](super::linear_algebra::covariance_column_features())
1873     */
1874    pub fn covariance_column_features(&self) -> Matrix<T> {
1875        linear_algebra::covariance_column_features::<T>(self)
1876    }
1877
1878    /**
1879     * Computes the covariance matrix for this NxM feature matrix, in which
1880     * each M'th column has N features to find the covariance and variance of. See
1881     * [`linear_algebra`](super::linear_algebra::covariance_row_features())
1882     */
1883    pub fn covariance_row_features(&self) -> Matrix<T> {
1884        linear_algebra::covariance_row_features::<T>(self)
1885    }
1886}
1887
1888/**
1889 * Methods for matrices with numerical real valued types, such as f32 or f64.
1890 *
1891 * This excludes signed and unsigned integers as they do not support decimal
1892 * precision and hence can't be used for operations like square roots.
1893 *
1894 * Third party fixed precision and infinite precision decimal types should
1895 * be able to implement all of the methods for [Real] and then utilise these functions.
1896 */
1897impl<T: Real> Matrix<T>
1898where
1899    for<'a> &'a T: RealRef<T>,
1900{
1901    /**
1902     * Computes the [L2 norm](https://en.wikipedia.org/wiki/Euclidean_vector#Length)
1903     * of this row or column vector, also referred to as the length or magnitude,
1904     * and written as ||x||, or sometimes |x|.
1905     *
1906     * ||**a**|| = sqrt(a<sub>1</sub><sup>2</sup> + a<sub>2</sub><sup>2</sup> + a<sub>3</sub><sup>2</sup>...) = sqrt(**a**<sup>T</sup> * **a**)
1907     *
1908     * This is a shorthand for `(x.transpose() * x).scalar().sqrt()` for
1909     * column vectors and `(x * x.transpose()).scalar().sqrt()` for row vectors, ie
1910     * the square root of the dot product of a vector with itself.
1911     *
1912     * The euclidean length can be used to compute a
1913     * [unit vector](https://en.wikipedia.org/wiki/Unit_vector), that is, a
1914     * vector with length of 1. This should not be confused with a unit matrix,
1915     * which is another name for an identity matrix.
1916     *
1917     * ```
1918     * use easy_ml::matrices::Matrix;
1919     * let a = Matrix::column(vec![ 1.0, 2.0, 3.0 ]);
1920     * let length = a.euclidean_length(); // (1^2 + 2^2 + 3^2)^0.5
1921     * let unit = a / length;
1922     * assert_eq!(unit.euclidean_length(), 1.0);
1923     * ```
1924     *
1925     * # Panics
1926     *
1927     * If the matrix is not a vector, ie if it has more than one row and more than one
1928     * column.
1929     */
1930    #[track_caller]
1931    pub fn euclidean_length(&self) -> T {
1932        if self.columns() == 1 {
1933            // column vector
1934            (self.transpose() * self).scalar().sqrt()
1935        } else if self.rows() == 1 {
1936            // row vector
1937            (self * self.transpose()).scalar().sqrt()
1938        } else {
1939            panic!(
1940                "Cannot compute unit vector of a non vector, rows: {}, columns: {}",
1941                self.rows(),
1942                self.columns()
1943            );
1944        }
1945    }
1946}
1947
1948// FIXME: want this to be callable in the main numeric impl block
1949impl<T: Numeric> Matrix<T> {
1950    /**
1951     * Creates a diagonal matrix of the provided size with the diagonal elements
1952     * set to the provided value and all other elements in the matrix set to 0.
1953     * A diagonal matrix is always square.
1954     *
1955     * The size is still taken as a tuple to facilitate creating a diagonal matrix
1956     * from the dimensionality of an existing one. If the provided value is 1 then
1957     * this will create an identity matrix.
1958     *
1959     * A 3 x 3 identity matrix:
1960     * ```ignore
1961     * [
1962     *   1, 0, 0
1963     *   0, 1, 0
1964     *   0, 0, 1
1965     * ]
1966     * ```
1967     *
1968     * # Panics
1969     *
1970     * If the provided size is not square.
1971     */
1972    #[track_caller]
1973    pub fn diagonal(value: T, size: (Row, Column)) -> Matrix<T> {
1974        assert!(size.0 == size.1);
1975        let mut matrix = Matrix::empty(T::zero(), size);
1976        for i in 0..size.0 {
1977            matrix.set(i, i, value.clone());
1978        }
1979        matrix
1980    }
1981
1982    /**
1983     * Creates a diagonal matrix with the elements along the diagonal set to the
1984     * provided values and all other elements in the matrix set to 0.
1985     * A diagonal matrix is always square.
1986     *
1987     * Examples
1988     *
1989     * ```
1990     * use easy_ml::matrices::Matrix;
1991     * let matrix = Matrix::from_diagonal(vec![ 1, 1, 1 ]);
1992     * assert_eq!(matrix.size(), (3, 3));
1993     * let copy = Matrix::from_diagonal(matrix.diagonal_iter().collect());
1994     * assert_eq!(matrix, copy);
1995     * assert_eq!(matrix, Matrix::from(vec![
1996     *     vec![ 1, 0, 0 ],
1997     *     vec![ 0, 1, 0 ],
1998     *     vec![ 0, 0, 1 ],
1999     * ]))
2000     * ```
2001     */
2002    pub fn from_diagonal(values: Vec<T>) -> Matrix<T> {
2003        let mut matrix = Matrix::empty(T::zero(), (values.len(), values.len()));
2004        for (i, element) in values.into_iter().enumerate() {
2005            matrix.set(i, i, element);
2006        }
2007        matrix
2008    }
2009}
2010
2011/**
2012 * PartialEq is implemented as two matrices are equal if and only if all their elements
2013 * are equal and they have the same size.
2014 */
2015impl<T: PartialEq> PartialEq for Matrix<T> {
2016    #[inline]
2017    fn eq(&self, other: &Self) -> bool {
2018        if self.rows() != other.rows() {
2019            return false;
2020        }
2021        if self.columns() != other.columns() {
2022            return false;
2023        }
2024        // perform elementwise check, return true only if every element in
2025        // each matrix is the same
2026        self.data.iter().zip(other.data.iter()).all(|(x, y)| x == y)
2027    }
2028}
2029
2030#[test]
2031fn test_sync() {
2032    fn assert_sync<T: Sync>() {}
2033    assert_sync::<Matrix<f64>>();
2034}
2035
2036#[test]
2037fn test_send() {
2038    fn assert_send<T: Send>() {}
2039    assert_send::<Matrix<f64>>();
2040}
2041
2042#[cfg(feature = "serde")]
2043mod serde_impls {
2044    use crate::matrices::{Column, Matrix, Row};
2045    use serde::{Deserialize, Deserializer};
2046
2047    #[derive(Deserialize)]
2048    #[serde(rename = "Matrix")]
2049    struct MatrixDeserialize<T> {
2050        data: Vec<T>,
2051        rows: Row,
2052        columns: Column,
2053    }
2054
2055    impl<'de, T> Deserialize<'de> for Matrix<T>
2056    where
2057        T: Deserialize<'de>,
2058    {
2059        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2060        where
2061            D: Deserializer<'de>,
2062        {
2063            MatrixDeserialize::<T>::deserialize(deserializer).map(|d| {
2064                // Safety: Use the no copy constructor that performs validation to prevent invalid
2065                // serialized data being created as a Matrix, which would then break all the
2066                // code that's relying on these invariants.
2067                Matrix::from_flat_row_major((d.rows, d.columns), d.data)
2068            })
2069        }
2070    }
2071}
2072
2073#[cfg(feature = "serde")]
2074#[test]
2075fn test_serialize() {
2076    fn assert_serialize<T: Serialize>() {}
2077    assert_serialize::<Matrix<f64>>();
2078}
2079
2080#[cfg(feature = "serde")]
2081#[test]
2082fn test_deserialize() {
2083    use serde::Deserialize;
2084    fn assert_deserialize<'de, T: Deserialize<'de>>() {}
2085    assert_deserialize::<Matrix<f64>>();
2086}
2087
2088#[cfg(feature = "serde")]
2089#[test]
2090fn test_serialization_deserialization_loop() {
2091    #[rustfmt::skip]
2092    let matrix = Matrix::from(vec![
2093        vec![1,  2,  3,  4],
2094        vec![5,  6,  7,  8],
2095        vec![9, 10, 11, 12],
2096    ]);
2097    let encoded = toml::to_string(&matrix).unwrap();
2098    assert_eq!(
2099        encoded,
2100        r#"data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
2101rows = 3
2102columns = 4
2103"#,
2104    );
2105    let parsed: Result<Matrix<i32>, _> = toml::from_str(&encoded);
2106    assert!(parsed.is_ok());
2107    assert_eq!(matrix, parsed.unwrap())
2108}
2109
2110#[cfg(feature = "serde")]
2111#[test]
2112#[should_panic]
2113fn test_deserialization_validation() {
2114    let _result: Result<Matrix<i32>, _> = toml::from_str(
2115        r#"data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
2116rows = 3
2117columns = 3
2118"#,
2119    );
2120}
2121
2122#[test]
2123fn test_indexing() {
2124    let a = Matrix::from(vec![vec![1, 2], vec![3, 4]]);
2125    assert_eq!(a.get_index(0, 1), 1);
2126    assert_eq!(a.get_row_column(1), (0, 1));
2127    assert_eq!(a.get(0, 1), 2);
2128    let b = Matrix::from(vec![vec![1, 2, 3], vec![5, 6, 7]]);
2129    assert_eq!(b.get_index(1, 2), 5);
2130    assert_eq!(b.get_row_column(5), (1, 2));
2131    assert_eq!(b.get(1, 2), 7);
2132    assert_eq!(
2133        Matrix::from(vec![vec![0, 0], vec![0, 0], vec![0, 0]])
2134            .map_with_index(|_, r, c| format!("{:?}x{:?}", r, c)),
2135        Matrix::from(vec![
2136            vec!["0x0", "0x1"],
2137            vec!["1x0", "1x1"],
2138            vec!["2x0", "2x1"]
2139        ])
2140        .map(|x| x.to_owned())
2141    );
2142}