A modern Fast Fourier Transform library inspired by FFTE subroutines, written in modern Fortran.
Requirement: Fortran 2003 compiler. Also, C99 compiler, if Spiral kernels are used. Also, OpenMP. Tested with GCC (Gfortran), NVIDIA HPC SDK (nvfortran), Flang, and Intel compilers.
CMake is the recommended build. Configure from the repository root:
cmake -S . -B build
cmake --build build -j
ctest --test-dir build --output-on-failure
cmake --install build --prefix /your/installation/folder
Options:
| Option | Effect |
|---|---|
-DWITHSPRL=ON |
Spiral kernel backend |
-DWITHRVV=ON |
RISC-V RVV kernels (implies WITHSPRL) |
-DWITHSVE=ON |
Arm SVE kernels (implies WITHSPRL) |
-DWITH_REFERENCE_FFTW=ON |
Build the comparisons against a reference FFTW |
-DTHOROUGH_TESTS=ON |
Test about a thousand more sizes |
-DBUILD_EXAMPLES=OFF |
Skip the programs in examples/ |
-DBUILD_SHARED_LIBS=ON |
Shared instead of static library |
Only the RVV kernels are currently generated: -DWITHSVE=ON, and -DWITHSPRL=ON on its
own, stop at configure time until those kernel sets exist.
To use a different compiler, for example Intel's:
cmake -S . -B build -DCMAKE_Fortran_COMPILER=ifx -DCMAKE_C_COMPILER=icx
Installing writes the library, the public .mod files, src/juffte.h and a CMake
package config, so a downstream project can use it directly:
find_package(juffte REQUIRED)
target_link_libraries(myapp PRIVATE juffte::juffte)A toolchain file is provided for a riscv64-unknown-linux-gnu cross toolchain:
cmake -S . -B build-riscv -DCMAKE_TOOLCHAIN_FILE=cmake/riscv-rvv.cmake \
-DWITHSPRL=ON -DWITHRVV=ON
cmake --build build-riscv -j
Override RISCV_TOOLCHAIN_PREFIX (default /opt/riscv) and RISCV_TARGET_TRIPLE
(default riscv64-unknown-linux-gnu) if the toolchain lives elsewhere.
Executables are linked statically, and if qemu-riscv64-static is installed it is
registered as the CTest emulator, so the suite can be run under emulation:
ctest --test-dir build-riscv --output-on-failure
A plain Makefile build also exists, and is what tests/c, tests/fortran, examples/c,
examples/fortran and benchmark link against by default:
cd src
make
make install PREFIX=/your/installation/folder
It takes FC=ifx, WITHSPRL=1 and WITHRVV=1 in the same spirit as the CMake options.
Edit the Makefile if necessary for your system setup.
| function | Description / Functionality |
|---|---|
zfft1d(a, n, juffte_x) |
1-D complex-to-complex FFT |
zfft1d_out(a, n, juffte_x, a_out) |
1-D complex-to-complex FFT |
zfft2d(a, nx, ny, juffte_x) |
2-D complex-to-complex FFT |
zfft2d_out(a, nx, ny, juffte_x, a_out) |
2-D complex-to-complex FFT |
zfft3d(a, nx, ny, nz, juffte_x) |
3-D complex-to-complex FFT |
zfft3d_out(a, nx, ny, nz, juffte_x, a_out) |
3-D complex-to-complex FFT |
dzfft1d(a, a_c, n, juffte_x) |
1-D real-to-complex FFT |
zdfft1d(a_c, a, n, juffte_x) |
1-D complex-to-real FFT |
dzfft2d(a, a_c, nx, ny, juffte_x) |
2-D real-to-complex FFT |
zdfft2d(a_c, a, nx, ny, juffte_x) |
2-D complex-to-real FFT |
dzfft3d(a, a_c, nx, ny, nz, juffte_x) |
3-D real-to-complex FFT |
zdfft3d(a_c, a, nx, ny, nz, juffte_x) |
3-D complex-to-real FFT |
juffte_xcan bejuffte_initfor initialization,juffte_fwfor forward FFT, orjuffte_bwfor backward._outdenotes the out-of-place transformation (output goes last).- Dimensions are given contiguous first: in
zfft2d(a, nx, ny, ...),nxis the contiguous one (Fortran's array order), from C as well. - Real-to-complex FFTs produce output in half-complex format with size
(n/2 + 1)in the first dimension. - The API supports both single-precision (FP32) and double-precision (FP64) floating-point types for Fortran.
| function | Description / Functionality |
|---|---|
fft_init(a) |
Initialize 1-D complex FFT plan |
fft_execute(a, juffte_x) |
Execute 1-D complex FFT |
| function | C | Fortran |
|---|---|---|
fftw_malloc(size) |
yes | – |
fftw_free(ptr) |
yes | – |
fftw_plan_dft_1d(n, in, out, sign, flags) |
yes | yes |
fftw_plan_dft_2d(n0, n1, in, out, sign, flags) |
yes | yes |
fftw_plan_dft_3d(n0, n1, n2, in, out, sign, flags) |
yes | yes |
fftw_execute(plan) |
yes | – |
fftw_execute_dft(plan, in, out) |
yes | yes |
fftw_destroy_plan(plan) |
yes | yes |
Dimension order. FFTW lists the dimensions the other way round from juFFTe's native API:
slowest first, the contiguous one last (C's row-major order). fftw_plan_dft_2d(n0, n1, ...)
describes an n0 x n1 array with n1 contiguous, the same transform as
zfft2d(a, n1, n0, ...). From Fortran this means reversing the declared shape: a(nx, ny) is
planned as fftw_plan_dft_2d(ny, nx, ...), exactly as with FFTW's own Fortran interface. The
layer follows FFTW here, so that ported code runs unchanged.
The layer is always built into libjuffte — no build option, macro or extra library. From C,
include juffte.h instead of fftw3.h; from Fortran, use juffte instead of
include 'fftw3.f03'. Either way, link -ljuffte instead of -lfftw3.
The C entry points are exported as juffte_fftw_* and juffte.h maps the fftw_* names onto
them, so juFFTe exports nothing that clashes with real FFTW. A program can therefore link both
libraries at once — which is how the benchmark compares them.
Known limitation: only one plan can be live at a time. Creating a second plan currently fails. See the open issues.
See examples/c/fftw-test*.c and examples/fortran/test*-fftwint.F90 for FFTW code running on
juFFTe.
The library uses OpenMP for parallelization. Ensure your compiler has OpenMP support enabled:
gfortran -fopenmp your_code.f90 -ljuffte
To use juFFTe, link the library with -ljuffte. There is one library for every backend and for
both the native and the FFTW-compatible API. When using from C/C++, include Fortran runtime libraries, e.g., for GCC:
gcc your_code.c -ljuffte -lm -lgfortran
Contributions to juFFTe are welcome. Please see CONTRIBUTING.md for contribution instructions, maintainer information, and the definition of juFFTe developers.
juFFTe is licensed under the Apache License, Version 2.0. See LICENSES/Apache-2.0.txt for the full license text.
The project uses REUSE/SPDX metadata for license and copyright information.