11using BlockArrays: Block, BlockedMatrix, BlockedVector, blocks, mortar
22using BlockSparseArrays:
3- BlockSparseArray, BlockDiagonal, blockstoredlength, eachblockstoredindex
3+ BlockSparseArrays,
4+ BlockDiagonal,
5+ BlockSparseArray,
6+ BlockSparseMatrix,
7+ blockstoredlength,
8+ eachblockstoredindex
9+ using LinearAlgebra: LinearAlgebra, Diagonal, hermitianpart, pinv
410using MatrixAlgebraKit:
511 diagview,
612 eig_full,
@@ -22,10 +28,87 @@ using MatrixAlgebraKit:
2228 svd_trunc,
2329 truncrank,
2430 trunctol
25- using LinearAlgebra: LinearAlgebra, Diagonal, hermitianpart
2631using Random: Random
2732using StableRNGs: StableRNG
28- using Test: @inferred , @testset , @test
33+ using Test: @inferred , @test , @test_broken , @test_throws , @testset
34+
35+ @testset " Matrix functions (T=$elt )" for elt in (Float32, Float64, ComplexF64)
36+ rng = StableRNG (123 )
37+ a = BlockSparseMatrix {elt} (undef, [2 , 3 ], [2 , 3 ])
38+ a[Block (1 , 1 )] = randn (rng, elt, 2 , 2 )
39+ a[Block (2 , 2 )] = randn (rng, elt, 3 , 3 )
40+ MATRIX_FUNCTIONS = BlockSparseArrays. MATRIX_FUNCTIONS
41+ MATRIX_FUNCTIONS = [MATRIX_FUNCTIONS; [:inv , :pinv ]]
42+ # Only works when real, also isn't defined in Julia 1.10.
43+ MATRIX_FUNCTIONS = setdiff (MATRIX_FUNCTIONS, [:cbrt ])
44+ MATRIX_FUNCTIONS_LOW_ACCURACY = [:acoth ]
45+ for f in setdiff (MATRIX_FUNCTIONS, MATRIX_FUNCTIONS_LOW_ACCURACY)
46+ @eval begin
47+ fa = $ f ($ a)
48+ @test Matrix (fa) ≈ $ f (Matrix ($ a)) rtol = √ (eps (real ($ elt)))
49+ @test fa isa BlockSparseMatrix
50+ @test issetequal (eachblockstoredindex (fa), [Block (1 , 1 ), Block (2 , 2 )])
51+ end
52+ end
53+ for f in MATRIX_FUNCTIONS_LOW_ACCURACY
54+ @eval begin
55+ fa = $ f ($ a)
56+ if ! Sys. isapple () && ($ elt <: Real )
57+ # `acoth` appears to be broken on this matrix on Windows and Ubuntu
58+ # for real matrices.
59+ @test_broken Matrix (fa) ≈ $ f (Matrix ($ a)) rtol = √ eps (real ($ elt))
60+ else
61+ @test Matrix (fa) ≈ $ f (Matrix ($ a)) rtol = √ eps (real ($ elt))
62+ end
63+ @test fa isa BlockSparseMatrix
64+ @test issetequal (eachblockstoredindex (fa), [Block (1 , 1 ), Block (2 , 2 )])
65+ end
66+ end
67+
68+ # Catch case of off-diagonal blocks.
69+ rng = StableRNG (123 )
70+ a = BlockSparseMatrix {elt} (undef, [2 , 3 ], [2 , 3 ])
71+ a[Block (1 , 1 )] = randn (rng, elt, 2 , 2 )
72+ a[Block (1 , 2 )] = randn (rng, elt, 2 , 3 )
73+ for f in MATRIX_FUNCTIONS
74+ @eval begin
75+ @test_throws ArgumentError $ f ($ a)
76+ end
77+ end
78+
79+ # Missing diagonal blocks.
80+ rng = StableRNG (123 )
81+ a = BlockSparseMatrix {elt} (undef, [2 , 3 ], [2 , 3 ])
82+ a[Block (2 , 2 )] = randn (rng, elt, 3 , 3 )
83+ MATRIX_FUNCTIONS = BlockSparseArrays. MATRIX_FUNCTIONS
84+ # These functions involve inverses so they break when there are zeros on the diagonal.
85+ MATRIX_FUNCTIONS_SINGULAR = [
86+ :log , :acsc , :asec , :acot , :acsch , :asech , :acoth , :csc , :cot , :csch , :coth
87+ ]
88+ MATRIX_FUNCTIONS = setdiff (MATRIX_FUNCTIONS, MATRIX_FUNCTIONS_SINGULAR)
89+ # Dense version is broken for some reason, investigate.
90+ MATRIX_FUNCTIONS = setdiff (MATRIX_FUNCTIONS, [:cbrt ])
91+ for f in MATRIX_FUNCTIONS
92+ @eval begin
93+ fa = $ f ($ a)
94+ @test Matrix (fa) ≈ $ f (Matrix ($ a)) rtol = √ (eps (real ($ elt)))
95+ @test fa isa BlockSparseMatrix
96+ @test issetequal (eachblockstoredindex (fa), [Block (1 , 1 ), Block (2 , 2 )])
97+ end
98+ end
99+
100+ SINGULAR_EXCEPTION = if VERSION < v " 1.11-"
101+ # A different exception is thrown in older versions of Julia.
102+ LinearAlgebra. LAPACKException
103+ else
104+ LinearAlgebra. SingularException
105+ end
106+ for f in setdiff (MATRIX_FUNCTIONS_SINGULAR, [:log ])
107+ @eval begin
108+ @test_throws $ SINGULAR_EXCEPTION $ f ($ a)
109+ end
110+ end
111+ end
29112
30113function test_svd (a, (U, S, Vᴴ); full= false )
31114 # Check that the SVD is correct
0 commit comments