@@ -51,6 +51,26 @@ const TEST_CASES = (
51
51
dims= 3 )),
52
52
)
53
53
54
+ # Perform generic adjoint plan tests
55
+ function _adjoint_test (P, x; real_plan= false )
56
+ y = rand (eltype (P * x), size (P * x))
57
+ # test basic properties
58
+ @test_broken eltype (P' ) === typeof (y) # (AbstactFFTs.jl#110)
59
+ @test fftdims (P' ) == fftdims (P)
60
+ @test (P' )' === P # test adjoint of adjoint
61
+ @test size (P' ) == AbstractFFTs. output_size (P) # test size of adjoint
62
+ # test correctness of adjoint and its inverse via the dot test
63
+ if ! real_plan
64
+ @test dot (y, P * x) ≈ dot (P' * y, x)
65
+ @test dot (y, P \ x) ≈ dot (P' \ y, x)
66
+ else
67
+ _component_dot (x, y) = dot (real .(x), real .(y)) + dot (imag .(x), imag .(y))
68
+ @test _component_dot (y, P * copy (x)) ≈ _component_dot (P' * copy (y), x)
69
+ @test _component_dot (x, P \ copy (y)) ≈ _component_dot (P' \ copy (x), y)
70
+ end
71
+ @test_throws MethodError mul! (x, P' , y)
72
+ end
73
+
54
74
"""
55
75
TestUtils.test_complex_fft(ArrayType=Array; test_real=true, test_inplace=true)
56
76
@@ -63,8 +83,9 @@ The backend implementation is assumed to be loaded prior to calling this functio
63
83
which the correctness tests are run. Arrays are constructed via
64
84
`convert(ArrayType, ...)`.
65
85
- `test_inplace=true`: whether to test in-place plans.
86
+ - `test_adjoint=true`: whether to test adjoints of plans.
66
87
"""
67
- function TestUtils. test_complex_fft (ArrayType= Array; test_inplace= true )
88
+ function TestUtils. test_complex_fft (ArrayType= Array; test_inplace= true , test_adjoint = true )
68
89
@testset " correctness of fft, bfft, ifft" begin
69
90
for test_case in TEST_CASES
70
91
_x, dims, _x_fft = test_case. x, test_case. dims, test_case. x_fft
@@ -89,6 +110,9 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true)
89
110
_x_out = similar (x_fft)
90
111
@test mul! (_x_out, P, x_complexf) ≈ x_fft
91
112
@test _x_out ≈ x_fft
113
+ if test_adjoint
114
+ _adjoint_test (P, x_complexf)
115
+ end
92
116
end
93
117
if test_inplace
94
118
# test IIP plans
@@ -120,6 +144,9 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true)
120
144
_x_complexf = similar (x_complexf)
121
145
@test mul! (_x_complexf, P, x_fft) ≈ x_scaled
122
146
@test _x_complexf ≈ x_scaled
147
+ if test_adjoint
148
+ _adjoint_test (P, x_complexf)
149
+ end
123
150
end
124
151
# test IIP plans
125
152
for P in (plan_bfft! (similar (x_fft), dims),)
@@ -148,6 +175,9 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true)
148
175
_x_complexf = similar (x_complexf)
149
176
@test mul! (_x_complexf, P, x_fft) ≈ x
150
177
@test _x_complexf ≈ x
178
+ if test_adjoint
179
+ _adjoint_test (P, x_complexf)
180
+ end
151
181
end
152
182
# test IIP plans
153
183
if test_inplace
@@ -177,10 +207,11 @@ The backend implementation is assumed to be loaded prior to calling this functio
177
207
which the correctness tests are run. Arrays are constructed via
178
208
`convert(ArrayType, ...)`.
179
209
- `test_inplace=true`: whether to test in-place plans.
210
+ - `test_adjoint=true`: whether to test adjoints of plans.
180
211
"""
181
- function TestUtils. test_real_fft (ArrayType= Array; test_inplace= true )
212
+ function TestUtils. test_real_fft (ArrayType= Array; test_inplace= true , test_adjoint = true )
182
213
@testset " correctness of rfft, brfft, irfft" begin
183
- for test_case in TEST_CASES[ 5 : 5 ]
214
+ for test_case in TEST_CASES
184
215
_x, dims, _x_fft = test_case. x, test_case. dims, test_case. x_fft
185
216
x = convert (ArrayType, _x) # dummy array that will be passed to plans
186
217
x_real = float .(x) # for testing mutating real FFTs
@@ -202,6 +233,9 @@ function TestUtils.test_real_fft(ArrayType=Array; test_inplace=true)
202
233
_x_rfft = similar (x_rfft)
203
234
@test mul! (_x_rfft, P, copy (x_real)) ≈ x_rfft
204
235
@test _x_rfft ≈ x_rfft
236
+ if test_adjoint
237
+ _adjoint_test (P, x_real; real_plan= true )
238
+ end
205
239
end
206
240
207
241
# BRFFT
0 commit comments