///|
/// Block assembly front doors for dense matrices.
///
/// Current Limits:
/// - These helpers only materialize explicit dense block layouts.
/// - They do not preserve symbolic block structure; use `MatrixExpr` for unevaluated block syntax.
///
/// Assemble a block-diagonal dense matrix.
///
/// - Does: Places each block on the main block diagonal and fills all off-diagonal regions with exact zero.
/// - Input: An `Array[Matrix]` whose items can have different shapes.
/// - Returns: One dense `Matrix` whose shape is the sum of all block heights and widths.
/// - Limits: Raises any `MatrixError` emitted by the delegated dense zero-matrix construction.
pub fn block_diag(blocks : Array[Matrix]) -> Matrix raise MatrixError {
let mut total_rows = 0
let mut total_cols = 0
for block in blocks {
total_rows += block.rows
total_cols += block.cols
}
let out = zeros(total_rows, cols=Some(total_cols))
let data = clone_expr_rows(out.data)
let mut row_offset = 0
let mut col_offset = 0
for block in blocks {
for i in 0.. Matrix raise MatrixError {
if rows.is_empty() {
return zeros(0, cols=Some(0))
}
let row_heights : Array[Int] = []
let col_widths : Array[Int] = []
let first_width = rows[0].length()
for row in rows {
if row.length() != first_width {
raise MatrixError::ShapeError(
"block_matrix expects rectangular block layout",
)
}
}
for row in rows {
let height = if row.is_empty() { 0 } else { row[0].rows }
for block in row {
if block.rows != height {
raise MatrixError::ShapeError(
"blocks in the same row must have equal heights",
)
}
}
row_heights.push(height)
}
for j in 0..