Skip to content

Commit 64d662e

Browse files
committed
Now overwrite input vector (before, it was caching the return vector which was bad practice)
1 parent 710dfec commit 64d662e

File tree

3 files changed

+48
-41
lines changed

3 files changed

+48
-41
lines changed

src/FastTransforms.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import Compat: view
99
export cjt, icjt, jjt, plan_cjt, plan_icjt
1010
export leg2cheb, cheb2leg, leg2chebu, ultra2ultra, jac2jac
1111
export gaunt
12-
export paduatransform, ipaduatransform, paduapoints
13-
export plan_paduatransform, plan_ipaduatransform
12+
export paduatransform, ipaduatransform, paduatransform!, ipaduatransform!, paduapoints
13+
export plan_paduatransform!, plan_ipaduatransform!
1414

1515
# Other module methods and constants:
1616
#export ChebyshevJacobiPlan, jac2cheb, cheb2jac

src/PaduaTransform.jl

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,24 @@ Pre-plan an Inverse Padua Transform.
44
# lex indicates if its lexigraphical (i.e., x, y) or reverse (y, x)
55
immutable IPaduaTransformPlan{lex,IDCTPLAN,T}
66
cfsmat::Matrix{T}
7-
padvals::Vector{T}
87
idctplan::IDCTPLAN
98
end
109

11-
IPaduaTransformPlan{T,lex}(cfsmat::Matrix{T},padvals::Vector{T},idctplan,::Type{Val{lex}}) =
12-
IPaduaTransformPlan{lex,typeof(idctplan),T}(cfsmat,padvals,idctplan)
10+
IPaduaTransformPlan{T,lex}(cfsmat::Matrix{T},idctplan,::Type{Val{lex}}) =
11+
IPaduaTransformPlan{lex,typeof(idctplan),T}(cfsmat,idctplan)
1312

14-
function plan_ipaduatransform{T}(::Type{T},N::Integer,lex)
13+
function plan_ipaduatransform!{T}(::Type{T},N::Integer,lex)
1514
n=Int(cld(-3+sqrt(1+8N),2))
1615
if N div((n+1)*(n+2),2)
1716
error("Padua transforms can only be applied to vectors of length (n+1)*(n+2)/2.")
1817
end
19-
IPaduaTransformPlan(Array{T}(n+2,n+1),Array{T}(N),
20-
FFTW.plan_r2r!(Array{T}(n+2,n+1),FFTW.REDFT00),lex)
18+
IPaduaTransformPlan(Array{T}(n+2,n+1),FFTW.plan_r2r!(Array{T}(n+2,n+1),FFTW.REDFT00),lex)
2119
end
2220

2321

24-
plan_ipaduatransform{T}(::Type{T},N::Integer) = plan_ipaduatransform(T,N,Val{true})
22+
plan_ipaduatransform!{T}(::Type{T},N::Integer) = plan_ipaduatransform!(T,N,Val{true})
2523

26-
plan_ipaduatransform{T}(v::AbstractVector{T},lex...) = plan_ipaduatransform(eltype(v),length(v),lex...)
24+
plan_ipaduatransform!{T}(v::AbstractVector{T},lex...) = plan_ipaduatransform!(eltype(v),length(v),lex...)
2725

2826
"""
2927
Inverse Padua Transform maps the 2D Chebyshev coefficients to the values of the interpolation polynomial at the Padua points.
@@ -34,11 +32,11 @@ function *{T}(P::IPaduaTransformPlan,v::AbstractVector{T})
3432
scale!(view(cfsmat,:,2:m-1),0.5)
3533
scale!(view(cfsmat,2:n-1,:),0.5)
3634
tensorvals=P.idctplan*cfsmat
37-
paduavals=paduavec(P,tensorvals)
38-
return paduavals
35+
paduavec!(v,P,tensorvals)
3936
end
4037

41-
ipaduatransform(v::AbstractVector,lex...) = plan_ipaduatransform(v,lex...)*v
38+
ipaduatransform!(v::AbstractVector,lex...) = plan_ipaduatransform!(v,lex...)*v
39+
ipaduatransform(v::AbstractVector,lex...) = plan_ipaduatransform!(v,lex...)*copy(v)
4240

4341
"""
4442
Creates (n+2)x(n+1) Chebyshev coefficient matrix from triangle coefficients.
@@ -84,45 +82,43 @@ end
8482
"""
8583
Vectorizes the function values at the Padua points.
8684
"""
87-
function paduavec(P::IPaduaTransformPlan,padmat::Matrix)
85+
function paduavec!(v,P::IPaduaTransformPlan,padmat::Matrix)
8886
n=size(padmat,2)-1
8987
N=(n+1)*(n+2)
9088
if iseven(n)>0
9189
d=div(n+2,2)
9290
m=0
9391
@inbounds for i=1:n+1
94-
P.padvals[m+1:m+d]=view(padmat,1+mod(i,2):2:n+1+mod(i,2),i)
92+
v[m+1:m+d]=view(padmat,1+mod(i,2):2:n+1+mod(i,2),i)
9593
m+=d
9694
end
9795
else
98-
@inbounds P.padvals[:]=view(padmat,1:2:N-1)
96+
@inbounds v[:]=view(padmat,1:2:N-1)
9997
end
100-
return P.padvals
98+
return v
10199
end
102100

103101
"""
104102
Pre-plan a Padua Transform.
105103
"""
106104
immutable PaduaTransformPlan{lex,DCTPLAN,T}
107105
vals::Matrix{T}
108-
retvec::Vector{T}
109106
dctplan::DCTPLAN
110107
end
111108

112-
PaduaTransformPlan{T,lex}(vals::Matrix{T},retvec::Vector{T},dctplan,::Type{Val{lex}}) =
113-
PaduaTransformPlan{lex,typeof(dctplan),T}(vals,retvec,dctplan)
109+
PaduaTransformPlan{T,lex}(vals::Matrix{T},dctplan,::Type{Val{lex}}) =
110+
PaduaTransformPlan{lex,typeof(dctplan),T}(vals,dctplan)
114111

115-
function plan_paduatransform{T}(::Type{T},N::Integer,lex)
112+
function plan_paduatransform!{T}(::Type{T},N::Integer,lex)
116113
n=Int(cld(-3+sqrt(1+8N),2))
117114
if N  ((n+1)*(n+2))÷2
118115
error("Padua transforms can only be applied to vectors of length (n+1)*(n+2)/2.")
119116
end
120-
PaduaTransformPlan(Array{T}(n+2,n+1),Array{T}(N),
121-
FFTW.plan_r2r!(Array{T}(n+2,n+1),FFTW.REDFT00),lex)
117+
PaduaTransformPlan(Array{T}(n+2,n+1),FFTW.plan_r2r!(Array{T}(n+2,n+1),FFTW.REDFT00),lex)
122118
end
123119

124-
plan_paduatransform{T}(::Type{T},N::Integer) = plan_paduatransform(T,N,Val{true})
125-
plan_paduatransform{T}(v::AbstractVector{T},lex...) = plan_paduatransform(eltype(v),length(v),lex...)
120+
plan_paduatransform!{T}(::Type{T},N::Integer) = plan_paduatransform!(T,N,Val{true})
121+
plan_paduatransform!{T}(v::AbstractVector{T},lex...) = plan_paduatransform!(eltype(v),length(v),lex...)
126122

127123
"""
128124
Padua Transform maps from interpolant values at the Padua points to the 2D Chebyshev coefficients.
@@ -138,11 +134,11 @@ function *{T}(P::PaduaTransformPlan,v::AbstractVector{T})
138134
scale!(view(tensorcfs,:,1),0.5)
139135
scale!(view(tensorcfs,m,:),0.5)
140136
scale!(view(tensorcfs,:,l),0.5)
141-
cfs=trianglecfsvec(P,tensorcfs)
142-
return cfs
137+
trianglecfsvec!(v,P,tensorcfs)
143138
end
144139

145-
paduatransform(v::AbstractVector,lex...) = plan_paduatransform(v,lex...)*v
140+
paduatransform!(v::AbstractVector,lex...) = plan_paduatransform!(v,lex...)*v
141+
paduatransform(v::AbstractVector,lex...) = plan_paduatransform!(v,lex...)*copy(v)
146142

147143
"""
148144
Creates (n+2)x(n+1) matrix of interpolant values on the tensor grid at the (n+1)(n+2)/2 Padua points.
@@ -167,30 +163,30 @@ end
167163
"""
168164
Creates length (n+1)(n+2)/2 vector from matrix of triangle Chebyshev coefficients.
169165
"""
170-
function trianglecfsvec(P::PaduaTransformPlan{true},cfs::Matrix)
166+
function trianglecfsvec!(v,P::PaduaTransformPlan{true},cfs::Matrix)
171167
m=size(cfs,2)
172168
l=1
173169
for d=1:m
174170
@inbounds for k=1:d
175171
j=d-k+1
176-
P.retvec[l]=cfs[k,j]
172+
v[l]=cfs[k,j]
177173
l+=1
178174
end
179175
end
180-
return P.retvec
176+
return v
181177
end
182178

183-
function trianglecfsvec(P::PaduaTransformPlan{false},cfs::Matrix)
179+
function trianglecfsvec!(v,P::PaduaTransformPlan{false},cfs::Matrix)
184180
m=size(cfs,2)
185181
l=1
186182
for d=1:m
187183
@inbounds for k=d:-1:1
188184
j=d-k+1
189-
P.retvec[l]=cfs[k,j]
185+
v[l]=cfs[k,j]
190186
l+=1
191187
end
192188
end
193-
return P.retvec
189+
return v
194190
end
195191

196192
"""

test/runtests.jl

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,23 @@ println("Testing (I)Padua Transforms and their inverse function property")
211211
n=200
212212
N=div((n+1)*(n+2),2)
213213
v=rand(N) #Length of v is the no. of Padua points
214-
Pl=plan_paduatransform(v)
215-
IPl=plan_ipaduatransform(v)
216-
@test_approx_eq Pl*(IPl*v) v
217-
@test_approx_eq IPl*(Pl*v) v
218-
@test_approx_eq Pl*v paduatransform(v)
219-
@test_approx_eq IPl*v ipaduatransform(v)
214+
Pl=plan_paduatransform!(v)
215+
IPl=plan_ipaduatransform!(v)
216+
@test_approx_eq Pl*(IPl*copy(v)) v
217+
@test_approx_eq IPl*(Pl*copy(v)) v
218+
@test_approx_eq Pl*copy(v) paduatransform(v)
219+
@test_approx_eq IPl*copy(v) ipaduatransform(v)
220+
221+
# check that the return vector is NOT reused
222+
Pl=plan_paduatransform!(v)
223+
x=Pl*v
224+
y=Pl*rand(N)
225+
@test x y
226+
227+
IPl=plan_ipaduatransform!(v)
228+
x=IPl*v
229+
y=IPl*rand(N)
230+
@test x y
220231

221232
println("Testing runtimes for (I)Padua Transforms")
222233
@time Pl*v
@@ -234,7 +245,7 @@ function paduaeval(f::Function,x::AbstractFloat,y::AbstractFloat,m::Integer,lex)
234245
p=paduapoints(T,m)
235246
map!(f,pvals,p[:,1],p[:,2])
236247
coeffs=paduatransform(pvals,lex)
237-
plan=plan_ipaduatransform(pvals,lex)
248+
plan=plan_ipaduatransform!(pvals,lex)
238249
cfs_mat=FastTransforms.trianglecfsmat(plan,coeffs)
239250
f_x=sum([cfs_mat[k,j]*cos((j-1)*acos(x))*cos((k-1)*acos(y)) for k=1:m+1, j=1:m+1])
240251
return f_x

0 commit comments

Comments
 (0)