1use crate::algebra::{CscMatrix, MatrixShape, MatrixTriangle};
7use num_traits::Num;
8use std::iter::zip;
9
10impl<T> CscMatrix<T>
11where
12 T: Num + Copy,
13{
14 pub(crate) fn colcount_dense_triangle(
17 &mut self,
18 initcol: usize,
19 blockcols: usize,
20 shape: MatrixTriangle,
21 ) {
22 let cols = self.colptr[(initcol)..(initcol + blockcols)].iter_mut();
23 let counts = 1..(blockcols + 1);
24 match shape {
25 MatrixTriangle::Triu => {
26 zip(cols, counts).for_each(|(x, c)| *x += c);
27 }
28
29 MatrixTriangle::Tril => {
30 zip(cols, counts.rev()).for_each(|(x, c)| *x += c);
31 }
32 }
33 }
34
35 pub(crate) fn colcount_diag(&mut self, initcol: usize, blockcols: usize) {
38 let cols = self.colptr[initcol..(initcol + blockcols)].iter_mut();
39 cols.for_each(|x| *x += 1);
40 }
41
42 pub(crate) fn colcount_missing_diag(&mut self, M: &CscMatrix<T>, initcol: usize) {
46 assert_eq!(M.colptr.len(), M.n + 1);
47 assert!(self.colptr.len() >= M.n + initcol);
48
49 for i in 0..M.n {
50 if M.colptr[i] == M.colptr[i+1] || M.rowval[M.colptr[i+1]-1] != i
52 {
54 self.colptr[i + initcol] += 1;
55 }
56 }
57 }
58
59 pub(crate) fn colcount_colvec(&mut self, n: usize, _firstrow: usize, firstcol: usize) {
63 self.colptr[firstcol] += n;
65 }
66
67 pub(crate) fn colcount_rowvec(&mut self, n: usize, _firstrow: usize, firstcol: usize) {
71 let cols = self.colptr[firstcol..(firstcol + n)].iter_mut();
75 cols.for_each(|x| *x += 1);
76 }
77
78 pub(crate) fn colcount_block(&mut self, M: &CscMatrix<T>, initcol: usize, shape: MatrixShape) {
81 match shape {
82 MatrixShape::T => {
83 for row in M.rowval.iter() {
84 self.colptr[initcol + row] += 1;
85 }
86 }
87 MatrixShape::N => {
88 for i in 0..M.n {
90 self.colptr[initcol + i] += M.colptr[i + 1] - M.colptr[i];
91 }
92 }
93 }
94 }
95
96 pub(crate) fn fill_colvec(&mut self, vtoKKT: &mut [usize], initrow: usize, initcol: usize) {
99 for (i, v) in vtoKKT.iter_mut().enumerate() {
100 let dest = self.colptr[initcol];
101 self.rowval[dest] = initrow + i;
102 self.nzval[dest] = T::zero();
103 *v = dest;
104 self.colptr[initcol] += 1;
105 }
106 }
107
108 pub(crate) fn fill_rowvec(&mut self, vtoKKT: &mut [usize], initrow: usize, initcol: usize) {
111 for (i, v) in vtoKKT.iter_mut().enumerate() {
112 let col = initcol + i;
113 let dest = self.colptr[col];
114 self.rowval[dest] = initrow;
115 self.nzval[dest] = T::zero();
116 *v = dest;
117 self.colptr[col] += 1;
118 }
119 }
120
121 #[allow(clippy::needless_range_loop)]
124 pub(crate) fn fill_block(
125 &mut self,
126 M: &CscMatrix<T>,
127 MtoKKT: &mut [usize],
128 initrow: usize,
129 initcol: usize,
130 shape: MatrixShape,
131 ) {
132 for i in 0..M.n {
133 let start = M.colptr[i];
134 let stop = M.colptr[i + 1];
135
136 for j in start..stop {
137 let (col, row);
138
139 match shape {
140 MatrixShape::T => {
141 col = M.rowval[j] + initcol;
142 row = i + initrow;
143 }
144 MatrixShape::N => {
145 col = i + initcol;
146 row = M.rowval[j] + initrow;
147 }
148 };
149
150 let dest = self.colptr[col];
151 self.rowval[dest] = row;
152 self.nzval[dest] = M.nzval[j];
153 MtoKKT[j] = dest;
154 self.colptr[col] += 1;
155 }
156 }
157 }
158
159 pub(crate) fn fill_dense_triangle(
162 &mut self,
163 blocktoKKT: &mut [usize],
164 offset: usize,
165 blockdim: usize,
166 shape: MatrixTriangle,
167 ) {
168 match shape {
173 MatrixTriangle::Triu => {
174 self._fill_dense_triangle_triu(blocktoKKT, offset, blockdim);
175 }
176
177 MatrixTriangle::Tril => {
178 self._fill_dense_triangle_tril(blocktoKKT, offset, blockdim);
179 }
180 }
181 }
182
183 pub(crate) fn _fill_dense_triangle_triu(
184 &mut self,
185 blocktoKKT: &mut [usize],
186 offset: usize,
187 blockdim: usize,
188 ) {
189 let mut kidx = 0;
190 for col in offset..(offset + blockdim) {
191 for row in offset..=col {
192 let dest = self.colptr[col];
193 self.rowval[dest] = row;
194 self.nzval[dest] = T::zero(); self.colptr[col] += 1;
196 blocktoKKT[kidx] = dest;
197 kidx += 1;
198 }
199 }
200 }
201
202 pub(crate) fn _fill_dense_triangle_tril(
203 &mut self,
204 blocktoKKT: &mut [usize],
205 offset: usize,
206 blockdim: usize,
207 ) {
208 let mut kidx = 0;
209 for row in offset..(offset + blockdim) {
210 for col in offset..=row {
211 let dest = self.colptr[col];
212 self.rowval[dest] = row;
213 self.nzval[dest] = T::zero(); self.colptr[col] += 1;
215 blocktoKKT[kidx] = dest;
216 kidx += 1;
217 }
218 }
219 }
220
221 pub(crate) fn fill_diag(&mut self, diagtoKKT: &mut [usize], offset: usize, blockdim: usize) {
224 for (i, col) in (offset..(offset + blockdim)).enumerate() {
225 let dest = self.colptr[col];
226 self.rowval[dest] = col;
227 self.nzval[dest] = T::zero(); self.colptr[col] += 1;
229 diagtoKKT[i] = dest;
230 }
231 }
232
233 pub(crate) fn fill_missing_diag(&mut self, M: &CscMatrix<T>, initcol: usize) {
237 for i in 0..M.n {
238 if M.colptr[i] == M.colptr[i+1] || M.rowval[M.colptr[i+1]-1] != i
241 {
242 let dest = self.colptr[i + initcol];
244 self.rowval[dest] = i + initcol;
245 self.nzval[dest] = T::zero(); self.colptr[i + initcol] += 1;
247 }
248 }
249 }
250
251 pub(crate) fn colcount_to_colptr(&mut self) {
254 let mut currentptr = 0;
255 for p in &mut self.colptr {
256 let count = *p;
257 *p = currentptr;
258 currentptr += count;
259 }
260 }
261
262 pub(crate) fn colptr_to_colcount(&mut self) {
265 for i in 0..self.n {
266 self.colptr[i] = self.colptr[i + 1] - self.colptr[i];
267 }
268 self.colptr[self.n] = 0;
269 }
270
271 pub(crate) fn backshift_colptrs(&mut self) {
272 self.colptr.rotate_right(1);
273 self.colptr[0] = 0;
274 }
275
276 pub(crate) fn count_diagonal_entries(&self, shape: MatrixTriangle) -> usize {
277 let mut count = 0;
278
279 match shape {
280 MatrixTriangle::Triu => {
281 for i in 0..self.n {
282 if self.colptr[i+1] != self.colptr[i] && self.rowval[self.colptr[i+1]-1] == i
286 {
287 count += 1;
289 }
290 }
291 }
292
293 MatrixTriangle::Tril => {
294 for i in 0..self.n {
295 if self.colptr[i+1] != self.colptr[i] && self.rowval[self.colptr[i]] == i
299 {
300 count += 1;
302 }
303 }
304 }
305 }
306 count
307 }
308}
309
310#[test]
311fn test_count_diagonal_entries_triu() {
312 let shape = MatrixTriangle::Triu;
313
314 let A = CscMatrix::from(&[
315 [1., 2., 3.], [0., 0., 4.], [0., 0., 1.],
318 ]); assert_eq!(A.count_diagonal_entries(shape), 2);
320
321 let A = CscMatrix::from(&[
322 [1., 0., 3.], [0., 0., 4.], [0., 0., 1.],
325 ]); assert_eq!(A.count_diagonal_entries(shape), 2);
327
328 let A = CscMatrix::from(&[
329 [1., 0., 3.], [0., 4., 4.], [0., 0., 1.],
332 ]); assert_eq!(A.count_diagonal_entries(shape), 3);
334
335 let A = CscMatrix::<f64>::zeros((5, 5)); assert_eq!(A.count_diagonal_entries(shape), 0);
337}
338
339#[test]
340fn test_count_diagonal_entries_tril() {
341 let shape = MatrixTriangle::Tril;
342
343 let A = CscMatrix::from(&[
344 [1., 0., 0.], [2., 0., 0.], [3., 4., 1.],
347 ]); assert_eq!(A.count_diagonal_entries(shape), 2);
349
350 let A = CscMatrix::from(&[
351 [1., 0., 0.], [0., 0., 0.], [3., 4., 1.],
354 ]); assert_eq!(A.count_diagonal_entries(shape), 2);
356
357 let A = CscMatrix::from(&[
358 [1., 0., 0.], [0., 4., 0.], [3., 4., 1.],
361 ]); assert_eq!(A.count_diagonal_entries(shape), 3);
363
364 let A = CscMatrix::<f64>::zeros((5, 5)); assert_eq!(A.count_diagonal_entries(shape), 0);
366}