1 /****************************************************************
2 Copyright (C) 1997, 1998, 2000 Lucent Technologies
3 All Rights Reserved
4
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name of Lucent or any of its entities
11 not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior
13 permission.
14
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 THIS SOFTWARE.
23 ****************************************************************/
24
25 /* Try to deduce arith.h from arithmetic properties. */
26
27 #include <stdio.h>
28 #include <math.h>
29 #include <errno.h>
30
31 #ifdef NO_FPINIT
32 #define fpinit_ASL()
33 #else
34 #ifndef KR_headers
35 extern
36 #ifdef __cplusplus
37 "C"
38 #endif
39 void fpinit_ASL(void);
40 #endif /*KR_headers*/
41 #endif /*NO_FPINIT*/
42
43 static int dalign;
44 typedef struct
45 Akind {
46 char *name;
47 int kind;
48 } Akind;
49
50 static Akind
51 IEEE_8087 = { "IEEE_8087", 1 },
52 IEEE_MC68k = { "IEEE_MC68k", 2 },
53 IBM = { "IBM", 3 },
54 VAX = { "VAX", 4 },
55 CRAY = { "CRAY", 5};
56
57 static double t_nan;
58
59 static Akind *
Lcheck(void)60 Lcheck(void)
61 {
62 union {
63 double d;
64 long L[2];
65 } u;
66 struct {
67 double d;
68 long L;
69 } x[2];
70
71 if (sizeof(x) > 2*(sizeof(double) + sizeof(long)))
72 dalign = 1;
73 u.L[0] = u.L[1] = 0;
74 u.d = 1e13;
75 if (u.L[0] == 1117925532 && u.L[1] == -448790528)
76 return &IEEE_MC68k;
77 if (u.L[1] == 1117925532 && u.L[0] == -448790528)
78 return &IEEE_8087;
79 if (u.L[0] == -2065213935 && u.L[1] == 10752)
80 return &VAX;
81 if (u.L[0] == 1267827943 && u.L[1] == 704643072)
82 return &IBM;
83 return 0;
84 }
85
86 static Akind *
icheck(void)87 icheck(void)
88 {
89 union {
90 double d;
91 int L[2];
92 } u;
93 struct {
94 double d;
95 int L;
96 } x[2];
97
98 if (sizeof(x) > 2*(sizeof(double) + sizeof(int)))
99 dalign = 1;
100 u.L[0] = u.L[1] = 0;
101 u.d = 1e13;
102 if (u.L[0] == 1117925532 && u.L[1] == -448790528)
103 return &IEEE_MC68k;
104 if (u.L[1] == 1117925532 && u.L[0] == -448790528)
105 return &IEEE_8087;
106 if (u.L[0] == -2065213935 && u.L[1] == 10752)
107 return &VAX;
108 if (u.L[0] == 1267827943 && u.L[1] == 704643072)
109 return &IBM;
110 return 0;
111 }
112
113 char *emptyfmt = ""; /* avoid possible warning message with printf("") */
114
115 static Akind *
ccheck(void)116 ccheck(void)
117 {
118 union {
119 double d;
120 long L;
121 } u;
122 long Cray1;
123
124 /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
125 Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762;
126 if (printf(emptyfmt, Cray1) >= 0)
127 Cray1 = 1000000*Cray1 + 693716;
128 if (printf(emptyfmt, Cray1) >= 0)
129 Cray1 = 1000000*Cray1 + 115456;
130 u.d = 1e13;
131 if (u.L == Cray1)
132 return &CRAY;
133 return 0;
134 }
135
136 static int
fzcheck(void)137 fzcheck(void)
138 {
139 double a, b;
140 int i;
141
142 a = 1.;
143 b = .1;
144 for(i = 155;; b *= b, i >>= 1) {
145 if (i & 1) {
146 a *= b;
147 if (i == 1)
148 break;
149 }
150 }
151 b = a * a;
152 return b == 0.;
153 }
154
155 static int
need_nancheck(void)156 need_nancheck(void)
157 {
158 double t;
159
160 errno = 0;
161 t = log(t_nan);
162 if (errno == 0)
163 return 1;
164 errno = 0;
165 t = sqrt(t_nan);
166 return errno == 0;
167 }
168
169 void
get_nanbits(unsigned int * b,int k)170 get_nanbits(unsigned int *b, int k)
171 {
172 union { double d; unsigned int z[2]; } u, u1, u2;
173
174 k = 2 - k;
175 u1.z[k] = u2.z[k] = 0x7ff00000;
176 u1.z[1-k] = u2.z[1-k] = 0;
177 u.d = u1.d - u2.d; /* Infinity - Infinity */
178 b[0] = u.z[0];
179 b[1] = u.z[1];
180 }
181
182 int
main(void)183 main(void)
184 {
185 FILE *f;
186 Akind *a = 0;
187 int Ldef = 0;
188 unsigned int nanbits[2];
189
190 fpinit_ASL();
191 #ifdef WRITE_ARITH_H /* for Symantec's buggy "make" */
192 f = fopen("arith.h", "w");
193 if (!f) {
194 printf("Cannot open arith.h\n");
195 return 1;
196 }
197 #else
198 f = stdout;
199 #endif
200
201 if (sizeof(double) == 2*sizeof(long))
202 a = Lcheck();
203 else if (sizeof(double) == 2*sizeof(int)) {
204 Ldef = 1;
205 a = icheck();
206 }
207 else if (sizeof(double) == sizeof(long))
208 a = ccheck();
209 if (a) {
210 fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
211 a->name, a->kind);
212 if (Ldef)
213 fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
214 if (dalign)
215 fprintf(f, "#define Double_Align\n");
216 if (sizeof(char*) == 8)
217 fprintf(f, "#define X64_bit_pointers\n");
218 #ifndef NO_LONG_LONG
219 if (sizeof(long long) < 8)
220 #endif
221 fprintf(f, "#define NO_LONG_LONG\n");
222 if (a->kind <= 2) {
223 if (fzcheck())
224 fprintf(f, "#define Sudden_Underflow\n");
225 t_nan = -a->kind;
226 if (need_nancheck())
227 fprintf(f, "#define NANCHECK\n");
228 if (sizeof(double) == 2*sizeof(unsigned int)) {
229 get_nanbits(nanbits, a->kind);
230 fprintf(f, "#define QNaN0 0x%x\n", nanbits[0]);
231 fprintf(f, "#define QNaN1 0x%x\n", nanbits[1]);
232 }
233 }
234 return 0;
235 }
236 fprintf(f, "/* Unknown arithmetic */\n");
237 return 1;
238 }
239
240 #ifdef __sun
241 #ifdef __i386
242 /* kludge for Intel Solaris */
fpsetprec(int x)243 void fpsetprec(int x) { }
244 #endif
245 #endif
246