Skip to content

Commit 9bf03cd

Browse files
committed
add missing files
1 parent 55e365f commit 9bf03cd

File tree

10 files changed

+683
-0
lines changed

10 files changed

+683
-0
lines changed

src/DCTOp.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
export DCTOp
2+
3+
mutable struct DCTOp{T} <: AbstractLinearOperator{T}
4+
nrow :: Int
5+
ncol :: Int
6+
symmetric :: Bool
7+
hermitian :: Bool
8+
prod! :: Function
9+
tprod! :: Nothing
10+
ctprod! :: Function
11+
nprod :: Int
12+
ntprod :: Int
13+
nctprod :: Int
14+
args5 :: Bool
15+
use_prod5! :: Bool
16+
allocated5 :: Bool
17+
Mv5 :: Vector{T}
18+
Mtu5 :: Vector{T}
19+
plan
20+
dcttype::Int
21+
end
22+
23+
LinearOperators.storage_type(op::DCTOp) = typeof(op.Mv5)
24+
25+
"""
26+
DCTOp(T::Type, shape::Tuple, dcttype=2)
27+
28+
returns a `DCTOp <: AbstractLinearOperator` which performs a DCT on a given input array.
29+
30+
# Arguments:
31+
* `T::Type` - type of the array to transform
32+
* `shape::Tuple` - size of the array to transform
33+
* `dcttype` - type of DCT (currently `2` and `4` are supported)
34+
"""
35+
function DCTOp(T::Type, shape::Tuple, dcttype=2)
36+
37+
tmp=Array{Complex{real(T)}}(undef, shape)
38+
if dcttype == 2
39+
plan = plan_dct!(tmp)
40+
iplan = plan_idct!(tmp)
41+
prod! = (res, x) -> dct_multiply2(res, plan, x, tmp)
42+
tprod! = (res, x) -> dct_multiply2(res, iplan, x, tmp)
43+
44+
elseif dcttype == 4
45+
factor = T(sqrt(1.0/(prod(shape)* 2^length(shape)) ))
46+
plan = FFTW.plan_r2r!(tmp,FFTW.REDFT11)
47+
prod! = (res, x) -> dct_multiply4(res, plan, x, tmp, factor)
48+
tprod! = (res, x) -> dct_multiply4(res, plan, x, tmp, factor)
49+
else
50+
error("DCT type $(dcttype) not supported")
51+
end
52+
53+
return DCTOp{T}(prod(shape), prod(shape), false, false,
54+
prod!, nothing, tprod!,
55+
0, 0, 0, true, false, true, T[], T[],
56+
plan, dcttype)
57+
end
58+
59+
function dct_multiply2(res::Vector{T}, plan::P, x::Vector{T}, tmp::Array{T,D}) where {T,P,D}
60+
tmp[:] .= x
61+
plan * tmp
62+
res .= vec(tmp)
63+
end
64+
65+
function dct_multiply4(res::Vector{T}, plan::P, x::Vector{T}, tmp::Array{T,D}, factor::T) where {T,P,D}
66+
tmp[:] .= x
67+
plan * tmp
68+
res .= factor.*vec(tmp)
69+
end
70+
71+
function Base.copy(S::DCTOp)
72+
return DCTOp(eltype(S), size(S.plan), S.dcttype)
73+
end

src/DSTOp.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
export DSTOp
2+
3+
mutable struct DSTOp{T} <: AbstractLinearOperator{T}
4+
nrow :: Int
5+
ncol :: Int
6+
symmetric :: Bool
7+
hermitian :: Bool
8+
prod! :: Function
9+
tprod! :: Nothing
10+
ctprod! :: Function
11+
nprod :: Int
12+
ntprod :: Int
13+
nctprod :: Int
14+
args5 :: Bool
15+
use_prod5! :: Bool
16+
allocated5 :: Bool
17+
Mv5 :: Vector{T}
18+
Mtu5 :: Vector{T}
19+
plan
20+
iplan
21+
end
22+
23+
LinearOperators.storage_type(op::DSTOp) = typeof(op.Mv5)
24+
25+
"""
26+
DSTOp(T::Type, shape::Tuple)
27+
28+
returns a `LinearOperator` which performs a DST on a given input array.
29+
30+
# Arguments:
31+
* `T::Type` - type of the array to transform
32+
* `shape::Tuple` - size of the array to transform
33+
"""
34+
function DSTOp(T::Type, shape::Tuple)
35+
tmp=Array{Complex{real(T)}}(undef, shape)
36+
37+
plan = FFTW.plan_r2r!(tmp,FFTW.RODFT10)
38+
iplan = FFTW.plan_r2r!(tmp,FFTW.RODFT01)
39+
40+
w = weights(shape, T)
41+
42+
return DSTOp{T}(prod(shape), prod(shape), true, false
43+
, (res,x) -> dst_multiply!(res,plan,x,tmp,w)
44+
, nothing
45+
, (res,x) -> dst_bmultiply!(res,iplan,x,tmp,w)
46+
, 0, 0, 0, true, false, true, T[], T[]
47+
, plan
48+
, iplan)
49+
end
50+
51+
function weights(s, T::Type)
52+
w = ones(T,s...)./T(sqrt(8*prod(s)))
53+
w[s[1],:,:]./= T(sqrt(2))
54+
if length(s)>1
55+
w[:,s[2],:]./= T(sqrt(2))
56+
if length(s)>2
57+
w[:,:,s[3]]./= T(sqrt(2))
58+
end
59+
end
60+
return reshape(w,prod(s))
61+
end
62+
63+
function dst_multiply!(res::Vector{T}, plan::P, x::Vector{T}, tmp::Array{T,D}, weights::Vector{T}) where {T,P,D}
64+
tmp[:] .= x
65+
plan * tmp
66+
res .= vec(tmp).*weights
67+
end
68+
69+
function dst_bmultiply!(res::Vector{T}, plan::P, x::Vector{T}, tmp::Array{T,D}, weights::Vector{T}) where {T,P,D}
70+
tmp[:] .= x./weights
71+
plan * tmp
72+
res[:] .= vec(tmp)./(8*length(tmp))
73+
end
74+
75+
function Base.copy(S::DSTOp)
76+
return DSTOp(eltype(S), size(S.plan))
77+
end

src/FFTOp.jl

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
export FFTOp
2+
import Base.copy
3+
4+
mutable struct FFTOp{T} <: AbstractLinearOperator{T}
5+
nrow :: Int
6+
ncol :: Int
7+
symmetric :: Bool
8+
hermitian :: Bool
9+
prod! :: Function
10+
tprod! :: Nothing
11+
ctprod! :: Function
12+
nprod :: Int
13+
ntprod :: Int
14+
nctprod :: Int
15+
args5 :: Bool
16+
use_prod5! :: Bool
17+
allocated5 :: Bool
18+
Mv5 :: Vector{T}
19+
Mtu5 :: Vector{T}
20+
plan
21+
iplan
22+
shift::Bool
23+
unitary::Bool
24+
end
25+
26+
LinearOperators.storage_type(op::FFTOp) = typeof(op.Mv5)
27+
28+
"""
29+
FFTOp(T::Type, shape::Tuple, shift=true, unitary=true)
30+
31+
returns an operator which performs an FFT on Arrays of type T
32+
33+
# Arguments:
34+
* `T::Type` - type of the array to transform
35+
* `shape::Tuple` - size of the array to transform
36+
* (`shift=true`) - if true, fftshifts are performed
37+
* (`unitary=true`) - if true, FFT is normalized such that it is unitary
38+
"""
39+
function FFTOp(T::Type, shape::NTuple{D,Int64}, shift::Bool=true; unitary::Bool=true, cuda::Bool=false) where D
40+
41+
#tmpVec = cuda ? CuArray{T}(undef,shape) : Array{Complex{real(T)}}(undef, shape)
42+
tmpVec = Array{Complex{real(T)}}(undef, shape)
43+
plan = plan_fft!(tmpVec; flags=FFTW.MEASURE)
44+
iplan = plan_bfft!(tmpVec; flags=FFTW.MEASURE)
45+
46+
if unitary
47+
facF = T(1.0/sqrt(prod(shape)))
48+
facB = T(1.0/sqrt(prod(shape)))
49+
else
50+
facF = T(1.0)
51+
facB = T(1.0)
52+
end
53+
54+
let shape_=shape, plan_=plan, iplan_=iplan, tmpVec_=tmpVec, facF_=facF, facB_=facB
55+
56+
if shift
57+
return FFTOp{T}(prod(shape), prod(shape), false, false
58+
, (res, x) -> fft_multiply_shift!(res, plan_, x, shape_, facF_, tmpVec_)
59+
, nothing
60+
, (res, x) -> fft_multiply_shift!(res, iplan_, x, shape_, facB_, tmpVec_)
61+
, 0, 0, 0, true, false, true, T[], T[]
62+
, plan
63+
, iplan
64+
, shift
65+
, unitary)
66+
else
67+
return FFTOp{T}(prod(shape), prod(shape), false, false
68+
, (res, x) -> fft_multiply!(res, plan_, x, facF_, tmpVec_)
69+
, nothing
70+
, (res, x) -> fft_multiply!(res, iplan_, x, facB_, tmpVec_)
71+
, 0, 0, 0, true, false, true, T[], T[]
72+
, plan
73+
, iplan
74+
, shift
75+
, unitary)
76+
end
77+
end
78+
end
79+
80+
function fft_multiply!(res::AbstractVector{T}, plan::P, x::AbstractVector{Tr}, factor::T, tmpVec::Array{T,D}) where {T, Tr, P<:AbstractFFTs.Plan, D}
81+
tmpVec[:] .= x
82+
plan * tmpVec
83+
res .= factor .* vec(tmpVec)
84+
end
85+
86+
function fft_multiply_shift!(res::AbstractVector{T}, plan::P, x::AbstractVector{Tr}, shape::NTuple{D}, factor::T, tmpVec::Array{T,D}) where {T, Tr, P<:AbstractFFTs.Plan, D}
87+
ifftshift!(tmpVec, reshape(x,shape))
88+
plan * tmpVec
89+
fftshift!(reshape(res,shape), tmpVec)
90+
res .*= factor
91+
end
92+
93+
94+
function Base.copy(S::FFTOp)
95+
return FFTOp(eltype(S), size(S.plan), S.shift, unitary=S.unitary)
96+
end

src/GradientOp.jl

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
export GradientOp
2+
3+
"""
4+
gradOp(T::Type, shape::NTuple{1,Int64})
5+
6+
1d gradient operator for an array of size `shape`
7+
"""
8+
GradientOp(T::Type, shape::NTuple{1,Int64}) = GradientOp(T,shape,1)
9+
10+
"""
11+
gradOp(T::Type, shape::NTuple{2,Int64})
12+
13+
2d gradient operator for an array of size `shape`
14+
"""
15+
function GradientOp(T::Type, shape::NTuple{2,Int64})
16+
return vcat( GradientOp(T,shape,1), GradientOp(T,shape,2) )
17+
end
18+
19+
"""
20+
gradOp(T::Type, shape::NTuple{3,Int64})
21+
22+
3d gradient operator for an array of size `shape`
23+
"""
24+
function GradientOp(T::Type, shape::NTuple{3,Int64})
25+
return vcat( GradientOp(T,shape,1), GradientOp(T,shape,2), GradientOp(T,shape,3) )
26+
end
27+
28+
"""
29+
gradOp(T::Type, shape::NTuple{N,Int64}, dim::Int64) where N
30+
31+
directional gradient operator along the dimension `dim`
32+
for an array of size `shape`
33+
"""
34+
function GradientOp(T::Type, shape::NTuple{N,Int64}, dim::Int64) where N
35+
nrow = div( (shape[dim]-1)*prod(shape), shape[dim] )
36+
ncol = prod(shape)
37+
return LinearOperator{T}(nrow, ncol, false, false,
38+
(res,x) -> (grad!(res,x,shape,dim) ),
39+
(res,x) -> (grad_t!(res,x,shape,dim) ),
40+
nothing )
41+
end
42+
43+
# directional gradients
44+
function grad!(res::T, img::U, shape::NTuple{1,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
45+
res .= img[1:end-1].-img[2:end]
46+
end
47+
48+
function grad!(res::T, img::U, shape::NTuple{2,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
49+
img = reshape(img,shape)
50+
51+
if dim==1
52+
res .= vec(img[1:end-1,:].-img[2:end,:])
53+
else
54+
res .= vec(img[:,1:end-1].-img[:,2:end])
55+
end
56+
end
57+
58+
function grad!(res::T,img::U, shape::NTuple{3,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
59+
img = reshape(img,shape)
60+
61+
if dim==1
62+
res .= vec(img[1:end-1,:,:].-img[2:end,:,:])
63+
elseif dim==2
64+
res.= vec(img[:,1:end-1,:].-img[:,2:end,:])
65+
else
66+
res.= vec(img[:,:,1:end-1].-img[:,:,2:end])
67+
end
68+
end
69+
70+
# adjoint of directional gradients
71+
function grad_t!(res::T, g::U, shape::NTuple{1,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
72+
res .= zero(eltype(g))
73+
res[1:shape[1]-1] .= g
74+
res[2:shape[1]] .-= g
75+
end
76+
77+
function grad_t!(res::T, g::U, shape::NTuple{2,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
78+
res .= zero(eltype(g))
79+
res_ = reshape(res,shape)
80+
81+
if dim==1
82+
g = reshape(g,shape[1]-1,shape[2])
83+
res_[1:shape[1]-1,:] .= g
84+
res_[2:shape[1],:] .-= g
85+
else
86+
g = reshape(g,shape[1],shape[2]-1)
87+
res_[:,1:shape[2]-1] .= g
88+
res_[:,2:shape[2]] .-= g
89+
end
90+
end
91+
92+
function grad_t!(res::T, g::U, shape::NTuple{3,Int64}, dim::Int64) where {T<:AbstractVector,U<:AbstractVector}
93+
res .= zero(eltype(g))
94+
res_ = reshape(res,shape)
95+
96+
if dim==1
97+
g = reshape(g,shape[1]-1,shape[2],shape[3])
98+
res_[1:shape[1]-1,:,:] .= g
99+
res_[2:shape[1],:,:] .-= g
100+
elseif dim==2
101+
g = reshape(g,shape[1],shape[2]-1,shape[3])
102+
res_[:,1:shape[2]-1,:] .= g
103+
res_[:,2:shape[2],:] .-= g
104+
else
105+
g = reshape(g,shape[1],shape[2],shape[3]-1)
106+
res_[:,:,1:shape[3]-1] .= g
107+
res_[:,:,2:shape[3]] .-= g
108+
end
109+
end

0 commit comments

Comments
 (0)