Skip to content

Inconsistent treatment of NaNs (and Infs) by conv #668

Open

Description

@jonathanlilly

conv handles NaNs differently depending upon the algorithm employed

You might think that NaNs simply propagate outward by the half length of the filter, however, this only happens for the direct algorithm. This could allow the edge effects and imprints of any missing data (represented as NaNs) to be viewed.

In what follows, with a 6-element vector whose first element is a NaN convolved with a three-element vector, we get (as expected) 3 leading NaNs with :direct, 6 leading NaNs with :fft_overlapsave, and all NaNs with :fft_simple.

A similar thing happens if the signal contains Infs, but in this case the :direct algorithm produces Infs while the others produce NaNs.

An implication is that as :auto switches algorithms dependent upon signal length and other factors, the output will be unpredictable when the signal contains NaNs or Infs.

It would be preferable to automatically switch to :direct when NaNs or Infs are present.

x = [NaN;randn(5)]

6-element Vector{Float64}:
 NaN
   1.0284058817215251
  -1.667755275236572
   0.7917827535218328
   0.1509806512150328

conv(x,[1,1,1],algorithm = :direct)
8-element Vector{Float64}:
 NaN
 NaN
 NaN
   0.15243336000678587
  -0.7249918704997065
   0.5214250366481759
  -0.2703577168736569
  -0.4213383680886897

conv(x,[1,1,1],algorithm = :fft_overlapsave)
8-element Vector{Float64}:
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
  -0.27035771687365695
  -0.42133836808868974

conv(x,[1,1,1],algorithm = :fft_simple)
8-element Vector{Float64}:
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN

Platform information

Copy and paste the output of versioninfo() into a code block like this

julia> versioninfo()
Julia Version 1.13.1
Commit 96ca370cf0e (2026-09-25 19:34 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: macOS (arm64-apple-darwin27.0.0)
  CPU: 10 × Apple M1 Max
  WORD_SIZE: 64
  LLVM: libLLVM-20.1.8 (ORCJIT, apple-m1)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 10 virtual cores)

Activity

  1. wheeheee commented on Sep 29, 2026

    @wheeheee
    Member

    Dunno about the extra overhead from the extra isfinite check; on one hand it's asymptotically negligible... but the assumption that there are no NaNs/Infs is fine 99% of the time for float inputs, and it's not very clear how meaningful such inputs are. Granted that should be documented regardless, but it's also a trade-off that the algorithm selection allows users to override and check for NaNs/Infs themselves if so desired.

    It's kinda the same deal for FFTs, so it's at least not more wrong.

  2. wheeheee commented on Sep 29, 2026

    @wheeheee
    Member

    Also in theory perfectly finite inputs can still produce inconsistent results depending on arithmetic order even with :direct. So really, it's not possible to avoid that problem anyway as long as we are limited to finite precision. To prevent this, I assume the only solution would be to make :auto equal to :direct which defeats the purpose of its existence as a sane default.

  3. jonathanlilly commented on Sep 29, 2026

    @jonathanlilly
    Author

    Thanks a lot for the quick response.

    As someone who teaches time series analysis of data, I find NaNs (and to a lesser extent Infs) are quite common as markers of missing data, and people don't necessarily check to see if their data contains NaNs. I therefore imagine it would come up for other users.

    My opinion is that :auto should make a sensible decision for any valid input, which could include NaNs and Infs as these are Floats, without the user having to worry about it. That's why it's called :auto, right?

    If there is a concern about speed, how about having :auto check and a :fastauto (or whatever) that does not check? That's consistent with other packages I've seen which have a faster version that skips checks.

    Out of curiosity, could you explain this?

    Also in theory perfectly finite inputs can still produce inconsistent results depending on arithmetic order even with :direct.

  4. wheeheee commented on Sep 29, 2026

    @wheeheee
    Member

    Sorry, that wasn't accurate, typing on mobile. What I meant was, finite inputs with :direct can still produce Infs and therefore, NaNs, so they are not reliable as sentinel values (direct could in theory give you an Inf/NaN, where an FFT may reassociate in such a way as to get a finite and more correct result). Although at typical array sizes and magnitudes that's unlikely. Furthermore for larger inputs, the numerical error from :direct can also be >> than from :fft methods. But it depends on your data, and you can choose what's appropriate.

    Better to use missing if you want sentinels, IMO. We should maybe think more on how to support that.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions