|
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 |