11# This file contains code that was formerly part of Julia. License is MIT: https://julialang.org/license
22
3- module AbstractFFTsTestUtilsExt
3+ module AbstractFFTsTestExt
44
55using AbstractFFTs
66using AbstractFFTs: TestUtils
77using AbstractFFTs. LinearAlgebra
88using Test
99
10- # Ground truth _x_fft computed using FFTW library
10+ # Ground truth x_fft computed using FFTW library
1111const TEST_CASES = (
1212 (; x = collect (1 : 7 ), dims = 1 ,
1313 x_fft = [28.0 + 0.0im ,
@@ -51,29 +51,47 @@ const TEST_CASES = (
5151 dims= 3 )),
5252 )
5353
54- function TestUtils. test_plan_adjoint (P:: AbstractFFTs.Plan , x:: AbstractArray ; real_plan= false )
55- y = rand (eltype (P * x), size (P * x))
54+
55+ function TestUtils. test_plan (P:: AbstractFFTs.Plan , x:: AbstractArray , x_transformed:: AbstractArray ; inplace_plan= false , copy_input= false )
56+ _copy = copy_input ? copy : identity
57+ if ! inplace_plan
58+ @test P * _copy (x) ≈ x_transformed
59+ @test P \ (P * _copy (x)) ≈ x
60+ _x_out = similar (P * _copy (x))
61+ @test mul! (_x_out, P, _copy (x)) ≈ x_transformed
62+ @test _x_out ≈ x_transformed
63+ else
64+ _x = copy (x)
65+ @test P * _copy (_x) ≈ x_transformed
66+ @test _x ≈ x_transformed
67+ @test P \ _copy (_x) ≈ x
68+ @test _x ≈ x
69+ end
70+ end
71+
72+ function TestUtils. test_plan_adjoint (P:: AbstractFFTs.Plan , x:: AbstractArray ; real_plan= false , copy_input= false )
73+ _copy = copy_input ? copy : identity
74+ y = rand (eltype (P * _copy (x)), size (P * _copy (x)))
5675 # test basic properties
57- @test_broken eltype (P' ) === typeof (y) # (AbstractFFTs.jl#110)
58- @test fftdims (P' ) == fftdims (P)
76+ @test_skip eltype (P' ) === typeof (y) # (AbstractFFTs.jl#110)
5977 @test (P' )' === P # test adjoint of adjoint
6078 @test size (P' ) == AbstractFFTs. output_size (P) # test size of adjoint
6179 # test correctness of adjoint and its inverse via the dot test
6280 if ! real_plan
63- @test dot (y, P * x) ≈ dot (P' * y , x)
64- @test dot (y, P \ x) ≈ dot (P' \ y , x)
81+ @test dot (y, P * _copy (x)) ≈ dot (P' * _copy (y) , x)
82+ @test dot (y, P \ _copy (x)) ≈ dot (P' \ _copy (y) , x)
6583 else
6684 _component_dot (x, y) = dot (real .(x), real .(y)) + dot (imag .(x), imag .(y))
67- @test _component_dot (y, P * copy (x)) ≈ _component_dot (P' * copy (y), x)
68- @test _component_dot (x, P \ copy (y)) ≈ _component_dot (P' \ copy (x), y)
85+ @test _component_dot (y, P * _copy (x)) ≈ _component_dot (P' * _copy (y), x)
86+ @test _component_dot (x, P \ _copy (y)) ≈ _component_dot (P' \ _copy (x), y)
6987 end
7088 @test_throws MethodError mul! (x, P' , y)
7189end
7290
73- function TestUtils. test_complex_fft (ArrayType= Array; test_inplace= true , test_adjoint= true )
91+ function TestUtils. test_complex_ffts (ArrayType= Array; test_inplace= true , test_adjoint= true )
7492 @testset " correctness of fft, bfft, ifft" begin
7593 for test_case in TEST_CASES
76- _x, dims, _x_fft = test_case. x, test_case. dims, test_case. x_fft
94+ _x, dims, _x_fft = copy ( test_case. x) , test_case. dims, copy ( test_case. x_fft)
7795 x = convert (ArrayType, _x) # dummy array that will be passed to plans
7896 x_complexf = convert (ArrayType, complex .(float .(x))) # for testing mutating complex FFTs
7997 x_fft = convert (ArrayType, _x_fft)
@@ -90,25 +108,16 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
90108 for P in (plan_fft (similar (x_complexf), dims), inv (plan_ifft (similar (x_complexf), dims)))
91109 @test eltype (P) <: Complex
92110 @test fftdims (P) == dims
93- @test P * x ≈ x_fft
94- @test P \ (P * x) ≈ x
95- _x_out = similar (x_fft)
96- @test mul! (_x_out, P, x_complexf) ≈ x_fft
97- @test _x_out ≈ x_fft
111+ TestUtils. test_plan (P, x_complexf, x_fft)
98112 if test_adjoint
113+ @test fftdims (P' ) == fftdims (P)
99114 TestUtils. test_plan_adjoint (P, x_complexf)
100115 end
101116 end
102117 if test_inplace
103118 # test IIP plans
104119 for P in (plan_fft! (similar (x_complexf), dims), inv (plan_ifft! (similar (x_complexf), dims)))
105- @test eltype (P) <: Complex
106- @test fftdims (P) == dims
107- _x_complexf = copy (x_complexf)
108- @test P * _x_complexf ≈ x_fft
109- @test _x_complexf ≈ x_fft
110- @test P \ _x_complexf ≈ x
111- @test _x_complexf ≈ x
120+ TestUtils. test_plan (P, x_complexf, x_fft; inplace_plan= true )
112121 end
113122 end
114123
@@ -124,24 +133,16 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
124133 for P in (plan_bfft (similar (x_fft), dims),)
125134 @test eltype (P) <: Complex
126135 @test fftdims (P) == dims
127- @test P * x_fft ≈ x_scaled
128- @test P \ (P * x_fft) ≈ x_fft
129- _x_complexf = similar (x_complexf)
130- @test mul! (_x_complexf, P, x_fft) ≈ x_scaled
131- @test _x_complexf ≈ x_scaled
136+ TestUtils. test_plan (P, x_fft, x_scaled)
132137 if test_adjoint
133- TestUtils. test_plan_adjoint (P, x_complexf )
138+ TestUtils. test_plan_adjoint (P, x_fft )
134139 end
135140 end
136141 # test IIP plans
137142 for P in (plan_bfft! (similar (x_fft), dims),)
138143 @test eltype (P) <: Complex
139144 @test fftdims (P) == dims
140- _x_fft = copy (x_fft)
141- @test P * _x_fft ≈ x_scaled
142- @test _x_fft ≈ x_scaled
143- @test P \ _x_fft ≈ x_fft
144- @test _x_fft ≈ x_fft
145+ TestUtils. test_plan (P, x_fft, x_scaled; inplace_plan= true )
145146 end
146147
147148 # IFFT
@@ -155,35 +156,27 @@ function TestUtils.test_complex_fft(ArrayType=Array; test_inplace=true, test_adj
155156 for P in (plan_ifft (similar (x_complexf), dims), inv (plan_fft (similar (x_complexf), dims)))
156157 @test eltype (P) <: Complex
157158 @test fftdims (P) == dims
158- @test P * x_fft ≈ x
159- @test P \ (P * x_fft) ≈ x_fft
160- _x_complexf = similar (x_complexf)
161- @test mul! (_x_complexf, P, x_fft) ≈ x
162- @test _x_complexf ≈ x
159+ TestUtils. test_plan (P, x_fft, x)
163160 if test_adjoint
164- TestUtils. test_plan_adjoint (P, x_complexf )
161+ TestUtils. test_plan_adjoint (P, x_fft )
165162 end
166163 end
167164 # test IIP plans
168165 if test_inplace
169166 for P in (plan_ifft! (similar (x_complexf), dims), inv (plan_fft! (similar (x_complexf), dims)))
170167 @test eltype (P) <: Complex
171168 @test fftdims (P) == dims
172- _x_fft = copy (x_fft)
173- @test P * _x_fft ≈ x
174- @test _x_fft ≈ x
175- @test P \ _x_fft ≈ x_fft
176- @test _x_fft ≈ x_fft
169+ TestUtils. test_plan (P, x_fft, x; inplace_plan= true )
177170 end
178171 end
179172 end
180173 end
181174end
182175
183- function TestUtils. test_real_fft (ArrayType= Array; test_inplace = true , test_adjoint = true )
176+ function TestUtils. test_real_ffts (ArrayType= Array; test_adjoint = true , copy_input = false )
184177 @testset " correctness of rfft, brfft, irfft" begin
185178 for test_case in TEST_CASES
186- _x, dims, _x_fft = test_case. x, test_case. dims, test_case. x_fft
179+ _x, dims, _x_fft = copy ( test_case. x) , test_case. dims, copy ( test_case. x_fft)
187180 x = convert (ArrayType, _x) # dummy array that will be passed to plans
188181 x_real = float .(x) # for testing mutating real FFTs
189182 x_fft = convert (ArrayType, _x_fft)
@@ -198,14 +191,9 @@ function TestUtils.test_real_fft(ArrayType=Array; test_inplace=true, test_adjoin
198191 for P in (plan_rfft (similar (x_real), dims), inv (plan_irfft (similar (x_rfft), size (x, first (dims)), dims)))
199192 @test eltype (P) <: Real
200193 @test fftdims (P) == dims
201- # Always copy input before application due to FFTW real plans possibly mutating input (AbstractFFTs.jl#101)
202- @test P * copy (x) ≈ x_rfft
203- @test P \ (P * copy (x)) ≈ x
204- _x_rfft = similar (x_rfft)
205- @test mul! (_x_rfft, P, copy (x_real)) ≈ x_rfft
206- @test _x_rfft ≈ x_rfft
194+ TestUtils. test_plan (P, x_real, x_rfft; copy_input)
207195 if test_adjoint
208- TestUtils. test_plan_adjoint (P, x_real; real_plan= true )
196+ TestUtils. test_plan_adjoint (P, x_real; real_plan= true , copy_input )
209197 end
210198 end
211199
@@ -215,25 +203,18 @@ function TestUtils.test_real_fft(ArrayType=Array; test_inplace=true, test_adjoin
215203 for P in (plan_brfft (similar (x_rfft), size (x, first (dims)), dims),)
216204 @test eltype (P) <: Complex
217205 @test fftdims (P) == dims
218- @test P * copy (x_rfft) ≈ x_scaled
219- @test P \ (P * copy (x_rfft)) ≈ x_rfft
220- _x_scaled = similar (x_real)
221- @test mul! (_x_scaled, P, copy (x_rfft)) ≈ x_scaled
222- @test _x_scaled ≈ x_scaled
206+ TestUtils. test_plan (P, x_rfft, x_scaled; copy_input)
223207 end
224208
225209 # IRFFT
226210 @test irfft (x_rfft, size (x, first (dims)), dims) ≈ x
227211 for P in (plan_irfft (similar (x_rfft), size (x, first (dims)), dims), inv (plan_rfft (similar (x_real), dims)))
228212 @test eltype (P) <: Complex
229213 @test fftdims (P) == dims
230- @test P * copy (x_rfft) ≈ x
231- @test P \ (P * copy (x_rfft)) ≈ x_rfft
232- _x_real = similar (x_real)
233- @test mul! (_x_real, P, copy (x_rfft)) ≈ x_real
214+ TestUtils. test_plan (P, x_rfft, x; copy_input)
234215 end
235216 end
236217 end
237218end
238219
239- end
220+ end
0 commit comments