Skip to content

Commit 862afdc

Browse files
authored
Merge pull request #10 from martinholters/fixes_0.7
Fixes for Julia 0.7 (and drop support for a range of DEV versions)
2 parents c1eb41d + 7cb569b commit 862afdc

File tree

7 files changed

+57
-38
lines changed

7 files changed

+57
-38
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ To define a new FFT implementation in your own module, you should
2525
* Define a new method `AbstractFFTs.plan_fft(x, region; kws...)` that returns a `MyPlan` for at least some types of
2626
`x` and some set of dimensions `region`.
2727

28-
* Define a method of `A_mul_B!(y, p::MyPlan, x)` that computes the transform `p` of `x` and stores the result in `y`.
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`.
2930

30-
* Define a method of `*(p::MyPlan, x)`, which can simply call your `A_mul_B!` method.
31+
* Define a method of `*(p::MyPlan, x)`, which can simply call your `mul!` (or `A_mul_B!`) method.
3132
This is not defined generically in this package due to subtleties that arise for in-place and real-input FFTs.
3233

3334
* If the inverse transform is implemented, you should also define `plan_inv(p::MyPlan)`, which should construct the

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
julia 0.6
1+
julia 0.6 0.7.0-DEV.602 0.7.0-DEV.3449

docs/src/implementations.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ The following packages extend the functionality provided by AbstractFFTs:
99

1010
## Defining a new implementation
1111

12-
Implementations should implement `Base.A_mul_B!(Y, plan, X)` so as to support
12+
Implementations should implement `LinearAlgebra.mul!(Y, plan, X)` (or
13+
`A_mul_B!(y, p::MyPlan, x)` on Julia prior to 0.7.0-DEV.3204) so as to support
1314
pre-allocated output arrays.
14-
We don't define `*` in terms of `A_mul_B!` generically here, however, because
15+
We don't define `*` in terms of `mul!` generically here, however, because
1516
of subtleties for in-place and real FFT plans.
1617

17-
To support `inv`, `\`, and `A_ldiv_B!(y, plan, x)`, we require `Plan` subtypes
18+
To support `inv`, `\`, and `ldiv!(y, plan, x)`, we require `Plan` subtypes
1819
to have a `pinv::Plan` field, which caches the inverse plan, and which should be
1920
initially undefined.
2021
They should also implement `plan_inv(p)` to construct the inverse of a plan `p`.

src/AbstractFFTs.jl

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,20 @@ module AbstractFFTs
33

44
# After this version, the bindings can overwrite deprecated bindings in Base safely, but
55
# prior to it we want to extend/reexport the Base definitions
6-
if VERSION < v"0.7.0-DEV.986"
6+
if VERSION < v"0.7.0-DEV.602"
77
import Base: fft, ifft, bfft, fft!, ifft!, bfft!,
88
plan_fft, plan_ifft, plan_bfft, plan_fft!, plan_ifft!, plan_bfft!,
99
rfft, irfft, brfft, plan_rfft, plan_irfft, plan_brfft,
1010
fftshift, ifftshift
11-
if VERSION < v"0.7.0-DEV.602"
12-
import Base.DFT: Plan, ScaledPlan, plan_inv, pinv_type, normalization,
13-
rfft_output_size, brfft_output_size, realfloat, complexfloat
14-
end
11+
import Base.DFT: Plan, ScaledPlan, plan_inv, pinv_type, normalization,
12+
rfft_output_size, brfft_output_size, realfloat, complexfloat
1513
end
1614
# Reexport the Base bindings unchanged for versions before FFTW was removed, or export the
1715
# new definitions after overwritable deprecation bindings were introduced
18-
if VERSION < v"0.7.0-DEV.602" || VERSION >= v"0.7.0-DEV.986"
19-
export fft, ifft, bfft, fft!, ifft!, bfft!,
20-
plan_fft, plan_ifft, plan_bfft, plan_fft!, plan_ifft!, plan_bfft!,
21-
rfft, irfft, brfft, plan_rfft, plan_irfft, plan_brfft,
22-
fftshift, ifftshift
23-
end
16+
export fft, ifft, bfft, fft!, ifft!, bfft!,
17+
plan_fft, plan_ifft, plan_bfft, plan_fft!, plan_ifft!, plan_bfft!,
18+
rfft, irfft, brfft, plan_rfft, plan_irfft, plan_brfft,
19+
fftshift, ifftshift
2420

2521
# Only define things if we aren't using the existing Base bindings
2622
VERSION >= v"0.7.0-DEV.602" && include("definitions.jl")

src/definitions.jl

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# This file was formerly a part of Julia. License is MIT: https://julialang.org/license
22

3-
using Base.LinAlg: BlasReal
3+
using LinearAlgebra
4+
using LinearAlgebra: BlasReal
45
import Base: show, summary, size, ndims, length, eltype,
5-
*, A_mul_B!, inv, \, A_ldiv_B!
6+
*, inv, \
67

78
# DFT plan where the inputs are an array of eltype T
89
abstract type Plan{T} end
@@ -33,11 +34,11 @@ realfloat(x::AbstractArray{T}) where {T<:Real} = copy1(typeof(fftfloat(zero(T)))
3334

3435
# copy to a 1-based array, using circular permutation
3536
function copy1(::Type{T}, x) where T
36-
y = Array{T}(map(length, indices(x)))
37+
y = Array{T}(uninitialized, map(length, axes(x)))
3738
Base.circcopy!(y, x)
3839
end
3940

40-
to1(x::AbstractArray) = _to1(indices(x), x)
41+
to1(x::AbstractArray) = _to1(axes(x), x)
4142
_to1(::Tuple{Base.OneTo,Vararg{Base.OneTo}}, x) = x
4243
_to1(::Tuple, x) = copy1(eltype(x), x)
4344

@@ -93,11 +94,11 @@ contains all of the information needed to compute `fft(A, dims)` quickly.
9394
To apply `P` to an array `A`, use `P * A`; in general, the syntax for applying plans is much
9495
like that of matrices. (A plan can only be applied to arrays of the same size as the `A`
9596
for which the plan was created.) You can also apply a plan with a preallocated output array `Â`
96-
by calling `A_mul_B!(Â, plan, A)`. (For `A_mul_B!`, however, the input array `A` must
97+
by calling `mul!(Â, plan, A)`. (For `mul!`, however, the input array `A` must
9798
be a complex floating-point array like the output `Â`.) You can compute the inverse-transform plan by `inv(P)`
9899
and apply the inverse plan with `P \\ Â` (the inverse plan is cached and reused for
99100
subsequent calls to `inv` or `\\`), and apply the inverse plan to a pre-allocated output
100-
array `A` with `A_ldiv_B!(A, P, Â)`.
101+
array `A` with `ldiv!(A, P, Â)`.
101102
102103
The `flags` argument is a bitwise-or of FFTW planner flags, defaulting to `FFTW.ESTIMATE`.
103104
e.g. passing `FFTW.MEASURE` or `FFTW.PATIENT` will instead spend several seconds (or more)
@@ -206,12 +207,12 @@ plan_rfft(x::AbstractArray, region; kws...) = plan_rfft(realfloat(x), region; kw
206207
# only require implementation to provide *(::Plan{T}, ::Array{T})
207208
*(p::Plan{T}, x::AbstractArray) where {T} = p * copy1(T, x)
208209

209-
# Implementations should also implement A_mul_B!(Y, plan, X) so as to support
210-
# pre-allocated output arrays. We don't define * in terms of A_mul_B!
210+
# Implementations should also implement mul!(Y, plan, X) so as to support
211+
# pre-allocated output arrays. We don't define * in terms of mul!
211212
# generically here, however, because of subtleties for in-place and rfft plans.
212213

213214
##############################################################################
214-
# To support inv, \, and A_ldiv_B!(y, p, x), we require Plan subtypes
215+
# To support inv, \, and ldiv!(y, p, x), we require Plan subtypes
215216
# to have a pinv::Plan field, which caches the inverse plan, and which
216217
# should be initially undefined. They should also implement
217218
# plan_inv(p) to construct the inverse of a plan p.
@@ -224,7 +225,7 @@ pinv_type(p::Plan) = eltype(_pinv_type(p))
224225
inv(p::Plan) =
225226
isdefined(p, :pinv) ? p.pinv::pinv_type(p) : (p.pinv = plan_inv(p))
226227
\(p::Plan, x::AbstractArray) = inv(p) * x
227-
A_ldiv_B!(y::AbstractArray, p::Plan, x::AbstractArray) = A_mul_B!(y, inv(p), x)
228+
LinearAlgebra.ldiv!(y::AbstractArray, p::Plan, x::AbstractArray) = LinearAlgebra.mul!(y, inv(p), x)
228229

229230
##############################################################################
230231
# implementations only need to provide the unnormalized backwards FFT,
@@ -245,7 +246,13 @@ size(p::ScaledPlan) = size(p.p)
245246
show(io::IO, p::ScaledPlan) = print(io, p.scale, " * ", p.p)
246247
summary(p::ScaledPlan) = string(p.scale, " * ", summary(p.p))
247248

248-
*(p::ScaledPlan, x::AbstractArray) = scale!(p.p * x, p.scale)
249+
if VERSION >= v"0.7.0-DEV.3665"
250+
*(p::ScaledPlan, x::AbstractArray) = LinearAlgebra.rmul!(p.p * x, p.scale)
251+
elseif VERSION >= v"0.7.0-DEV.3563"
252+
*(p::ScaledPlan, x::AbstractArray) = LinearAlgebra.mul1!(p.p * x, p.scale)
253+
else
254+
*(p::ScaledPlan, x::AbstractArray) = scale!(p.p * x, p.scale)
255+
end
249256

250257
*::Number, p::Plan) = ScaledPlan(p, α)
251258
*(p::Plan, α::Number) = ScaledPlan(p, α)
@@ -265,8 +272,16 @@ plan_ifft!(x::AbstractArray, region; kws...) =
265272

266273
plan_inv(p::ScaledPlan) = ScaledPlan(plan_inv(p.p), inv(p.scale))
267274

268-
A_mul_B!(y::AbstractArray, p::ScaledPlan, x::AbstractArray) =
269-
scale!(p.scale, A_mul_B!(y, p.p, x))
275+
if VERSION >= v"0.7.0-DEV.3665"
276+
LinearAlgebra.mul!(y::AbstractArray, p::ScaledPlan, x::AbstractArray) =
277+
LinearAlgebra.lmul!(p.scale, LinearAlgebra.mul!(y, p.p, x))
278+
elseif VERSION >= v"0.7.0-DEV.3563"
279+
LinearAlgebra.mul!(y::AbstractArray, p::ScaledPlan, x::AbstractArray) =
280+
LinearAlgebra.mul2!(p.scale, LinearAlgebra.mul!(y, p.p, x))
281+
else
282+
LinearAlgebra.mul!(y::AbstractArray, p::ScaledPlan, x::AbstractArray) =
283+
scale!(p.scale, LinearAlgebra.mul!(y, p.p, x))
284+
end
270285

271286
##############################################################################
272287
# Real-input DFTs are annoying because the output has a different size

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Compat 0.48

test/runtests.jl

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
# This file contains code that was formerly part of Julia. License is MIT: https://julialang.org/license
22

33
using AbstractFFTs
4-
using Base.Test
5-
6-
import AbstractFFTs: Plan, plan_fft, plan_inv, plan_bfft
7-
import Base: A_mul_B!, *
4+
using AbstractFFTs: Plan
5+
using Compat.LinearAlgebra
6+
using Compat.Test
7+
8+
if VERSION < v"0.7.0-DEV.3204"
9+
const mul! = Base.A_mul_B!
10+
else
11+
const mul! = LinearAlgebra.mul!
12+
end
813

914
mutable struct TestPlan{T} <: Plan{T}
1015
region
@@ -34,11 +39,11 @@ function dft!(y::Vector, x::Vector, sign::Int)
3439
return y
3540
end
3641

37-
Base.A_mul_B!(y::Vector, p::TestPlan, x::Vector) = dft!(y, x, -1)
38-
Base.A_mul_B!(y::Vector, p::InverseTestPlan, x::Vector) = dft!(y, x, 1)
42+
mul!(y::Vector, p::TestPlan, x::Vector) = dft!(y, x, -1)
43+
mul!(y::Vector, p::InverseTestPlan, x::Vector) = dft!(y, x, 1)
3944

40-
Base.:*(p::TestPlan, x::Vector) = A_mul_B!(copy(x), p, x)
41-
Base.:*(p::InverseTestPlan, x::Vector) = A_mul_B!(copy(x), p, x)
45+
Base.:*(p::TestPlan, x::Vector) = mul!(copy(x), p, x)
46+
Base.:*(p::InverseTestPlan, x::Vector) = mul!(copy(x), p, x)
4247

4348
@testset "Custom Plan" begin
4449
x = AbstractFFTs.fft(collect(1:8))

0 commit comments

Comments
 (0)