13
13
14
14
# The following implements Bluestein's algorithm, following http://www.dsprelated.com/dspbooks/mdft/Bluestein_s_FFT_Algorithm.html
15
15
# To add more types, add them in the union of the function's signature.
16
- function fft (x:: Vector{T} ) where T<: AbstractFloats
16
+
17
+ function generic_fft (x:: Vector{T} ) where T<: AbstractFloats
17
18
n = length (x)
18
- ispow2 (n) && return fft_pow2 (x)
19
+ ispow2 (n) && return generic_fft_pow2 (x)
19
20
ks = range (zero (real (T)),stop= n- one (real (T)),length= n)
20
21
Wks = exp .((- im). * convert (T,π).* ks.^ 2 ./ n)
21
22
xq, wq = x.* Wks, conj ([exp (- im* convert (T,π)* n);reverse (Wks);Wks[2 : end ]])
22
23
return Wks.* conv (xq,wq)[n+ 1 : 2 n]
23
24
end
24
25
25
26
26
- function fft ! (x:: Vector{T} ) where T<: AbstractFloats
27
- x[:] = fft (x)
27
+ function generic_fft ! (x:: Vector{T} ) where T<: AbstractFloats
28
+ x[:] = generic_fft (x)
28
29
return x
29
30
end
30
31
31
32
# add rfft for AbstractFloat, by calling fft
32
33
# this creates ToeplitzMatrices.rfft, so avoids changing rfft
33
34
34
- rfft (v:: Vector{T} ) where T<: AbstractFloats = fft (v)[1 : div (length (v),2 )+ 1 ]
35
- function irfft (v:: Vector{T} ,n:: Integer ) where T<: AbstractFloats
35
+ generic_rfft (v:: Vector{T} ) where T<: AbstractFloats = fft (v)[1 : div (length (v),2 )+ 1 ]
36
+ function generic_irfft (v:: Vector{T} ,n:: Integer ) where T<: AbstractFloats
36
37
@assert n== 2 length (v)- 1
37
38
r = Vector {Complex{real(T)}} (undef, n)
38
39
r[1 : length (v)]= v
39
40
r[length (v)+ 1 : end ]= reverse (conj (v[2 : end ]))
40
- real (ifft (r))
41
+ real (generic_ifft (r))
41
42
end
42
43
43
- ifft (x:: Vector{T} ) where {T<: AbstractFloats } = conj! (fft (conj (x)))/ length (x)
44
- function ifft ! (x:: Vector{T} ) where T<: AbstractFloats
45
- x[:] = ifft (x)
44
+ generic_ifft (x:: Vector{T} ) where {T<: AbstractFloats } = conj! (generic_fft (conj (x)))/ length (x)
45
+ function generic_ifft ! (x:: Vector{T} ) where T<: AbstractFloats
46
+ x[:] = generic_ifft (x)
46
47
return x
47
48
end
48
49
@@ -51,7 +52,7 @@ function conv(u::StridedVector{T}, v::StridedVector{T}) where T<:AbstractFloats
51
52
n = nu + nv - 1
52
53
np2 = nextpow (2 ,n)
53
54
append! (u,zeros (T,np2- nu)),append! (v,zeros (T,np2- nv))
54
- y = ifft_pow2 ( fft_pow2 (u).* fft_pow2 (v))
55
+ y = generic_ifft_pow2 ( generic_fft_pow2 (u).* generic_fft_pow2 (v))
55
56
# TODO This would not handle Dual/ComplexDual numbers correctly
56
57
y = T<: Real ? real (y[1 : n]) : y[1 : n]
57
58
end
60
61
# c_radix2.c in the GNU Scientific Library and four1 in the Numerical Recipes in C.
61
62
# However, the trigonometric recurrence is improved for greater efficiency.
62
63
# The algorithm starts with bit-reversal, then divides and conquers in-place.
63
- function fft_pow2 ! (x:: Vector{T} ) where T<: AbstractFloat
64
+ function generic_fft_pow2 ! (x:: Vector{T} ) where T<: AbstractFloat
64
65
n,big2= length (x),2 one (T)
65
66
nn,j= n÷ 2 ,1
66
67
for i= 1 : 2 : n- 1
@@ -96,32 +97,32 @@ function fft_pow2!(x::Vector{T}) where T<:AbstractFloat
96
97
return x
97
98
end
98
99
99
- function fft_pow2 (x:: Vector{Complex{T}} ) where T<: AbstractFloat
100
+ function generic_fft_pow2 (x:: Vector{Complex{T}} ) where T<: AbstractFloat
100
101
y = interlace (real (x),imag (x))
101
- fft_pow2 ! (y)
102
+ generic_fft_pow2 ! (y)
102
103
return complex .(y[1 : 2 : end ],y[2 : 2 : end ])
103
104
end
104
- fft_pow2 (x:: Vector{T} ) where {T<: AbstractFloat } = fft_pow2 (complex (x))
105
+ generic_fft_pow2 (x:: Vector{T} ) where {T<: AbstractFloat } = generic_fft_pow2 (complex (x))
105
106
106
- function ifft_pow2 (x:: Vector{Complex{T}} ) where T<: AbstractFloat
107
+ function generic_ifft_pow2 (x:: Vector{Complex{T}} ) where T<: AbstractFloat
107
108
y = interlace (real (x),- imag (x))
108
- fft_pow2 ! (y)
109
+ generic_fft_pow2 ! (y)
109
110
return complex .(y[1 : 2 : end ],- y[2 : 2 : end ])/ length (x)
110
111
end
111
112
112
- function dct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
113
+ function generic_dct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
113
114
N = length (a)
114
115
twoN = convert (T,2 ) * N
115
- c = fft ([a; flipdim (a,1 )])
116
+ c = generic_fft ([a; flipdim (a,1 )])
116
117
d = c[1 : N]
117
118
d .*= exp .((- im* convert (T, pi )). * (0 : N- 1 ). / twoN)
118
119
d[1 ] = d[1 ] / sqrt (convert (T, 2 ))
119
120
lmul! (inv (sqrt (twoN)), d)
120
121
end
121
122
122
- dct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (dct (complex (a)))
123
+ generic_dct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (generic_dct (complex (a)))
123
124
124
- function idct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
125
+ function generic_idct (a:: AbstractVector{Complex{T}} ) where {T <: AbstractFloat }
125
126
N = length (a)
126
127
twoN = convert (T,2 )* N
127
128
b = a * sqrt (twoN)
@@ -132,10 +133,18 @@ function idct(a::AbstractVector{Complex{T}}) where {T <: AbstractFloat}
132
133
flipdim (c[1 : N],1 )
133
134
end
134
135
135
- idct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (idct (complex (a)))
136
+ generic_idct (a:: AbstractArray{T} ) where {T <: AbstractFloat } = real (generic_idct (complex (a)))
136
137
137
- dct! (a:: AbstractArray{T} ) where {T<: AbstractFloats } = (b = dct (a); a[:] = b)
138
- idct! (a:: AbstractArray{T} ) where {T<: AbstractFloats } = (b = idct (a); a[:] = b)
138
+ generic_dct! (a:: AbstractArray{T} ) where {T<: AbstractFloats } = (b = generic_dct (a); a[:] = b)
139
+ generic_idct! (a:: AbstractArray{T} ) where {T<: AbstractFloats } = (b = generic_idct (a); a[:] = b)
140
+
141
+ for f in (:dct , :dct! , :idct , :idct! )
142
+ pf = Symbol (" plan_" , f)
143
+ @eval begin
144
+ $ f (x:: AbstractArray{<:AbstractFloats} ) = $ pf (x) * x
145
+ $ f (x:: AbstractArray{<:AbstractFloats} , region) = $ pf (x, region) * x
146
+ end
147
+ end
139
148
140
149
# dummy plans
141
150
struct DummyFFTPlan{T,inplace} <: Plan{T} end
@@ -155,39 +164,42 @@ for (Plan,iPlan) in ((:DummyFFTPlan,:DummyiFFTPlan),
155
164
end
156
165
157
166
158
- for (Plan,ff,ff!) in ((:DummyFFTPlan ,:fft , :fft ! ),
159
- (:DummyiFFTPlan ,:ifft , :ifft ! ),
160
- (:DummyrFFTPlan ,:rfft , :rfft ! ),
161
- (:DummyirFFTPlan ,:irfft , :irfft ! ),
162
- (:DummyDCTPlan ,:dct , :dct ! ),
163
- (:DummyiDCTPlan ,:idct , :idct ! ))
167
+ for (Plan,ff,ff!) in ((:DummyFFTPlan ,:generic_fft , :generic_fft ! ),
168
+ (:DummyiFFTPlan ,:generic_ifft , :generic_ifft ! ),
169
+ (:DummyrFFTPlan ,:generic_rfft , :generic_rfft ! ),
170
+ (:DummyirFFTPlan ,:generic_irfft , :generic_irfft ! ),
171
+ (:DummyDCTPlan ,:generic_dct , :generic_dct ! ),
172
+ (:DummyiDCTPlan ,:generic_idct , :generic_idct ! ))
164
173
@eval begin
165
- * (p:: $Plan{T,true} , x:: StridedArray{T,N} ) where {T,N} = $ ff! (x)
166
- * (p:: $Plan{T,false} , x:: StridedArray{T,N} ) where {T,N} = $ ff (x)
174
+ * (p:: $Plan{T,true} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = $ ff! (x)
175
+ * (p:: $Plan{T,false} , x:: StridedArray{T,N} ) where {T<: AbstractFloats ,N} = $ ff (x)
167
176
function LAmul! (C:: StridedVector , p:: $Plan , x:: StridedVector )
168
177
C[:] = $ ff (x)
169
178
C
170
179
end
171
180
end
172
181
end
173
182
183
+ # We override these for AbstractFloat, so that conversion from reals to
184
+ # complex numbers works for any AbstractFloat (instead of only BlasFloat's)
185
+ AbstractFFTs. complexfloat (x:: StridedArray{Complex{<:AbstractFloat}} ) = x
186
+ AbstractFFTs. realfloat (x:: StridedArray{<:Real} ) = x
187
+ AbstractFFTs. _fftfloat (:: Type{T} ) where {T <: AbstractFloat } = T
174
188
175
-
176
-
177
- plan_fft! (x:: Vector{T} ) where {T<: AbstractFloats } = DummyFFTPlan {Complex{real(T)},true} ()
178
- plan_ifft! (x:: Vector{T} ) where {T<: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},true} ()
189
+ plan_fft! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyFFTPlan {Complex{real(T)},true} ()
190
+ plan_ifft! (x:: StridedArray{T} , region) where {T <: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},true} ()
179
191
180
192
# plan_rfft!{T<:AbstractFloats}(x::Vector{T}) = DummyrFFTPlan{Complex{real(T)},true}()
181
193
# plan_irfft!{T<:AbstractFloats}(x::Vector{T},n::Integer) = DummyirFFTPlan{Complex{real(T)},true}()
182
- plan_dct! (x:: Vector {T} ) where {T<: AbstractFloats } = DummyDCTPlan {T,true} ()
183
- plan_idct! (x:: Vector {T} ) where {T<: AbstractFloats } = DummyiDCTPlan {T,true} ()
184
-
185
- plan_fft (x:: Vector {T} ) where {T<: AbstractFloats } = DummyFFTPlan {Complex{real(T)},false} ()
186
- plan_ifft (x:: Vector {T} ) where {T<: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},false} ()
187
- plan_rfft (x:: Vector {T} ) where {T<: AbstractFloats } = DummyrFFTPlan {Complex{real(T)},false} ()
188
- plan_irfft (x:: Vector {T} ,n:: Integer ) where {T<: AbstractFloats } = DummyirFFTPlan {Complex{real(T)},false} ()
189
- plan_dct (x:: Vector {T} ) where {T<: AbstractFloats } = DummyDCTPlan {T,false} ()
190
- plan_idct (x:: Vector {T} ) where {T<: AbstractFloats } = DummyiDCTPlan {T,false} ()
194
+ plan_dct! (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyDCTPlan {T,true} ()
195
+ plan_idct! (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyiDCTPlan {T,true} ()
196
+
197
+ plan_fft (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyFFTPlan {Complex{real(T)},false} ()
198
+ plan_ifft (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyiFFTPlan {Complex{real(T)},false} ()
199
+ plan_rfft (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyrFFTPlan {Complex{real(T)},false} ()
200
+ plan_irfft (x:: StridedArray {T} ,n:: Integer ) where {T <: AbstractFloats } = DummyirFFTPlan {Complex{real(T)},false} ()
201
+ plan_dct (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyDCTPlan {T,false} ()
202
+ plan_idct (x:: StridedArray {T}, region ) where {T <: AbstractFloats } = DummyiDCTPlan {T,false} ()
191
203
192
204
193
205
function interlace (a:: Vector{S} ,b:: Vector{V} ) where {S<: Number ,V<: Number }
0 commit comments