1use std::alloc::{Allocator, Global};
2use std::fmt::{Debug, Formatter, Result};
3use std::mem::MaybeUninit;
4
5use self::submatrix::{AsFirstElement, Submatrix, SubmatrixMut};
6use super::*;
7
8pub struct OwnedMatrix<T, A: Allocator = Global> {
29 data: Vec<T, A>,
30 col_count: usize,
31 row_count: usize,
32}
33
34impl<T> OwnedMatrix<T> {
35 pub fn from_fn<F>(row_count: usize, col_count: usize, f: F) -> Self
38 where
39 F: FnMut(usize, usize) -> T,
40 {
41 Self::from_fn_in(row_count, col_count, f, Global)
42 }
43
44 pub fn zero<R: RingStore>(row_count: usize, col_count: usize, ring: R) -> Self
46 where
47 R::Type: RingBase<Element = T>,
48 {
49 Self::zero_in(row_count, col_count, ring, Global)
50 }
51
52 pub fn identity<R: RingStore>(row_count: usize, col_count: usize, ring: R) -> Self
54 where
55 R::Type: RingBase<Element = T>,
56 {
57 Self::identity_in(row_count, col_count, ring, Global)
58 }
59}
60
61impl<T, A: Allocator> OwnedMatrix<T, A> {
62 pub fn new(data: Vec<T, A>, col_count: usize) -> Self {
69 let row_count = data.len() / col_count;
70 Self::new_with_shape(data, row_count, col_count)
71 }
72
73 pub fn new_with_shape(data: Vec<T, A>, row_count: usize, col_count: usize) -> Self {
84 assert_eq!(row_count * col_count, data.len());
85 Self {
86 data,
87 col_count,
88 row_count,
89 }
90 }
91
92 #[stability::unstable(feature = "enable")]
95 pub fn from_fn_in<F>(row_count: usize, col_count: usize, mut f: F, allocator: A) -> Self
96 where
97 F: FnMut(usize, usize) -> T,
98 {
99 let mut data = Vec::with_capacity_in(row_count * col_count, allocator);
100 for i in 0..row_count {
101 for j in 0..col_count {
102 data.push(f(i, j));
103 }
104 }
105 return Self::new_with_shape(data, row_count, col_count);
106 }
107
108 pub fn data<'a>(&'a self) -> Submatrix<'a, AsFirstElement<T>, T> {
110 Submatrix::<AsFirstElement<_>, _>::from_1d(&self.data, self.row_count(), self.col_count())
111 }
112
113 pub fn data_mut<'a>(&'a mut self) -> SubmatrixMut<'a, AsFirstElement<T>, T> {
115 let row_count = self.row_count();
116 let col_count = self.col_count();
117 SubmatrixMut::<AsFirstElement<_>, _>::from_1d(&mut self.data, row_count, col_count)
118 }
119
120 pub fn at(&self, i: usize, j: usize) -> &T { &self.data[i * self.col_count + j] }
122
123 pub fn at_mut(&mut self, i: usize, j: usize) -> &mut T { &mut self.data[i * self.col_count + j] }
125
126 pub fn row_count(&self) -> usize { self.row_count }
128
129 pub fn col_count(&self) -> usize { self.col_count }
132
133 #[stability::unstable(feature = "enable")]
135 pub fn zero_in<R: RingStore>(row_count: usize, col_count: usize, ring: R, allocator: A) -> Self
136 where
137 R::Type: RingBase<Element = T>,
138 {
139 let mut result = Vec::with_capacity_in(row_count * col_count, allocator);
140 for _ in 0..row_count {
141 for _ in 0..col_count {
142 result.push(ring.zero());
143 }
144 }
145 return Self::new_with_shape(result, row_count, col_count);
146 }
147
148 #[stability::unstable(feature = "enable")]
150 pub fn identity_in<R: RingStore>(row_count: usize, col_count: usize, ring: R, allocator: A) -> Self
151 where
152 R::Type: RingBase<Element = T>,
153 {
154 let mut result = Vec::with_capacity_in(row_count * col_count, allocator);
155 for i in 0..row_count {
156 for j in 0..col_count {
157 if i != j {
158 result.push(ring.zero());
159 } else {
160 result.push(ring.one());
161 }
162 }
163 }
164 return Self::new_with_shape(result, row_count, col_count);
165 }
166
167 #[stability::unstable(feature = "enable")]
168 pub fn clone_matrix<R: RingStore>(&self, ring: R) -> Self
169 where
170 R::Type: RingBase<Element = T>,
171 A: Clone,
172 {
173 let mut result = Vec::with_capacity_in(self.row_count() * self.col_count(), self.data.allocator().clone());
174 for i in 0..self.row_count() {
175 for j in 0..self.col_count() {
176 result.push(ring.clone_el(self.at(i, j)));
177 }
178 }
179 return Self::new_with_shape(result, self.row_count(), self.col_count());
180 }
181
182 #[stability::unstable(feature = "enable")]
183 pub fn set_row_count<F>(&mut self, new_count: usize, new_entries: F)
184 where
185 F: FnMut() -> T,
186 {
187 self.data.resize_with(new_count * self.col_count(), new_entries);
188 }
189}
190
191impl<T> OwnedMatrix<MaybeUninit<T>> {
192 #[stability::unstable(feature = "enable")]
193 pub fn uninit(row_count: usize, col_count: usize) -> Self { Self::uninit_in(row_count, col_count, Global) }
194}
195
196impl<T, A: Allocator> OwnedMatrix<MaybeUninit<T>, A> {
197 #[stability::unstable(feature = "enable")]
198 pub fn uninit_in(row_count: usize, col_count: usize, allocator: A) -> Self {
199 let mut data = Vec::with_capacity_in(row_count * col_count, allocator);
200 data.resize_with(row_count * col_count, || MaybeUninit::uninit());
201 return Self {
202 data,
203 row_count,
204 col_count,
205 };
206 }
207
208 #[stability::unstable(feature = "enable")]
210 pub unsafe fn assume_init(self) -> OwnedMatrix<T, A> {
211 let (ptr, len, cap, alloc) = self.data.into_raw_parts_with_alloc();
212 let new_vec = unsafe { Vec::from_raw_parts_in(ptr.cast::<T>(), len, cap, alloc) };
216
217 OwnedMatrix {
218 data: new_vec,
219 col_count: self.col_count,
220 row_count: self.row_count,
221 }
222 }
223}
224
225impl<T: Debug, A: Allocator> Debug for OwnedMatrix<T, A> {
226 fn fmt(&self, f: &mut Formatter<'_>) -> Result { self.data().fmt(f) }
227}
228
229#[cfg(test)]
230use crate::primitive_int::*;
231
232#[test]
233fn test_zero_col_matrix() {
234 let A: OwnedMatrix<i64> = OwnedMatrix::new_with_shape(Vec::new(), 10, 0);
235 assert_eq!(0, A.col_count());
236 assert_eq!(10, A.row_count());
237
238 let B: OwnedMatrix<i64> = OwnedMatrix::zero(11, 0, StaticRing::<i64>::RING);
239 assert_eq!(0, B.col_count());
240 assert_eq!(11, B.row_count());
241}