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