|
1 | 1 | using MatrixAlgebraKit |
2 | | -using MatrixAlgebraKit: check_hermitian, default_hermitian_tol |
3 | 2 | using Test |
4 | 3 | using TestExtras |
5 | 4 | using StableRNGs |
6 | 5 | using LinearAlgebra: LinearAlgebra, Diagonal, norm, normalize! |
| 6 | +using CUDA, AMDGPU |
7 | 7 |
|
8 | | -const BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) |
| 8 | +BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) |
| 9 | +GenericFloats = (Float16, BigFloat, Complex{BigFloat}) |
9 | 10 |
|
10 | | -@testset "project_(anti)hermitian! for T = $T" for T in BLASFloats |
11 | | - rng = StableRNG(123) |
12 | | - m = 54 |
13 | | - noisefactor = eps(real(T))^(3 / 4) |
| 11 | +@isdefined(TestSuite) || include("testsuite/TestSuite.jl") |
| 12 | +using .TestSuite |
14 | 13 |
|
15 | | - mat0 = zeros(T, (1, 1)) |
16 | | - @test ishermitian(mat0) |
17 | | - @test ishermitian(mat0; atol = default_hermitian_tol(mat0)) |
18 | | - @test isnothing(check_hermitian(mat0)) |
| 14 | +is_buildkite = get(ENV, "BUILDKITE", "false") == "true" |
19 | 15 |
|
20 | | - for alg in (NativeBlocked(blocksize = 16), NativeBlocked(blocksize = 32), NativeBlocked(blocksize = 64)) |
21 | | - for A in (randn(rng, T, m, m), Diagonal(randn(rng, T, m))) |
22 | | - Ah = (A + A') / 2 |
23 | | - Aa = (A - A') / 2 |
24 | | - Ac = copy(A) |
25 | 16 |
|
26 | | - Bh = project_hermitian(A, alg) |
27 | | - @test ishermitian(Bh) |
28 | | - @test Bh ≈ Ah |
29 | | - @test A == Ac |
30 | | - Bh_approx = Bh + noisefactor * Aa |
31 | | - # this is still hermitian for real Diagonal: |A - A'| == 0 |
32 | | - @test !ishermitian(Bh_approx) || norm(Aa) == 0 |
33 | | - @test ishermitian(Bh_approx; rtol = 10 * noisefactor) |
34 | | - |
35 | | - Ba = project_antihermitian(A, alg) |
36 | | - @test isantihermitian(Ba) |
37 | | - @test Ba ≈ Aa |
38 | | - @test A == Ac |
39 | | - Ba_approx = Ba + noisefactor * Ah |
40 | | - @test !isantihermitian(Ba_approx) |
41 | | - # this is never anti-hermitian for real Diagonal: |A - A'| == 0 |
42 | | - @test isantihermitian(Ba_approx; rtol = 10 * noisefactor) || norm(Aa) == 0 |
43 | | - |
44 | | - Bh = project_hermitian!(Ac, alg) |
45 | | - @test Bh === Ac |
46 | | - @test ishermitian(Bh) |
47 | | - @test Bh ≈ Ah |
48 | | - |
49 | | - copy!(Ac, A) |
50 | | - Ba = project_antihermitian!(Ac, alg) |
51 | | - @test Ba === Ac |
52 | | - @test isantihermitian(Ba) |
53 | | - @test Ba ≈ Aa |
| 17 | +m = 54 |
| 18 | +for T in (BLASFloats..., GenericFloats...) |
| 19 | + TestSuite.seed_rng!(123) |
| 20 | + if T ∈ BLASFloats |
| 21 | + if CUDA.functional() |
| 22 | + TestSuite.test_projections(CuMatrix{T}, (m, m); test_blocksize = false) |
| 23 | + TestSuite.test_projections(Diagonal{T, CuVector{T}}, m; test_blocksize = false) |
54 | 24 | end |
55 | | - end |
56 | | - |
57 | | - # test approximate error calculation |
58 | | - A = normalize!(randn(rng, T, m, m)) |
59 | | - Ah = project_hermitian(A) |
60 | | - Aa = project_antihermitian(A) |
61 | | - |
62 | | - Ah_approx = Ah + noisefactor * Aa |
63 | | - ϵ = norm(project_antihermitian(Ah_approx)) |
64 | | - @test !ishermitian(Ah_approx; atol = (999 // 1000) * ϵ) |
65 | | - @test ishermitian(Ah_approx; atol = (1001 // 1000) * ϵ) |
66 | | - |
67 | | - Aa_approx = Aa + noisefactor * Ah |
68 | | - ϵ = norm(project_hermitian(Aa_approx)) |
69 | | - @test !isantihermitian(Aa_approx; atol = (999 // 1000) * ϵ) |
70 | | - @test isantihermitian(Aa_approx; atol = (1001 // 1000) * ϵ) |
71 | | -end |
72 | | - |
73 | | -@testset "project_isometric! for T = $T" for T in BLASFloats |
74 | | - rng = StableRNG(123) |
75 | | - m = 54 |
76 | | - @testset "size ($m, $n)" for n in (37, m) |
77 | | - k = min(m, n) |
78 | | - if LinearAlgebra.LAPACK.version() < v"3.12.0" |
79 | | - svdalgs = (LAPACK_DivideAndConquer(), LAPACK_QRIteration(), LAPACK_Bisection()) |
80 | | - else |
81 | | - svdalgs = (LAPACK_DivideAndConquer(), LAPACK_QRIteration(), LAPACK_Bisection(), LAPACK_Jacobi()) |
82 | | - end |
83 | | - algs = (PolarViaSVD.(svdalgs)..., PolarNewton()) |
84 | | - @testset "algorithm $alg" for alg in algs |
85 | | - A = randn(rng, T, m, n) |
86 | | - W = project_isometric(A, alg) |
87 | | - @test isisometric(W) |
88 | | - W2 = project_isometric(W, alg) |
89 | | - @test W2 ≈ W # stability of the projection |
90 | | - @test W * (W' * A) ≈ A |
91 | | -
|
92 | | - Ac = similar(A) |
93 | | - W2 = @constinferred project_isometric!(copy!(Ac, A), W, alg) |
94 | | - @test W2 === W |
95 | | - @test isisometric(W) |
96 | | -
|
97 | | - # test that W is closer to A then any other isometry |
98 | | - for k in 1:10 |
99 | | - δA = randn(rng, T, m, n) |
100 | | - W = project_isometric(A, alg) |
101 | | - W2 = project_isometric(A + δA / 100, alg) |
102 | | - @test norm(A - W2) > norm(A - W) |
103 | | - end |
| 25 | + if AMDGPU.functional() |
| 26 | + TestSuite.test_projections(ROCMatrix{T}, (m, m); test_blocksize = false) |
| 27 | + TestSuite.test_projections(Diagonal{T, ROCVector{T}}, m; test_blocksize = false) |
104 | 28 | end |
105 | 29 | end |
| 30 | + if !is_buildkite |
| 31 | + TestSuite.test_projections(T, (m, m)) |
| 32 | + AT = Diagonal{T, Vector{T}} |
| 33 | + TestSuite.test_projections(AT, m) |
| 34 | + end |
106 | 35 | end |
0 commit comments