diff --git a/src/adjtrans.jl b/src/adjtrans.jl index 2c144903..b8b0efd7 100644 --- a/src/adjtrans.jl +++ b/src/adjtrans.jl @@ -1,4 +1,5 @@ -export AdjointLinearOperator, TransposeLinearOperator, adjoint, transpose +export AdjointLinearOperator, TransposeLinearOperator, ConjugateLinearOperator, + adjoint, transpose, conj # From julialang:stdlib/LinearAlgebra/src/adjtrans.jl struct AdjointLinearOperator{T} <: AbstractLinearOperator{T} @@ -37,6 +38,7 @@ size(A :: ConjugateLinearOperator, d :: Int) = size(A.parent, d) for f in [:hermitian, :ishermitian, :symmetric, :issymmetric] @eval begin $f(A :: AdjTrans) = $f(A.parent) + $f(A :: ConjugateLinearOperator) = $f(A.parent) end end @@ -89,14 +91,17 @@ end function *(op :: ConjugateLinearOperator, v :: AbstractVector) p = op.parent - return conj.(p * v) + return conj.(p * conj.(v)) end --(op :: AdjointLinearOperator) = adjoint(-op.parent) +-(op :: AdjointLinearOperator) = adjoint(-op.parent) -(op :: TransposeLinearOperator) = transpose(-op.parent) +-(op :: ConjugateLinearOperator) = conj(-op.parent) -*(op :: AdjointLinearOperator, x :: Number) = adjoint(op.parent * x) +*(op :: AdjointLinearOperator, x :: Number) = adjoint(op.parent * conj(x)) *(op :: TransposeLinearOperator, x :: Number) = transpose(op.parent * x) +*(op :: ConjugateLinearOperator, x :: Number) = conj(op.parent * conj(x)) -*(x :: Number, op :: AdjointLinearOperator) = adjoint(x * op.parent) +*(x :: Number, op :: AdjointLinearOperator) = adjoint(conj(x) * op.parent) *(x :: Number, op :: TransposeLinearOperator) = transpose(x * op.parent) +*(x :: Number, op :: ConjugateLinearOperator) = conj(conj(x) * op.parent) diff --git a/test/runtests.jl b/test/runtests.jl index e0bfcb76..24e7aaa8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,6 +3,7 @@ using Test, TestSetExtensions, LinearOperators include("test_aux.jl") include("test_linop.jl") +include("test_adjtrans.jl") include("test_cat.jl") include("test_lbfgs.jl") include("test_lsr1.jl") diff --git a/test/test_adjtrans.jl b/test/test_adjtrans.jl new file mode 100644 index 00000000..a8f5440c --- /dev/null +++ b/test/test_adjtrans.jl @@ -0,0 +1,38 @@ +function test_adjtrans() + @testset ExtendedTestSet "Adjoint/Transpose/Conjugate" begin + A = rand(5,3) + im * rand(5,3) + opA = LinearOperator(A) + + aopA = AdjointLinearOperator(opA) + copA = ConjugateLinearOperator(opA) + topA = TransposeLinearOperator(opA) + + for (foo,fop) in [(adjoint, aopA), + (conj, copA), + (transpose, topA)] + @test foo(opA) === fop + @test Matrix(fop) == foo(A) + @test foo(fop) === opA + + @test Matrix(-fop) == foo(-A) + @test Matrix((2 + 3im) * fop) == (2 + 3im) * foo(A) + @test Matrix(fop * (2 + 3im)) == foo(A) * (2 + 3im) + end + + @test adjoint(topA) === copA + @test adjoint(copA) === topA + @test conj(aopA) === topA + @test conj(topA) === aopA + @test transpose(copA) === aopA + @test transpose(aopA) === copA + + v = rand(5) + im * rand(5) + @test aopA * v == adjoint(A) * v + @test topA * v == transpose(A) * v + + v = rand(3) + im * rand(3) + @test copA * v == conj(A) * v + end +end + +test_adjtrans() diff --git a/test/test_linop.jl b/test/test_linop.jl index 8907329c..0915a7e9 100644 --- a/test/test_linop.jl +++ b/test/test_linop.jl @@ -7,6 +7,7 @@ function test_linop() @testset ExtendedTestSet "Basic operations" begin for op = (LinearOperator(A1), LinearOperator(A1')', transpose(LinearOperator(transpose(A1))), + conj(LinearOperator(conj(A1))), PreallocatedLinearOperator(A1)) show(op); @@ -437,6 +438,13 @@ function test_linop() A = simple_matrix(ComplexF64, 5, 5) @test_throws LinearOperatorException opCholesky(A, check=true) # Not Hermitian / positive definite @test_throws LinearOperatorException opCholesky(-A'*A, check=true) # Not positive definite + + # Adjoint of a symmetric non-hermitian + A = simple_matrix(ComplexF64, 3, 3) + A = A + transpose(A) + op = LinearOperator(3, 3, true, false, v -> A * v) + v = rand(3) + @test op' * v ≈ A' * v end @testset ExtendedTestSet "Type specific operator" begin