1+ import Base: *
2+ import LinearAlgebra: mul!
3+
4+ abstract type FFTAPlan{T,N} <: Plan{T} end
5+
6+ struct FFTAInvPlan{T,N} <: FFTAPlan{T,N} end
7+
8+ struct FFTAPlan_cx{T,N} <: FFTAPlan{T,N}
9+ callgraph:: NTuple{N, CallGraph{T}}
10+ region:: Union{Int,AbstractVector{<:Int}}
11+ dir:: Direction
12+ pinv:: FFTAInvPlan{T}
13+ end
14+
15+ struct FFTAPlan_re{T,N} <: FFTAPlan{T,N}
16+ callgraph:: NTuple{N, CallGraph{T}}
17+ region:: Union{Int,AbstractVector{<:Int}}
18+ dir:: Direction
19+ pinv:: FFTAInvPlan{T}
20+ flen:: Int
21+ end
22+
23+ function AbstractFFTs. plan_fft (x:: AbstractArray{T} , region; kwargs... ):: FFTAPlan_cx{T} where {T <: Complex }
24+ N = length (region)
25+ @assert N <= 2 " Only supports vectors and matrices"
26+ if N == 1
27+ g = CallGraph {T} (size (x,region[]))
28+ pinv = FFTAInvPlan {T,N} ()
29+ return FFTAPlan_cx {T,N} ((g,), region, FFT_FORWARD, pinv)
30+ else
31+ sort! (region)
32+ g1 = CallGraph {T} (size (x,region[1 ]))
33+ g2 = CallGraph {T} (size (x,region[2 ]))
34+ pinv = FFTAInvPlan {T,N} ()
35+ return FFTAPlan_cx {T,N} ((g1,g2), region, FFT_FORWARD, pinv)
36+ end
37+ end
38+
39+ function AbstractFFTs. plan_bfft (x:: AbstractArray{T} , region; kwargs... ):: FFTAPlan_cx{T} where {T <: Complex }
40+ N = length (region)
41+ @assert N <= 2 " Only supports vectors and matrices"
42+ if N == 1
43+ g = CallGraph {T} (size (x,region[]))
44+ pinv = FFTAInvPlan {T,N} ()
45+ return FFTAPlan_cx {T,N} ((g,), region, FFT_BACKWARD, pinv)
46+ else
47+ sort! (region)
48+ g1 = CallGraph {T} (size (x,region[1 ]))
49+ g2 = CallGraph {T} (size (x,region[2 ]))
50+ pinv = FFTAInvPlan {T,N} ()
51+ return FFTAPlan_cx {T,N} ((g1,g2), region, FFT_BACKWARD, pinv)
52+ end
53+ end
54+
55+ function AbstractFFTs. plan_rfft (x:: AbstractArray{T} , region; kwargs... ):: FFTAPlan_re{Complex{T}} where {T <: Real }
56+ N = length (region)
57+ @assert N <= 2 " Only supports vectors and matrices"
58+ if N == 1
59+ g = CallGraph {Complex{T}} (size (x,region[]))
60+ pinv = FFTAInvPlan {Complex{T},N} ()
61+ return FFTAPlan_re {Complex{T},N} (tuple (g), region, FFT_FORWARD, pinv, size (x,region[]))
62+ else
63+ sort! (region)
64+ g1 = CallGraph {Complex{T}} (size (x,region[1 ]))
65+ g2 = CallGraph {Complex{T}} (size (x,region[2 ]))
66+ pinv = FFTAInvPlan {Complex{T},N} ()
67+ return FFTAPlan_re {Complex{T},N} (tuple (g1,g2), region, FFT_FORWARD, pinv, size (x,region[1 ]))
68+ end
69+ end
70+
71+ function AbstractFFTs. plan_brfft (x:: AbstractArray{T} , len, region; kwargs... ):: FFTAPlan_re{T} where {T}
72+ N = length (region)
73+ @assert N <= 2 " Only supports vectors and matrices"
74+ if N == 1
75+ g = CallGraph {T} (len)
76+ pinv = FFTAInvPlan {T,N} ()
77+ return FFTAPlan_re {T,N} ((g,), region, FFT_BACKWARD, pinv, len)
78+ else
79+ sort! (region)
80+ g1 = CallGraph {T} (len)
81+ g2 = CallGraph {T} (size (x,region[2 ]))
82+ pinv = FFTAInvPlan {T,N} ()
83+ return FFTAPlan_re {T,N} ((g1,g2), region, FFT_BACKWARD, pinv, len)
84+ end
85+ end
86+
87+ function AbstractFFTs. plan_bfft (p:: FFTAPlan_cx{T,N} ) where {T,N}
88+ return FFTAPlan_cx {T,N} (p. callgraph, p. region, - p. dir, p. pinv)
89+ end
90+
91+ function AbstractFFTs. plan_brfft (p:: FFTAPlan_re{T,N} ) where {T,N}
92+ return FFTAPlan_re {T,N} (p. callgraph, p. region, - p. dir, p. pinv, p. flen)
93+ end
94+
95+ function LinearAlgebra. mul! (y:: AbstractVector{U} , p:: FFTAPlan{T,1} , x:: AbstractVector{T} ) where {T,U}
96+ fft! (y, x, 1 , 1 , p. dir, p. callgraph[1 ][1 ]. type, p. callgraph[1 ], 1 )
97+ end
98+
99+ function LinearAlgebra. mul! (y:: AbstractArray{U,N} , p:: FFTAPlan{T,1} , x:: AbstractArray{T,N} ) where {T,U,N}
100+ Rpre = CartesianIndices (size (x)[1 : p. region- 1 ])
101+ Rpost = CartesianIndices (size (x)[p. region+ 1 : end ])
102+ for Ipre in Rpre
103+ for Ipost in Rpost
104+ @views fft! (y[Ipre,:,Ipost], x[Ipre,:,Ipost], 1 , 1 , p. dir, p. callgraph[1 ][1 ]. type, p. callgraph[1 ], 1 )
105+ end
106+ end
107+ end
108+
109+ function LinearAlgebra. mul! (y:: AbstractArray{U,N} , p:: FFTAPlan{T,2} , x:: AbstractArray{T,N} ) where {T,U,N}
110+ R1 = CartesianIndices (size (x)[1 : p. region[1 ]- 1 ])
111+ R2 = CartesianIndices (size (x)[p. region[1 ]+ 1 : p. region[2 ]- 1 ])
112+ R3 = CartesianIndices (size (x)[p. region[2 ]+ 1 : end ])
113+ y_tmp = similar (y, axes (y)[p. region])
114+ rows,cols = size (x)[p. region]
115+ for I1 in R1
116+ for I2 in R2
117+ for I3 in R3
118+ for k in 1 : cols
119+ @views fft! (y_tmp[:,k], x[I1,:,I2,k,I3], 1 , 1 , p. dir, p. callgraph[1 ][1 ]. type, p. callgraph[1 ], 1 )
120+ end
121+
122+ for k in 1 : rows
123+ @views fft! (y[I1,k,I2,:,I3], y_tmp[k,:], 1 , 1 , p. dir, p. callgraph[2 ][1 ]. type, p. callgraph[2 ], 1 )
124+ end
125+ end
126+ end
127+ end
128+ end
129+
130+ function * (p:: FFTAPlan{T,1} , x:: AbstractVector{T} ) where {T<: Union{Real,Complex} }
131+ y = similar (x, T <: Real ? Complex{T} : T)
132+ LinearAlgebra. mul! (y, p, x)
133+ y
134+ end
135+
136+ function * (p:: FFTAPlan{T,N1} , x:: AbstractArray{T,N2} ) where {T<: Union{Real, Complex} , N1, N2}
137+ y = similar (x, T <: Real ? Complex{T} : T)
138+ LinearAlgebra. mul! (y, p, x)
139+ y
140+ end
141+
142+ function * (p:: FFTAPlan_re{T,1} , x:: AbstractVector{T} ) where {T<: Union{Real, Complex} }
143+ if p. dir == FFT_FORWARD
144+ y = similar (x, T <: Real ? Complex{T} : T)
145+ LinearAlgebra. mul! (y, p, x)
146+ return y[1 : end ÷ 2 + 1 ]
147+ else
148+ x_tmp = similar (x, p. flen)
149+ x_tmp[1 : end ÷ 2 + 1 ] .= x
150+ x_tmp[end ÷ 2 + 2 : end ] .= iseven (p. flen) ? conj .(x[end - 1 : - 1 : 2 ]) : conj .(x[end : - 1 : 2 ])
151+ y = similar (x_tmp)
152+ LinearAlgebra. mul! (y, p, x_tmp)
153+ return y
154+ end
155+ end
156+
157+ function * (p:: FFTAPlan_re{T,N} , x:: AbstractArray{T,2} ) where {T<: Union{Real, Complex} , N}
158+ if p. dir == FFT_FORWARD
159+ y = similar (x, T <: Real ? Complex{T} : T)
160+ LinearAlgebra. mul! (y, p, x)
161+ return y[1 : end ÷ 2 + 1 ,:]
162+ else
163+ x_tmp = similar (x, p. flen, size (x)[2 ])
164+ x_tmp[1 : end ÷ 2 + 1 ,:] .= x
165+ x_tmp[end ÷ 2 + 2 : end ,:] .= iseven (p. flen) ? conj .(x[end - 1 : - 1 : 2 ,:]) : conj .(x[end : - 1 : 2 ,:])
166+ y = similar (x_tmp)
167+ LinearAlgebra. mul! (y, p, x_tmp)
168+ return y
169+ end
170+ end
0 commit comments