]> www.ginac.de Git - cln.git/blob - autoconf/floatparam.c
Avoid using undeclared function exit().
[cln.git] / autoconf / floatparam.c
1 /* Determine some float parameters, much like gcc's "enquire.c". */
2 /* Bruno Haible 24.8.1996 */
3
4 /* This program expects to be compiled by an ANSI C or C++ compiler. */
5
6 #include <stdio.h>
7
8 #if !(defined(__STDC__) || defined(__cplusplus))
9 /* Only for use in function parameter lists and as function return type. */
10 #define void
11 #endif
12
13 typedef int boolean;
14 #define TRUE  1
15 #define FALSE 0
16
17 #ifdef HAVE_LONGDOUBLE
18 typedef long double ldouble;
19 #endif
20
21 static void header (void)
22 {
23   printf("/* Rounding modes, for use below */\n");
24   printf("#define rounds_to_nearest        0  /* 0.5 ulp */\n");
25   printf("#define rounds_to_zero           1  /* 1 ulp */\n");
26   printf("#define rounds_to_infinity       2  /* 1 ulp */\n");
27   printf("#define rounds_to_minus_infinity 3  /* 1 ulp */\n");
28   printf("\n");
29 }
30
31 #define check(type,typeprefix,typestr,equalfn,mainfn)  \
32 static boolean equalfn (type* x, type* y);                              \
33 static void mainfn (void)                                               \
34 {                                                                       \
35   int mant_bits;                                                        \
36   int epsilon_bits = -1;                                                \
37   int negepsilon_bits = -1;                                             \
38   { type x = 1.0; type y; type z;                                       \
39     for (y = 1.0; ; y = 0.5*y)                                          \
40       { z = x + y; if (equalfn(&x,&z)) break;                           \
41         z = z - x; if (!equalfn(&y,&z)) break;                          \
42         epsilon_bits++;                                                 \
43   }   }                                                                 \
44   { type x = 1.0; type y; type z;                                       \
45     for (y = -1.0; ; y = 0.5*y)                                         \
46       { z = x + y; if (equalfn(&x,&z)) break;                           \
47         z = z - x; if (!equalfn(&y,&z)) break;                          \
48         negepsilon_bits++;                                              \
49   }   }                                                                 \
50   printf("/* Properties of type `%s': */\n",typestr);                   \
51   printf("/* Largest n for which 1+2^(-n) is exactly represented is %d. */\n",epsilon_bits); \
52   printf("/* Largest n for which 1-2^(-n) is exactly represented is %d. */\n",negepsilon_bits); \
53   if (negepsilon_bits <= epsilon_bits)                                  \
54     { printf("#error \"No exponent jump at 1.0 for type %s!\"\n",typestr); \
55       mant_bits = -1;                                                   \
56     }                                                                   \
57   else                                                                  \
58     { if (negepsilon_bits > epsilon_bits+1)                             \
59         printf("/* Base for type `%s' is 2^%d\n",typestr,negepsilon_bits-epsilon_bits); \
60       mant_bits = epsilon_bits+1;                                       \
61       printf("#define %s_mant_bits %d\n",typeprefix,mant_bits);         \
62     }                                                                   \
63   { int i; type x, y1, y2, ys1, ys2, z1, z2, zs1, zs2;                  \
64     x = 1.0; for (i = 0; i < epsilon_bits; i++) { x = 0.5*x; }          \
65     y1 = 1.0 + 5.0*x; y2 = 1.0 + 6.0*x;                                 \
66     ys1 = 1.0 + 5.4*x; ys2 = 1.0 + 5.6*x;                               \
67     z1 = -1.0 + (-5.0)*x; z2 = -1.0 + (-6.0)*x;                         \
68     zs1 = -1.0 + (-5.4)*x; zs2 = -1.0 + (-5.6)*x;                       \
69     if (equalfn(&ys1,&y1) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z2)) \
70       printf("#define %s_rounds rounds_to_nearest\n",typeprefix);       \
71     else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \
72       printf("#define %s_rounds rounds_to_zero\n",typeprefix);          \
73     else if (equalfn(&ys1,&y2) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \
74       printf("#define %s_rounds rounds_to_infinity\n",typeprefix);      \
75     else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z2) && equalfn(&zs2,&z2)) \
76       printf("#define %s_rounds rounds_to_minus_infinity\n",typeprefix); \
77     else                                                                \
78       printf("#error \"Unknown rounding mode for type %s!\"\n",typestr); \
79   }                                                                     \
80   printf("\n");                                                         \
81 }                                                                       \
82 static boolean equalfn (type* x, type* y) { return *x == *y; }          \
83
84 check(float,"float","float",equal_float,main_float)
85 check(double,"double","double",equal_double,main_double)
86 #ifdef HAVE_LONGDOUBLE
87 check(ldouble,"long_double","long double",equal_ldouble,main_ldouble)
88 #endif
89
90 /* Some systems (arm/linux) store doubles as little endian but with higher
91  * and lower word reversed. */
92 static void flipped_double (void)
93 {
94   typedef struct { unsigned lo, hi; } dfloat;
95   double x = 2;
96   dfloat test = *(dfloat*)&x;
97   if (test.lo==0 && test.hi!=0) {
98     printf("#define double_wordorder_bigendian_p 0\n");
99   } else if (test.lo!=0 && test.hi==0) {
100     printf("#define double_wordorder_bigendian_p 1\n");
101   } else {
102     /* Dazed and confused!  Better not define anything.
103          * Code should rely on CL_CPU_BIG_ENDIAN_P instead. */
104   }
105   printf("\n");
106 }
107          
108 int main()
109 {
110   header();
111   main_float();
112   main_double();
113 #ifdef HAVE_LONGDOUBLE
114   main_ldouble();
115 #endif
116   flipped_double();
117
118   if (ferror(stdout)) return 1;
119   return 0;
120 }