fn

rfftn

Tensor
rfftn(input: Tensor, s: int | Sequence[int] | None = None, dim: int | Sequence[int] | None = None, norm: str | None = None)
source

N-dimensional FFT of a real-valued input, exploiting conjugate symmetry.

When the input is real, its N-dimensional DFT satisfies the Hermitian (conjugate-symmetric) property:

X[k1,,kd]=X[N1k1,,Ndkd].X[k_1, \ldots, k_d] = X^*[N_1 - k_1, \ldots, N_d - k_d].

Only the non-redundant half of the spectrum along the last transformed axis needs to be stored. For a last-axis length NN, the output contains only N/2+1\lfloor N/2 \rfloor + 1 unique complex values along that axis. All other axes are full-length (NiN_i bins each).

Parameters

inputTensor
Real-valued input tensor of any shape. Passing a complex tensor is accepted but the imaginary part is silently discarded by the engine.
sint or sequence of int= None
Signal length(s) along each transformed axis. When given, the last element s[-1] determines the last-axis size before the real FFT; the output last axis will be s[-1] // 2 + 1. len(s) must equal len(dim) when both are sequences. If None, each axis is transformed at its current size.
dimint or sequence of int= None
Axis or axes over which to compute the transform. The last element of dim is the axis that gets the conjugate-symmetry compression. Defaults to all axes when None.
normstr or None= None
Normalisation mode — "backward" (default), "forward", or "ortho". NN is the product of the full (uncompressed) lengths of all transformed axes.

Returns

Tensor

Complex tensor (complex64) with the same shape as input except:

  • All transformed axes except the last have their original lengths (or s[i] when specified).
  • The last transformed axis has length Nlast/2+1\lfloor N_{\text{last}} / 2 \rfloor + 1.

Notes

Why n//2 + 1? — A real-to-complex 1-D DFT of length NN has the symmetry X[Nk]=X[k]X[N-k] = X^*[k]. The unique bins are therefore k=0,1,,N/2k = 0, 1, \ldots, \lfloor N/2 \rfloor, giving N/2+1\lfloor N/2 \rfloor + 1 complex values. For even NN this is N/2+1N/2 + 1; for odd NN it is (N+1)/2(N+1)/2.

Nyquist theorem — for a real discrete signal sampled at rate fsf_s, the highest representable frequency is the Nyquist frequency fs/2f_s / 2. The bin at index N/2\lfloor N/2 \rfloor corresponds exactly to this frequency. Any signal energy above fs/2f_s / 2 aliases back into the [0,fs/2][0, f_s/2] range — this is the aliasing artefact that the sampling theorem warns against.

Memory saving — compared to fftn, rfftn stores roughly half the complex coefficients along the last axis, reducing peak memory and compute by ~2× for large real tensors.

Examples

1-D real FFT:
>>> x = lucid.randn(128)
>>> X = lucid.fft.rfftn(x)
>>> X.shape   # 128 // 2 + 1 = 65
(65,)
3-D real FFT over all axes:
>>> x = lucid.randn(16, 32, 64)
>>> X = lucid.fft.rfftn(x)
>>> X.shape   # last axis: 64 // 2 + 1 = 33
(16, 32, 33)
Explicit output size for zero-padding:
>>> X = lucid.fft.rfftn(lucid.randn(60), s=[64])
>>> X.shape   # 64 // 2 + 1 = 33
(33,)