11const AbstractFloats = Union{AbstractFloat,Complex{T} where T<: AbstractFloat }
22
3+ # We use these type definitions for clarity
4+ const RealFloats = T where T<: AbstractFloat
5+ const ComplexFloats = Complex{T} where T<: AbstractFloat
6+
37if VERSION < v " 0.7-"
48 import Base. FFTW: fft, fft!, rfft, irfft, ifft, ifft!, conv, dct, idct, dct!, idct!,
5- plan_fft!, plan_ifft!, plan_dct!, plan_idct!,
6- plan_fft, plan_ifft, plan_rfft, plan_irfft, plan_dct, plan_idct
9+ plan_fft!, plan_ifft!, plan_dct!, plan_idct!, plan_bfft, plan_bfft!,
10+ plan_fft, plan_ifft, plan_rfft, plan_irfft, plan_dct, plan_idct,
11+ plan_brfft
712else
813 import FFTW: dct, dct!, idct, idct!,
914 plan_fft!, plan_ifft!, plan_dct!, plan_idct!,
10- plan_fft, plan_ifft, plan_rfft, plan_irfft, plan_dct, plan_idct
15+ plan_fft, plan_ifft, plan_rfft, plan_irfft, plan_dct, plan_idct,
16+ plan_bfft, plan_bfft!, plan_brfft
1117 import DSP: conv
1218end
1319
1420# The following implements Bluestein's algorithm, following http://www.dsprelated.com/dspbooks/mdft/Bluestein_s_FFT_Algorithm.html
1521# To add more types, add them in the union of the function's signature.
1622
1723function generic_fft (x:: Vector{T} ) where T<: AbstractFloats
24+ T <: FFTW.fftwNumber && (@warn (" Using generic fft for FFTW number type." ))
1825 n = length (x)
1926 ispow2 (n) && return generic_fft_pow2 (x)
2027 ks = range (zero (real (T)),stop= n- one (real (T)),length= n)
@@ -30,18 +37,24 @@ function generic_fft!(x::Vector{T}) where T<:AbstractFloats
3037end
3138
3239# add rfft for AbstractFloat, by calling fft
33- # this creates ToeplitzMatrices.rfft, so avoids changing rfft
34-
3540generic_rfft (v:: Vector{T} ) where T<: AbstractFloats = generic_fft (v)[1 : div (length (v),2 )+ 1 ]
3641
37- function generic_irfft (v:: Vector{T} ,n:: Integer ) where T<: AbstractFloats
42+ function generic_irfft (v:: Vector{T} , n:: Integer ) where T<: ComplexFloats
3843 @assert n== 2 length (v)- 1
39- r = Vector {Complex{real(T)} } (undef, n)
44+ r = Vector {T } (undef, n)
4045 r[1 : length (v)]= v
4146 r[length (v)+ 1 : end ]= reverse (conj (v[2 : end ]))
4247 real (generic_ifft (r))
4348end
4449
50+ generic_bfft (x:: Vector{T} ) where {T <: AbstractFloats } = conj! (generic_fft (conj (x)))
51+ function generic_bfft! (x:: Vector{T} ) where {T <: AbstractFloats }
52+ x[:] = generic_bfft (x)
53+ return x
54+ end
55+
56+ generic_brfft (v:: Vector , n:: Integer ) = generic_irfft (v, n)* n
57+
4558generic_ifft (x:: Vector{T} ) where {T<: AbstractFloats } = conj! (generic_fft (conj (x)))/ length (x)
4659function generic_ifft! (x:: Vector{T} ) where T<: AbstractFloats
4760 x[:] = generic_ifft (x)
@@ -112,6 +125,7 @@ function generic_ifft_pow2(x::Vector{Complex{T}}) where T<:AbstractFloat
112125end
113126
114127function generic_dct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
128+ T <: FFTW.fftwNumber && (@warn (" Using generic dct for FFTW number type." ))
115129 N = length (a)
116130 twoN = convert (T,2 ) * N
117131 c = generic_fft ([a; flipdim (a,1 )])
124138generic_dct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (generic_dct (complex (a)))
125139
126140function generic_idct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
141+ T <: FFTW.fftwNumber && (@warn (" Using generic idct for FFTW number type." ))
127142 N = length (a)
128143 twoN = convert (T,2 )* N
129144 b = a * sqrt (twoN)
@@ -150,35 +165,39 @@ for f in (:dct, :dct!, :idct, :idct!)
150165end
151166
152167# dummy plans
153- struct DummyFFTPlan{T,inplace} <: Plan{T} end
154- struct DummyiFFTPlan{T,inplace} <: Plan{T} end
155- struct DummyDCTPlan{T,inplace} <: Plan{T} end
156- struct DummyiDCTPlan{T,inplace} <: Plan{T} end
157- struct DummyrFFTPlan{T,inplace} <: Plan{T}
168+ abstract type DummyPlan{T} <: Plan{T} end
169+ struct DummyFFTPlan{T,inplace} <: DummyPlan{T} end
170+ struct DummyiFFTPlan{T,inplace} <: DummyPlan{T} end
171+ struct DummybFFTPlan{T,inplace} <: DummyPlan{T} end
172+ struct DummyDCTPlan{T,inplace} <: DummyPlan{T} end
173+ struct DummyiDCTPlan{T,inplace} <: DummyPlan{T} end
174+ struct DummyrFFTPlan{T,inplace} <: DummyPlan{T}
158175 n :: Integer
159176end
160- struct DummyirFFTPlan{T,inplace} <: Plan{T}
177+ struct DummyirFFTPlan{T,inplace} <: DummyPlan{T}
178+ n :: Integer
179+ end
180+ struct DummybrFFTPlan{T,inplace} <: DummyPlan{T}
161181 n :: Integer
162182end
163183
164184for (Plan,iPlan) in ((:DummyFFTPlan ,:DummyiFFTPlan ),
165- # (:DummyrFFTPlan,:DummyirFFTPlan),
166185 (:DummyDCTPlan ,:DummyiDCTPlan ))
167186 @eval begin
168187 Base. inv (:: $Plan{T,inplace} ) where {T,inplace} = $ iPlan {T,inplace} ()
169188 Base. inv (:: $iPlan{T,inplace} ) where {T,inplace} = $ Plan {T,inplace} ()
170189 end
171190end
172191
173- # Specific for rfft and irfft :
192+ # Specific for rfft, irfft and brfft :
174193Base. inv (:: DummyirFFTPlan{T,inplace} ) where {T,inplace} = DummyrFFTPlan {T,Inplace} (p. n)
175194Base. inv (:: DummyrFFTPlan{T,inplace} ) where {T,inplace} = DummyirFFTPlan {T,Inplace} (p. n)
176195
177196
178197for (Plan,ff,ff!) in ((:DummyFFTPlan ,:generic_fft ,:generic_fft! ),
198+ (:DummybFFTPlan ,:generic_bfft ,:generic_bfft! ),
179199 (:DummyiFFTPlan ,:generic_ifft ,:generic_ifft! ),
180200 (:DummyrFFTPlan ,:generic_rfft ,:generic_rfft! ),
181- # (:DummyirFFTPlan,:generic_irfft,:generic_irfft!),
182201 (:DummyDCTPlan ,:generic_dct ,:generic_dct! ),
183202 (:DummyiDCTPlan ,:generic_idct ,:generic_idct! ))
184203 @eval begin
@@ -191,13 +210,20 @@ for (Plan,ff,ff!) in ((:DummyFFTPlan,:generic_fft,:generic_fft!),
191210 end
192211end
193212
194- # Specific for irfft:
213+ # Specific for irfft and brfft :
195214* (p:: DummyirFFTPlan{T,true} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_irfft! (x, p. n)
196215* (p:: DummyirFFTPlan{T,false} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_irfft (x, p. n)
197216function LAmul! (C:: StridedVector , p:: DummyirFFTPlan , x:: StridedVector )
198217 C[:] = generic_irfft (x, p. n)
199218 C
200219end
220+ * (p:: DummybrFFTPlan{T,true} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_brfft! (x, p. n)
221+ * (p:: DummybrFFTPlan{T,false} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_brfft (x, p. n)
222+ function LAmul! (C:: StridedVector , p:: DummybrFFTPlan , x:: StridedVector )
223+ C[:] = generic_brfft (x, p. n)
224+ C
225+ end
226+
201227
202228# We override these for AbstractFloat, so that conversion from reals to
203229# complex numbers works for any AbstractFloat (instead of only BlasFloat's)
@@ -207,21 +233,38 @@ AbstractFFTs.realfloat(x::StridedArray{<:Real}) = x
207233# unsupported (as defined in AbstractFFTs)
208234AbstractFFTs. _fftfloat (:: Type{T} ) where {T <: AbstractFloat } = T
209235
210- plan_fft! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyFFTPlan {Complex{real(T)},true} ()
211- plan_ifft! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},true} ()
212236
213- # plan_rfft!(x::StridedArray{T}) where {T <: AbstractFloat} = DummyrFFTPlan{Complex{real(T)},true}()
214- # plan_irfft!(x::StridedArray{T},n::Integer) where {T <: AbstractFloat} = DummyirFFTPlan{Complex{real(T)},true}()
215- plan_dct! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyDCTPlan {T,true} ()
216- plan_idct! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiDCTPlan {T,true} ()
237+ # We intercept the calls to plan_X(x, region) below.
238+ # In order not to capture any calls that should go to FFTW, we have to be
239+ # careful about the typing, so that the calls to FFTW remain more specific.
240+ # This is the reason for using StridedArray below. We also have to carefully
241+ # distinguish between real and complex arguments.
242+
243+ plan_fft (x:: StridedArray{T} , region) where {T <: ComplexFloats } = DummyFFTPlan {Complex{real(T)},false} ()
244+ plan_fft! (x:: StridedArray{T} , region) where {T <: ComplexFloats } = DummyFFTPlan {Complex{real(T)},true} ()
245+
246+ plan_bfft (x:: StridedArray{T} , region) where {T <: ComplexFloats } = DummybFFTPlan {Complex{real(T)},false} ()
247+ plan_bfft! (x:: StridedArray{T} , region) where {T <: ComplexFloats } = DummybFFTPlan {Complex{real(T)},true} ()
248+
249+ # The ifft plans are automatically provided in terms of the bfft plans above.
250+ # plan_ifft(x::StridedArray{T}, region) where {T <: ComplexFloats} = DummyiFFTPlan{Complex{real(T)},false}()
251+ # plan_ifft!(x::StridedArray{T}, region) where {T <: ComplexFloats} = DummyiFFTPlan{Complex{real(T)},true}()
217252
218- plan_fft (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyFFTPlan {Complex{real(T)},false} ()
219- plan_ifft (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},false} ()
220- plan_rfft (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyrFFTPlan {Complex{real(T)},false} (length (x))
221- plan_irfft (x:: StridedArray{T} , n:: Integer , region) where {T <: AbstractFloats } = DummyirFFTPlan {Complex{real(T)},false} (n)
222253plan_dct (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyDCTPlan {T,false} ()
254+ plan_dct! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyDCTPlan {T,true} ()
255+
223256plan_idct (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiDCTPlan {T,false} ()
257+ plan_idct! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiDCTPlan {T,true} ()
258+
259+ plan_rfft (x:: StridedArray{T} , region) where {T <: RealFloats } = DummyrFFTPlan {Complex{real(T)},false} (length (x))
260+ plan_brfft (x:: StridedArray{T} , n:: Integer , region) where {T <: ComplexFloats } = DummybrFFTPlan {Complex{real(T)},false} (n)
261+
262+ # A plan for irfft is created in terms of a plan for brfft.
263+ # plan_irfft(x::StridedArray{T}, n::Integer, region) where {T <: ComplexFloats} = DummyirFFTPlan{Complex{real(T)},false}(n)
224264
265+ # These don't exist for now:
266+ # plan_rfft!(x::StridedArray{T}) where {T <: RealFloats} = DummyrFFTPlan{Complex{real(T)},true}()
267+ # plan_irfft!(x::StridedArray{T},n::Integer) where {T <: RealFloats} = DummyirFFTPlan{Complex{real(T)},true}()
225268
226269function interlace (a:: Vector{S} ,b:: Vector{V} ) where {S<: Number ,V<: Number }
227270 na= length (a);nb= length (b)
0 commit comments