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()60 Lcheck()
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()87 icheck()
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()116 ccheck()
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()137 fzcheck()
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()156 need_nancheck()
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 
main()169 main()
170 {
171         FILE *f;
172         Akind *a = 0;
173         int Ldef = 0;
174 
175         fpinit_ASL();
176 #ifdef WRITE_ARITH_H    /* for Symantec's buggy "make" */
177         f = fopen("arith.h", "w");
178         if (!f) {
179                 printf("Cannot open arith.h\n");
180                 return 1;
181                 }
182 #else
183         f = stdout;
184 #endif
185 
186         if (sizeof(double) == 2*sizeof(long))
187                 a = Lcheck();
188         else if (sizeof(double) == 2*sizeof(int)) {
189                 Ldef = 1;
190                 a = icheck();
191                 }
192         else if (sizeof(double) == sizeof(long))
193                 a = ccheck();
194         if (a) {
195                 fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
196                         a->name, a->kind);
197                 if (Ldef)
198                         fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
199                 if (dalign)
200                         fprintf(f, "#define Double_Align\n");
201                 if (sizeof(char*) == 8)
202                         fprintf(f, "#define X64_bit_pointers\n");
203 #ifndef NO_LONG_LONG
204                 if (sizeof(long long) < 8)
205 #endif
206                         fprintf(f, "#define NO_LONG_LONG\n");
207                 if (a->kind <= 2) {
208                         if (fzcheck())
209                                 fprintf(f, "#define Sudden_Underflow\n");
210                         t_nan = -a->kind;
211                         if (need_nancheck())
212                                 fprintf(f, "#define NANCHECK\n");
213                         }
214                 return 0;
215                 }
216         fprintf(f, "/* Unknown arithmetic */\n");
217         return 1;
218         }
219 
220 #ifdef __sun
221 #ifdef __i386
222 /* kludge for Intel Solaris */
fpsetprec(int x)223 void fpsetprec(int x) { }
224 #endif
225 #endif
226