Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 98fdcde

Browse files
committedJul 9, 2023
Document test utilities
1 parent fe2793e commit 98fdcde

File tree

4 files changed

+55
-35
lines changed

4 files changed

+55
-35
lines changed
 

‎docs/src/implementations.md

+10
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,13 @@ To define a new FFT implementation in your own module, you should
3939

4040
The normalization convention for your FFT should be that it computes ``y_k = \sum_j x_j \exp(-2\pi i j k/n)`` for a transform of
4141
length ``n``, and the "backwards" (unnormalized inverse) transform computes the same thing but with ``\exp(+2\pi i jk/n)``.
42+
43+
## Testing implementations
44+
45+
`AbstractFFTs.jl` provides a `TestUtils` module to help with testing downstream implementations.
46+
47+
```@docs
48+
AbstractFFTs.TestUtils.test_complex_fft
49+
AbstractFFTs.TestUtils.test_real_fft
50+
AbstractFFTs.TestUtils.test_plan_adjoint
51+
```

‎ext/AbstractFFTsTestUtilsExt.jl

+5-34
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ const TEST_CASES = (
5151
dims=3)),
5252
)
5353

54-
# Perform generic adjoint plan tests
55-
function _adjoint_test(P, x; real_plan=false)
54+
function TestUtils.test_plan_adjoint(P::AbstractFFTs.Plan, x::AbstractArray; real_plan=false)
5655
y = rand(eltype(P * x), size(P * x))
5756
# test basic properties
5857
@test_broken eltype(P') === typeof(y) # (AbstractFFTs.jl#110)
@@ -71,20 +70,6 @@ function _adjoint_test(P, x; real_plan=false)
7170
@test_throws MethodError mul!(x, P', y)
7271
end
7372

74-
"""
75-
TestUtils.test_complex_fft(ArrayType=Array; test_real=true, test_inplace=true)
76-
77-
Run tests to verify correctness of FFT/BFFT/IFFT functionality using a particular backend plan implementation.
78-
The backend implementation is assumed to be loaded prior to calling this function.
79-
80-
# Arguments
81-
82-
- `ArrayType`: determines the `AbstractArray` implementation for
83-
which the correctness tests are run. Arrays are constructed via
84-
`convert(ArrayType, ...)`.
85-
- `test_inplace=true`: whether to test in-place plans.
86-
- `test_adjoint=true`: whether to test adjoints of plans.
87-
"""
8873
function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adjoint=true)
8974
@testset "correctness of fft, bfft, ifft" begin
9075
for test_case in TEST_CASES
@@ -111,7 +96,7 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
11196
@test mul!(_x_out, P, x_complexf) x_fft
11297
@test _x_out x_fft
11398
if test_adjoint
114-
_adjoint_test(P, x_complexf)
99+
TestUtils.test_plan_adjoint(P, x_complexf)
115100
end
116101
end
117102
if test_inplace
@@ -145,7 +130,7 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
145130
@test mul!(_x_complexf, P, x_fft) x_scaled
146131
@test _x_complexf x_scaled
147132
if test_adjoint
148-
_adjoint_test(P, x_complexf)
133+
TestUtils.test_plan_adjoint(P, x_complexf)
149134
end
150135
end
151136
# test IIP plans
@@ -176,7 +161,7 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
176161
@test mul!(_x_complexf, P, x_fft) x
177162
@test _x_complexf x
178163
if test_adjoint
179-
_adjoint_test(P, x_complexf)
164+
TestUtils.test_plan_adjoint(P, x_complexf)
180165
end
181166
end
182167
# test IIP plans
@@ -195,20 +180,6 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
195180
end
196181
end
197182

198-
"""
199-
TestUtils.test_real_fft(ArrayType=Array; test_real=true, test_inplace=true)
200-
201-
Run tests to verify correctness of RFFT/BRFFT/IRFFT functionality using a particular backend plan implementation.
202-
The backend implementation is assumed to be loaded prior to calling this function.
203-
204-
# Arguments
205-
206-
- `ArrayType`: determines the `AbstractArray` implementation for
207-
which the correctness tests are run. Arrays are constructed via
208-
`convert(ArrayType, ...)`.
209-
- `test_inplace=true`: whether to test in-place plans.
210-
- `test_adjoint=true`: whether to test adjoints of plans.
211-
"""
212183
function TestUtils.test_real_fft(ArrayType=Array; test_inplace=true, test_adjoint=true)
213184
@testset "correctness of rfft, brfft, irfft" begin
214185
for test_case in TEST_CASES
@@ -234,7 +205,7 @@ function TestUtils.test_real_fft(ArrayType=Array; test_inplace=true, test_adjoin
234205
@test mul!(_x_rfft, P, copy(x_real)) x_rfft
235206
@test _x_rfft x_rfft
236207
if test_adjoint
237-
_adjoint_test(P, x_real; real_plan=true)
208+
TestUtils.test_plan_adjoint(P, x_real; real_plan=true)
238209
end
239210
end
240211

‎src/TestUtils.jl

+39
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,47 @@
11
module TestUtils
22

3+
"""
4+
TestUtils.test_complex_fft(ArrayType=Array; test_real=true, test_inplace=true)
5+
6+
Run tests to verify correctness of FFT/BFFT/IFFT functionality using a particular backend plan implementation.
7+
The backend implementation is assumed to be loaded prior to calling this function.
8+
9+
# Arguments
10+
11+
- `ArrayType`: determines the `AbstractArray` implementation for
12+
which the correctness tests are run. Arrays are constructed via
13+
`convert(ArrayType, ...)`.
14+
- `test_inplace=true`: whether to test in-place plans.
15+
- `test_adjoint=true`: whether to test [plan adjoints](api.md#Base.adjoint).
16+
"""
317
function test_complex_fft end
18+
19+
"""
20+
TestUtils.test_real_fft(ArrayType=Array; test_real=true, test_inplace=true)
21+
22+
Run tests to verify correctness of RFFT/BRFFT/IRFFT functionality using a particular backend plan implementation.
23+
The backend implementation is assumed to be loaded prior to calling this function.
24+
25+
# Arguments
26+
27+
- `ArrayType`: determines the `AbstractArray` implementation for
28+
which the correctness tests are run. Arrays are constructed via
29+
`convert(ArrayType, ...)`.
30+
- `test_inplace=true`: whether to test in-place plans.
31+
- `test_adjoint=true`: whether to test [plan adjoints](api.md#Base.adjoint).
32+
"""
433
function test_real_fft end
534

35+
"""
36+
TestUtils.test_plan_adjoint(P::Plan, x::AbstractArray; real_plan=false)
37+
38+
Test basic properties of the adjoint `P'` of a particular plan given an input array to the plan `x`,
39+
including its accuracy via the dot test. Real-to-complex and complex-to-real plans require
40+
a slightly modified dot test, in which case `real_plan=true` should be provided.
41+
42+
"""
43+
function test_plan_adjoint end
44+
645
function __init__()
746
if isdefined(Base, :Experimental)
847
# Better error message if users forget to load Test

‎src/definitions.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ Form the adjoint operator of an FFT plan. Returns a plan that performs the adjoi
608608
the original plan. Note that this differs from the corresponding backwards plan in the case of real
609609
FFTs due to the halving of one of the dimensions of the FFT output, as described in [`rfft`](@ref).
610610
611-
!!! note
611+
!!! warning
612612
Adjoint plans do not currently support `LinearAlgebra.mul!`. Further, as a new addition to `AbstractFFTs`,
613613
coverage of `Base.adjoint` in downstream implementations may be limited.
614614
"""

0 commit comments

Comments
 (0)
Please sign in to comment.