DFT#

  • Domain: ai.onnx

  • Since version: 20

Computes the discrete Fourier Transform (DFT) of the input.

Assuming the input has shape [M, N], where N is the dimension over which the DFT is computed and M denotes the conceptual “all other dimensions,” the DFT y[m, k] of shape [M, N] is defined as

$$y[m, k] = sum{n=0}^{N-1} e^{-2 pi j frac{k n}{N} } x[m, n] ,$$

and the inverse transform is defined as

$$x[m, n] = frac{1}{N} sum{k=0}^{N-1} e^{2 pi j frac{k n}{N} } y[m, k] ,$$

where $j$ is the imaginary unit.

The actual shape of the output is specified in the “output” section.

Reference: https://docs.scipy.org/doc/scipy/tutorial/fft.html

Inputs

  • input (T1): For real input, the following shape is expected: [signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][1]. For complex input, the following shape is expected: [signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2]. The final dimension represents the real and imaginary parts of the value in that order.

  • dft_length (T2): The length of the signal as a scalar. If greater than the axis dimension, the signal will be zero-padded up to dft_length. If less than the axis dimension, only the first dft_length values will be used as the signal. If not provided, the default dft_length = signal_dim_axis, except for the IRFFT case (onesided=1, inverse=1), in which case the default dft_length is 2 * (signal_dim_axis - 1).

  • axis (tensor(int64)): The axis as a scalar on which to perform the DFT. Default is -2 (last signal axis). Negative value means counting dimensions from the back. Accepted range is $[-r, -2] cup [0, r-2]$ where r = rank(input). The last dimension is for representing complex numbers and thus is an invalid axis.

Outputs

  • output (T1): The Fourier Transform of the input vector. For standard DFT (onesided=0), the output shape is: [signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2] (complex), with signal_dim_axis = dft_length. For RFFT (onesided=1, inverse=0), the output shape is: [signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2] (one-sided complex), with signal_dim_axis = floor(dft_length/2) + 1. For IRFFT (onesided=1, inverse=1), the output shape is: [signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][1] (real), where signal_dim_axis = dft_length.

Attributes

  • inverse (int): Whether to perform the inverse discrete Fourier Transform. Default is 0, which corresponds to false.

  • onesided (int): If onesided is 1, only values for k in [0, 1, 2, ..., floor(n_fft/2) + 1] are used or returned because the real-to-complex Fourier transform satisfies the conjugate symmetry, i.e., X[m, k] = X[m, n_fft-k]*, where m denotes “all other dimensions” DFT was not applied on. When onesided=1 and inverse=0 (forward DFT), only real input is supported and a one-sided complex spectrum is returned (RFFT). When onesided=1 and inverse=1 (inverse DFT), only complex input is supported and a full real signal is returned (IRFFT). Value can be 0 or 1. Default is 0.

Type Constraints

  • T1: Constrain input and output types to float tensors. Allowed types: tensor(bfloat16), tensor(double), tensor(float), tensor(float16).

  • T2: Constrain scalar length types to integers. Allowed types: tensor(int32), tensor(int64).

Examples#

test_cc_dft

Node:
  DFT(x, "", axis) -> (y)
Inputs:
  x: shape=(1, 4, 1), dtype=float32
    [[[1.],
      [2.],
      [3.],
      [4.]]]
  axis: shape=(), dtype=int64
    1

Outputs:
  y: shape=(1, 4, 2), dtype=float32
    [[[ 1.000000e+01,  0.000000e+00],
      [-2.000000e+00,  2.000000e+00],
      [-2.000000e+00, -9.797175e-16],
      [-2.000000e+00, -2.000000e+00]]]

test_cc_dft_axis

Node:
  DFT(x, "", axis) -> (y)
Inputs:
  x: shape=(1, 10, 10, 1), dtype=float32
    [[[[ 0.],
       [ 1.],
       [ 2.],
       ...,
       [ 7.],
       [ 8.],
       [ 9.]],

      [[10.],
       [11.],
       [12.],
       ...,
       [17.],
       [18.],
       [19.]],

      [[20.],
       [21.],
       [22.],
       ...,
       [27.],
       [28.],
       [29.]],

      ...,

      [[70.],
       [71.],
       [72.],
       ...,
       [77.],
       [78.],
       [79.]],

      [[80.],
       [81.],
       [82.],
       ...,
       [87.],
       [88.],
       [89.]],

      [[90.],
       [91.],
       [92.],
       ...,
       [97.],
       [98.],
       [99.]]]]
  axis: shape=(), dtype=int64
    2

Outputs:
  y: shape=(1, 10, 10, 2), dtype=float32
    [[[[ 45.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]],

      [[145.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]],

      [[245.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]],

      ...,

      [[745.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]],

      [[845.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]],

      [[945.       ,   0.       ],
       [ -5.       ,  15.388417 ],
       [ -5.       ,   6.8819094],
       ...,
       [ -5.       ,  -3.6327126],
       [ -5.       ,  -6.8819094],
       [ -5.       , -15.388417 ]]]]

test_cc_dft_inverse

Node:
  DFT(x, "", axis) -> (y)
  Attributes:
    inverse = 1
Inputs:
  x: shape=(1, 4, 2), dtype=float32
    [[[1., 0.],
      [2., 0.],
      [3., 0.],
      [4., 0.]]]
  axis: shape=(), dtype=int64
    1

Outputs:
  y: shape=(1, 4, 2), dtype=float32
    [[[ 2.5000000e+00,  0.0000000e+00],
      [-5.0000000e-01, -5.0000000e-01],
      [-5.0000000e-01,  2.4492937e-16],
      [-5.0000000e-01,  5.0000000e-01]]]

test_cc_dft_irfft

Node:
  DFT(x, "", axis) -> (y)
  Attributes:
    inverse = 1
    onesided = 1
Inputs:
  x: shape=(1, 6, 10, 2), dtype=float32
    [[[[ 4.5000000e+02,  0.0000000e+00],
       [ 4.6000000e+02,  0.0000000e+00],
       [ 4.7000000e+02,  0.0000000e+00],
       ...,
       [ 5.2000000e+02,  0.0000000e+00],
       [ 5.3000000e+02,  0.0000000e+00],
       [ 5.4000000e+02,  0.0000000e+00]],

      [[-5.0000000e+01,  1.5388417e+02],
       [-5.0000000e+01,  1.5388417e+02],
       [-5.0000000e+01,  1.5388417e+02],
       ...,
       [-5.0000000e+01,  1.5388417e+02],
       [-5.0000000e+01,  1.5388417e+02],
       [-5.0000000e+01,  1.5388417e+02]],

      [[-5.0000000e+01,  6.8819099e+01],
       [-5.0000000e+01,  6.8819099e+01],
       [-5.0000000e+01,  6.8819099e+01],
       ...,
       [-5.0000000e+01,  6.8819099e+01],
       [-5.0000000e+01,  6.8819099e+01],
       [-5.0000000e+01,  6.8819099e+01]],

      [[-5.0000000e+01,  3.6327126e+01],
       [-5.0000000e+01,  3.6327126e+01],
       [-5.0000000e+01,  3.6327126e+01],
       ...,
       [-5.0000000e+01,  3.6327126e+01],
       [-5.0000000e+01,  3.6327126e+01],
       [-5.0000000e+01,  3.6327126e+01]],

      [[-5.0000000e+01,  1.6245985e+01],
       [-5.0000000e+01,  1.6245985e+01],
       [-5.0000000e+01,  1.6245985e+01],
       ...,
       [-5.0000000e+01,  1.6245985e+01],
       [-5.0000000e+01,  1.6245985e+01],
       [-5.0000000e+01,  1.6245985e+01]],

      [[-5.0000000e+01, -5.5109105e-14],
       [-5.0000000e+01, -5.5721429e-14],
       [-5.0000000e+01, -5.6333752e-14],
       ...,
       [-5.0000000e+01, -5.9395367e-14],
       [-5.0000000e+01, -6.0007690e-14],
       [-5.0000000e+01, -6.0620014e-14]]]]
  axis: shape=(), dtype=int64
    1

Outputs:
  y: shape=(1, 10, 10, 1), dtype=float32
    [[[[ 0.],
       [ 1.],
       [ 2.],
       ...,
       [ 7.],
       [ 8.],
       [ 9.]],

      [[10.],
       [11.],
       [12.],
       ...,
       [17.],
       [18.],
       [19.]],

      [[20.],
       [21.],
       [22.],
       ...,
       [27.],
       [28.],
       [29.]],

      ...,

      [[70.],
       [71.],
       [72.],
       ...,
       [77.],
       [78.],
       [79.]],

      [[80.],
       [81.],
       [82.],
       ...,
       [87.],
       [88.],
       [89.]],

      [[90.],
       [91.],
       [92.],
       ...,
       [97.],
       [98.],
       [99.]]]]

test_cc_dft_irfft_roundtrip

Node:
  DFT(x, "", axis) -> (y)
  Attributes:
    inverse = 1
    onesided = 1
Inputs:
  x: shape=(1, 3, 2), dtype=float32
    [[[10.,  0.],
      [-2.,  2.],
      [-2.,  0.]]]
  axis: shape=(), dtype=int64
    1

Outputs:
  y: shape=(1, 4, 1), dtype=float32
    [[[1.],
      [2.],
      [3.],
      [4.]]]

test_cc_dft_rfft

Node:
  DFT(x, "", axis) -> (y)
  Attributes:
    onesided = 1
Inputs:
  x: shape=(1, 4, 1), dtype=float32
    [[[1.],
      [2.],
      [3.],
      [4.]]]
  axis: shape=(), dtype=int64
    1

Outputs:
  y: shape=(1, 3, 2), dtype=float32
    [[[ 1.000000e+01,  0.000000e+00],
      [-2.000000e+00,  2.000000e+00],
      [-2.000000e+00, -9.797175e-16]]]

Differences with previous version (17)#

SchemaDiff: DFT (domain 'ai.onnx')

  • old version: 17

  • new version: 20

  • breaking: yes

Breaking reasons:

  • input ‘axis’ (added): at position 2; option=Single; type_str=’tensor(int64)’

  • attribute ‘axis’ (removed): type=INT; required=False

Inputs:

  • [BREAKING] added ‘axis’: at position 2; option=Single; type_str=’tensor(int64)’

Attributes:

  • [BREAKING] removed ‘axis’: type=INT; required=False

Documentation:

  • line similarity: 0.00 (+17/-1 lines)

--- DFT v17
+++ DFT v20
@@ -1 +1,17 @@
-Computes the discrete Fourier transform of input.
+Computes the discrete Fourier Transform (DFT) of the input.
+
+Assuming the input has shape `[M, N]`, where `N` is the dimension over which the
+DFT is computed and `M` denotes the conceptual "all other dimensions,"
+the DFT `y[m, k]` of shape `[M, N]` is defined as
+
+$$y[m, k] = \sum_{n=0}^{N-1} e^{-2 \pi j \frac{k n}{N} } x[m, n] ,$$
+
+and the inverse transform is defined as
+
+$$x[m, n] = \frac{1}{N} \sum_{k=0}^{N-1} e^{2 \pi j \frac{k n}{N} } y[m, k] ,$$
+
+where $j$ is the imaginary unit.
+
+The actual shape of the output is specified in the "output" section.
+
+Reference: https://docs.scipy.org/doc/scipy/tutorial/fft.html

Version History#