diff --git a/src/AbstractFFTs.jl b/src/AbstractFFTs.jl index 7b0902f..734c7d4 100644 --- a/src/AbstractFFTs.jl +++ b/src/AbstractFFTs.jl @@ -5,7 +5,7 @@ import ChainRulesCore export fft, ifft, bfft, fft!, ifft!, bfft!, plan_fft, plan_ifft, plan_bfft, plan_fft!, plan_ifft!, plan_bfft!, rfft, irfft, brfft, plan_rfft, plan_irfft, plan_brfft, - fftshift, ifftshift, Frequencies, fftfreq, rfftfreq + fftshift, ifftshift, fftshift!, ifftshift!, Frequencies, fftfreq, rfftfreq include("definitions.jl") include("chainrules.jl") diff --git a/src/definitions.jl b/src/definitions.jl index 80a6656..41df3e5 100644 --- a/src/definitions.jl +++ b/src/definitions.jl @@ -344,6 +344,16 @@ plan_irfft ############################################################################## +""" + fftshift!(dest, src, [dim]) + +Nonallocating version of [`fftshift`](@ref). Stores the result of the shift of the `src` array into the `dest` array. +""" +function fftshift!(dest, src, dim = 1:ndims(src)) + s = ntuple(d -> d in dim ? div(size(dest,d),2) : 0, Val(ndims(dest))) + circshift!(dest, src, s) +end + """ fftshift(x, [dim]) @@ -356,12 +366,21 @@ swapping the first and second halves, so `fftshift` and [`ifftshift`](@ref) are the same. If `dim` is not given then the signal is shifted along each dimension. + +The output of `fftshift` is allocated. If one desires to store the output in a preallocated array, use [`fftshift!`](@ref) instead. """ fftshift -function fftshift(x, dim = 1:ndims(x)) - s = ntuple(d -> d in dim ? div(size(x,d),2) : 0, Val(ndims(x))) - circshift(x, s) +fftshift(x, dim = 1:ndims(x)) = fftshift!(similar(x), x, dim) + +""" + ifftshift!(dest, src, [dim]) + +Nonallocating version of [`ifftshift`](@ref). Stores the result of the shift of the `src` array into the `dest` array. +""" +function ifftshift!(dest, src, dim = 1:ndims(src)) + s = ntuple(d -> d in dim ? -div(size(src,d),2) : 0, Val(ndims(src))) + circshift!(dest, src, s) end """ @@ -376,13 +395,12 @@ swapping the first and second halves, so [`fftshift`](@ref) and `ifftshift` are the same. If `dim` is not given then the signal is shifted along each dimension. + +The output of `ifftshift` is allocated. If one desires to store the output in a preallocated array, use [`ifftshift!`](@ref) instead. """ ifftshift -function ifftshift(x, dim = 1:ndims(x)) - s = ntuple(d -> d in dim ? -div(size(x,d),2) : 0, Val(ndims(x))) - circshift(x, s) -end +ifftshift(x, dim = 1:ndims(x)) = ifftshift!(similar(x), x, dim) ############################################################################## diff --git a/test/runtests.jl b/test/runtests.jl index de0304d..95c7c5d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -103,20 +103,37 @@ end @test @inferred(AbstractFFTs.fftshift([1 2 3])) == [3 1 2] @test @inferred(AbstractFFTs.fftshift([1, 2, 3])) == [3, 1, 2] @test @inferred(AbstractFFTs.fftshift([1 2 3; 4 5 6])) == [6 4 5; 3 1 2] + a = [0 0 0] + b = [0, 0, 0] + c = [0 0 0; 0 0 0] + @test (AbstractFFTs.fftshift!(a, [1 2 3]); a == [3 1 2]) + @test (AbstractFFTs.fftshift!(b, [1, 2, 3]); b == [3, 1, 2]) + @test (AbstractFFTs.fftshift!(c, [1 2 3; 4 5 6]); c == [6 4 5; 3 1 2]) @test @inferred(AbstractFFTs.fftshift([1 2 3; 4 5 6], 1)) == [4 5 6; 1 2 3] @test @inferred(AbstractFFTs.fftshift([1 2 3; 4 5 6], ())) == [1 2 3; 4 5 6] @test @inferred(AbstractFFTs.fftshift([1 2 3; 4 5 6], (1,2))) == [6 4 5; 3 1 2] @test @inferred(AbstractFFTs.fftshift([1 2 3; 4 5 6], 1:2)) == [6 4 5; 3 1 2] + @test (AbstractFFTs.fftshift!(c, [1 2 3; 4 5 6], 1); c == [4 5 6; 1 2 3]) + @test (AbstractFFTs.fftshift!(c, [1 2 3; 4 5 6], ()); c == [1 2 3; 4 5 6]) + @test (AbstractFFTs.fftshift!(c, [1 2 3; 4 5 6], (1,2)); c == [6 4 5; 3 1 2]) + @test (AbstractFFTs.fftshift!(c, [1 2 3; 4 5 6], 1:2); c == [6 4 5; 3 1 2]) @test @inferred(AbstractFFTs.ifftshift([1 2 3])) == [2 3 1] @test @inferred(AbstractFFTs.ifftshift([1, 2, 3])) == [2, 3, 1] @test @inferred(AbstractFFTs.ifftshift([1 2 3; 4 5 6])) == [5 6 4; 2 3 1] + @test (AbstractFFTs.ifftshift!(a, [1 2 3]); a == [2 3 1]) + @test (AbstractFFTs.ifftshift!(b, [1, 2, 3]); b == [2, 3, 1]) + @test (AbstractFFTs.ifftshift!(c, [1 2 3; 4 5 6]); c == [5 6 4; 2 3 1]) @test @inferred(AbstractFFTs.ifftshift([1 2 3; 4 5 6], 1)) == [4 5 6; 1 2 3] @test @inferred(AbstractFFTs.ifftshift([1 2 3; 4 5 6], ())) == [1 2 3; 4 5 6] @test @inferred(AbstractFFTs.ifftshift([1 2 3; 4 5 6], (1,2))) == [5 6 4; 2 3 1] @test @inferred(AbstractFFTs.ifftshift([1 2 3; 4 5 6], 1:2)) == [5 6 4; 2 3 1] + @test (AbstractFFTs.ifftshift!(c, [1 2 3; 4 5 6], 1); c == [4 5 6; 1 2 3]) + @test (AbstractFFTs.ifftshift!(c, [1 2 3; 4 5 6], ()); c == [1 2 3; 4 5 6]) + @test (AbstractFFTs.ifftshift!(c, [1 2 3; 4 5 6], (1,2)); c == [5 6 4; 2 3 1]) + @test (AbstractFFTs.ifftshift!(c, [1 2 3; 4 5 6], 1:2); c == [5 6 4; 2 3 1]) end @testset "FFT Frequencies" begin