[Numpy-discussion] Numpy FFT.FFT slow with certain samples

Oscar Benjamin oscar.j.benjamin at gmail.com
Tue Sep 1 11:14:41 EDT 2015


On 1 September 2015 at 11:38, Joseph Codadeen <jdmc80 at hotmail.com> wrote:
>
>> And while you zero-pad, you can zero-pad to a sequence that is a power of
>> two, thus preventing awkward factorizations.
>
> Does numpy have an easy way to do this, i.e. for a given number, find the
> next highest number (within a range) that could be factored into small,
> prime numbers as Phil explained? It would help if it gave a list,
> prioritised by number of factors.

Just use the next power of 2. Pure powers of 2 are the most efficient
for FFT algorithms so it potentially works out better than finding a
smaller but similarly composite size to pad to. Finding the next power
of 2 is easy to code and never a bad choice.

To avoid the problems mentioned about zero-padding distorting the FFT
you can use the Bluestein transform as below. This pads up to a power
of two (greater than 2N-1) but does it in a special way that ensures
that it is still calculating the exact (up to floating point error)
same DFT:

from numpy import array, exp, pi, arange, concatenate
from numpy.fft import fft, ifft

def ceilpow2(N):
    '''
        >>> ceilpow2(15)
        16
        >>> ceilpow2(16)
        16
    '''
    p = 1
    while p < N:
        p *= 2
    return p

def fftbs(x):
    '''
        >>> data = [1, 2, 5, 2, 5, 2, 3]
        >>> from numpy.fft import fft
        >>> from numpy import allclose
        >>> from numpy.random import randn
        >>> for n in range(1, 1000):
        ...     data = randn(n)
        ...     assert allclose(fft(data), fftbs(data))
    '''
    N = len(x)
    x = array(x)

    n = arange(N)
    b = exp((1j*pi*n**2)/N)
    a = x * b.conjugate()

    M = ceilpow2(N) * 2
    A = concatenate((a, [0] * (M - N)))
    B = concatenate((b, [0] * (M - 2*N + 1), b[:0:-1]))
    C = ifft(fft(A) * fft(B))
    c = C[:N]
    return b.conjugate() * c

if __name__ == "__main__":
    import doctest
    doctest.testmod()


--
Oscar



More information about the NumPy-Discussion mailing list