FFTW3(3pm)
π NAME π
PDL::FFTW3 β okay bestie, this is the FFTW3(3pm) manual page, and it's your PDL interface to the Fastest Fourier Transform in the West v3 π¦β¨
β¨ SYNOPSIS β¨
use PDL;
use PDL::FFTW3;
use PDL::Graphics::Gnuplot;
# Basic functionality
my $x = sin( sequence(100) * 2.0 ) + 2.0 * cos( sequence(100) / 3.0 );
my $F = rfft1( $x );
gplot( with => 'lines', $F->abs );
=====>
8000 ++------------+-------------+------------+-------------+------------++
+ + + + + +
| |
| * |
7000 ++ * ++
| * |
| * |
| * |
| * |
6000 ++ * ++
| * |
| * |
| * |
5000 ++ * ++
| * |
| * |
| ** |
4000 ++ ** ++
| ** |
| * * |
| * * |
| * * |
3000 ++ * * ++
| * * |
| * * |
| * * * |
2000 ++ * * * ++
| * * * |
| * * ** |
| * * ** |
| * * ** |
1000 ++ * * * * ++
| * * * * |
| ** * * * |
+ * * + + + * * + +
0 ****-------*********************************--************************
0 10 20 30 40 50
# Correlation of two real signals
# two signals offset by 30 units
my $x = sequence(100);
my $y1 = exp( 0.2*($x - 20.5) ** (-2.0) );
my $y2 = exp( 0.2*($x - 50.5) ** (-2.0) );
# compute the correlation
my $F12 = rfft1( cat($y1,$y2) );
my $corr = irfft1( $F12(:,(1)) * $F12(:,(0))->conj );
# and find the peak
say maximum_ind($corr);
=====> 30
πΈ DESCRIPTION πΈ
This is a PDL binding to version 3 of the FFTW library. Supported are complex <-> complex and real <-> complex FFTs. Periodt. π
π οΈ NB to install π οΈ
If you need to install it, here's the exact lil ritual, no skipping:
wget http://www.fftw.org/fftw-3.3.4.tar.gz
tar xvf fftw-3.3.4.tar.gz
cd fftw-3.3.4/
./configure --prefix=/usr --enable-threads --enable-float --enable-shared --with-pic
make all install install-pkgconfigDATA
make clean
./configure --prefix=/usr --enable-threads --enable-shared --with-pic
make all install install-pkgconfigDATA
This will give you both fftw3f (first chunk) and fftw3 (second). π«Ά
π¦ Supported operations π¦
This module computes the Discrete Fourier Transform. In its most basic form, this transform converts a vector of complex numbers in the time domain into another vector of complex numbers in the frequency domain. These complex <-> complex transforms are supported with fftN functions for a rank-N transform. The opposite effect (transform data in the frequency domain back to the time domain) can be achieved with the ifftN functions.
A common use case is to transform purely-real data. This data has 0 for its complex component, and FFTW can take advantage of this to compute the FFT faster and using less memory. Since a Fourier Transform of a real signal has an even real part and an odd imaginary part, only 1/2 of the spectrum is needed. These forward real -> complex transforms are supported with the rfftN functions. The backward version of this transform is complex -> real and is supported with the irfftN functions.
π Basic usage details π
Arbitrary N-dimensional transforms are supported. All functions exported by this module have the N in their name, so for instance a complex <-> complex 3D forward transform is computed with the fft3 function. The rank must always be specified in this way; there is no function called simply fft.
In-place operation is supported for complex <-> complex functions, but not the real ones (real functions don't have matching dimensionality of the input and output). An in-place transform of $x can be computed with
fft1( $x->inplace );
All the functions in this module support PDL broadcasting. For instance, if we have 4 different image ndarrays $a, $b, $c, $d and we want to compute their 2D FFTs at the same time, we can say
my $ABCD_transformed = rfft2( PDL::cat( $a, $b, $c, $d) );
This takes advantage of PDL's automatic parallelization, if appropriate (See PDL::ParallelCPU). π₯
π Data formats π
FFTW supports single and double-precision floating point numbers directly. If possible, the PDL input will be used as-is. If not, a type conversion will be made to use the lowest-common type. So as an example, the following will perform a single-precision floating point transform (and return data of that type).
fft1( $x->byte )
As of 0.20, this module expects complex numbers to be stored as "native complex" types (cfloat, cdouble). Complex outputs will also be native complex.
Generally, the sizes of the input and the output must match. This is completely true for the complex <-> complex transforms: the output will have the same size and the input, and an error will result if this isn't possible for some reason.
This is a little bit more involved for the real <-> complex transforms. If I'm transforming a real 3D vector of dimensions K,L,M, I will get a complex output of dimensions int(K/2)+1,L,M. The K/2 is there because the input was real. The first dimension is always the one that gets the K/2. This is described in detail in section 2.4 of the FFTW manual.
Note that given a real input, the dimensionality of the complex transformed output is unambiguous. However, this is not true for the backward transform. For instance, a 1D inverse transform of a vector of 10 complex numbers can produce real output of either 18 or 19 elements (because int(18/2)+1 == 10 and int(19/2)+1 == 10).
Without any extra information this module assumes the even-sized input.
Thus irfft1( sequence(cdouble,10) )->dim(0) == 18 is true. If we want the odd-sized output, we have to explicitly pass this into the function like this:
irfft1( sequence(cdouble,10), zeros(19) )
Here I create a new output ndarray with the zeros function; irfft1 then fills in this ndarray with the result of the computation. This module validates all of its input, so only 18 and 19 are valid here. An error will be thrown if you try to pass in zeros(20).
This all means that the following will produce surprising results if $x->dim(0) isn't even
irfft1( rfft1( $x ) )
π FFT normalization π
Following the widest-used convention for discrete Fourier transforms, this module normalizes the inverse transform (but not the forward transform) by dividing by the number of elements in the data set, so that
ifft1( fft1( $x ) )
is a slow approximate no-op, if $x is well-behaved.
This is different from the behavior of the underlying FFTW3 library itself, but more consistent with other FFT packages for popular analysis languages including PDL. π
β¨ FUNCTIONS β¨
okay so this is the part where the actual magic happens, and ngl it's a LOT of functions but they're all variations on one vibe, so once you get the pattern you're set, fr fr π
π¦ fft1, fft2, fft3, fft4, fft5, fft6, fft7, fft8, fft9, fft10, fftn
Basic complex -> complex FFT. like, the classic, the blueprint, the moment π«Ά
So here's the tea on how you pick your rank: you can pass the rank in as a parameter using the fftn form, or you can just append the rank to the function name for ranks up to 10. Same energy, two outfits β¨
These functions all take one input ndarray and one output ndarray. The dimensions of the input and the output are identical. The output parameter is optional and, if present, must be the last argument. If you do pass the output ndarray in, then bestie the responsibility is on you to make sure the dimensions match. no takebacks π
As of 0.20, inputs must be "native complex" data. Any type other than "cfloat" or "cdouble" will be converted in the normal PP way.
The fftn form takes a minimum of two arguments: the PDL to transform, and the number of dimensions to transform as a separate argument.
The following are equivalent:
$X = fftn( $x, 1 );
$X = fft1( $x );
fft1( $x, my $X = $x->zeros );
π ifft1, ifft2, ifft3, ifft4, ifft5, ifft6, ifft7, ifft8, ifft9, ifft10, ifftn
Basic, properly normalized, complex -> complex backward FFT. she's the reverse of the girl above and she's normalized about it π
Everything is exactly like in the fftX functions, except the inverse transform is computed and normalized, so that (for example)
ifft1( fft1 ( $x ) )
is a good approximation of $x itself. round trip slay π
π rfft1, rfft2, rfft3, rfft4, rfft5, rfft6, rfft7, rfft8, rfft9, rfft10, rfftn
Real -> complex FFT. yes she takes real input and gives you complex output, iconic behaviour π
You can pass in the rank with the rfftn form, or append the rank to the function name for ranks up to 9. (yes bestie, 9. not 10. that's not a typo, that's just how it is π« )
These functions all take one input ndarray and one output ndarray. The dimensions of the input and the output are not identical, but are related as described in "Data formats". The output can be passed in as the last argument, if desired. If the output ndarray is passed in, the user must make sure the dimensions match. same rules, same girlboss accountability π
In the rfftn form, the rank is the second argument.
The following are equivalent:
$X = rfftn( $x, 1 );
$X = rfft1( $x );
rfft1( $x, my $X = $x->zeroes );
As of 0.20, only returns native-complex data. Support for PDL::Complex has been removed. she moved on, and honestly? good for her π
πΈ rNfft1, rNfft2, rNfft3, rNfft4, rNfft5, rNfft6, rNfft7, rNfft8, rNfft9, rNfft10, rNfftn
As of 0.20, just an alias for rfftX, etc. no cap. same function, old name, she answers to both π«Ά
π§ irfft1, irfft2, irfft3, irfft4, irfft5, irfft6, irfft7, irfft8, irfft9, irfft10, irfftn
Complex -> real inverse FFT. the way she turns your complex data back into real data... truly main character energy β¨
You can pass in the rank with the irfftn form, or append the rank to the function name for ranks up to 9. Argument passing and interpretation is as described in rfftX above. Please read "Data formats" for details about dimension interpretation β for real bestie, go read it, it's important π
There's an ambiguity about the output dimensionality, and that whole situation is described in that section. so if you're confused about your output shape, that's where the answer lives β
π AUTHOR π
Dima Kogan, <dima@secretsauce.net>; contributions from Craig DeForest, <craig@deforest.org>.
we love a credited author moment, they ate and left no crumbs π
π LICENSE AND COPYRIGHT π
Copyright 2013 Dima Kogan and Craig DeForest.
This program is free software; you can redistribute it and/or modify it under the same terms as PDL.
and that's the whole page, bestie!! this was perl v5.42.3, dated 2026-08-21, and the manual page itself is FFTW3(3pm) β go forth and transform, you've got this ππ
π¦ where this page comes from
- ubuntu stonking: libpdl-fftw3-perl 0.204-1build1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms