Skip to content

Commit 322a9d0

Browse files
committed
BlockArrays in module and more efficient Conv
1 parent af0bf85 commit 322a9d0

File tree

6 files changed

+153
-41
lines changed

6 files changed

+153
-41
lines changed

src/AbstractOperators.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ __precompile__()
22

33
module AbstractOperators
44

5+
# Block stuff
6+
include("utilities/block.jl")
7+
using AbstractOperators.BlockArrays
8+
59
abstract type AbstractOperator end
610

711
abstract type LinearOperator <: AbstractOperator end
@@ -13,11 +17,6 @@ export LinearOperator,
1317
NonLinearOperator,
1418
AbstractOperator
1519

16-
# Block stuff
17-
18-
include("utilities/block.jl")
19-
#include("utilities/deep.jl") # TODO: remove this eventually
20-
2120
# Predicates and properties
2221

2322
include("properties.jl")

src/linearoperators/Conv.jl

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,70 @@ Creates a `LinearOperator` which, when multiplied with an array `x::AbstractVect
99
1010
"""
1111

12-
struct Conv{T,H <: AbstractVector{T}} <: LinearOperator
12+
struct Conv{T,
13+
H <: AbstractVector{T},
14+
Hc <: AbstractVector{Complex{T}},
15+
} <: LinearOperator
1316
dim_in::Tuple{Int}
1417
h::H
18+
buf::H
19+
buf_c1::Hc
20+
buf_c2::Hc
21+
R::Base.DFT.Plan
22+
I::Base.DFT.Plan
1523
end
1624

1725
# Constructors
1826

1927
###standard constructor
20-
function Conv(DomainType::Type, DomainDim::NTuple{N,Int}, h::H) where {H<:AbstractVector, N}
28+
function Conv(DomainType::Type, dim_in::Tuple{Int}, h::H) where {H<:AbstractVector}
2129
eltype(h) != DomainType && error("eltype(h) is $(eltype(h)), should be $(DomainType)")
22-
N != 1 && error("Conv treats only SISO, check Filt and MIMOFilt for MIMO")
23-
Conv{DomainType,H}(DomainDim,h)
30+
31+
buf = zeros(dim_in[1]+length(h)-1)
32+
R = plan_rfft(buf)
33+
buf_c1 = zeros(Complex{eltype(h)}, div(dim_in[1]+length(h)-1,2)+1)
34+
buf_c2 = zeros(Complex{eltype(h)}, div(dim_in[1]+length(h)-1,2)+1)
35+
I = plan_irfft(buf_c1,dim_in[1]+length(h)-1)
36+
Conv{DomainType, H, typeof(buf_c1)}(dim_in,h,buf,buf_c1,buf_c2,R,I)
2437
end
2538

26-
Conv(DomainDim::NTuple{N,Int}, h::H) where {H<:AbstractVector, N} = Conv(eltype(h), DomainDim, h)
39+
Conv(dim_in::NTuple{N,Int}, h::H) where {H<:AbstractVector, N} = Conv(eltype(h), dim_in, h)
2740
Conv(x::H, h::H) where {H} = Conv(eltype(x), size(x), h)
2841

2942
# Mappings
3043

31-
function A_mul_B!(y::H,A::Conv{T,H},b::H) where {T,H}
32-
y .= conv(A.h,b)
44+
function A_mul_B!(y::H, A::Conv{T,H}, b::H) where {T, H}
45+
#y .= conv(A.h,b) #naive implementation
46+
for i in eachindex(A.buf)
47+
A.buf[i] = i <= length(A.h) ? A.h[i] : zero(T)
48+
end
49+
A_mul_B!(A.buf_c1, A.R, A.buf)
50+
for i in eachindex(A.buf)
51+
A.buf[i] = i <= length(b) ? b[i] : zero(T)
52+
end
53+
A_mul_B!(A.buf_c2, A.R, A.buf)
54+
A.buf_c2 .*= A.buf_c1
55+
A_mul_B!(y,A.I,A.buf_c2)
56+
3357
end
3458

35-
function Ac_mul_B!(y::H,A::Conv{T,H},b::H) where {T,H}
36-
y .= xcorr(b,A.h)[size(A,1)[1]:end-length(A.h)+1]
59+
function Ac_mul_B!(y::H, A::Conv{T,H}, b::H) where {T, H}
60+
#y .= xcorr(b,A.h)[size(A,1)[1]:end-length(A.h)+1] #naive implementation
61+
for i in eachindex(A.buf)
62+
ii = length(A.buf)-i+1
63+
A.buf[ii] = i <= length(A.h) ? A.h[i] : zero(T)
64+
end
65+
A_mul_B!(A.buf_c1, A.R, A.buf)
66+
for i in eachindex(A.buf)
67+
A.buf[i] = b[i]
68+
end
69+
A_mul_B!(A.buf_c2, A.R, A.buf)
70+
A.buf_c2 .*= A.buf_c1
71+
A_mul_B!(A.buf,A.I,A.buf_c2)
72+
y[1] = A.buf[end]
73+
for i = 2:length(y)
74+
y[i] = A.buf[i-1]
75+
end
3776
end
3877

3978
# Properties

src/utilities/block.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
# Define block-arrays
2+
module BlockArrays
3+
4+
export RealOrComplex,
5+
BlockArray,
6+
blocksize,
7+
blockeltype,
8+
blocklength,
9+
blockvecnorm,
10+
blockmaxabs,
11+
blocksimilar,
12+
blockcopy,
13+
blockcopy!,
14+
blockset!,
15+
blockvecdot,
16+
blockzeros,
17+
blockaxpy!
18+
219

320
const RealOrComplex{R} = Union{R, Complex{R}}
421
const BlockArray{R} = Union{
@@ -86,3 +103,5 @@ function broadcast!(f::Any, dest::Tuple, op1::Tuple, coef::Number, op2::Tuple, o
86103
end
87104
return dest
88105
end
106+
107+
end

test/runtests.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ verb = true
99

1010
@testset "AbstractOperators" begin
1111

12-
#@testset "Tuple operations" begin
13-
# include("test_deep.jl")
14-
#end
12+
@testset "Block Arrays" begin
13+
include("test_block.jl")
14+
end
1515

1616
@testset "Linear operators" begin
1717
include("test_linear_operators.jl")

test/test_block.jl

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
@printf("\nTesting BlockArrays\n")
2+
3+
using AbstractOperators:BlockArrays
4+
5+
T = Float64
6+
x = [2.0; 3.0]
7+
xb = ([2.0; 3.0], Complex{T}[4.0; 5.0; 6.0], [1.0 2.0 3.0; 4.0 5.0 6.0])
8+
9+
x2 = randn(2)
10+
x2b = (randn(2), randn(3)+im.*randn(3), randn(2,3))
11+
12+
@test blocksize(x) == (2,)
13+
@test blocksize(xb) == ((2,),(3,),(2,3))
14+
15+
@test blockeltype(x) == T
16+
@test blockeltype(xb) == (T, Complex{T},T)
17+
18+
@test blocklength(x) == 2
19+
@test blocklength(xb) == 2+3+6
20+
21+
@test blockvecnorm(x) == vecnorm(x)
22+
@test blockvecnorm(xb) == sqrt(vecnorm(xb[1])^2+vecnorm(xb[2])^2+vecnorm(xb[3])^2)
23+
24+
@test blockmaxabs(x) == 3.0
25+
@test blockmaxabs(xb) == 6.0
26+
27+
@test typeof(blocksimilar(x)) == typeof(x)
28+
@test typeof(blocksimilar(xb)) == typeof(xb)
29+
30+
@test blockcopy(x) == x
31+
@test blockcopy(xb) == xb
32+
33+
y = blocksimilar(x)
34+
yb = blocksimilar(xb)
35+
blockcopy!(y,x)
36+
blockcopy!(yb,xb)
37+
38+
@test y == x
39+
@test yb == xb
40+
41+
y = blocksimilar(x)
42+
yb = blocksimilar(xb)
43+
blockset!(y,x)
44+
blockset!(yb,xb)
45+
46+
@test y == x
47+
@test yb == xb
48+
49+
z = blockvecdot(x,x2)
50+
zb = blockvecdot(xb,x2b)
51+
@test z == vecdot(x,x2)
52+
@test zb == vecdot(xb[1],x2b[1])+vecdot(xb[2],x2b[2])+vecdot(xb[3],x2b[3])
53+
54+
y = blockzeros(x)
55+
yb = blockzeros(xb)
56+
@test y == zeros(2)
57+
@test yb == (zeros(2),zeros(3)+im*zeros(3),zeros(2,3))
58+
59+
y = blockzeros(blocksize(x))
60+
yb = blockzeros(blocksize(xb))
61+
@test y == zeros(2)
62+
@test yb == (zeros(2),zeros(3)+im*zeros(3),zeros(2,3))
63+
64+
y = blockzeros(blockeltype(x),blocksize(x))
65+
yb = blockzeros(blockeltype(xb),blocksize(xb))
66+
@test y == zeros(2)
67+
@test yb == (zeros(2),zeros(3)+im*zeros(3),zeros(2,3))
68+
69+
blockaxpy!(y,x,2,x2)
70+
blockaxpy!(yb,xb,2,x2b)
71+
72+
@test y == x .+ 2.*x2
73+
@test yb == (xb[1] .+ 2.*x2b[1], xb[2] .+ 2.*x2b[2], xb[3] .+ 2.*x2b[3])
74+
75+
76+
77+
78+
79+

test/test_deep.jl

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)