summaryrefslogtreecommitdiff
path: root/hints/t001.c
diff options
context:
space:
mode:
authorPaul Green <Paul.Green@stratus.com>2002-04-22 16:35:00 -0400
committerJarkko Hietaniemi <jhi@iki.fi>2002-04-23 01:05:37 +0000
commitc50b6f56db28b9899ebe08201288c8d0707ffb6d (patch)
tree57db306374e35a20a4ed07d0fe82dbfa840d6cba /hints/t001.c
parent74f68c8da607d6749d83c3b19f78b04cebfb1a6a (diff)
downloadperl-c50b6f56db28b9899ebe08201288c8d0707ffb6d.tar.gz
(Updated) Work around bug in gcc 2.95.2 on hppa targets
Message-Id: <200204230034.UAA01134@mailhub2.stratus.com> p4raw-id: //depot/perl@16092
Diffstat (limited to 'hints/t001.c')
-rw-r--r--hints/t001.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/hints/t001.c b/hints/t001.c
new file mode 100644
index 0000000000..51fdefda84
--- /dev/null
+++ b/hints/t001.c
@@ -0,0 +1,90 @@
+/* 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+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;
+ }
+}