mborgerding / kissfft

a Fast Fourier Transform (FFT) library that tries to Keep it Simple, Stupid
Other
1.39k stars 278 forks source link

Allow setting a suffix for constants and trigonometric functions #14

Open steffen-kiess opened 5 years ago

steffen-kiess commented 5 years ago

This is similar to #12, but for the C version. The C version uses sin() and cos() and constants (for pi) which are not accurate enough for long double.

In order to use constants or trigonometric functions with a type other than double, a suffix ('f' for float or 'l' for long double) has to be used in C. This commit adds a preprocessor macro 'kiss_fft_suffix' which can be set to either 'f' or 'l' and which will be added to floating point constants and to the trigonometric functions (sin and cos).

Without this suffix, the code will use a too high precision for float and a too low precision for long double.

mborgerding commented 5 years ago

Thanks for the input. I think this will improve accuracy for long double. However, I think this can (and should) be accomplished without requiring any new build flags.
Maybe define KISS_FFT_COS and KISS_FFT_SIN differently depending on the kiss_fft_scalar definition?

steffen-kiess commented 5 years ago

Comparing strings in the C preprocessor is rather difficult, especially because long double consists of two words. The following code would work, but is a rather ugly hack:

#define kiss_fft_scalar float
//#define kiss_fft_scalar double
//#define kiss_fft_scalar long double

#define X_float_X 1
#define X__X 2
#define X_long_X 3
#define concat2(a, b, c) a##b##c
#define concat(a, b, c) concat2(a, b, c)

#define double

#if concat(X_, kiss_fft_scalar, _X) == X_float_X
#define kiss_fft_suffix f
#elif concat(X_, kiss_fft_scalar, _X) == X__X
#undef kiss_fft_suffix
#elif concat(X_, kiss_fft_scalar, _X) == X_long_X
#define kiss_fft_suffix l
#else
#undef kiss_fft_suffix
#warning "Unknown kiss_fft_scalar type"
#endif

#undef double

#include <stdio.h>
#define tostr1(x) #x
#define tostr(x) tostr1(x)
int main () {
  printf("%s\n", tostr(kiss_fft_suffix));
}
mborgerding commented 4 years ago

@steffen-kiess Could you put the above preprocessor hack into a PR?

steffen-kiess commented 4 years ago

I've updated this pull request.

steffen-kiess commented 4 years ago

The change was breaking USE_SIMD / FIXED_POINT, this should be fixed now. Currently both USE_SIMD and FIXED_POINT use double for floating point operations (like before), but this can be changed in kiss_fft.h.

mborgerding commented 4 years ago

Thanks for the update. Your preprocessor kung fu is strong. At times like this, I would reach for templates in a c++ project. I'll take a closer look and expect to merge this soon.