1+ value (x:: Complex{<:Dual} ) = Complex (x. re. value, x. im. value)
2+
3+ partials (x:: Complex{<:Dual} , n:: Int ) = Complex (partials (x. re, n), partials (x. im, n))
4+
5+ npartials (x:: Complex{<:Dual{T,V,N}} ) where {T,V,N} = N
6+ npartials (:: Type{<:Complex{<:Dual{T,V,N}}} ) where {T,V,N} = N
7+
8+ # AbstractFFTs.complexfloat(x::AbstractArray{<:Dual}) = float.(x .+ 0im)
9+ AbstractFFTs. complexfloat (x:: AbstractArray{<:Dual} ) = AbstractFFTs. complexfloat .(x)
10+ AbstractFFTs. complexfloat (d:: Dual{T,V,N} ) where {T,V,N} = convert (Dual{T,float (V),N}, d) + 0im
11+
12+ AbstractFFTs. realfloat (x:: AbstractArray{<:Dual} ) = AbstractFFTs. realfloat .(x)
13+ AbstractFFTs. realfloat (d:: Dual{T,V,N} ) where {T,V,N} = convert (Dual{T,float (V),N}, d)
14+
15+ for plan in [:plan_fft , :plan_ifft , :plan_bfft ]
16+ @eval begin
17+
18+ AbstractFFTs.$ plan (x:: AbstractArray{<:Dual} , region= 1 : ndims (x)) =
19+ AbstractFFTs.$ plan (value .(x), region)
20+
21+ AbstractFFTs.$ plan (x:: AbstractArray{<:Complex{<:Dual}} , region= 1 : ndims (x)) =
22+ AbstractFFTs.$ plan (value .(x), region)
23+
24+ end
25+ end
26+
27+ # rfft only accepts real arrays
28+ AbstractFFTs. plan_rfft (x:: AbstractArray{<:Dual} , region= 1 : ndims (x)) =
29+ AbstractFFTs. plan_rfft (value .(x), region)
30+
31+ for plan in [:plan_irfft , :plan_brfft ] # these take an extra argument, only when complex?
32+ @eval begin
33+
34+ AbstractFFTs.$ plan (x:: AbstractArray{<:Dual} , region= 1 : ndims (x)) =
35+ AbstractFFTs.$ plan (value .(x), region)
36+
37+ AbstractFFTs.$ plan (x:: AbstractArray{<:Complex{<:Dual}} , d:: Integer , region= 1 : ndims (x)) =
38+ AbstractFFTs.$ plan (value .(x), d, region)
39+
40+ end
41+ end
42+
43+ # for f in (:dct, :idct)
44+ # pf = Symbol("plan_", f)
45+ # @eval begin
46+ # AbstractFFTs.$f(x::AbstractArray{<:Dual}) = $pf(x) * x
47+ # AbstractFFTs.$f(x::AbstractArray{<:Dual}, region) = $pf(x, region) * x
48+ # AbstractFFTs.$pf(x::AbstractArray{<:Dual}, region; kws...) = $pf(value.(x), region; kws...)
49+ # AbstractFFTs.$pf(x::AbstractArray{<:Complex}, region; kws...) = $pf(value.(x), region; kws...)
50+ # end
51+ # end
52+
53+
54+ for P in [:Plan , :ScaledPlan ] # need ScaledPlan to avoid ambiguities
55+ @eval begin
56+
57+ Base.:* (p:: AbstractFFTs. $ P, x:: AbstractArray{<:Dual} ) =
58+ _apply_plan (p, x)
59+
60+ Base.:* (p:: AbstractFFTs. $ P, x:: AbstractArray{<:Complex{<:Dual}} ) =
61+ _apply_plan (p, x)
62+
63+ end
64+ end
65+
66+ function _apply_plan (p:: AbstractFFTs.Plan , x:: AbstractArray )
67+ xtil = p * value .(x)
68+ dxtils = ntuple (npartials (eltype (x))) do n
69+ p * partials .(x, n)
70+ end
71+ __apply_plan (tagtype (eltype (x)), xtil, dxtils)
72+ end
73+
74+ function __apply_plan (T, xtil, dxtils)
75+ map (xtil, dxtils... ) do val, parts...
76+ Complex (
77+ Dual {T} (real (val), map (real, parts)),
78+ Dual {T} (imag (val), map (imag, parts)),
79+ )
80+ end
81+ end
0 commit comments