c – Why does FFTW use ptrdiff_t (instead of e.g. size_t) for sizes?
The FFTW library uses the C type ptrdiff_t
in its interface to specify large array sizes, in particular in its “64-bit guru interface”:
fftw_plan fftw_plan_guru64_dft( int rank, const fftw_iodim64 *dims, int howmany_rank, const fftw_iodim64 *howmany_dims, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);
The
fftw_iodim64
type is similar tofftw_iodim
, with the same
interpretation, except that it uses typeptrdiff_t
instead of type
int
.typedef struct { ptrdiff_t n; ptrdiff_t is; ptrdiff_t os; } fftw_iodim64;
and its MPI functions, e. g.:
ptrdiff_t fftw_mpi_local_size_2d(ptrdiff_t n0, ptrdiff_t n1, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start); ptrdiff_t fftw_mpi_local_size_3d(ptrdiff_t n0, ptrdiff_t n1, ptrdiff_t n2, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start); ptrdiff_t fftw_mpi_local_size(int rnk, const ptrdiff_t *n, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start); ptrdiff_t fftw_mpi_local_size_2d_transposed(ptrdiff_t n0, ptrdiff_t n1, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ptrdiff_t fftw_mpi_local_size_3d_transposed(ptrdiff_t n0, ptrdiff_t n1, ptrdiff_t n2, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ptrdiff_t fftw_mpi_local_size_transposed(int rnk, const ptrdiff_t *n, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start);
fftw_plan fftw_mpi_plan_dft_1d(ptrdiff_t n0, fftw_complex *in, fftw_complex *out, MPI_Comm comm, int sign, unsigned flags); fftw_plan fftw_mpi_plan_dft_2d(ptrdiff_t n0, ptrdiff_t n1, fftw_complex *in, fftw_complex *out, MPI_Comm comm, int sign, unsigned flags); fftw_plan fftw_mpi_plan_dft_3d(ptrdiff_t n0, ptrdiff_t n1, ptrdiff_t n2, fftw_complex *in, fftw_complex *out, MPI_Comm comm, int sign, unsigned flags); fftw_plan fftw_mpi_plan_dft(int rnk, const ptrdiff_t *n, fftw_complex *in, fftw_complex *out, MPI_Comm comm, int sign, unsigned flags); fftw_plan fftw_mpi_plan_many_dft(int rnk, const ptrdiff_t *n, ptrdiff_t howmany, ptrdiff_t block, ptrdiff_t tblock, fftw_complex *in, fftw_complex *out, MPI_Comm comm, int sign, unsigned flags);
However, this seems strange to me:
- None of these quantities can ever have a valid negative value, so why use a signed type instead of (e. g.)
size_t
, which is exactly the type meant for array sizes? This is even more puzzling becausefftw_malloc(size_t n)
does usesize_t
for its argument, and the documentation always states that all of these size arguments must not be negative. - In particular for MPI, I don’t see why
ptrdiff_t
(or evensize_t
) was chosen, since the data to transform could be distributed across multiple machines, and could thus (in principle) be larger than a single machine could hold in a single array (i. e. larger thanSIZE_MAX
). Wouldn’tuintmax_t
(or evenintmax_t
) be more appropriate?