>  -   { .angle = π *      -1.89999999999999991, .sin =       
> 0.30901699437494767, .cos =       0.95105651629515353 },
>  +   { .angle = π *      -1.89999999999999991, .sin =       
> 0.30901699437494762, .cos =       0.95105651629515353 },

That's very odd. Is this using exactly the same compiler and C library
on both machines? This is calling the math library 'sin' function for
the bulk of the computation, so any tiny variation in library source or
compiler version used to build that library could easily have this kind
of effect.

> This is a native build on amd64/x86_64 both runs, and yet I can't
> reproduce it locally. I thought the point of IEEE 754 or whatever it
> was was to ensure this sort of thing didn't happen across runs? :)

C doesn't guarantee to respect the order of operations in floating point
computations, so maybe there was some variation in how the math library
was compiled? The two values above differ by only a single ULP. The
higher value above is also less accurate than the lower value by a tiny
amount; the true answer lies almost exactly between them.

One credible alternative would be to write a bc script to generate this
table, rather than using a C program. That would also make this
reproducible between x86_64 and i386; I'm sure those two targets would
produce wildly different answers for these test vectors.

To rule out a hardware bug, can we run a single static binary on both
physical machines? Build this on one machine, then run on both and
compare the results. A hardware bug would be surprising, of course.

#include <stdio.h>
#include <math.h>


volatile double v 	= -0x1.7e0485cda5e0ap+2;	/* -5.9690260418206069203961305902339518070220947265625 */
volatile double sinv	=  0x1.3c6ef372fe953p-2;	/*  0.309016994374947617796323129368829540908336639404296875 */

/*
 * nickle and bc agree that the answer is about
 *                         0x1.3c6ef372fe9537f49            0.309016994374947645396873930110359227221870944045016832
 *
 * sometimes x86_64 gets   0x1.3c6ef372fe954p-2             0.3090169943749476733074743606266565620899200439453125
 *
 * As you can see from the hex numbers above, the correct answer is
 * almost exactly between the two values:
 *
 * correct - 0x1.3c6ef372fe953p-2 = 2.760055080074153e-17
 * 0x1.3c6ef372fe954p-2 - correct = 2.79106004305163e-17
 */

int main(void)
{
	volatile double s = sin(v);
	int ret = 0;
	printf("value: ( %.18g %a ) sin(value): ( %.18g %a )\n", v, v, s, s);
	if (s != sinv) {
		printf("Error: expected ( %.18g %a ) got ( %.18g %a )\n", sinv, sinv, s, s);
		ret = 1;
	}
	return ret;
}
$ cc -static -O2 bug-1086188.c -lm

-- 
-keith

Attachment: signature.asc
Description: PGP signature

Reply via email to