Sat, 20 Feb 2021 16:26:31 -0500
Add "extra" string output to simple_iterate.
| 20 | 1 | ######################################################## |
| 2 | # Abstract Hilbert space linear operators. Does not set | |
| 3 | # any limits on the input and output data types unlike | |
| 4 | # the package LinearOperators. | |
| 5 | ######################################################## | |
| 6 | ||
| 7 | __precompile__() | |
| 8 | ||
| 9 | module LinOps | |
| 10 | ||
| 11 | export LinOp, IdOp, AdjointOp, AdjointableOp, | |
| 12 | calc_adjoint, calc_adjoint!, inplace!, | |
| 13 | opnorm_estimate | |
| 14 | ||
| 15 | # General type | |
| 16 | ||
| 17 | abstract type LinOp{X, Y} end | |
| 18 | ||
| 19 | function inplace!(y::Y, op::LinOp{X,Y}, x::X) where {X, Y} | |
| 20 | y .= op(x) | |
| 21 | end | |
| 22 | ||
| 23 | # Adjoint operator for operators that define calc_adjoint and calc_adjoint! | |
| 24 | ||
| 25 | abstract type AdjointableOp{X, Y} <: LinOp{X,Y} end | |
| 26 | ||
| 27 | struct AdjointOp{X,Y,T<:AdjointableOp{X,Y}} <: LinOp{Y,X} | |
| 28 | op :: T | |
| 29 | end | |
| 30 | ||
| 31 | function Base.adjoint(op::T) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 32 | return AdjointOp{X,Y,T}(op) | |
| 33 | end | |
| 34 | ||
| 35 | function Base.adjoint(adj::AdjointOp{X,Y,T}) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 36 | return adj.op | |
| 37 | end | |
| 38 | ||
| 39 | function (adj::AdjointOp{X,Y,T})(y::Y) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 40 | calc_adjoint(adj, y) | |
| 41 | end | |
| 42 | ||
| 43 | function inplace!(x::X, adj::AdjointOp{X,Y,T}, y::Y) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 44 | calc_adjoint!(x, adj.op, y) | |
| 45 | end | |
| 46 | ||
| 47 | function calc_adjoint(op::T, y::Y) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 48 | @error "unimplemented" | |
| 49 | end | |
| 50 | ||
| 51 | function calc_adjoint!(x::X, adj::T, y::Y) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 52 | x .= calc_adjoint(adj, y) | |
| 53 | end | |
| 54 | ||
| 55 | function opnorm_estimate(adj::AdjointOp{X,Y,T}) where {X, Y, T<:AdjointableOp{X,Y}} | |
| 56 | return opnorm_estimate(adj.op) | |
| 57 | end | |
| 58 | ||
| 59 | # Identity operator | |
| 60 | ||
| 61 | struct IdOp{X} <: LinOp{X,X} | |
| 62 | end | |
| 63 | ||
| 64 | function (op::IdOp{X})(x::X) where X | |
| 65 | return x | |
| 66 | end | |
| 67 | ||
| 68 | function Base.adjoint(op::IdOp{X}) where X | |
| 69 | return op | |
| 70 | end | |
| 71 | ||
| 72 | function opnorm_estimate(op::IdOp{X}) where X | |
| 73 | return 1 | |
| 74 | end | |
| 75 | ||
| 76 | # Matrix operator | |
| 77 | ||
| 78 | struct MatrixOp{T<:Real} | |
| 79 | m :: AbstractArray{T, 2} | |
| 80 | end | |
| 81 | ||
| 82 | function (op::MatrixOp{T})(v::Vector{T}) where T | |
| 83 | return op.m*v | |
| 84 | end | |
| 85 | ||
| 86 | function Base.adjoint(op::MatrixOp{T}) where T | |
| 87 | return MatrixOp(op.m') | |
| 88 | end | |
| 89 | ||
| 90 | function opnorm_estimate(op::MatrixOp{T}) where T | |
| 91 | return opnorm(op.m, 2) | |
| 92 | end | |
| 93 | ||
| 94 | end |