extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / hints / t001.c
1 /* Beginning of modification history */
2 /* Written 02-04-10 by Paul Green (Paul.Green@stratus.com) */
3 /* End of modification history */
4
5 /* This test case is extracted from Perl version 5.7.3.  It is
6    in the Perl_unpack_str function of the pp_pack.c source file.
7
8    GCC 2.95.2 improperly assumes that it can compensate for an
9    extra fsub by performing a fadd.  This would work in
10    fixed-point arithmetic, but does not work in floating-point
11    arithmetic.
12
13    This problem has been seen on HP-UX and on Stratus VOS, both
14    of which have an HP PA-RISC target (hppa1.1).  The Stratus
15    bug number is gnu_g++-220.  */
16
17 /* #define _POSIX_C_SOURCE 199506L -- added by Configure */
18 #include <stdio.h>
19 #include <string.h>
20 #include <math.h>
21
22 void test(double *result)
23 {
24         float   afloat;
25         double  adouble;
26         int             checksum = 0;
27         unsigned        cuv = 0;
28         double  cdouble = 0.0;
29         const int       bits_in_uv = 8 * sizeof(cuv);
30
31         checksum = 53;
32         cdouble = -1.0;
33
34         if (checksum) {
35                 if (checksum > bits_in_uv) {
36                         double trouble;
37
38                         adouble = (double) (1 << (checksum & 15));
39
40                         while (checksum >= 16) {
41                                 checksum -= 16;
42                                 adouble *= 65536.0;
43                         }
44
45                         /* At -O1, GCC 2.95.2 compiles the following loop
46                            into:
47
48                            L$0014
49                                 fcmp,dbl,>= %fr4,%fr0
50                                 ftest
51                                 b L$0014
52                                 fadd,dbl %fr4,%fr12,%fr4
53                                 fsub,dbl %fr4,%fr12,%fr4
54
55                                 This code depends on the floading-add and
56                                 floating-subtract retaining all of the
57                                 precision present in the operands.  There is
58                                 no such guarantee when using floating-point,
59                                 as this test case demonstrates.
60
61                                 The code is okay at -O0.  */
62
63                         while (cdouble < 0.0)
64                                 cdouble += adouble;
65
66                         cdouble = modf (cdouble / adouble, &trouble) * adouble;
67                 }
68         }
69
70         *result = cdouble;
71 }
72
73 int main (int argc, char ** argv)
74 {
75 double  value;
76
77         test (&value);
78
79         if (argc == 2 && !strcmp(argv[1],"-v"))
80                 printf ("value = %.18e\n", value);
81
82         if (value != 9.007199254740991e+15) {
83                 printf ("t001 fails!\n");
84                 return -1;
85         }
86         else {
87                 printf ("t001 works.\n");
88                 return 0;
89         }
90 }