tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
mysterious remquo bug
C99/POSIX define remquo:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/remquo.html
The basic idea is that return value r is a remainder, and in q is stored
the low-order k bits of the quotient, but with q having the same sign as
the quotient.
The point is to reduce possibly large angles before using sin/cos.
I'm doing all this on netbsd-10, amd64, system gcc 10, intel 9th
generation i7. The following test program calls remquo with (-90, 90).
This is from a test in geodesiclib in proj of a high-accuracy sincos
implementation, which reduces angles to [45,-45] and then adjusts sign
by quadrant. But, it can be understood from the remquo specification.
The remainder is 0, and that's ok (-0, but not worrying about that).
The true quotient value is -1, and the low order bits should be
not only congruent to -1, but < 0.
The test program calls remquo twice, one with the -90 in a double, and
once with it as a literal. The first time gets a positive q -- which
messes up the sin calculation, wwhich is how I got here. The second is
correct.
Adding -ffloat-store didn't change the output.
I got the same behavior on netbsd-9 earmv7hf-el.
src/lib/libm/src/s_remquo.c is somewhat hard to understand....
Does anyone consider themselves the guardian of numerical correctness?
You are hereby nerdsniped!
----------------------------------------
#include <math.h>
#include <stdio.h>
int
main()
{
double x = -90.0;
double r; int q = 0;
r = remquo(x, 90, &q);
printf("remquo(x == -90.0, 90) r %f q %d", r, q);
if (q > 0)
printf("\tERROR: q positive");
printf("\n");
r = remquo(-90.0, 90, &q);
printf("remquo(-90.0, 90) r %f q %d", r, q);
if (q > 0)
printf("\tERROR: q positive");
printf("\n");
}
----------------------------------------
remquo(x == -90.0, 90) r -0.000000 q 1 ERROR: q positive
remquo(-90.0, 90) r -0.000000 q -1
----------------------------------------
Home |
Main Index |
Thread Index |
Old Index