From 5938c7c14abca509122ecff224ba23f067456cde Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 23 Dec 2025 03:08:52 -0500 Subject: [PATCH 1/6] Use TestSuite for orthnull --- test/amd/orthnull.jl | 285 ------------------------------------ test/cuda/orthnull.jl | 264 --------------------------------- test/orthnull.jl | 234 +++-------------------------- test/runtests.jl | 12 +- test/testsuite/TestSuite.jl | 1 + test/testsuite/orthnull.jl | 268 +++++++++++++++++++++++++++++++++ 6 files changed, 293 insertions(+), 771 deletions(-) delete mode 100644 test/amd/orthnull.jl delete mode 100644 test/cuda/orthnull.jl create mode 100644 test/testsuite/orthnull.jl diff --git a/test/amd/orthnull.jl b/test/amd/orthnull.jl deleted file mode 100644 index 3223979c..00000000 --- a/test/amd/orthnull.jl +++ /dev/null @@ -1,285 +0,0 @@ -using MatrixAlgebraKit -using Test -using TestExtras -using StableRNGs -using LinearAlgebra: LinearAlgebra, I, mul!, diagm, norm -using MatrixAlgebraKit: GPU_SVDAlgorithm, check_input, copy_input, default_svd_algorithm, - initialize_output, AbstractAlgorithm -using AMDGPU - -# testing non-AbstractArray codepaths: -include(joinpath("..", "linearmap.jl")) - -eltypes = (Float32, Float64, ComplexF32, ComplexF64) - -@testset "left_orth and left_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - @testset for n in (37, m, 63) - minmn = min(m, n) - A = ROCArray(randn(rng, T, m, n)) - V, C = @constinferred left_orth(A) - N = @constinferred left_null(A) - @test V isa ROCMatrix{T} && size(V) == (m, minmn) - @test C isa ROCMatrix{T} && size(C) == (minmn, n) - @test N isa ROCMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - M = LinearMap(A) - VM, CM = @constinferred left_orth(M; alg = :svd) - @test parent(VM) * parent(CM) ≈ A - - if m > n - nullity = 5 - V, C = @constinferred left_orth(A) - AMDGPU.@allowscalar begin - N = @constinferred left_null(A; trunc = (; maxnullity = nullity)) - end - @test V isa ROCMatrix{T} && size(V) == (m, minmn) - @test C isa ROCMatrix{T} && size(C) == (minmn, n) - @test N isa ROCMatrix{T} && size(N) == (m, nullity) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - end - - # passing a kind and some kwargs - V, C = @constinferred left_orth(A; alg = :qr, positive = true) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa ROCMatrix{T} && size(V) == (m, minmn) - @test C isa ROCMatrix{T} && size(C) == (minmn, n) - @test N isa ROCMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - # passing an algorithm - V, C = @constinferred left_orth(A; alg = CUSOLVER_HouseholderQR()) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa ROCMatrix{T} && size(V) == (m, minmn) - @test C isa ROCMatrix{T} && size(C) == (minmn, n) - @test N isa ROCMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - Ac = similar(A) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C)) - N2 = @constinferred left_null!(copy!(Ac, A), N) - @test V2 === V - @test C2 === C - @test N2 === N - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - atol = eps(real(T)) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = (; atol = atol)) - AMDGPU.@allowscalar begin - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = (; atol = atol)) - end - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - rtol = eps(real(T)) - for (trunc_orth, trunc_null) in ( - ((; rtol = rtol), (; rtol = rtol)), - (trunctol(; rtol), trunctol(; rtol, keep_below = true)), - ) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = trunc_orth) - AMDGPU.@allowscalar begin - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = trunc_null) - end - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - end - - @testset for alg in (:qr, :polar, :svd) # explicit alg kwarg - m < n && alg == :polar && continue - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg))) - @test V2 * C2 ≈ A - @test isisometric(V2) - if alg != :polar - N2 = @constinferred left_null!(copy!(Ac, A), N; alg) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - end - - # with alg and tol kwargs - if alg == :svd - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; atol)) - AMDGPU.@allowscalar begin - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - end - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; rtol)) - AMDGPU.@allowscalar begin - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - end - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - else - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; atol)) - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - end - end - end -end - -@testset "right_orth and right_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - @testset for n in (37, m, 63) - minmn = min(m, n) - A = ROCArray(randn(rng, T, m, n)) - C, Vᴴ = @constinferred right_orth(A) - Nᴴ = @constinferred right_null(A) - @test C isa ROCMatrix{T} && size(C) == (m, minmn) - @test Vᴴ isa ROCMatrix{T} && size(Vᴴ) == (minmn, n) - @test Nᴴ isa ROCMatrix{T} && size(Nᴴ) == (n - minmn, n) - @test C * Vᴴ ≈ A - @test isisometric(Vᴴ; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ = collect(Vᴴ) - hNᴴ = collect(Nᴴ) - @test hVᴴ' * hVᴴ + hNᴴ' * hNᴴ ≈ I - - M = LinearMap(A) - CM, VMᴴ = @constinferred right_orth(M; alg = :svd) - @test parent(CM) * parent(VMᴴ) ≈ A - - Ac = similar(A) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - atol = eps(real(T)) - rtol = eps(real(T)) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; atol = atol)) - AMDGPU.@allowscalar begin - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; atol = atol)) - end - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; rtol = rtol)) - AMDGPU.@allowscalar begin - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; rtol = rtol)) - end - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - - @testset "alg = $alg" for alg in (:lq, :polar, :svd) - n < m && alg == :polar && continue - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg))) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - if alg != :polar - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg))) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - end - - if alg == :svd - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; atol)) - AMDGPU.@allowscalar begin - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; atol)) - end - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; rtol)) - AMDGPU.@allowscalar begin - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; rtol)) - end - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - else - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; atol)) - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; atol)) - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; rtol)) - end - end - - end -end diff --git a/test/cuda/orthnull.jl b/test/cuda/orthnull.jl deleted file mode 100644 index 2a2a26f6..00000000 --- a/test/cuda/orthnull.jl +++ /dev/null @@ -1,264 +0,0 @@ -using MatrixAlgebraKit -using Test -using TestExtras -using StableRNGs -using LinearAlgebra: LinearAlgebra, I, mul!, diagm, norm -using MatrixAlgebraKit: GPU_SVDAlgorithm, check_input, copy_input, default_svd_algorithm, - initialize_output, AbstractAlgorithm -using CUDA - -# testing non-AbstractArray codepaths: -include(joinpath("..", "linearmap.jl")) - -eltypes = (Float32, Float64, ComplexF32, ComplexF64) - -@testset "left_orth and left_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - @testset for n in (37, m, 63) - minmn = min(m, n) - A = CuArray(randn(rng, T, m, n)) - V, C = @constinferred left_orth(A) - N = @constinferred left_null(A) - @test V isa CuMatrix{T} && size(V) == (m, minmn) - @test C isa CuMatrix{T} && size(C) == (minmn, n) - @test N isa CuMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - M = LinearMap(A) - VM, CM = @constinferred left_orth(M; alg = :svd) - @test parent(VM) * parent(CM) ≈ A - - if m > n - nullity = 5 - V, C = @constinferred left_orth(A) - CUDA.@allowscalar begin - N = @constinferred left_null(A; trunc = (; maxnullity = nullity)) - end - @test V isa CuMatrix{T} && size(V) == (m, minmn) - @test C isa CuMatrix{T} && size(C) == (minmn, n) - @test N isa CuMatrix{T} && size(N) == (m, nullity) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - end - - # passing a kind and some kwargs - V, C = @constinferred left_orth(A; alg = :qr, positive = true) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa CuMatrix{T} && size(V) == (m, minmn) - @test C isa CuMatrix{T} && size(C) == (minmn, n) - @test N isa CuMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - # passing an algorithm - V, C = @constinferred left_orth(A; alg = CUSOLVER_HouseholderQR()) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa CuMatrix{T} && size(V) == (m, minmn) - @test C isa CuMatrix{T} && size(C) == (minmn, n) - @test N isa CuMatrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - hV = collect(V) - hN = collect(N) - @test hV * hV' + hN * hN' ≈ I - - Ac = similar(A) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C)) - N2 = @constinferred left_null!(copy!(Ac, A), N) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - atol = eps(real(T)) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = (; atol = atol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = (; atol = atol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - rtol = eps(real(T)) - for (trunc_orth, trunc_null) in ( - ((; rtol = rtol), (; rtol = rtol)), - (trunctol(; rtol), trunctol(; rtol, keep_below = true)), - ) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = trunc_orth) - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = trunc_null) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - end - - @testset for alg in (:qr, :polar, :svd) # explicit alg kwarg - m < n && alg == :polar && continue - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg))) - @test V2 * C2 ≈ A - @test isisometric(V2) - if alg != :polar - N2 = @constinferred left_null!(copy!(Ac, A), N; alg) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - end - - # with alg and tol kwargs - if alg == :svd - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; atol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; rtol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - hV2 = collect(V2) - hN2 = collect(N2) - @test hV2 * hV2' + hN2 * hN2' ≈ I - else - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; atol)) - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - end - end - end -end - -@testset "right_orth and right_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - @testset for n in (37, m, 63) - minmn = min(m, n) - A = CuArray(randn(rng, T, m, n)) - C, Vᴴ = @constinferred right_orth(A) - Nᴴ = @constinferred right_null(A) - @test C isa CuMatrix{T} && size(C) == (m, minmn) - @test Vᴴ isa CuMatrix{T} && size(Vᴴ) == (minmn, n) - @test Nᴴ isa CuMatrix{T} && size(Nᴴ) == (n - minmn, n) - @test C * Vᴴ ≈ A - @test isisometric(Vᴴ; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ = collect(Vᴴ) - hNᴴ = collect(Nᴴ) - @test hVᴴ' * hVᴴ + hNᴴ' * hNᴴ ≈ I - - M = LinearMap(A) - CM, VMᴴ = @constinferred right_orth(M; alg = :svd) - @test parent(CM) * parent(VMᴴ) ≈ A - - Ac = similar(A) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - atol = eps(real(T)) - rtol = eps(real(T)) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; atol = atol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; atol = atol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; rtol = rtol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; rtol = rtol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - @testset "alg = $alg" for alg in (:lq, :polar, :svd) - n < m && alg == :polar && continue - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg))) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - if alg != :polar - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg))) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - end - - if alg == :svd - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; atol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; atol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; rtol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; rtol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - hVᴴ2 = collect(Vᴴ2) - hNᴴ2 = collect(Nᴴ2) - @test hVᴴ2' * hVᴴ2 + hNᴴ2' * hNᴴ2 ≈ I - else - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; atol)) - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; atol)) - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; rtol)) - end - end - end -end diff --git a/test/orthnull.jl b/test/orthnull.jl index ce742e8f..874971ec 100644 --- a/test/orthnull.jl +++ b/test/orthnull.jl @@ -2,225 +2,33 @@ using MatrixAlgebraKit using Test using TestExtras using StableRNGs -using LinearAlgebra: LinearAlgebra, I +using LinearAlgebra: LinearAlgebra, I, Diagonal +using CUDA, AMDGPU -# testing non-AbstractArray codepaths: -include("linearmap.jl") +BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) +GenericFloats = (Float16, BigFloat, Complex{BigFloat}) -eltypes = (Float32, Float64, ComplexF32, ComplexF64) -@testset "left_orth and left_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - for n in (37, m, 63) - minmn = min(m, n) - A = randn(rng, T, m, n) - V, C = @constinferred left_orth(A) - N = @constinferred left_null(A) - @test V isa Matrix{T} && size(V) == (m, minmn) - @test C isa Matrix{T} && size(C) == (minmn, n) - @test N isa Matrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - @test V * V' + N * N' ≈ I +@isdefined(TestSuite) || include("testsuite/TestSuite.jl") +using .TestSuite - M = LinearMap(A) - VM, CM = @constinferred left_orth(M; alg = :svd) - @test parent(VM) * parent(CM) ≈ A +is_buildkite = get(ENV, "BUILDKITE", "false") == "true" - if m > n - nullity = 5 - V, C = @constinferred left_orth(A) - N = @constinferred left_null(A; trunc = (; maxnullity = nullity)) - @test V isa Matrix{T} && size(V) == (m, minmn) - @test C isa Matrix{T} && size(C) == (minmn, n) - @test N isa Matrix{T} && size(N) == (m, nullity) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) +m = 54 +for T in (BLASFloats..., GenericFloats...), n in (37, m, 63) + TestSuite.seed_rng!(123) + if T ∈ BLASFloats + if CUDA.functional() + TestSuite.test_orthnull(CuMatrix{T}, (m, n)) + n == m && TestSuite.test_orthnull(Diagonal{T, CuVector{T}}, m) end - - # passing a kind and some kwargs - V, C = @constinferred left_orth(A; alg = :qr, positive = true) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa Matrix{T} && size(V) == (m, minmn) - @test C isa Matrix{T} && size(C) == (minmn, n) - @test N isa Matrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - @test V * V' + N * N' ≈ I - - # passing an algorithm - V, C = @constinferred left_orth(A; alg = LAPACK_HouseholderQR()) - N = @constinferred left_null(A; alg = :qr, positive = true) - @test V isa Matrix{T} && size(V) == (m, minmn) - @test C isa Matrix{T} && size(C) == (minmn, n) - @test N isa Matrix{T} && size(N) == (m, m - minmn) - @test V * C ≈ A - @test isisometric(V) - @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N) - @test V * V' + N * N' ≈ I - - Ac = similar(A) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C)) - N2 = @constinferred left_null!(copy!(Ac, A), N) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - - atol = eps(real(T)) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = (; atol = atol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = (; atol = atol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - - rtol = eps(real(T)) - for (trunc_orth, trunc_null) in ( - ((; rtol = rtol), (; rtol = rtol)), - (trunctol(; rtol), trunctol(; rtol, keep_below = true)), - ) - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); trunc = trunc_orth) - N2 = @constinferred left_null!(copy!(Ac, A), N; trunc = trunc_null) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - end - - for alg in (:qr, :polar, :svd) # explicit kind kwarg - m < n && alg === :polar && continue - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg))) - @test V2 * C2 ≈ A - @test isisometric(V2) - if alg != :polar - N2 = @constinferred left_null!(copy!(Ac, A), N; alg) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - end - - # with kind and tol kwargs - if alg == :svd - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; atol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - - V2, C2 = @constinferred left_orth!(copy!(Ac, A), (V, C); alg = $(QuoteNode(alg)), trunc = (; rtol)) - N2 = @constinferred left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - @test V2 * C2 ≈ A - @test isisometric(V2) - @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(N2) - @test V2 * V2' + N2 * N2' ≈ I - else - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; atol)) - @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) - @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) - end + if AMDGPU.functional() + TestSuite.test_orthnull(ROCMatrix{T}, (m, n)) + n == m && TestSuite.test_orthnull(Diagonal{T, ROCVector{T}}, m) end end -end - -@testset "right_orth and right_null for T = $T" for T in eltypes - rng = StableRNG(123) - m = 54 - for n in (37, m, 63) - minmn = min(m, n) - A = randn(rng, T, m, n) - C, Vᴴ = @constinferred right_orth(A) - Nᴴ = @constinferred right_null(A) - @test C isa Matrix{T} && size(C) == (m, minmn) - @test Vᴴ isa Matrix{T} && size(Vᴴ) == (minmn, n) - @test Nᴴ isa Matrix{T} && size(Nᴴ) == (n - minmn, n) - @test C * Vᴴ ≈ A - @test isisometric(Vᴴ; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - @test Vᴴ' * Vᴴ + Nᴴ' * Nᴴ ≈ I - - M = LinearMap(A) - CM, VMᴴ = @constinferred right_orth(M; alg = :svd) - @test parent(CM) * parent(VMᴴ) ≈ A - - Ac = similar(A) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - - atol = eps(real(T)) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; atol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; atol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - - rtol = eps(real(T)) - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; rtol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; rtol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - - for alg in (:lq, :polar, :svd) - n < m && alg == :polar && continue - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg))) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - if alg != :polar - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg))) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - end - - if alg == :svd - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; atol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; atol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - - C2, Vᴴ2 = @constinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = $(QuoteNode(alg)), trunc = (; rtol)) - Nᴴ2 = @constinferred right_null!(copy!(Ac, A), Nᴴ; alg = $(QuoteNode(alg)), trunc = (; rtol)) - @test C2 * Vᴴ2 ≈ A - @test isisometric(Vᴴ2; side = :right) - @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) - @test isisometric(Nᴴ2; side = :right) - @test Vᴴ2' * Vᴴ2 + Nᴴ2' * Nᴴ2 ≈ I - else - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; atol)) - @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; rtol)) - alg == :polar && continue - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; atol)) - @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; rtol)) - end - end + if !is_buildkite + TestSuite.test_orthnull(T, (m, n)) + AT = Diagonal{T, Vector{T}} + TestSuite.test_orthnull(AT, m) end end diff --git a/test/runtests.jl b/test/runtests.jl index baeb77bb..9fe64002 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,9 +16,6 @@ if !is_buildkite @safetestset "Generalized Eigenvalue Decomposition" begin include("gen_eig.jl") end - @safetestset "Image and Null Space" begin - include("orthnull.jl") - end @safetestset "Mooncake" begin include("mooncake.jl") end @@ -63,15 +60,15 @@ end @safetestset "Hermitian Eigenvalue Decomposition" begin include("eigh.jl") end +@safetestset "Image and Null Space" begin + include("orthnull.jl") +end using CUDA if CUDA.functional() @safetestset "CUDA SVD" begin include("cuda/svd.jl") end - @safetestset "CUDA Image and Null Space" begin - include("cuda/orthnull.jl") - end end using AMDGPU @@ -79,7 +76,4 @@ if AMDGPU.functional() @safetestset "AMDGPU SVD" begin include("amd/svd.jl") end - @safetestset "AMDGPU Image and Null Space" begin - include("amd/orthnull.jl") - end end diff --git a/test/testsuite/TestSuite.jl b/test/testsuite/TestSuite.jl index 25da777a..f288eff5 100644 --- a/test/testsuite/TestSuite.jl +++ b/test/testsuite/TestSuite.jl @@ -76,5 +76,6 @@ include("projections.jl") include("schur.jl") include("eig.jl") include("eigh.jl") +include("orthnull.jl") end diff --git a/test/testsuite/orthnull.jl b/test/testsuite/orthnull.jl new file mode 100644 index 00000000..fa09214e --- /dev/null +++ b/test/testsuite/orthnull.jl @@ -0,0 +1,268 @@ +using TestExtras +using LinearAlgebra + +include("../linearmap.jl") + +function test_orthnull(T::Type, sz; kwargs...) + summary_str = testargs_summary(T, sz) + return @testset "orthnull $summary_str" begin + test_left_orthnull(T, sz; kwargs...) + test_right_orthnull(T, sz; kwargs...) + end +end + +function test_left_orthnull( + T::Type, sz; + atol::Real = 0, rtol::Real = precision(T), + kwargs... + ) + summary_str = testargs_summary(T, sz) + return @testset "left_orth! and left_null! $summary_str" begin + A = instantiate_matrix(T, sz) + Ac = deepcopy(A) + V, C = @testinferred left_orth(A) + N = @testinferred left_null(A) + m, n = size(A) + minmn = min(m, n) + @test V isa typeof(A) && size(V) == (m, minmn) + @test C isa typeof(A) && size(C) == (minmn, n) + @test eltype(N) == eltype(A) && size(N) == (m, m - minmn) + @test V * C ≈ A + @test isisometric(V) + @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N) + @test collect(V) * collect(V)' + collect(N) * collect(N)' ≈ I + + M = LinearMap(A) + # broken + #VM, CM = @testinferred left_orth(M; alg = :svd) + VM, CM = left_orth(M; alg = :svd) + @test parent(VM) * parent(CM) ≈ A + + if m > n && (T <: Number || T <: Diagonal{<:Number, <:Vector}) + nullity = 5 + V, C = @testinferred left_orth(A) + N = @testinferred left_null(A; trunc = (; maxnullity = nullity)) + @test V isa typeof(A) && size(V) == (m, minmn) + @test C isa typeof(A) && size(C) == (minmn, n) + @test eltype(N) == eltype(A) && size(N) == (m, nullity) + @test V * C ≈ A + @test isisometric(V) + @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N) + end + + # passing a kind and some kwargs + # broken + # V, C = @testinferred left_orth(A; alg = :qr, positive = true) + V, C = left_orth(A; alg = :qr, positive = true) + N = @testinferred left_null(A; alg = :qr, positive = true) + @test V isa typeof(A) && size(V) == (m, minmn) + @test C isa typeof(A) && size(C) == (minmn, n) + @test eltype(N) == eltype(A) && size(N) == (m, m - minmn) + @test V * C ≈ A + @test isisometric(V) + @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N) + @test collect(V) * collect(V)' + collect(N) * collect(N)' ≈ I + + # passing an algorithm + if !isa(A, Diagonal) + V, C = @testinferred left_orth(A; alg = MatrixAlgebraKit.default_qr_algorithm(A)) + N = @testinferred left_null(A; alg = :qr, positive = true) + @test V isa typeof(A) && size(V) == (m, minmn) + @test C isa typeof(A) && size(C) == (minmn, n) + @test eltype(N) == eltype(A) && size(N) == (m, m - minmn) + @test V * C ≈ A + @test isisometric(V) + @test LinearAlgebra.norm(A' * N) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N) + @test collect(V) * collect(V)' + collect(N) * collect(N)' ≈ I + end + + Ac = similar(A) + V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C)) + N2 = @testinferred left_null!(copy!(Ac, A), N) + @test V2 * C2 ≈ A + @test isisometric(V2) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + + # doesn't work on AMD... + atol = eps(real(eltype(T))) + V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); trunc = (; atol = atol)) + N2 = @testinferred left_null!(copy!(Ac, A), N; trunc = (; atol = atol)) + @test V2 * C2 ≈ A + @test isisometric(V2) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + + if (T <: Number || T <: Diagonal{<:Number, <:Vector}) + rtol = eps(real(eltype(T))) + for (trunc_orth, trunc_null) in ( + ((; rtol = rtol), (; rtol = rtol)), + (trunctol(; rtol), trunctol(; rtol, keep_below = true)), + ) + V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); trunc = trunc_orth) + N2 = @testinferred left_null!(copy!(Ac, A), N; trunc = trunc_null) + @test V2 * C2 ≈ A + @test isisometric(V2) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + end + end + + for alg in (:qr, :polar, :svd) # explicit kind kwarg + m < n && alg === :polar && continue + # broken + # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg) + V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg) + @test V2 * C2 ≈ A + @test isisometric(V2) + if alg != :polar + N2 = @testinferred left_null!(copy!(Ac, A), N; alg) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + end + + # with kind and tol kwargs + if alg == :svd + if (T <: Number || T <: Diagonal{<:Number, <:Vector}) + # broken + # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; atol)) + V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; atol)) + N2 = @testinferred left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) + @test V2 * C2 ≈ A + @test isisometric(V2) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + + # broken + # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; rtol)) + V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; rtol)) + N2 = @testinferred left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) + @test V2 * C2 ≈ A + @test isisometric(V2) + @test LinearAlgebra.norm(A' * N2) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(N2) + @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I + end + else + @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; atol)) + @test_throws ArgumentError left_orth!(copy!(Ac, A), (V, C); alg, trunc = (; rtol)) + alg == :polar && continue + @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) + @test_throws ArgumentError left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) + end + end + end +end + +function test_right_orthnull( + T::Type, sz; + atol::Real = 0, rtol::Real = precision(T), + kwargs... + ) + summary_str = testargs_summary(T, sz) + return @testset "right_orth! and right_null! $summary_str" begin + A = instantiate_matrix(T, sz) + m, n = size(A) + minmn = min(m, n) + Ac = deepcopy(A) + C, Vᴴ = @testinferred right_orth(A) + Nᴴ = @testinferred right_null(A) + @test C isa typeof(A) && size(C) == (m, minmn) + @test Vᴴ isa typeof(A) && size(Vᴴ) == (minmn, n) + @test eltype(Nᴴ) == eltype(A) && size(Nᴴ) == (n - minmn, n) + @test C * Vᴴ ≈ A + @test isisometric(Vᴴ; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ; side = :right) + @test collect(Vᴴ)' * collect(Vᴴ) + collect(Nᴴ)' * collect(Nᴴ) ≈ I + + M = LinearMap(A) + # broken + #CM, VMᴴ = @testinferred right_orth(M; alg = :svd) + CM, VMᴴ = right_orth(M; alg = :svd) + @test parent(CM) * parent(VMᴴ) ≈ A + + Ac = similar(A) + C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ)) + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + + if (T <: Number || T <: Diagonal{<:Number, <:Vector}) + atol = eps(real(eltype(T))) + C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; atol)) + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; atol)) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + + rtol = eps(real(eltype(T))) + C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); trunc = (; rtol)) + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; trunc = (; rtol)) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ2; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + end + + for alg in (:lq, :polar, :svd) + n < m && alg == :polar && continue + # broken + #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg) + C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + if alg != :polar + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; alg = alg) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ2; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + end + + if alg == :svd + if (T <: Number || T <: Diagonal{<:Number, <:Vector}) + # broken + #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; atol)) + C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; atol)) + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; alg = alg, trunc = (; atol)) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ2; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + + # broken + #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; rtol)) + C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; rtol)) + Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; alg = alg, trunc = (; rtol)) + @test C2 * Vᴴ2 ≈ A + @test isisometric(Vᴴ2; side = :right) + @test LinearAlgebra.norm(A * adjoint(Nᴴ2)) ≈ 0 atol = MatrixAlgebraKit.defaulttol(T) + @test isisometric(Nᴴ2; side = :right) + @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I + end + else + @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; atol)) + @test_throws ArgumentError right_orth!(copy!(Ac, A), (C, Vᴴ); alg, trunc = (; rtol)) + alg == :polar && continue + @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; atol)) + @test_throws ArgumentError right_null!(copy!(Ac, A), Nᴴ; alg, trunc = (; rtol)) + end + end + end +end From 10aaff989fd37362fee22778b4bf7c493b98faad Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 23 Dec 2025 11:22:52 +0100 Subject: [PATCH 2/6] Don't test nonworking stuff --- test/orthnull.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/orthnull.jl b/test/orthnull.jl index 874971ec..5db9d2de 100644 --- a/test/orthnull.jl +++ b/test/orthnull.jl @@ -27,8 +27,10 @@ for T in (BLASFloats..., GenericFloats...), n in (37, m, 63) end end if !is_buildkite - TestSuite.test_orthnull(T, (m, n)) - AT = Diagonal{T, Vector{T}} - TestSuite.test_orthnull(AT, m) + if T ∈ BLASFloats # no qr_null or lq_null for GenericFloats + TestSuite.test_orthnull(T, (m, n)) + end + #AT = Diagonal{T, Vector{T}} + #TestSuite.test_orthnull(AT, m) # not supported end end From 62f8ce5b5eaa87fabac712d8396c7e2c25e8b675 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 23 Dec 2025 08:47:16 -0500 Subject: [PATCH 3/6] Fix linearmap --- test/linearmap.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/linearmap.jl b/test/linearmap.jl index bbf84e5e..ad6102d7 100644 --- a/test/linearmap.jl +++ b/test/linearmap.jl @@ -3,7 +3,7 @@ module LinearMaps export LinearMap using MatrixAlgebraKit - using MatrixAlgebraKit: AbstractAlgorithm + using MatrixAlgebraKit: AbstractAlgorithm, DiagonalAlgorithm import MatrixAlgebraKit as MAK using LinearAlgebra: LinearAlgebra, lmul!, rmul! @@ -32,6 +32,12 @@ module LinearMaps LinearMap.(MAK.initialize_output($f!, parent(A), alg)) @eval MAK.$f!(A::LinearMap, F, alg::AbstractAlgorithm) = LinearMap.(MAK.$f!(parent(A), parent.(F), alg)) + @eval MAK.check_input(::typeof($f!), A::LinearMap, F, alg::DiagonalAlgorithm) = + MAK.check_input($f!, parent(A), parent.(F), alg) + @eval MAK.initialize_output(::typeof($f!), A::LinearMap, alg::DiagonalAlgorithm) = + LinearMap.(MAK.initialize_output($f!, parent(A), alg)) + @eval MAK.$f!(A::LinearMap, F, alg::DiagonalAlgorithm) = + LinearMap.(MAK.$f!(parent(A), parent.(F), alg)) end for f in (:qr, :lq, :svd) From 2e7aced5a1be607e55fd7b431ea55c84d6b9a3c6 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 23 Dec 2025 09:15:31 -0500 Subject: [PATCH 4/6] Fix AMD --- .../MatrixAlgebraKitAMDGPUExt.jl | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/ext/MatrixAlgebraKitAMDGPUExt/MatrixAlgebraKitAMDGPUExt.jl b/ext/MatrixAlgebraKitAMDGPUExt/MatrixAlgebraKitAMDGPUExt.jl index ff150f24..4e2255a6 100644 --- a/ext/MatrixAlgebraKitAMDGPUExt/MatrixAlgebraKitAMDGPUExt.jl +++ b/ext/MatrixAlgebraKitAMDGPUExt/MatrixAlgebraKitAMDGPUExt.jl @@ -159,43 +159,4 @@ function MatrixAlgebraKit._avgdiff!(A::StridedROCMatrix, B::StridedROCMatrix) return A, B end -function MatrixAlgebraKit.truncate( - ::typeof(left_null!), US::Tuple{TU, TS}, strategy::TruncationStrategy - ) where {TU <: ROCMatrix, TS} - # TODO: avoid allocation? - U, S = US - extended_S = vcat(diagview(S), zeros(eltype(S), max(0, size(S, 1) - size(S, 2)))) - ind = MatrixAlgebraKit.findtruncated(extended_S, strategy) - trunc_cols = collect(1:size(U, 2))[ind] - Utrunc = U[:, trunc_cols] - return Utrunc, ind -end -function MatrixAlgebraKit.truncate( - ::typeof(right_null!), SVᴴ::Tuple{TS, TVᴴ}, strategy::TruncationStrategy - ) where {TS, TVᴴ <: ROCMatrix} - # TODO: avoid allocation? - S, Vᴴ = SVᴴ - extended_S = vcat(diagview(S), zeros(eltype(S), max(0, size(S, 2) - size(S, 1)))) - ind = MatrixAlgebraKit.findtruncated(extended_S, strategy) - trunc_rows = collect(1:size(Vᴴ, 1))[ind] - Vᴴtrunc = Vᴴ[trunc_rows, :] - return Vᴴtrunc, ind -end - -# disambiguate: -function MatrixAlgebraKit.truncate( - ::typeof(left_null!), (U, S)::Tuple{TU, TS}, ::NoTruncation - ) where {TU <: ROCMatrix, TS} - m, n = size(S) - ind = (n + 1):m - return U[:, ind], ind -end -function MatrixAlgebraKit.truncate( - ::typeof(right_null!), (S, Vᴴ)::Tuple{TS, TVᴴ}, ::NoTruncation - ) where {TS, TVᴴ <: ROCMatrix} - m, n = size(S) - ind = (m + 1):n - return Vᴴ[ind, :], ind -end - end From 5d7d06deef7b8f97701b5b3068eccc9090a493e1 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 27 Dec 2025 20:05:33 +0100 Subject: [PATCH 5/6] Support GenericFloats too --- ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl | 3 +++ test/linearmap.jl | 7 ++++++- test/orthnull.jl | 6 ++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl b/ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl index 14c63a4e..b78b38a0 100644 --- a/ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl +++ b/ext/MatrixAlgebraKitGenericLinearAlgebraExt.jl @@ -2,6 +2,7 @@ module MatrixAlgebraKitGenericLinearAlgebraExt using MatrixAlgebraKit using MatrixAlgebraKit: sign_safe, check_input, diagview, gaugefix!, one!, default_fixgauge +using MatrixAlgebraKit: left_orth_alg using GenericLinearAlgebra: svd!, svdvals!, eigen!, eigvals!, Hermitian, qr! using LinearAlgebra: I, Diagonal, lmul! @@ -133,4 +134,6 @@ function MatrixAlgebraKit.default_lq_algorithm(::Type{T}; kwargs...) where {T <: return MatrixAlgebraKit.LQViaTransposedQR(GLA_HouseholderQR(; kwargs...)) end +MatrixAlgebraKit.left_orth_alg(alg::GLA_HouseholderQR) = MatrixAlgebraKit.LeftOrthViaQR(alg) + end diff --git a/test/linearmap.jl b/test/linearmap.jl index ad6102d7..a7adaae7 100644 --- a/test/linearmap.jl +++ b/test/linearmap.jl @@ -3,7 +3,8 @@ module LinearMaps export LinearMap using MatrixAlgebraKit - using MatrixAlgebraKit: AbstractAlgorithm, DiagonalAlgorithm + using MatrixAlgebraKit: AbstractAlgorithm, DiagonalAlgorithm, GLA_QRIteration + using GenericLinearAlgebra import MatrixAlgebraKit as MAK using LinearAlgebra: LinearAlgebra, lmul!, rmul! @@ -30,8 +31,12 @@ module LinearMaps MAK.check_input($f!, parent(A), parent.(F), alg) @eval MAK.initialize_output(::typeof($f!), A::LinearMap, alg::AbstractAlgorithm) = LinearMap.(MAK.initialize_output($f!, parent(A), alg)) + @eval MAK.initialize_output(::typeof($f!), A::LinearMap, alg::GLA_QRIteration) = + (nothing, nothing, nothing) @eval MAK.$f!(A::LinearMap, F, alg::AbstractAlgorithm) = LinearMap.(MAK.$f!(parent(A), parent.(F), alg)) + @eval MAK.$f!(A::LinearMap, F, alg::GLA_QRIteration) = + LinearMap.(MAK.$f!(parent(A), F, alg)) @eval MAK.check_input(::typeof($f!), A::LinearMap, F, alg::DiagonalAlgorithm) = MAK.check_input($f!, parent(A), parent.(F), alg) @eval MAK.initialize_output(::typeof($f!), A::LinearMap, alg::DiagonalAlgorithm) = diff --git a/test/orthnull.jl b/test/orthnull.jl index 5db9d2de..f2e0e611 100644 --- a/test/orthnull.jl +++ b/test/orthnull.jl @@ -6,7 +6,7 @@ using LinearAlgebra: LinearAlgebra, I, Diagonal using CUDA, AMDGPU BLASFloats = (Float32, Float64, ComplexF32, ComplexF64) -GenericFloats = (Float16, BigFloat, Complex{BigFloat}) +GenericFloats = (BigFloat, Complex{BigFloat}) @isdefined(TestSuite) || include("testsuite/TestSuite.jl") using .TestSuite @@ -27,9 +27,7 @@ for T in (BLASFloats..., GenericFloats...), n in (37, m, 63) end end if !is_buildkite - if T ∈ BLASFloats # no qr_null or lq_null for GenericFloats - TestSuite.test_orthnull(T, (m, n)) - end + TestSuite.test_orthnull(T, (m, n)) #AT = Diagonal{T, Vector{T}} #TestSuite.test_orthnull(AT, m) # not supported end From d482cf0f8a60dc23af681189043984af02678e9c Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 31 Dec 2025 11:04:14 +0100 Subject: [PATCH 6/6] Try to fix testinferred with algs --- test/testsuite/orthnull.jl | 62 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/test/testsuite/orthnull.jl b/test/testsuite/orthnull.jl index fa09214e..4a3c7b0e 100644 --- a/test/testsuite/orthnull.jl +++ b/test/testsuite/orthnull.jl @@ -3,6 +3,20 @@ using LinearAlgebra include("../linearmap.jl") +_left_orth_svd(x; kwargs...) = left_orth(x; alg = :svd, kwargs...) +_left_orth_svd!(x, VC; kwargs...) = left_orth!(x, VC; alg = :svd, kwargs...) +_left_orth_qr(x; kwargs...) = left_orth(x; alg = :qr, kwargs...) +_left_orth_qr!(x, VC; kwargs...) = left_orth!(x, VC; alg = :qr, kwargs...) +_left_orth_polar(x; kwargs...) = left_orth(x; alg = :polar, kwargs...) +_left_orth_polar!(x, VC; kwargs...) = left_orth!(x, VC; alg = :polar, kwargs...) + +_right_orth_svd(x; kwargs...) = right_orth(x; alg = :svd, kwargs...) +_right_orth_svd!(x, CVᴴ; kwargs...) = right_orth!(x, CVᴴ; alg = :svd, kwargs...) +_right_orth_lq(x; kwargs...) = right_orth(x; alg = :lq, kwargs...) +_right_orth_lq!(x, CVᴴ; kwargs...) = right_orth!(x, CVᴴ; alg = :lq, kwargs...) +_right_orth_polar(x; kwargs...) = right_orth(x; alg = :polar, kwargs...) +_right_orth_polar!(x, CVᴴ; kwargs...) = right_orth!(x, CVᴴ; alg = :polar, kwargs...) + function test_orthnull(T::Type, sz; kwargs...) summary_str = testargs_summary(T, sz) return @testset "orthnull $summary_str" begin @@ -34,9 +48,7 @@ function test_left_orthnull( @test collect(V) * collect(V)' + collect(N) * collect(N)' ≈ I M = LinearMap(A) - # broken - #VM, CM = @testinferred left_orth(M; alg = :svd) - VM, CM = left_orth(M; alg = :svd) + VM, CM = @testinferred _left_orth_svd(M) @test parent(VM) * parent(CM) ≈ A if m > n && (T <: Number || T <: Diagonal{<:Number, <:Vector}) @@ -53,9 +65,7 @@ function test_left_orthnull( end # passing a kind and some kwargs - # broken - # V, C = @testinferred left_orth(A; alg = :qr, positive = true) - V, C = left_orth(A; alg = :qr, positive = true) + V, C = @testinferred _left_orth_qr(A; positive = true) N = @testinferred left_null(A; alg = :qr, positive = true) @test V isa typeof(A) && size(V) == (m, minmn) @test C isa typeof(A) && size(C) == (minmn, n) @@ -117,9 +127,13 @@ function test_left_orthnull( for alg in (:qr, :polar, :svd) # explicit kind kwarg m < n && alg === :polar && continue - # broken - # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg) - V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg) + if alg == :svd + V2, C2 = @testinferred _left_orth_svd!(copy!(Ac, A), (V, C)) + elseif alg == :qr + V2, C2 = @testinferred _left_orth_qr!(copy!(Ac, A), (V, C)) + elseif alg == :polar + V2, C2 = @testinferred _left_orth_polar!(copy!(Ac, A), (V, C)) + end @test V2 * C2 ≈ A @test isisometric(V2) if alg != :polar @@ -132,9 +146,7 @@ function test_left_orthnull( # with kind and tol kwargs if alg == :svd if (T <: Number || T <: Diagonal{<:Number, <:Vector}) - # broken - # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; atol)) - V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; atol)) + V2, C2 = @testinferred _left_orth_svd!(copy!(Ac, A), (V, C); trunc = (; atol)) N2 = @testinferred left_null!(copy!(Ac, A), N; alg, trunc = (; atol)) @test V2 * C2 ≈ A @test isisometric(V2) @@ -142,9 +154,7 @@ function test_left_orthnull( @test isisometric(N2) @test collect(V2) * collect(V2)' + collect(N2) * collect(N2)' ≈ I - # broken - # V2, C2 = @testinferred left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; rtol)) - V2, C2 = left_orth!(copy!(Ac, A), (V, C); alg = alg, trunc = (; rtol)) + V2, C2 = @testinferred _left_orth_svd!(copy!(Ac, A), (V, C); trunc = (; rtol)) N2 = @testinferred left_null!(copy!(Ac, A), N; alg, trunc = (; rtol)) @test V2 * C2 ≈ A @test isisometric(V2) @@ -186,9 +196,7 @@ function test_right_orthnull( @test collect(Vᴴ)' * collect(Vᴴ) + collect(Nᴴ)' * collect(Nᴴ) ≈ I M = LinearMap(A) - # broken - #CM, VMᴴ = @testinferred right_orth(M; alg = :svd) - CM, VMᴴ = right_orth(M; alg = :svd) + CM, VMᴴ = @testinferred _right_orth_svd(M) @test parent(CM) * parent(VMᴴ) ≈ A Ac = similar(A) @@ -222,9 +230,13 @@ function test_right_orthnull( for alg in (:lq, :polar, :svd) n < m && alg == :polar && continue - # broken - #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg) - C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg) + if alg == :lq + C2, Vᴴ2 = @testinferred _right_orth_lq!(copy!(Ac, A), (C, Vᴴ)) + elseif alg == :polar + C2, Vᴴ2 = @testinferred _right_orth_polar!(copy!(Ac, A), (C, Vᴴ)) + elseif alg == :svd + C2, Vᴴ2 = @testinferred _right_orth_svd!(copy!(Ac, A), (C, Vᴴ)) + end @test C2 * Vᴴ2 ≈ A @test isisometric(Vᴴ2; side = :right) if alg != :polar @@ -236,9 +248,7 @@ function test_right_orthnull( if alg == :svd if (T <: Number || T <: Diagonal{<:Number, <:Vector}) - # broken - #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; atol)) - C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; atol)) + C2, Vᴴ2 = @testinferred _right_orth_svd!(copy!(Ac, A), (C, Vᴴ); trunc = (; atol)) Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; alg = alg, trunc = (; atol)) @test C2 * Vᴴ2 ≈ A @test isisometric(Vᴴ2; side = :right) @@ -246,9 +256,7 @@ function test_right_orthnull( @test isisometric(Nᴴ2; side = :right) @test collect(Vᴴ2)' * collect(Vᴴ2) + collect(Nᴴ2)' * collect(Nᴴ2) ≈ I - # broken - #C2, Vᴴ2 = @testinferred right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; rtol)) - C2, Vᴴ2 = right_orth!(copy!(Ac, A), (C, Vᴴ); alg = alg, trunc = (; rtol)) + C2, Vᴴ2 = @testinferred _right_orth_svd!(copy!(Ac, A), (C, Vᴴ); trunc = (; rtol)) Nᴴ2 = @testinferred right_null!(copy!(Ac, A), Nᴴ; alg = alg, trunc = (; rtol)) @test C2 * Vᴴ2 ≈ A @test isisometric(Vᴴ2; side = :right)