Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/implementations/polar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function left_polar!(A::AbstractMatrix, WP, alg::PolarViaSVD)
if !isempty(P)
S .= sqrt.(S)
SsqrtVᴴ = lmul!(S, Vᴴ)
P = mul!(P, SsqrtVᴴ', SsqrtVᴴ)
P = _mul_herm!(P, SsqrtVᴴ)
end
return (W, P)
end
Expand All @@ -65,11 +65,24 @@ function right_polar!(A::AbstractMatrix, PWᴴ, alg::PolarViaSVD)
if !isempty(P)
S .= sqrt.(S)
USsqrt = rmul!(U, S)
P = mul!(P, USsqrt, USsqrt')
P = _mul_herm!(P, USsqrt')
end
return (P, Wᴴ)
end

# Implement `mul!(C, A', A)` and guarantee the result is hermitian.
# For BLAS calls that dispatch to `syrk` or `herk` this works automatically
# for GPU this currently does not seem to be guaranteed so we manually project
function _mul_herm!(C, A)
mul!(C, A', A)
project_hermitian!(C)
return C
end
function _mul_herm!(C::YALAPACK.BlasMat{T}, A::YALAPACK.BlasMat{T}) where {T}
mul!(C, A', A)
return C
end

# Implementation via Newton
# --------------------------
function left_polar!(A::AbstractMatrix, WP, alg::PolarNewton)
Expand Down
12 changes: 4 additions & 8 deletions test/testsuite/polar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,14 @@ function test_left_polar(
@test eltype(P) == eltype(A) && size(P) == (size(A, 2), size(A, 2))
@test W * P ≈ A
@test isisometric(W)
@test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P))
@test isposdef(project_hermitian!(P))
@test isposdef(P)

W2, P2 = @testinferred left_polar!(Ac, (W, P), alg)
@test W2 === W
@test P2 === P
@test W * P ≈ A
@test isisometric(W)
@test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P))
@test isposdef(project_hermitian!(P))
@test isposdef(P)

noP = similar(P, (0, 0))
W2, P2 = @testinferred left_polar!(copy!(Ac, A), (W, noP), alg)
Expand Down Expand Up @@ -62,16 +60,14 @@ function test_right_polar(
@test eltype(P) == eltype(A) && size(P) == (size(A, 1), size(A, 1))
@test P * Wᴴ ≈ A
@test isisometric(Wᴴ; side = :right)
@test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P))
@test isposdef(project_hermitian!(P))
@test isposdef(P)

P2, Wᴴ2 = @testinferred right_polar!(Ac, (P, Wᴴ), alg)
@test P2 === P
@test Wᴴ2 === Wᴴ
@test P * Wᴴ ≈ A
@test isisometric(Wᴴ; side = :right)
@test ishermitian(P; rtol = MatrixAlgebraKit.defaulttol(P))
@test isposdef(project_hermitian!(P))
@test isposdef(P)

noP = similar(P, (0, 0))
P2, Wᴴ2 = @testinferred right_polar!(copy!(Ac, A), (noP, Wᴴ), alg)
Expand Down
Loading