Skip to content

disallow plan * real for in-place complex plan#342

Open
j-fu wants to merge 7 commits into
JuliaMath:masterfrom
j-fu:fix_inline_complex_plan
Open

disallow plan * real for in-place complex plan#342
j-fu wants to merge 7 commits into
JuliaMath:masterfrom
j-fu:fix_inline_complex_plan

Conversation

@j-fu

@j-fu j-fu commented Jul 17, 2026

Copy link
Copy Markdown

When applying a complex in-place plan to a real vector, '*' should throw similar to 'mul!'.
However, AbstractFFTs.jl defines *(::Plan{T}, ::AbstractArray) which copies the real vector to a Vector{T} which then is passed to the *(cFFTWPlan{T,K,true}, StridedArray{T}) method in FFTW.jl which now calculates and return the complex FFT for the complex vector without ever knowing that it should mutate the vector it has been passed.

Issue #341 has an MWE which shows what happens.

This PR changes the signature of *(cFFTWPlan{T,K,true}, StridedArray{T}) to *(cFFTWPlan{T,K,true}, AbstractArray). Now this method is directly invoked and throws as expected. A test for this behavior has been added.

Fixes #341.

When applying a complex inline plan to a real vector, '*' should throw
similar to 'mul!'.
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.89%. Comparing base (290d161) to head (cb25120).

Files with missing lines Patch % Lines
src/fft.jl 75.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #342      +/-   ##
==========================================
+ Coverage   73.45%   73.89%   +0.43%     
==========================================
  Files           5        5              
  Lines         535      544       +9     
==========================================
+ Hits          393      402       +9     
  Misses        142      142              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@stevengj

Copy link
Copy Markdown
Member

s/inline/inplace/

@stevengj stevengj changed the title Fix inline complex plan disallow plan * real for in-place complex plan Jul 18, 2026
Comment thread test/runtests.jl Outdated
Co-authored-by: Steven G. Johnson <stevenj@mit.edu>
Comment thread test/runtests.jl Outdated
Co-authored-by: Mosè Giordano <765740+giordano@users.noreply.github.com>
Comment thread test/runtests.jl
@j-fu

j-fu commented Jul 19, 2026

Copy link
Copy Markdown
Author

mul! is a different story. It always used to throw MethodError in this case, as there is no "wrapper" in AbstractFFTs .

Comment thread src/fft.jl Outdated
end


function assert_applicable(p::FFTWPlan{T}, X::AbstractArray) where T

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be restricted to in-place plans?

@j-fu

j-fu commented Jul 20, 2026

Copy link
Copy Markdown
Author

Well, that case was handeled by *(::Plan{T}, ::AbstractArray) where a copy is created.

But I agree that testing for inline in assert_applicable is more readable.

Ah and method dispatch based on the type parameter via defining assert_applicable(::Plan{T,K,true}...) results in method ambiguities.

Comment thread src/fft.jl

function assert_applicable(p::FFTWPlan{T}, X::AbstractArray) where T
throw(ArgumentError("In-place plan FFTWPlan{$(T)} cannot be applied to a $(typeof(X))"))
function assert_applicable(p::FFTWPlan{T,K, inplace}, X::AbstractArray) where {T,K, inplace}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of an if inplace stqtement, why not just make only to p::FFTWPlan{<:Any,<:Any,true}?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we need to make sure that the parent assert_applicable is called when appropriate too…

Comment thread src/fft.jl

function mul!(y::AbstractArray, p::cFFTWPlan{T}, x::AbstractArray) where T
throw(ArgumentError("mul!(x,::cFFTWPlan{$(T)},y) expects x and y be of type StridedArray{$(T)}"))
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this method necessary? If you just delete this method won't it throw a MethodError?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Applying a complex in-place plan via '*' to a real vector should throw

3 participants