/* Beginning of modification history */ /* Written 02-04-10 by Paul Green (Paul.Green@stratus.com) */ /* End of modification history */ /* This test case is extracted from Perl version 5.7.3. It is in the Perl_unpack_str function of the pp_pack.c source file. GCC 2.95.2 improperly assumes that it can compensate for an extra fsub by performing a fadd. This would work in fixed-point arithmetic, but does not work in floating-point arithmetic. This problem has been seen on HP-UX and on Stratus VOS, both of which have an HP PA-RISC target (hppa1.1). The Stratus bug number is gnu_g++-220. */ /* #define _POSIX_C_SOURCE 199506L -- added by Configure */ #include #include #include void test(double *result) { float afloat; double adouble; int checksum = 0; unsigned cuv = 0; double cdouble = 0.0; const int bits_in_uv = 8 * sizeof(cuv); checksum = 53; cdouble = -1.0; if (checksum) { if (checksum > bits_in_uv) { double trouble; adouble = (double) (1 << (checksum & 15)); while (checksum >= 16) { checksum -= 16; adouble *= 65536.0; } /* At -O1, GCC 2.95.2 compiles the following loop into: L$0014 fcmp,dbl,>= %fr4,%fr0 ftest b L$0014 fadd,dbl %fr4,%fr12,%fr4 fsub,dbl %fr4,%fr12,%fr4 This code depends on the floading-add and floating-subtract retaining all of the precision present in the operands. There is no such guarantee when using floating-point, as this test case demonstrates. The code is okay at -O0. */ while (cdouble < 0.0) cdouble += adouble; cdouble = modf (cdouble / adouble, &trouble) * adouble; } } *result = cdouble; } int main (int argc, char ** argv) { double value; test (&value); if (argc == 2 && !strcmp(argv[1],"-v")) printf ("value = %.18e\n", value); if (value != 9.007199254740991e+15) { printf ("t001 fails!\n"); return -1; } else { printf ("t001 works.\n"); return 0; } }