mborgerding / kissfft

a Fast Fourier Transform (FFT) library that tries to Keep it Simple, Stupid

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document what each element of input and output arrays means

AndrewBelt opened this issue · comments

There's no one-and-only convention for how input and output arrays in FFT libraries are organized, so it would nice to explicitly document this. It's obvious for complex FFT/IFFT, but it gets more ambiguous for real FFT and especially multidimensional FFT. (It's better to overdocument than underdocument.) For example, kiss_fftndri says

output freqdata has dims[0] X dims[1] X ... X dims[ndims-1]/2+1 complex points

but it's unclear of the order of the points. Is F(k1, k2) found in freqdata[k1 + dims[0] * k2]? I'm suggesting this because I think a lot of people have to spend several minutes making sure their assumptions about how their arrays are organized are correct with their FFT library.

Maybe a 2D example in the comments or referral to some test code would make a good addition. Care to submit a pull request?

Incidentally, this is the same data layout as multi-dim real transforms in FFTW.
I've regretted adopting this. It would be much better for data alignment if the leading dimension were the one cut (almost) in half.

I actually can't figure out how the multidimensional real transform is organized, been at it for an hour. I'll submit something if I figure it out, but I might have to switch to another library.

In the common case where ndim==2: an MxN transform, the frequency domain version will have Mx(N/2+1) points.
e.g. a float[7][1024] array goes in to kiss_fftndr and float complex[7][513] comes out.

The documentation is clear on the sizes of the arrays, not what they contain. If I take the DFT of x to obtain X, where should I expect to find X(k_1, k_2) in the array? It doesn't look like it's a direct mapping to output[k1][k2].

The (almost)half spectrum contains the frequency components from DC to Nyquist bin inclusive. This is the same as every FFT library I've ever seen.

Other FFT libraries aren't documented well either, so it's not very useful to assume common knowledge, similar to abbreviations in publications. (Undefined abbreviations can throw off readers for several minutes, while it takes an author a second to define it.)

Are you saying that the following is correct?

float input[Y][X];
float complex output[Y][X / 2 + 1];

for (int ky = -Y / 2 + 1; ky <= Y / 2; ky++) {
	for (int kx = 0; kx <= X / 2; kx++) {
		int ix = kx;
		int iy = eucMod(ky, Y);

		// Equals the complex component of wavenumber (kx, ky).
		output[iy * (X / 2 + 1) + ix];
	}
}

"wavenumber (kx,kky)" is much less descriptive than "DC" and "Nyquist" to someone who knows what a DFT is. Sorry to brush you off, but you'll have to spend some time on your research. Ask your questions over at stackoverflow.com or dsp.stackexchange.com. I cannot spend any more time on this right now.

Yes, I know what DC and Nyquist are. Those terms are strictly less descriptive than wavenumbers because they describe a subset of the space of wavenumbers.

This is not a question of FFTs in general, this is a question of documenting specifically KISS FFT. There are dozens of ways to organize the input and output of multidimensional FFTs. I could hypothetically write my own FFT library that uses its own arbitrary ordering. pffft uses an arbitrary system, which I think is the same used in FFTPACK. It leaves the order unspecified but offers a function for converting back and forth between a well-defined "canonical" ordering. I believe that Apple vDSP and Intel MKL have multiple ways of configuring the input/output, such as choosing which axis to "slice". Numpy's numpy.fft.rfftn slices the last axis, like KISS FFT (if I'm understanding you correctly).

My point is, your API as it stands now requires guesswork. If you don't want to document it, that's fine, but keep in mind that all of your users will then need to find out what your API does in more roundabout ways, such as by guessing, experimenting, or reading the source. If I have the time, I'll overhaul your documentation, but it won't be today.