Skip to content

Commit 782cf6c

Browse files
modify butterfly to remove power-of-two restriction
see issue #16
1 parent e2b7c59 commit 782cf6c

File tree

6 files changed

+25
-29
lines changed

6 files changed

+25
-29
lines changed

src/SphericalHarmonics/Butterfly.jl

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ function Butterfly{T}(A::AbstractMatrix{T}, L::Int64; isorthogonal::Bool = false
4646
indices[1] = Vector{Int64}(tL+1)
4747
cs[1] = Vector{Vector{Int64}}(tL)
4848

49-
nd = n÷tL
50-
nl = 1
51-
nu = nd
49+
ninds = linspace(1, n+1, tL+1)
5250
indices[1][1] = 1
5351
for j = 1:tL
52+
nl = round(Int, ninds[j])
53+
nu = round(Int, ninds[j+1]) - 1
54+
nd = nu-nl+1
5455
if isorthogonal
5556
factors[1][j] = IDPackedV{T}(collect(1:nd),Int64[],Array{T}(nd,0))
5657
else
@@ -59,8 +60,6 @@ function Butterfly{T}(A::AbstractMatrix{T}, L::Int64; isorthogonal::Bool = false
5960
permutations[1][j] = factors[1][j][:P]
6061
indices[1][j+1] = indices[1][j] + size(factors[1][j], 1)
6162
cs[1][j] = factors[1][j].sk+nl-1
62-
nl += nd
63-
nu += nd
6463
end
6564

6665
ii, jj = 2, (tL>>1)
@@ -71,41 +70,37 @@ function Butterfly{T}(A::AbstractMatrix{T}, L::Int64; isorthogonal::Bool = false
7170
cs[l] = Vector{Vector{Int64}}(tL)
7271

7372
ctr = 0
74-
md = m÷ii
75-
ml = 1
76-
mu = md
73+
minds = linspace(1, m+1, ii+1)
7774
indices[l][1] = 1
7875
for i = 1:ii
7976
shft = 2jj*div(ctr,2jj)
77+
ml = round(Int, minds[i])
78+
mu = round(Int, minds[i+1]) - 1
8079
for j = 1:jj
8180
cols = vcat(cs[l-1][2j-1+shft],cs[l-1][2j+shft])
8281
lc = length(cols)
8382
Av = A[ml:mu,cols]
8483
if maximum(abs, Av) < realmin(real(T))/eps(real(T))
8584
factors[l][j+ctr] = IDPackedV{T}(Int64[], collect(1:lc), Array{T}(0,lc))
8685
else
87-
LRAOpts.rtol = eps(real(T))*max(length(ml:mu),lc)
86+
LRAOpts.rtol = eps(real(T))*max(mu-ml+1, lc)
8887
factors[l][j+ctr] = idfact!(Av, LRAOpts)
8988
end
9089
permutations[l][j+ctr] = factors[l][j+ctr][:P]
9190
indices[l][j+ctr+1] = indices[l][j+ctr] + size(factors[l][j+ctr], 1)
9291
cs[l][j+ctr] = cols[factors[l][j+ctr].sk]
9392
end
94-
ml += md
95-
mu += md
9693
ctr += jj
9794
end
9895
ii <<= 1
9996
jj >>= 1
10097
end
10198

102-
md = m÷tL
103-
ml = 1
104-
mu = md
99+
minds = linspace(1, m+1, tL+1)
105100
for i = 1:tL
106-
columns[i] = A[ml:mu,cs[L+1][i]]
107-
ml += md
108-
mu += md
101+
ml = round(Int, minds[i])
102+
mu = round(Int, minds[i+1]) - 1
103+
columns[i] = A[ml:mu, cs[L+1][i]]
109104
end
110105

111106
kk = sumkmax(indices)

src/SphericalHarmonics/fastplan.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ end
1010

1111
function FastSphericalHarmonicPlan{T}(A::Matrix{T}, L::Int; opts...)
1212
M, N = size(A)
13-
@assert ispow2(M)
1413
@assert N == 2M-1
1514
n = (N+1)÷2
1615
RP = RotationPlan(T, n-1)
@@ -36,7 +35,7 @@ function FastSphericalHarmonicPlan{T}(A::Matrix{T}, L::Int; opts...)
3635
FastSphericalHarmonicPlan(RP, BF, p1, p2, p1inv, p2inv, B)
3736
end
3837

39-
FastSphericalHarmonicPlan(A::Matrix; opts...) = FastSphericalHarmonicPlan(A, round(Int, log2(size(A, 1)+1)-6); opts...)
38+
FastSphericalHarmonicPlan(A::Matrix; opts...) = FastSphericalHarmonicPlan(A, floor(Int, log2(size(A, 1)+1)-6); opts...)
4039

4140
function Base.A_mul_B!(Y::Matrix, FP::FastSphericalHarmonicPlan, X::Matrix)
4241
RP, BF, p1, p2, B = FP.RP, FP.BF, FP.p1, FP.p2, FP.B

src/SphericalHarmonics/thinplan.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ end
1414

1515
function ThinSphericalHarmonicPlan{T}(A::Matrix{T}, L::Int; opts...)
1616
M, N = size(A)
17-
@assert ispow2(M)
1817
@assert N == 2M-1
1918
n = (N+1)÷2
2019
RP = RotationPlan(T, n-1)
@@ -40,7 +39,7 @@ function ThinSphericalHarmonicPlan{T}(A::Matrix{T}, L::Int; opts...)
4039
ThinSphericalHarmonicPlan(RP, BF, p1, p2, p1inv, p2inv, B)
4140
end
4241

43-
ThinSphericalHarmonicPlan(A::Matrix; opts...) = ThinSphericalHarmonicPlan(A, round(Int, log2(size(A, 1)+1)-6); opts...)
42+
ThinSphericalHarmonicPlan(A::Matrix; opts...) = ThinSphericalHarmonicPlan(A, floor(Int, log2(size(A, 1)+1)-6); opts...)
4443

4544
function Base.A_mul_B!(Y::Matrix, TP::ThinSphericalHarmonicPlan, X::Matrix)
4645
RP, BF, p1, p2, B = TP.RP, TP.BF, TP.p1, TP.p2, TP.B

test/butterflytests.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ end
3131
for n in 7:N
3232
println("N = ", n)
3333
@time B = Butterfly(A[n], n-5)
34-
b = rand(Complex{Float64},2^n)./(1:2^n)
34+
nb = size(A[n], 2)
35+
b = rand(Complex{Float64}, nb)./(1:nb)
3536
u = zero(b)
3637
@time uf = A[n]*b
3738
@time A_mul_B!(u, B, b)
@@ -46,20 +47,21 @@ end
4647
N = 10
4748
A = Vector{Matrix{Float64}}(N)
4849
for n in 1:N
49-
A[n] = Float64[1/(i+j-1) for i = 1:2^n,j=1:2^n]
50+
A[n] = Float64[1/(i+j-1) for i = 1:2^n+50,j=1:2^n+50]
5051
println(n)
5152
end
5253

5354
for n in 7:N
5455
println("N = ", n)
5556
@time B = Butterfly(A[n], n-5)
56-
b = rand(Float64,2^n)./(1:2^n)
57+
nb = size(A[n], 2)
58+
b = rand(Float64, nb)./(1:nb)
5759
u = zero(b)
5860
@time uf = A[n]*b
5961
@time A_mul_B!(u, B, b)
6062
w = zero(b)
6163
@time At_mul_B!(w, B, b)
62-
println(norm(u-uf)/2^n)
64+
println(norm(u-uf)/nb)
6365
println(norm(w-A[n]'b))
6466
println(norm(u-w))
6567
end
@@ -68,14 +70,15 @@ N = 10
6870
A = Vector{Matrix{Complex{Float64}}}(N)
6971
B = Vector{Butterfly{Complex{Float64}}}(N)
7072
for n in 7:N
71-
A[n] = randnfft(2^n,2^n,0.1)
73+
A[n] = randnfft(2^n+50,2^n+50,0.1)
7274
@time B[n] = Butterfly(A[n], n-6)
7375
println(n)
7476
end
7577

7678
for n in 7:N
7779
println("N = ", n)
78-
b = rand(Complex{Float64},2^n)./(1:2^n)
80+
nb = size(A[n], 2)
81+
b = rand(Complex{Float64}, nb)./(1:nb)
7982
uf = zero(b)
8083
u = zero(b)
8184
@time A_mul_B!(uf, A[n], b)

test/test_fastplan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import FastTransforms: allranks, normalizecolumns!, maxcolnorm
22

3-
n = 255
3+
n = 362
44

55
A = sphrandn(Float64, n+1, n+1);
66
normalizecolumns!(A);

test/test_thinplan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import FastTransforms: allranks, normalizecolumns!, maxcolnorm
22

3-
n = VERSION < v"0.6.0-" ? 255 : 511
3+
n = VERSION < v"0.6.0-" ? 362 : 724
44

55
A = sphrandn(Float64, n+1, n+1);
66
normalizecolumns!(A);

0 commit comments

Comments
 (0)