@@ -17,3 +17,36 @@ function supremum(r1::AbstractUnitRange, r2::AbstractUnitRange)
17
17
return r2
18
18
end
19
19
end
20
+
21
+ function blockdiagonalize (A:: AbstractBlockSparseMatrix )
22
+ # sort in order to avoid depending on internal details such as dictionary order
23
+ bIs = sort! (collect (eachblockstoredindex (A)); by= Int ∘ last ∘ Tuple)
24
+
25
+ # obtain permutation for the blocks that are present
26
+ rowperm = map (first ∘ Tuple, bIs)
27
+ colperm = map (last ∘ Tuple, bIs)
28
+
29
+ # These checks might be expensive but are convenient for now
30
+ allunique (rowperm) || throw (ArgumentError (" input contains more than one block per row" ))
31
+ allunique (colperm) ||
32
+ throw (ArgumentError (" input contains more than one block per column" ))
33
+
34
+ # post-process empty rows and columns: this pairs them up in order of occurance,
35
+ # putting empty rows and columns due to rectangularity at the end
36
+ emptyrows = setdiff (Block .(1 : blocksize (A, 1 )), rowperm)
37
+ append! (rowperm, emptyrows)
38
+ emptycols = setdiff (Block .(1 : blocksize (A, 2 )), colperm)
39
+ append! (colperm, emptycols)
40
+
41
+ return A[rowperm, colperm], rowperm, colperm
42
+ end
43
+
44
+ function isblockdiagonal (A:: AbstractBlockSparseMatrix )
45
+ for bI in eachblockstoredindex (A)
46
+ row, col = Tuple (bI)
47
+ row == col || return false
48
+ end
49
+ # don't need to check for rows and cols appearing only once
50
+ # this is guaranteed as long as eachblockstoredindex is unique, which we assume
51
+ return true
52
+ end
0 commit comments