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