Skip to main content

feanor_math/matrix/
owned.rs

1use std::alloc::{Allocator, Global};
2use std::fmt::{Debug, Formatter, Result};
3
4use self::submatrix::{AsFirstElement, Submatrix, SubmatrixMut};
5use super::*;
6
7/// A matrix that owns its elements.
8///
9/// To pass it to algorithms, use the `.data()` and `.data_mut()` functions.
10///
11/// # Example
12/// ```rust
13/// #![feature(allocator_api)]
14/// # use std::alloc::*;
15/// # use feanor_math::ring::*;
16/// # use feanor_math::primitive_int::*;
17/// # use feanor_math::matrix::*;
18/// # use feanor_math::algorithms::linsolve::*;
19/// let mut A = OwnedMatrix::identity(2, 2, StaticRing::<i32>::RING);
20/// let mut B = OwnedMatrix::identity(2, 2, StaticRing::<i32>::RING);
21/// let mut C = OwnedMatrix::identity(2, 2, StaticRing::<i32>::RING);
22/// StaticRing::<i32>::RING
23///     .get_ring()
24///     .solve_right(A.data_mut(), B.data_mut(), C.data_mut(), Global)
25///     .assert_solved();
26/// ```
27pub struct OwnedMatrix<T, A: Allocator = Global> {
28    data: Vec<T, A>,
29    col_count: usize,
30    row_count: usize,
31}
32
33impl<T> OwnedMatrix<T> {
34    /// Creates the `row_count x col_count` [`OwnedMatrix`] whose `(i, j)`-th entry
35    /// is the output of the given function on `(i, j)`.
36    pub fn from_fn<F>(row_count: usize, col_count: usize, f: F) -> Self
37    where
38        F: FnMut(usize, usize) -> T,
39    {
40        Self::from_fn_in(row_count, col_count, f, Global)
41    }
42
43    /// Creates the `row_count x col_count` zero matrix over the given ring.
44    pub fn zero<R: RingStore>(row_count: usize, col_count: usize, ring: R) -> Self
45    where
46        R::Type: RingBase<Element = T>,
47    {
48        Self::zero_in(row_count, col_count, ring, Global)
49    }
50
51    /// Creates the `row_count x col_count` identity matrix over the given ring.
52    pub fn identity<R: RingStore>(row_count: usize, col_count: usize, ring: R) -> Self
53    where
54        R::Type: RingBase<Element = T>,
55    {
56        Self::identity_in(row_count, col_count, ring, Global)
57    }
58}
59
60impl<T, A: Allocator> OwnedMatrix<T, A> {
61    /// Creates the `row_count x col_count` [`OwnedMatrix`] matrix, whose entries are
62    /// taken from the given vector, interpreted as a row-major matrix. The number of
63    /// rows is `row_count = data.len() / col_count`.
64    ///
65    /// If `col_count` is zero, this will panic. If that can happen, consider
66    /// using [`OwnedMatrix::new_with_shape()`].
67    pub fn new(data: Vec<T, A>, col_count: usize) -> Self {
68        let row_count = data.len() / col_count;
69        Self::new_with_shape(data, row_count, col_count)
70    }
71
72    /// Creates the `row_count x col_count` [`OwnedMatrix`] matrix, whose entries are
73    /// taken from the given vector, interpreted as a row-major matrix.
74    ///
75    /// # Example
76    /// ```
77    /// # use feanor_math::matrix::*;
78    /// let matrix = OwnedMatrix::new_with_shape(vec![1, 2, 3, 4, 5, 6], 3, 2);
79    /// assert_eq!(3, *matrix.at(1, 0));
80    /// assert_eq!(6, *matrix.at(2, 1));
81    /// ```
82    pub fn new_with_shape(data: Vec<T, A>, row_count: usize, col_count: usize) -> Self {
83        assert_eq!(row_count * col_count, data.len());
84        Self {
85            data,
86            col_count,
87            row_count,
88        }
89    }
90
91    /// Creates the `row_count x col_count` [`OwnedMatrix`] whose `(i, j)`-th entry
92    /// is the output of the given function on `(i, j)`.
93    #[stability::unstable(feature = "enable")]
94    pub fn from_fn_in<F>(row_count: usize, col_count: usize, mut f: F, allocator: A) -> Self
95    where
96        F: FnMut(usize, usize) -> T,
97    {
98        let mut data = Vec::with_capacity_in(row_count * col_count, allocator);
99        for i in 0..row_count {
100            for j in 0..col_count {
101                data.push(f(i, j));
102            }
103        }
104        return Self::new_with_shape(data, row_count, col_count);
105    }
106
107    /// Returns a [`Submatrix`] view on the data of this matrix.
108    pub fn data<'a>(&'a self) -> Submatrix<'a, AsFirstElement<T>, T> {
109        Submatrix::<AsFirstElement<_>, _>::from_1d(&self.data, self.row_count(), self.col_count())
110    }
111
112    /// Returns a [`SubmatrixMut`] view on the data of this matrix.
113    pub fn data_mut<'a>(&'a mut self) -> SubmatrixMut<'a, AsFirstElement<T>, T> {
114        let row_count = self.row_count();
115        let col_count = self.col_count();
116        SubmatrixMut::<AsFirstElement<_>, _>::from_1d(&mut self.data, row_count, col_count)
117    }
118
119    /// Returns a reference to the `(i, j)`-th entry of this matrix.
120    pub fn at(&self, i: usize, j: usize) -> &T { &self.data[i * self.col_count + j] }
121
122    /// Returns a mutable reference to the `(i, j)`-th entry of this matrix.
123    pub fn at_mut(&mut self, i: usize, j: usize) -> &mut T { &mut self.data[i * self.col_count + j] }
124
125    /// Returns the number of rows of this matrix.
126    pub fn row_count(&self) -> usize { self.row_count }
127
128    ////
129    /// Returns the number of columns of this matrix.
130    pub fn col_count(&self) -> usize { self.col_count }
131
132    /// Creates the `row_count x col_count` zero matrix over the given ring.
133    #[stability::unstable(feature = "enable")]
134    pub fn zero_in<R: RingStore>(row_count: usize, col_count: usize, ring: R, allocator: A) -> Self
135    where
136        R::Type: RingBase<Element = T>,
137    {
138        let mut result = Vec::with_capacity_in(row_count * col_count, allocator);
139        for _ in 0..row_count {
140            for _ in 0..col_count {
141                result.push(ring.zero());
142            }
143        }
144        return Self::new_with_shape(result, row_count, col_count);
145    }
146
147    /// Creates the `row_count x col_count` identity matrix over the given ring.
148    #[stability::unstable(feature = "enable")]
149    pub fn identity_in<R: RingStore>(row_count: usize, col_count: usize, ring: R, allocator: A) -> Self
150    where
151        R::Type: RingBase<Element = T>,
152    {
153        let mut result = Vec::with_capacity_in(row_count * col_count, allocator);
154        for i in 0..row_count {
155            for j in 0..col_count {
156                if i != j {
157                    result.push(ring.zero());
158                } else {
159                    result.push(ring.one());
160                }
161            }
162        }
163        return Self::new_with_shape(result, row_count, col_count);
164    }
165
166    #[stability::unstable(feature = "enable")]
167    pub fn clone_matrix<R: RingStore>(&self, ring: R) -> Self
168    where
169        R::Type: RingBase<Element = T>,
170        A: Clone,
171    {
172        let mut result = Vec::with_capacity_in(self.row_count() * self.col_count(), self.data.allocator().clone());
173        for i in 0..self.row_count() {
174            for j in 0..self.col_count() {
175                result.push(ring.clone_el(self.at(i, j)));
176            }
177        }
178        return Self::new_with_shape(result, self.row_count(), self.col_count());
179    }
180
181    #[stability::unstable(feature = "enable")]
182    pub fn set_row_count<F>(&mut self, new_count: usize, new_entries: F)
183    where
184        F: FnMut() -> T,
185    {
186        self.data.resize_with(new_count * self.col_count(), new_entries);
187    }
188}
189
190impl<T: Debug, A: Allocator> Debug for OwnedMatrix<T, A> {
191    fn fmt(&self, f: &mut Formatter<'_>) -> Result { self.data().fmt(f) }
192}
193
194#[cfg(test)]
195use crate::primitive_int::*;
196
197#[test]
198fn test_zero_col_matrix() {
199    let A: OwnedMatrix<i64> = OwnedMatrix::new_with_shape(Vec::new(), 10, 0);
200    assert_eq!(0, A.col_count());
201    assert_eq!(10, A.row_count());
202
203    let B: OwnedMatrix<i64> = OwnedMatrix::zero(11, 0, StaticRing::<i64>::RING);
204    assert_eq!(0, B.col_count());
205    assert_eq!(11, B.row_count());
206}