1
1
const AbstractFloats = Union{AbstractFloat,Complex{T} where T<: AbstractFloat }
2
2
3
+ # We use these type definitions for clarity
4
+ const RealFloats = T where T<: AbstractFloat
5
+ const ComplexFloats = Complex{T} where T<: AbstractFloat
6
+
3
7
if VERSION < v " 0.7-"
4
8
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
7
12
else
8
13
import FFTW: dct, dct!, idct, idct!,
9
14
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
11
17
import DSP: conv
12
18
end
13
19
14
20
# The following implements Bluestein's algorithm, following http://www.dsprelated.com/dspbooks/mdft/Bluestein_s_FFT_Algorithm.html
15
21
# To add more types, add them in the union of the function's signature.
16
22
17
23
function generic_fft (x:: Vector{T} ) where T<: AbstractFloats
24
+ T <: FFTW.fftwNumber && (@warn (" Using generic fft for FFTW number type." ))
18
25
n = length (x)
19
26
ispow2 (n) && return generic_fft_pow2 (x)
20
27
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
30
37
end
31
38
32
39
# add rfft for AbstractFloat, by calling fft
33
- # this creates ToeplitzMatrices.rfft, so avoids changing rfft
34
-
35
40
generic_rfft (v:: Vector{T} ) where T<: AbstractFloats = generic_fft (v)[1 : div (length (v),2 )+ 1 ]
36
41
37
- function generic_irfft (v:: Vector{T} ,n:: Integer ) where T<: AbstractFloats
42
+ function generic_irfft (v:: Vector{T} , n:: Integer ) where T<: ComplexFloats
38
43
@assert n== 2 length (v)- 1
39
- r = Vector {Complex{real(T)} } (undef, n)
44
+ r = Vector {T } (undef, n)
40
45
r[1 : length (v)]= v
41
46
r[length (v)+ 1 : end ]= reverse (conj (v[2 : end ]))
42
47
real (generic_ifft (r))
43
48
end
44
49
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
+
45
58
generic_ifft (x:: Vector{T} ) where {T<: AbstractFloats } = conj! (generic_fft (conj (x)))/ length (x)
46
59
function generic_ifft! (x:: Vector{T} ) where T<: AbstractFloats
47
60
x[:] = generic_ifft (x)
@@ -112,6 +125,7 @@ function generic_ifft_pow2(x::Vector{Complex{T}}) where T<:AbstractFloat
112
125
end
113
126
114
127
function generic_dct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
128
+ T <: FFTW.fftwNumber && (@warn (" Using generic dct for FFTW number type." ))
115
129
N = length (a)
116
130
twoN = convert (T,2 ) * N
117
131
c = generic_fft ([a; flipdim (a,1 )])
124
138
generic_dct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (generic_dct (complex (a)))
125
139
126
140
function generic_idct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
141
+ T <: FFTW.fftwNumber && (@warn (" Using generic idct for FFTW number type." ))
127
142
N = length (a)
128
143
twoN = convert (T,2 )* N
129
144
b = a * sqrt (twoN)
@@ -150,35 +165,39 @@ for f in (:dct, :dct!, :idct, :idct!)
150
165
end
151
166
152
167
# 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}
158
175
n :: Integer
159
176
end
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}
161
181
n :: Integer
162
182
end
163
183
164
184
for (Plan,iPlan) in ((:DummyFFTPlan ,:DummyiFFTPlan ),
165
- # (:DummyrFFTPlan,:DummyirFFTPlan),
166
185
(:DummyDCTPlan ,:DummyiDCTPlan ))
167
186
@eval begin
168
187
Base. inv (:: $Plan{T,inplace} ) where {T,inplace} = $ iPlan {T,inplace} ()
169
188
Base. inv (:: $iPlan{T,inplace} ) where {T,inplace} = $ Plan {T,inplace} ()
170
189
end
171
190
end
172
191
173
- # Specific for rfft and irfft :
192
+ # Specific for rfft, irfft and brfft :
174
193
Base. inv (:: DummyirFFTPlan{T,inplace} ) where {T,inplace} = DummyrFFTPlan {T,Inplace} (p. n)
175
194
Base. inv (:: DummyrFFTPlan{T,inplace} ) where {T,inplace} = DummyirFFTPlan {T,Inplace} (p. n)
176
195
177
196
178
197
for (Plan,ff,ff!) in ((:DummyFFTPlan ,:generic_fft ,:generic_fft! ),
198
+ (:DummybFFTPlan ,:generic_bfft ,:generic_bfft! ),
179
199
(:DummyiFFTPlan ,:generic_ifft ,:generic_ifft! ),
180
200
(:DummyrFFTPlan ,:generic_rfft ,:generic_rfft! ),
181
- # (:DummyirFFTPlan,:generic_irfft,:generic_irfft!),
182
201
(:DummyDCTPlan ,:generic_dct ,:generic_dct! ),
183
202
(:DummyiDCTPlan ,:generic_idct ,:generic_idct! ))
184
203
@eval begin
@@ -191,13 +210,20 @@ for (Plan,ff,ff!) in ((:DummyFFTPlan,:generic_fft,:generic_fft!),
191
210
end
192
211
end
193
212
194
- # Specific for irfft:
213
+ # Specific for irfft and brfft :
195
214
* (p:: DummyirFFTPlan{T,true} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_irfft! (x, p. n)
196
215
* (p:: DummyirFFTPlan{T,false} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = generic_irfft (x, p. n)
197
216
function LAmul! (C:: StridedVector , p:: DummyirFFTPlan , x:: StridedVector )
198
217
C[:] = generic_irfft (x, p. n)
199
218
C
200
219
end
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
+
201
227
202
228
# We override these for AbstractFloat, so that conversion from reals to
203
229
# complex numbers works for any AbstractFloat (instead of only BlasFloat's)
@@ -207,21 +233,38 @@ AbstractFFTs.realfloat(x::StridedArray{<:Real}) = x
207
233
# unsupported (as defined in AbstractFFTs)
208
234
AbstractFFTs. _fftfloat (:: Type{T} ) where {T <: AbstractFloat } = T
209
235
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} ()
212
236
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}()
217
252
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)
222
253
plan_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
+
223
256
plan_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)
224
264
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}()
225
268
226
269
function interlace (a:: Vector{S} ,b:: Vector{V} ) where {S<: Number ,V<: Number }
227
270
na= length (a);nb= length (b)
0 commit comments