I am curious about the ways to wrap a floating-point value x
in a semi-closed interval [0; a[
.
For instance, I could have an arbitrary real number, say x = 354638.515
, that I wish to fold into [0; 2π[
because I have a good sin
approximation for that range.
The fmod
standard C functions show up quite high in my benchmarks, and by checking the source code of various libc implementations, I can understand why: the thing is fairly branch-ey, likely in order to handle a lot of IEEE754-specific issues:
- glibc: https://github.com/bminor/glibc/blob/master/sysdeps/ieee754/flt-32/e_fmodf.c
- Apple: https://opensource.apple.com/source/Libm/Libm-315/Source/ARM/fmod.c.auto.html
- musl: https://git.musl-libc.org/cgit/musl/tree/src/math/fmod.c
- Running with
-ffast-math
causes GCC to generate code that goes through the x87 FPU on x86/x86_64 which comes with its own set of problems (such as 80-bit doubles, FP state, and other fun things). I would like the implementation to vectorize at least semi-correctly, and if possible to not go through the x87 FPU but through vector registers at least as the rest of my code ends up vectorized, even if not necessarily an optimal way, by the compiler. - This one looks much simpler: https://github.com/KnightOS/libc/blob/master/src/fmod.c
In my case, I am only concerned about usual real values, not NaNs, not infinity. My range is also known at compile-time and sane (a common occurence being π/2
), thus the checks for "special cases" such as range == 0 are unnecessary.
Thus, what would be good implementations of fmod
for that specific use case ?