Skip to content

Commit 8474141

Browse files
committed
Update adjoint plan docs
1 parent ac7c78c commit 8474141

File tree

3 files changed

+31
-35
lines changed

3 files changed

+31
-35
lines changed

README.md

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,4 @@ This allows multiple FFT packages to co-exist with the same underlying `fft(x)`
1616

1717
## Developer information
1818

19-
To define a new FFT implementation in your own module, you should
20-
21-
* Define a new subtype (e.g. `MyPlan`) of `AbstractFFTs.Plan{T}` for FFTs and related transforms on arrays of `T`.
22-
This must have a `pinv::Plan` field, initially undefined when a `MyPlan` is created, that is used for caching the
23-
inverse plan.
24-
25-
* Define a new method `AbstractFFTs.plan_fft(x, region; kws...)` that returns a `MyPlan` for at least some types of
26-
`x` and some set of dimensions `region`. The `region` (or a copy thereof) should be accessible via `fftdims(p::MyPlan)` (which defaults to `p.region`).
27-
28-
* Define a method of `LinearAlgebra.mul!(y, p::MyPlan, x)` (or `A_mul_B!(y, p::MyPlan, x)` on Julia prior to
29-
0.7.0-DEV.3204) that computes the transform `p` of `x` and stores the result in `y`.
30-
31-
* Define a method of `*(p::MyPlan, x)`, which can simply call your `mul!` (or `A_mul_B!`) method.
32-
This is not defined generically in this package due to subtleties that arise for in-place and real-input FFTs.
33-
34-
* If the inverse transform is implemented, you should also define `plan_inv(p::MyPlan)`, which should construct the
35-
inverse plan to `p`, and `plan_bfft(x, region; kws...)` for an unnormalized inverse ("backwards") transform of `x`.
36-
37-
* You can also define similar methods of `plan_rfft` and `plan_brfft` for real-input FFTs.
38-
39-
The normalization convention for your FFT should be that it computes yₖ = ∑ⱼ xⱼ exp(-2πi jk/n) for a transform of
40-
length n, and the "backwards" (unnormalized inverse) transform computes the same thing but with exp(+2πi jk/n).
19+
To define a new FFT implementation in your own module, see [defining a new implementation](https://juliamath.github.io/AbstractFFTs.jl/stable/implementations/#Defining-a-new-implementation).

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[deps]
2+
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
23
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
34

45
[compat]

docs/src/implementations.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,32 @@ The following packages extend the functionality provided by AbstractFFTs:
1111

1212
## Defining a new implementation
1313

14-
Implementations should implement `LinearAlgebra.mul!(Y, plan, X)` (or
15-
`A_mul_B!(y, p::MyPlan, x)` on Julia prior to 0.7.0-DEV.3204) so as to support
16-
pre-allocated output arrays.
17-
We don't define `*` in terms of `mul!` generically here, however, because
18-
of subtleties for in-place and real FFT plans.
19-
20-
To support `inv`, `\`, and `ldiv!(y, plan, x)`, we require `Plan` subtypes
21-
to have a `pinv::Plan` field, which caches the inverse plan, and which should be
22-
initially undefined.
23-
They should also implement `plan_inv(p)` to construct the inverse of a plan `p`.
24-
25-
Implementations only need to provide the unnormalized backwards FFT,
26-
similar to FFTW, and we do the scaling generically to get the inverse FFT.
14+
To define a new FFT implementation in your own module, you should
15+
16+
* Define a new subtype (e.g. `MyPlan`) of `AbstractFFTs.Plan{T}` for FFTs and related transforms on arrays of `T`.
17+
This must have a `pinv::Plan` field, initially undefined when a `MyPlan` is created, that is used for caching the
18+
inverse plan.
19+
20+
* Define a new method `AbstractFFTs.plan_fft(x, region; kws...)` that returns a `MyPlan` for at least some types of
21+
`x` and some set of dimensions `region`. The `region` (or a copy thereof) should be accessible via `fftdims(p::MyPlan)` (which defaults to `p.region`).
22+
23+
* Define a method of `LinearAlgebra.mul!(y, p::MyPlan, x)` (or `A_mul_B!(y, p::MyPlan, x)` on Julia prior to
24+
0.7.0-DEV.3204) that computes the transform `p` of `x` and stores the result in `y`.
25+
26+
* Define a method of `*(p::MyPlan, x)`, which can simply call your `mul!` (or `A_mul_B!`) method.
27+
This is not defined generically in this package due to subtleties that arise for in-place and real-input FFTs.
28+
29+
* If the inverse transform is implemented, you should also define `plan_inv(p::MyPlan)`, which should construct the
30+
inverse plan to `p`, and `plan_bfft(x, region; kws...)` for an unnormalized inverse ("backwards") transform of `x`.
31+
Implementations only need to provide the unnormalized backwards FFT, similar to FFTW, and we do the scaling generically
32+
to get the inverse FFT.
33+
34+
* You can also define similar methods of `plan_rfft` and `plan_brfft` for real-input FFTs.
35+
36+
* To enable automatic computation of adjoint plans via [`Base.adjoint`](@ref) (used in rules for reverse differentiation), define the trait `AbstractFFTs.ProjectionStyle(::MyPlan)`, which can take values:
37+
* `AbstractFFTs.NoProjectionStyle()`,
38+
* `AbstractFFTs.RealProjectionStyle()`, for plans which halve one of the output's dimensions analogously to [`rfft`](@ref),
39+
* `AbstractFFTs.RealInverseProjectionStyle(d::Integer)`, for plans which expect an input with a halved dimension analogously to [`irfft`](@ref), where `d` is the original length of the dimension.
40+
41+
The normalization convention for your FFT should be that it computes yₖ = ∑ⱼ xⱼ exp(-2πi jk/n) for a transform of
42+
length n, and the "backwards" (unnormalized inverse) transform computes the same thing but with exp(+2πi jk/n).

0 commit comments

Comments
 (0)