clarabel/algebra/
matrix_traits.rs1#![allow(non_snake_case)]
2
3use crate::algebra::MatrixConcatenationError;
4use crate::algebra::MatrixShape;
5
6#[cfg_attr(not(feature = "sdp"), allow(dead_code))]
7pub(crate) trait ShapedMatrix {
8 fn shape(&self) -> MatrixShape;
9 fn size(&self) -> (usize, usize);
10 fn nrows(&self) -> usize {
11 self.size().0
12 }
13 fn ncols(&self) -> usize {
14 self.size().1
15 }
16 fn is_square(&self) -> bool {
17 self.nrows() == self.ncols()
18 }
19}
20
21pub trait TriangularMatrixChecks {
23 fn is_triu(&self) -> bool;
25 fn is_tril(&self) -> bool;
27}
28
29pub trait BlockConcatenate: Sized {
31 fn hcat(A: &Self, B: &Self) -> Result<Self, MatrixConcatenationError>;
39
40 fn vcat(A: &Self, B: &Self) -> Result<Self, MatrixConcatenationError>;
49
50 fn hvcat(mats: &[&[&Self]]) -> Result<Self, MatrixConcatenationError>;
52
53 fn blockdiag(mats: &[&Self]) -> Result<Self, MatrixConcatenationError>;
55}
56
57pub(crate) fn hvcat_dim_check<MAT: ShapedMatrix>(
58 mats: &[&[&MAT]],
59) -> Result<(), MatrixConcatenationError> {
60 if mats.is_empty() || mats[0].is_empty() {
62 return Err(MatrixConcatenationError::IncompatibleDimension);
63 };
64
65 let len0 = mats[0].len();
67 for mat in mats.iter().skip(1) {
68 if mat.len() != len0 {
69 return Err(MatrixConcatenationError::IncompatibleDimension);
70 }
71 }
72
73 for blockrow in mats {
77 let rows = blockrow[0].nrows();
78 for mat in blockrow.iter().skip(1) {
79 if mat.nrows() != rows {
80 return Err(MatrixConcatenationError::IncompatibleDimension);
81 }
82 }
83 }
84
85 for (blockcol, topblock) in mats[0].iter().enumerate() {
87 let cols = topblock.ncols();
88 for matrow in mats.iter().skip(1) {
89 if matrow[blockcol].ncols() != cols {
90 return Err(MatrixConcatenationError::IncompatibleDimension);
91 }
92 }
93 }
94
95 Ok(())
96}