fft2dComplex

Computes the complex discrete two-dimensional Fourier transform of a complex two-dimensional array.

Synopsis

fft2dComplex (p)

Required Arguments

complex p[[]] (Input)
Two-dimensional array of size n × m containing the sequence that is to be transformed.

Return Value

The transformed array. If no value can be computed, then None is returned.

Optional Arguments

backward
Compute the backward transform. If backward is used, the return value of the function is the backward transformed sequence.

Description

The function fft2dComplex computes the discrete Fourier transform of a two-dimensional complex array of size n × m. It uses the system’s high performance library for the computation, if available. Otherwise, the method used is a variant of the Cooley-Tukey algorithm, which is most efficient when both n and m are a product of small prime factors. If n and m satisfy this condition, then the computational effort is proportional to nm log nm. The Cooley-Tukey algorithm is based on the complex FFT in FFTPACK, which was developed by Paul Swarztrauber at the National Center for Atmospheric Research

By default, fft2dComplex computes the forward transform below.

\[q_{jk} = \sum_{s=0}^{n-1} \sum_{t=0}^{m-1} p_{st}e^{-2 \pi ijs/n}e^{-2 \pi ikt/m}\]

Note that we can invert the Fourier transform as follows.

\[p_{jk} = \tfrac{1}{nm} \sum_{s=0}^{n-1} \sum_{t=0}^{m-1} q_{st}e^{-2 \pi ijs/n}e^{-2 \pi ikt/m}\]

This formula reveals the fact that, after properly normalizing the Fourier coefficients, you have the coefficients for a trigonometric interpolating polynomial to the data. The function fft2dComplex is based on the complex FFT in FFTPACK, which was developed by Paul Swarztrauber at the National Center for Atmospheric Research.

If the option backward is selected, then the following computation is performed.

\[p_{jk} = \sum_{s=0}^{n-1} \sum_{t=0}^{m-1} q_{st}e^{2 \pi ijs/n}e^{2 \pi ikt/m}\]

The relation between the forward and backward transforms is that they are unnormalized inverses of each other. That is, the following code fragment begins with a vector p and concludes with a vector \(p_2 = nmp\).

q  = fft2dComplex(p)
p2 = fft2dComplex(q, backward)

Examples

Example 1

This example computes the Fourier transform of the pure frequency input for a 5 × 4 array

\[p_{st} = e^{2 \pi i2s/S}e^{2 \pi it3/4}\]

for \(0 \leq n \leq 4\) and \(0 \leq m \leq 3\). The result, \(\hat{p} = q\), has all zeros except in the [2][3] position.

from numpy import *
from pyimsl.math.constant import constant
from pyimsl.math.fft2dComplex import fft2dComplex
from pyimsl.math.writeMatrixComplex import writeMatrixComplex

n = 5
m = 4
two_pi = 2 * constant("pi")
p = empty((n, m), dtype=complex)

# Fill p with a pure exponential signal
for s in range(0, n):
    z = complex(0.0, (s * two_pi * 2. / n))
    for t in range(0, m):
        w = complex(0.0, (t * two_pi * 3. / m))
        p[s, t] = exp(z) * exp(w)

q = fft2dComplex(p)

writeMatrixComplex("The input matrix is ", p,
                   rowNumberZero=True, colNumberZero=True)
writeMatrixComplex("The output matrix is ", q,
                   rowNumberZero=True, colNumberZero=True)

Output

 
                 The input matrix is 
                           0                          1
0  (      1.000,      0.000)  (     -0.000,     -1.000)
1  (     -0.809,      0.588)  (      0.588,      0.809)
2  (      0.309,     -0.951)  (     -0.951,     -0.309)
3  (      0.309,      0.951)  (      0.951,     -0.309)
4  (     -0.809,     -0.588)  (     -0.588,      0.809)
 
                           2                          3
0  (     -1.000,      0.000)  (      0.000,      1.000)
1  (      0.809,     -0.588)  (     -0.588,     -0.809)
2  (     -0.309,      0.951)  (      0.951,      0.309)
3  (     -0.309,     -0.951)  (     -0.951,      0.309)
4  (      0.809,      0.588)  (      0.588,     -0.809)
 
                 The output matrix is 
                           0                          1
0  (         -0,         -0)  (          0,         -0)
1  (          0,          0)  (          0,         -0)
2  (          0,          0)  (         -0,          0)
3  (          0,          0)  (          0,          0)
4  (         -0,         -0)  (         -0,         -0)
 
                           2                          3
0  (          0,         -0)  (         -0,          0)
1  (         -0,          0)  (         -0,          0)
2  (         -0,          0)  (         20,         -0)
3  (         -0,          0)  (          0,          0)
4  (          0,         -0)  (          0,          0)

Example 2

This example uses the backward transform to recover the original sequence. Notice that the forward transform followed by the backward transform multiplies the entries in the original sequence by the product of the lengths of the two dimensions.

from numpy import *
from pyimsl.math.fft2dComplex import fft2dComplex
from pyimsl.math.writeMatrixComplex import writeMatrixComplex

n = 5
m = 4
p = empty((n, m), dtype=complex)

# Fill p with a pure exponential signal
for s in range(0, n):
    for t in range(0, m):
        p[s, t] = complex(s + 5 * t, 0.0)

# Forward transform
q = fft2dComplex(p)

# Backward transform
p2 = fft2dComplex(q, backward=True)

# Write the input
writeMatrixComplex("The input matrix is ", p,
                   rowNumberZero=True, colNumberZero=True)

# Write the output
writeMatrixComplex("The output matrix is ", p2,
                   rowNumberZero=True, colNumberZero=True)

Output

 
                 The input matrix is 
                           0                          1
0  (          0,          0)  (          5,          0)
1  (          1,          0)  (          6,          0)
2  (          2,          0)  (          7,          0)
3  (          3,          0)  (          8,          0)
4  (          4,          0)  (          9,          0)
 
                           2                          3
0  (         10,          0)  (         15,          0)
1  (         11,          0)  (         16,          0)
2  (         12,          0)  (         17,          0)
3  (         13,          0)  (         18,          0)
4  (         14,          0)  (         19,          0)
 
                 The output matrix is 
                           0                          1
0  (          0,          0)  (        100,          0)
1  (         20,          0)  (        120,          0)
2  (         40,          0)  (        140,          0)
3  (         60,          0)  (        160,          0)
4  (         80,          0)  (        180,          0)
 
                           2                          3
0  (        200,          0)  (        300,          0)
1  (        220,          0)  (        320,          0)
2  (        240,          0)  (        340,          0)
3  (        260,          0)  (        360,          0)
4  (        280,          0)  (        380,          0)

Warning Erors

IMSL_CUFFT_COPY_TO_GPU An error was encountered copying the data from the CPU to the GPU. Using the PyIMSL CPU algorithm instead.
IMSL_CUFFT_ERROR An error was encountered executing the problem on the GPU. Using the PyIMSL CPU algorithm instead.
IMSL_CUFFT_COPY_TO_CPU An error was encountered copying the data from the GPU to the CPU. Using the PyIMSL CPU algorithm instead.
IMSL_CUFFT_FREE An error was encountered when freeing memory from the GPU. Using the PyIMSL CPU algorithm instead.
IMSL_CUFFT_ALLOCATION An error was encountered allocating memory on the GPU. Using the PyIMSL CPU algorithm instead.