]> gcc.gnu.org Git - gcc.git/blob - gcc/enquire.c
(f_rep): Remove decl of unused variable F1.
[gcc.git] / gcc / enquire.c
1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
3
4 #ifndef VERSION
5 #define VERSION "4.3"
6 #endif
7
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9 Bugfixes and upgrades gratefully received.
10
11 Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
12 All rights reserved.
13
14 Changes by Richard Stallman:
15 Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
16 In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
17 Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
18 Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
19 Include sys/types.h before signal.h, Apr 92.
20 Support NO_LONG_DOUBLE_IO in f_define and f_rep; new fn fake_f_rep, Apr 92.
21 Enclose -f output in #ifndef _FLOAT_H___, Richard Stallman, May 92.
22
23 Add #undef before every #define, Jim Wilson, Dec 92.
24
25 Changes by Paul Eggert, installed Feb 93:
26 (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
27 (f_define): Use ordinary constants for long double
28 if it's same width as double. Make __convert_long_double_i unsigned.
29 Richard Stallman, May 93:
30 In F_check, check NO_LONG_DOUBLE_IO.
31
32 Changes by Stephen Moshier, installed Sep 93:
33 (FPROP): Recognize 80387 or 68881 XFmode format.
34
35
36 COMPILING
37 With luck and a following wind, just the following will work:
38 cc enquire.c -o enquire
39 You may get some messages about unreachable code, which you can ignore.
40
41 If your compiler doesn't support: add flag:
42 signed char (eg pcc) -DNO_SC
43 unsigned char -DNO_UC
44 unsigned short and long -DNO_UI
45 void -DNO_VOID
46 signal(), or setjmp/longjmp() -DNO_SIG
47 %Lf in printf -DNO_LONG_DOUBLE_IO
48
49 Try to compile first with no flags, and see if you get any errors -
50 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
51 Some compilers need a -f flag for floating point.
52
53 Don't use any optimisation flags: the program may not work if you do.
54 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
55 optimiser, to a floating-point unit there's a world of difference.
56
57 Some compilers offer various flags for different floating point
58 modes; it's worth trying all possible combinations of these.
59
60 Add -DID=\"name\" if you want the machine/flags identified in the output.
61
62 FAULTY COMPILERS
63 Because of bugs and/or inadequacies, some compilers need the following
64 defines:
65
66 If your C preprocessor doesn't have the predefined __FILE__ macro, and
67 you don't want to call this file enquire.c but, say, tell.c, add the
68 flag -DFILENAME=\"tell.c\" .
69
70 Some compilers won't accept the line "#include FILENAME".
71 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
72
73 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
74 or -DNO_FILE as above.
75
76 Some naughty compilers define __STDC__, but don't really support it.
77 Some define it as 0, in which case we treat it as undefined.
78 But if your compiler defines it, and isn't really ANSI C,
79 add flag -DNO_STDC. (To those compiler writers: for shame).
80
81 Some naughty compilers define __STDC__, but don't have the stddef.h
82 include file. Add flag -DNO_STDDEF.
83
84 Summary of naughty-compiler flags:
85 If your compiler doesn't support: add flag:
86 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
87 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
88 #include FILENAME -DNO_FILE
89 __STDC__ (properly) -DNO_STDC
90 stddef.h -DNO_STDDEF
91
92 Some systems crash when you try to malloc all store. To save users of
93 such defective systems too much grief, they may compile with -DNO_MEM,
94 which ignores that bit of the code.
95
96 While it is not our policy to support defective compilers, pity has been
97 taken on people with compilers that can't produce object files bigger than
98 32k (especially since it was an easy addition). Compile the program
99 into separate parts like this:
100 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
101 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
102 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
103 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
104 cc -o enquire p0.o p1.o p2.o p3.o
105
106 SYSTEM DEPENDENCIES
107 You may possibly need to add some calls to signal() for other sorts of
108 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
109 #ifdef SIGxxx in main() (and communicate the differences to me!).
110
111 OUTPUT
112 Run without argument to get the information as English text. If run
113 with argument -l (e.g. enquire -l), output is a series of #define's for
114 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
115 with argument -f, output is a series of #define's for the ANSI standard
116 float.h include file (according to ANSI C Draft of Dec 7, 1988).
117 Flag -v gives verbose output: output includes the English text above
118 as C comments. The program exit(0)'s if everything went ok, otherwise
119 it exits with a positive number, telling how many problems there were.
120
121 VERIFYING THE COMPILER
122 If, having produced the float.h and limits.h header files, you want to
123 verify that the compiler reads them back correctly (there are a lot of
124 boundary cases, of course, like minimum and maximum numbers), you can
125 recompile enquire.c with -DVERIFY set (plus the other flags that you used
126 when compiling the version that produced the header files). This then
127 recompiles the program so that it #includes "limits.h" and "float.h",
128 and checks that the constants it finds there are the same as the
129 constants it produces. Run the resulting program with enquire -fl.
130 Very few compilers have passed without error.
131 NB: You *must* recompile with the same compiler and flags, otherwise
132 you may get odd results.
133
134 You can also use this option if your compiler already has both files,
135 and you want to confirm that this program produces the right results.
136
137 TROUBLESHOOTING.
138 This program is now quite trustworthy, and suspicious and wrong output
139 may well be caused by bugs in the compiler, not in the program (however
140 of course, this is not guaranteed, and no responsibility can be
141 accepted, etc.)
142
143 The program only works if overflows are ignored by the C system or
144 are catchable with signal().
145
146 If the program fails to run to completion (often with the error message
147 "Unexpected signal at point x"), this often turns out to be a bug in the
148 C compiler's run-time system. Check what was about to be printed, and
149 try to narrow the problem down.
150
151 Another possible problem is that you have compiled the program to produce
152 loss-of-precision arithmetic traps. The program cannot cope with these,
153 and you should re-compile without them. (They should never be the default).
154
155 Make sure you compiled with optimisation turned off.
156
157 Output preceded by *** WARNING: identifies behaviour of the C system
158 deemed incorrect by the program. Likely problems are that printf or
159 scanf don't cope properly with certain boundary numbers: this program
160 goes to a lot of trouble to calculate its values, and these values
161 are mostly boundary numbers. Experience has shown that often printf
162 cannot cope with these values, and so in an attempt to increase
163 confidence in the output, for each float and double that is printed,
164 the printed value is checked by using sscanf to read it back.
165 Care is taken that numbers are printed with enough digits to uniquely
166 identify them, and therefore that they can be read back identically.
167 If the number read back is different, then there is probably a bug in
168 printf or sscanf, and the program prints the warning message.
169 If the two numbers in the warning look identical, then printf is more
170 than likely rounding the last digit(s) incorrectly. To put you at ease
171 that the two really are different, the bit patterns of the two numbers
172 are also printed. The difference is very likely in the last bit.
173 Many scanf's read the minimum double back as 0.0, and similarly cause
174 overflow when reading the maximum double. This program quite ruthlessly
175 declares all these behaviours faulty. The point is that if you get
176 one of these warnings, the output may be wrong, so you should check
177 the result carefully if you intend to use the results. Of course, printf
178 and sscanf may both be wrong, and cancel each other out, so you should
179 check the output carefully anyway.
180
181 The warning that "a cast didn't work" refers to cases like this:
182
183 float f;
184 #define C 1.234567890123456789
185 f= C;
186 if (f != (float) C) printf ("Wrong!");
187
188 A faulty compiler will widen f to double and ignore the cast to float,
189 and because there is more accuracy in a double than a float, fail to
190 recognise that they are the same. In the actual case in point, f and C
191 are passed as parameters to a function that discovers they are not equal,
192 so it's just possible that the error was in the parameter passing,
193 not in the cast (see function Validate()).
194 For ANSI C, which has float constants, the error message is "constant has
195 wrong precision".
196
197 REPORTING PROBLEMS
198 If the program doesn't work for you for any reason that can't be
199 narrowed down to a problem in the C compiler, or it has to be changed in
200 order to get it to compile, or it produces suspicious output (like a very
201 low maximum float, for instance), please mail the problem and an example
202 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
203 improvements can be worked into future versions; cwi.nl is the European
204 backbone, and is connected to uunet and other fine hosts.
205
206 The program tries to catch and diagnose bugs in the compiler/run-time
207 system. I would be especially pleased to have reports of failures so
208 that I can improve this service.
209
210 I apologise unreservedly for the contorted use of the preprocessor...
211
212 THE SMALL PRINT
213 You may copy and distribute verbatim copies of this source file.
214
215 You may modify this source file, and copy and distribute such
216 modified versions, provided that you leave the copyright notice
217 at the top of the file and also cause the modified file to carry
218 prominent notices stating that you changed the files and the date
219 of any change; and cause the whole of any work that you distribute
220 or publish, that in whole or in part contains or is a derivative of
221 this program or any part thereof, to be licensed at no charge to
222 all third parties on terms identical to those here.
223
224 If you do have a fix to any problem, please send it to me, so that
225 other people can have the benefits.
226
227 While every effort has been taken to make this program as reliable as
228 possible, no responsibility can be taken for the correctness of the
229 output, nor suitability for any particular use.
230
231 This program is an offshoot of a project funded by public funds.
232 If you use this program for research or commercial use (i.e. more
233 than just for the fun of knowing about your compiler) mailing a short
234 note of acknowledgement may help keep enquire.c supported.
235
236 ACKNOWLEDGEMENTS
237 Many people have given time and ideas to making this program what it is.
238 To all of them thanks, and apologies for not mentioning them by name.
239
240 HISTORY
241 Originally started as a program to generate configuration constants
242 for a large piece of software we were writing, which later took on
243 a life of its own...
244 1.0 Length 6658!; end 1984?
245 Unix only. Only printed a dozen maximum int/double values.
246 2.0 Length 10535; Spring 1985
247 Prints values as #defines (about 20 of them)
248 More extensive floating point, using Cody and Waite
249 Handles signals better
250 Programs around optimisations
251 Handles Cybers
252 3.0 Length 12648; Aug 1987; prints about 42 values
253 Added PASS stuff, so treats float as well as double
254 4.0 Length 33891; Feb 1989; prints around 85 values
255 First GNU version (for gcc, where they call it hard-params.c)
256 Generates float.h and limits.h files
257 Handles long double
258 Generates warnings for dubious output
259 4.1 Length 47738; April 1989
260 Added VERIFY and TEST
261 4.2 Length 63442; Feb 1990
262 Added SEP
263 Fixed eps/epsneg
264 Added check for pseudo-unsigned chars
265 Added description for each #define output
266 Added check for absence of defines during verify
267 Added prototypes
268 Added NO_STDC and NO_FILE
269 Fixed alignments output
270 4.3 Length 75000; Oct 1990; around 114 lines of output
271 Function xmalloc defined, Richard Stallman, June 89.
272 Alignments computed from member offsets rather than structure sizes,
273 Richard Stallman, Oct 89.
274 Print whether char* and int* pointers have the same format;
275 also char * and function *.
276 Update to Draft C version Dec 7, 1988
277 - types of constants produced in limits.h
278 (whether to put a U after unsigned shorts and chars and
279 whether to output -1024 as (-1023-1))
280 - values of SCHAR_MIN/MAX
281 - values of *_EPSILON (not the smallest but the effective smallest)
282 Added FILENAME, since standard C doesn't allow #define __FILE__
283 Renamed from config.c to enquire.c
284 Added size_t and ptrdiff_t enquiries
285 Added promotion enquiries
286 Added type checks of #defines
287 Added NO_STDDEF
288 Changed endian to allow for cases where not all bits are used
289 Sanity check for max integrals
290 Fixed definition of setjmp for -DNO_SIG
291 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
292 Added NO_MEM
293 */
294
295 /* Set FILENAME to the name of this file */
296 #ifndef FILENAME
297 #ifdef NO_FILE
298 #define FILENAME "enquire.c"
299 #else
300 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
301 #define FILENAME __FILE__
302 #else
303 #define FILENAME "enquire.c"
304 #endif /* __FILE__ */
305 #endif /* NO_FILE */
306 #endif /* FILENAME */
307
308 /* If PASS isn't defined, then this is the first pass over this file. */
309 #ifndef PASS
310 #ifndef SEP
311 #define PASS 1
312 #define PASS0 1
313 #define PASS1 1
314 #endif /* SEP */
315
316 /* A description of the ANSI constants */
317 #define D_CHAR_BIT "Number of bits in a storage unit"
318 #define D_CHAR_MAX "Maximum char"
319 #define D_CHAR_MIN "Minimum char"
320 #define D_SCHAR_MAX "Maximum signed char"
321 #define D_SCHAR_MIN "Minimum signed char"
322 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
323
324 #define D_INT_MAX "Maximum %s"
325 #define D_INT_MIN "Minimum %s"
326 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
327
328 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
329 #define D_FLT_RADIX "Radix of exponent representation"
330 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
331 #define D_DIG "Number of decimal digits of precision in a %s"
332 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
333 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
334 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
335 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
336 #define D_MAX "Maximum %s"
337 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
338 #define D_MIN "Minimum normalised %s"
339
340 /* Procedure just marks the functions that don't return a result */
341 #ifdef NO_VOID
342 #define Procedure int
343 #else
344 #define Procedure void
345 #endif
346
347 /* Some bad compilers define __STDC__, when they don't support it.
348 Compile with -DNO_STDC to get round this.
349 */
350 #ifndef NO_STDC
351 #ifdef __STDC__
352 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
353 #define STDC
354 #endif
355 #endif
356 #endif
357
358 /* Stuff different for ANSI C, and old C:
359 ARGS and NOARGS are used for function prototypes.
360 Volatile is used to reduce the chance of optimisation,
361 and to prevent variables being put in registers (when setjmp/longjmp
362 wouldn't work as we want)
363 Long_double is the longest floating point type available.
364 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
365 U is output after unsigned constants.
366 */
367 #ifdef STDC
368
369 #define ARGS(x) x
370 #define NOARGS (void)
371 #define Volatile volatile
372 #define Long_double long double
373 #define stdc 1
374 #define U "U"
375
376 #else /* Old style C */
377
378 #define ARGS(x) ()
379 #define NOARGS ()
380 #define Volatile static
381 #define Long_double double
382 #define stdc 0
383 #define U ""
384
385 #endif /* STDC */
386
387 /* include files */
388 #include <stdio.h>
389
390 #ifdef STDC
391 #ifndef NO_STDDEF
392 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
393 #endif
394 #endif
395
396 #ifdef NO_SIG
397 #define jmp_buf int
398 #else
399 #include <sys/types.h>
400 #include <signal.h>
401 #include <setjmp.h>
402 #endif
403
404 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
405 #ifdef CHAR_BIT
406 #undef CHAR_BIT
407 #undef CHAR_MAX
408 #undef CHAR_MIN
409 #undef SCHAR_MAX
410 #undef SCHAR_MIN
411 #undef UCHAR_MAX
412 #undef UCHAR_MIN
413 #endif
414
415 #ifdef VERIFY
416 #include "limits.h"
417 #include "float.h"
418 #endif
419
420 #define Vprintf if (V) printf
421 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
422 #define fabs(x) (((x)<0.0)?(-x):(x))
423
424 #endif /* PASS */
425
426 #ifdef PASS0
427
428 /* Prototypes for what's to come: */
429
430 int false NOARGS;
431
432 #ifdef NO_STDDEF
433 char *malloc (); /* Old style prototype */
434 #else
435 char *malloc ARGS((size_t size));
436 #endif
437
438 Procedure exit ARGS((int status));
439
440 char *f_rep ARGS((int precision, Long_double val));
441 char *fake_f_rep ARGS((char *type, Long_double val));
442
443 int maximum_int NOARGS;
444 int cprop NOARGS;
445 int basic NOARGS;
446 Procedure sprop NOARGS;
447 Procedure iprop NOARGS;
448 Procedure lprop NOARGS;
449 Procedure usprop NOARGS;
450 Procedure uiprop NOARGS;
451 Procedure ulprop NOARGS;
452 int fprop ARGS((int bits_per_byte));
453 int dprop ARGS((int bits_per_byte));
454 int ldprop ARGS((int bits_per_byte));
455 Procedure efprop ARGS((int fprec, int dprec, int lprec));
456 Procedure edprop ARGS((int fprec, int dprec, int lprec));
457 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
458
459 int setmode ARGS((char *s));
460 Procedure farewell ARGS((int bugs));
461 Procedure describe ARGS((char *description, char *extra));
462 Procedure missing ARGS((char *s));
463 Procedure fmissing ARGS((char *s));
464 Procedure check_defines NOARGS;
465 Procedure bitpattern ARGS((char *p, unsigned int size));
466 int ceil_log ARGS((int base, Long_double x));
467 Procedure croak ARGS((int place));
468 Procedure eek_a_bug ARGS((char *problem));
469 Procedure endian ARGS((int bits_per_byte));
470 int exponent ARGS((Long_double x, double *fract, int *exp));
471 int floor_log ARGS((int base, Long_double x));
472 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
473 int prec, Long_double val, char *mark));
474 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
475 long val, long lim, long req, char *mark));
476 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
477 unsigned long val, unsigned long req, char *mark));
478
479 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
480
481 /* Dummy routines instead */
482
483 int setjmp ARGS((int lab));
484
485 int lab=1;
486 int setjmp(lab) int lab; { return(0); }
487 Procedure signal(i, p) int i, (*p)(); {}
488
489 #else
490 jmp_buf lab;
491 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
492 signal(sig, overflow);
493 longjmp(lab, 1);
494 }
495
496 #endif /*NO_SIG*/
497
498 int V= 0, /* verbose */
499 L= 0, /* produce limits.h */
500 F= 0, /* produce float.h */
501 bugs=0; /* The number of (possible) bugs in the output */
502
503 char co[4], oc[4]; /* Comment starter and ender symbols */
504
505 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
506 int flt_rounds; /* The calculated value of FLT_ROUNDS */
507 int flt_radix; /* The calculated value of FLT_RADIX */
508
509 #ifdef TEST
510 /* Set the fp modes on a SUN with 68881 chip, to check that different
511 rounding modes etc. get properly detected.
512 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
513 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
514 register to hex-number
515 */
516
517 /* Bits 0x30 = rounding mode */
518 #define ROUND_BITS 0x30
519 #define TO_NEAREST 0x00
520 #define TO_ZERO 0x10
521 #define TO_MINUS_INF 0x20
522 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
523
524 /* Bits 0xc0 = extended rounding */
525 #define EXT_BITS 0xc0
526 #define ROUND_EXTENDED 0x00
527 #define ROUND_SINGLE 0x40
528 #define ROUND_DOUBLE 0x80
529
530 /* Enabled traps */
531 #define EXE_INEX1 0x100
532 #define EXE_INEX2 0x200
533 #define EXE_DZ 0x400
534 #define EXE_UNFL 0x800
535 #define EXE_OVFL 0x1000
536 #define EXE_OPERR 0x2000
537 #define EXE_SNAN 0x4000
538 #define EXE_BSUN 0x8000
539
540 /* Only used for testing, on a Sun with 68881 chip */
541 /* Print the FP mode */
542 printmode(new) unsigned new; {
543 fpmode_(&new);
544 printf("New fp mode:\n");
545 printf(" Round toward ");
546 switch (new & ROUND_BITS) {
547 case TO_NEAREST: printf("nearest"); break;
548 case TO_ZERO: printf("zero"); break;
549 case TO_MINUS_INF: printf("minus infinity"); break;
550 case TO_PLUS_INF: printf("plus infinity"); break;
551 default: printf("???"); break;
552 }
553
554 printf("\n Extended rounding precision: ");
555
556 switch (new & EXT_BITS) {
557 case ROUND_EXTENDED: printf("extended"); break;
558 case ROUND_SINGLE: printf("single"); break;
559 case ROUND_DOUBLE: printf("double"); break;
560 default: printf("???"); break;
561 }
562
563 printf("\n Enabled exceptions:");
564 if (new & (unsigned) EXE_INEX1) printf(" inex1");
565 if (new & (unsigned) EXE_INEX2) printf(" inex2");
566 if (new & (unsigned) EXE_DZ) printf(" dz");
567 if (new & (unsigned) EXE_UNFL) printf(" unfl");
568 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
569 if (new & (unsigned) EXE_OPERR) printf(" operr");
570 if (new & (unsigned) EXE_SNAN) printf(" snan");
571 if (new & (unsigned) EXE_BSUN) printf(" bsun");
572 printf("\n");
573 }
574
575 /* Only used for testing, on a Sun with 68881 chip */
576 /* Set the FP mode */
577 int setmode(s) char *s; {
578 unsigned mode=0, dig;
579 char c;
580
581 while (*s) {
582 c= *s++;
583 if (c>='0' && c<='9') dig= c-'0';
584 else if (c>='a' && c<='f') dig= c-'a'+10;
585 else if (c>='A' && c<='F') dig= c-'A'+10;
586 else return 1;
587 mode= mode<<4 | dig;
588 }
589 printmode(mode);
590 return 0;
591 }
592 #else
593 /* ARGSUSED */
594 int setmode(s) char *s; {
595 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
596 return(1);
597 }
598 #endif
599
600 Procedure farewell(bugs) int bugs; {
601 if (bugs == 0) exit(0);
602 printf("\n%sFor hints on dealing with the ", co);
603 if (bugs == 1) printf("problem");
604 else printf("%d problems", bugs);
605 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
606 printf("%s%s\n", FILENAME, oc);
607 exit(bugs);
608 }
609
610 /* The program has received a signal where it wasn't expecting one */
611 Procedure croak(place) int place; {
612 printf("*** Unexpected signal at point %d\n", place);
613 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
614 }
615
616 /* This is here in case alloca.c is used, which calls this. */
617 char *xmalloc(size) unsigned size; {
618 char *value = (char *)malloc(size);
619 if (value == 0) {
620 fprintf(stderr, "Virtual memory exceeded\n");
621 exit(bugs+1);
622 }
623 return value;
624 }
625
626 int maxint;
627
628 int maximum_int() {
629 /* Find the maximum integer */
630 Volatile int newi, int_max, two=2;
631
632 /* Calculate maxint ***********************************/
633 /* Calculate 2**n-1 until overflow - then use the previous value */
634
635 newi=1; int_max=0;
636
637 if (setjmp(lab)==0) { /* Yields int_max */
638 while(newi>int_max) {
639 int_max=newi;
640 newi=newi*two+1;
641 }
642 }
643 Unexpected(0);
644 return int_max;
645 }
646
647 int main(argc, argv) int argc; char *argv[]; {
648 int dprec, fprec, lprec;
649 int i; char *s; int bad;
650
651 #ifdef SIGFPE
652 signal(SIGFPE, overflow);
653 #endif
654 #ifdef SIGOVER
655 signal(SIGOVER, overflow);
656 #endif
657 /* Add more calls as necessary */
658
659 Unexpected(1);
660
661 bad=0;
662 for (i=1; i < argc; i++) {
663 s= argv[i];
664 if (*s == '-') {
665 s++;
666 while (*s) {
667 switch (*(s++)) {
668 case 'v': V=1; break;
669 case 'l': L=1; break;
670 case 'f': F=1; break;
671 default: bad=1; break;
672 }
673 }
674 } else if (*s == '+') {
675 s++;
676 bad= setmode(s);
677 } else bad= 1;
678 }
679 if (bad) {
680 fprintf(stderr,
681 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
682 argv[0]);
683 exit(1);
684 }
685 if (L || F) {
686 co[0]= '/'; oc[0]= ' ';
687 co[1]= '*'; oc[1]= '*';
688 co[2]= ' '; oc[2]= '/';
689 co[3]= '\0'; oc[3]= '\0';
690 } else {
691 co[0]= '\0'; oc[0]= '\0';
692 V=1;
693 }
694
695 if (L) printf("%slimits.h%s\n", co, oc);
696 if (F) printf("%sfloat.h%s\n", co, oc);
697 if (F) {
698 printf ("#ifndef _FLOAT_H___\n");
699 printf ("#define _FLOAT_H___\n");
700 }
701 #ifdef ID
702 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
703 co, ID, VERSION, oc);
704 #else
705 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
706 co, VERSION, oc);
707 #endif
708
709 #ifdef VERIFY
710 printf("%sVerification phase%s\n", co, oc);
711 #endif
712
713 #ifdef NO_SIG
714 Vprintf("%sCompiled without signal(): %s%s\n",
715 co,
716 "there's nothing that can be done if overflow occurs",
717 oc);
718 #endif
719 #ifdef NO_SC
720 Vprintf("%sCompiled without signed char%s\n", co, oc);
721 #endif
722 #ifdef NO_UC
723 Vprintf("%Compiled without unsigned char%s\n", co, oc);
724 #endif
725 #ifdef NO_UI
726 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
727 #endif
728 #ifdef __STDC__
729 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
730 co, __STDC__, oc);
731 #else
732 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
733 #endif
734 printf("\n");
735 check_defines();
736
737 maxint= maximum_int();
738 bits_per_byte= basic();
739 Vprintf("\n");
740 if (F||V) {
741 fprec= fprop(bits_per_byte);
742 dprec= dprop(bits_per_byte);
743 lprec= ldprop(bits_per_byte);
744 efprop(fprec, dprec, lprec);
745 edprop(fprec, dprec, lprec);
746 eldprop(fprec, dprec, lprec);
747 }
748 #ifndef NO_MEM
749 if (V) {
750 unsigned int size;
751 long total;
752 /* An extra goody: the approximate amount of data-space */
753 /* Allocate store until no more available */
754 /* Different implementations have a different argument type
755 to malloc. Here we assume that it's the same type as
756 that which sizeof() returns */
757 size=1<<((bits_per_byte*sizeof(int))-2);
758 total=0;
759 while (size!=0) {
760 while ( malloc((false()?sizeof(int):size)) !=
761 (char *)NULL
762 ) {
763 total+=(size/2);
764 }
765 size/=2;
766 }
767
768 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
769 co, (total+511)/512, oc);
770 }
771 #endif
772 if (F) {
773 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
774 }
775 farewell(bugs);
776 return bugs; /* To keep compilers and lint happy */
777 }
778
779 Procedure eek_a_bug(problem) char *problem; {
780 /* The program has discovered a problem */
781 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
782 bugs++;
783 }
784
785 Procedure describe(description, extra) char *description, *extra; {
786 /* Produce the description for a #define */
787 printf(" %s", co);
788 printf(description, extra);
789 printf("%s\n", oc);
790 }
791
792 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
793 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
794 /* Produce a #define for a signed int type */
795 describe(desc, extra);
796 printf("#undef %s%s\n", sort, name);
797 if (val >= 0) {
798 printf("#define %s%s %ld%s\n", sort, name, val, mark);
799 } else if (val + lim < 0) {
800 /* We may not produce a constant like -1024 if the max
801 allowable value is 1023. It has then to be output as
802 -1023-1. lim is the max allowable value. */
803 printf("#define %s%s (%ld%s%ld%s)\n",
804 sort, name, -lim, mark, val+lim, mark);
805 } else {
806 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
807 }
808 /* If VERIFY is not set, val and req are just the same value;
809 if it is set, val is the value as calculated, and req is
810 the #defined constant
811 */
812 if (val != req) {
813 printf("%s*** Verify failed for above #define!\n", co);
814 printf(" Compiler has %ld for value%s\n\n", req, oc);
815 bugs++;
816 }
817 Vprintf("\n");
818 }
819
820 Procedure u_define(desc, extra, sort, name, val, req, mark)
821 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
822 /* Produce a #define for an unsigned value */
823 describe(desc, extra);
824 printf("#undef %s%s\n", sort, name);
825 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
826 if (val != req) {
827 printf("%s*** Verify failed for above #define!\n", co);
828 printf(" Compiler has %lu for value%s\n\n", req, oc);
829 bugs++;
830 }
831 Vprintf("\n");
832 }
833
834 Procedure f_define(desc, extra, sort, name, precision, val, mark)
835 char *desc, *extra, *sort, *name; int precision;
836 Long_double val; char *mark; {
837 /* Produce a #define for a float/double/long double */
838 describe(desc, extra);
839 printf ("#undef %s%s\n", sort, name);
840 if (stdc) {
841 #ifdef NO_LONG_DOUBLE_IO
842 static int union_defined = 0;
843 if (sizeof(double) != sizeof(Long_double)
844 && !strcmp(sort, "LDBL")) {
845 if (!union_defined) {
846 printf("#ifndef __LDBL_UNION__\n");
847 printf("#define __LDBL_UNION__\n");
848 printf("union __convert_long_double {\n");
849 printf(" unsigned __convert_long_double_i[4];\n");
850 printf(" long double __convert_long_double_d;\n");
851 printf("};\n");
852 printf("#endif\n");
853 union_defined = 1;
854 }
855 printf("#define %s%s %s\n",
856 sort, name, fake_f_rep("long double", val));
857 } else {
858 printf("#define %s%s %s%s\n",
859 sort, name, f_rep(precision, val), mark);
860 }
861 #else
862 printf("#define %s%s %s%s\n",
863 sort, name, f_rep(precision, val), mark);
864 #endif
865 } else if (*mark == 'F') {
866 /* non-ANSI C has no float constants, so cast the constant */
867 printf("#define %s%s ((float)%s)\n",
868 sort, name, f_rep(precision, val));
869 } else {
870 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
871 }
872 Vprintf("\n");
873 }
874
875 int floor_log(base, x) int base; Long_double x; {
876 /* return floor(log base(x)) */
877 int r=0;
878 while (x>=base) { r++; x/=base; }
879 return r;
880 }
881
882 int ceil_log(base, x) int base; Long_double x; {
883 int r=0;
884 while (x>1.0) { r++; x/=base; }
885 return r;
886 }
887
888 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
889 /* Split x into a fraction and a power of ten;
890 returns 0 if x is unusable, 1 otherwise.
891 Only used for error messages about faulty output.
892 */
893 int r=0, neg=0;
894 Long_double old;
895 *fract=0.0; *exp=0;
896 if (x<0.0) {
897 x= -x;
898 neg= 1;
899 }
900 if (x==0.0) return 1;
901 if (x>=10.0) {
902 while (x>=10.0) {
903 old=x; r++; x/=10.0;
904 if (old==x) return 0;
905 }
906 } else {
907 while (x<1.0) {
908 old=x; r--; x*=10.0;
909 if (old==x) return 0;
910 }
911 }
912 if (neg) *fract= (double) -x;
913 else *fract=(double) x;
914 *exp=r;
915 return 1;
916 }
917
918 /* Print a value of type TYPE with value VAL,
919 assuming that sprintf can't handle this type properly (without truncation).
920 We create an expression that uses type casting to create the value from
921 a bit pattern. */
922
923 char *fake_f_rep(type, val) char *type; Long_double val; {
924 static char buf[1024];
925 union { unsigned int i[4]; Long_double ld;} u;
926 u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
927 u.ld = val;
928 sprintf(buf, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
929 u.i[0], u.i[1], u.i[2], u.i[3]);
930 return buf;
931 }
932
933 char *f_rep(precision, val) int precision; Long_double val; {
934 /* Return the floating representation of val */
935 static char buf[1024];
936 #ifdef NO_LONG_DOUBLE_IO
937 if (1)
938 #else
939 if (sizeof(double) == sizeof(Long_double))
940 #endif
941 {
942 double d = val;
943 /* Assume they're the same, and use non-stdc format */
944 /* This is for stdc compilers using non-stdc libraries */
945 sprintf(buf, "%.*e", precision, d);
946 } else {
947 /* It had better support Le then */
948 sprintf(buf, "%.*Le", precision, val);
949 }
950 return buf;
951 }
952
953 Procedure bitpattern(p, size) char *p; unsigned int size; {
954 /* Printf the bit-pattern of p */
955 char c;
956 int i, j;
957
958 for (i=1; i<=size; i++) {
959 c= *p;
960 p++;
961 for (j=bits_per_byte-1; j>=0; j--)
962 printf("%c", (c>>j)&1 ? '1' : '0');
963 if (i!=size) printf(" ");
964 }
965 }
966
967 #define Order(x, px, mode)\
968 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
969 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
970 putchar(c==0 ? '?' : (char)c); }\
971 printf("%s\n", oc);
972
973 Procedure endian(bits_per_byte) int bits_per_byte; {
974 /* Printf the byte-order used on this machine */
975 /*unsigned*/ short s=0;
976 /*unsigned*/ int j=0;
977 /*unsigned*/ long l=0;
978
979 char *ps= (char *) &s,
980 *pj= (char *) &j,
981 *pl= (char *) &l,
982 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
983 unsigned int mask, i, c;
984
985 mask=0;
986 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
987
988 if (V) {
989 printf("%sCHARACTER ORDER%s\n", co, oc);
990 Order(s, ps, "short:");
991 Order(j, pj, "int: ");
992 Order(l, pl, "long: ");
993 }
994 }
995
996 Procedure missing(s) char *s; {
997 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
998 bugs++;
999 }
1000
1001 Procedure fmissing(s) char *s; {
1002 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
1003 bugs++;
1004 }
1005
1006 /* To try and fool optimisers */
1007 int false() { return 0; }
1008
1009 #define Promoted(x) (false()?(x):(-1))
1010 #define is_signed(x) (Promoted(x) < 0)
1011 #define sign_of(x) ((x)?"signed":"unsigned")
1012 #define Signed 1
1013 #define Unsigned 0
1014 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1015
1016 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1017
1018 char *type_of(x) int x; {
1019 if (x == sizeof(char)) {
1020 if (sizeof(char) == sizeof(int)) return "char/short/int";
1021 if (sizeof(char) == sizeof(short)) return "char/short";
1022 return "char";
1023 }
1024 if (x == sizeof(short)) {
1025 if (sizeof(short) == sizeof(int)) return "short/int";
1026 return "short";
1027 }
1028 if (x == sizeof(int)) {
1029 if (sizeof(int) == sizeof(long)) return "int/long";
1030 return "int";
1031 }
1032 if (x == sizeof(long)) return "long";
1033 return "unknown-type";
1034 }
1035
1036 char *ftype_of(x) int x; {
1037 if (x == sizeof(float)) {
1038 return "float";
1039 }
1040 if (x == sizeof(double)) {
1041 if (sizeof(double) == sizeof(Long_double))
1042 return "(long)double";
1043 return "double";
1044 }
1045 if (x == sizeof(Long_double)) {
1046 return "long double";
1047 }
1048 return "unknown-type";
1049 }
1050
1051 Procedure typerr(name, esign, esize, sign, size)
1052 char *name; int esign, esize, sign, size;
1053 {
1054 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1055 name, sign_of(esign), type_of(esize),
1056 sign_of(sign), type_of(size));
1057 }
1058
1059 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
1060 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1061 name, ftype_of(esize), ftype_of(size));
1062 }
1063
1064 int promotions() {
1065 int si = 0; long sl = 0;
1066 unsigned int ui; unsigned long ul;
1067 short ss; unsigned short us;
1068
1069 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1070
1071 if (
1072 /* Possible warnings here; no problem */
1073 (sizeof(Promoted(si)) != sizeof(int)) ||
1074 (sizeof(Promoted(sl)) != sizeof(long)) ||
1075 (sizeof(Promoted(ss)) != sizeof(int)) ||
1076 (sizeof(Promoted(ui)) != sizeof(int)) ||
1077 (sizeof(Promoted(ul)) != sizeof(long)) ||
1078 (sizeof(Promoted(us)) != sizeof(int)) ||
1079 is_signed(ui) || is_signed(ul) ||
1080 !is_signed(si) || !is_signed(sl)
1081 )
1082 {
1083 eek_a_bug("promotions don't work properly in conditional expressions\n");
1084 }
1085
1086 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1087 showtype("long+unsigned gives", sl+ui);
1088 return 0;
1089 }
1090
1091 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1092
1093 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1094
1095 Procedure check_defines() {
1096 /* ensure that all #defines are present and have the correct type */
1097 #ifdef VERIFY
1098 int usign;
1099
1100 #ifdef NO_UI
1101 usign= Signed;
1102 #else
1103 /* Implementations promote unsigned short differently */
1104 usign= is_signed((unsigned short)0);
1105 #endif
1106
1107 if (L) {
1108 #ifdef CHAR_BIT
1109 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1110 #else
1111 missing("CHAR_BIT");
1112 #endif
1113 #ifdef CHAR_MAX
1114 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1115 #else
1116 missing("CHAR_MAX");
1117 #endif
1118 #ifdef CHAR_MIN
1119 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1120 #else
1121 missing("CHAR_MIN");
1122 #endif
1123 #ifdef SCHAR_MAX
1124 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1125 #else
1126 missing("SCHAR_MAX");
1127 #endif
1128 #ifdef SCHAR_MIN
1129 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1130 #else
1131 missing("SCHAR_MIN");
1132 #endif
1133 #ifdef UCHAR_MAX
1134 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1135 #else
1136 missing("UCHAR_MAX");
1137 #endif
1138 #ifdef SHRT_MAX
1139 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1140 #else
1141 missing("SHRT_MAX");
1142 #endif
1143 #ifdef SHRT_MIN
1144 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1145 #else
1146 missing("SHRT_MIN");
1147 #endif
1148 #ifdef INT_MAX
1149 checktype(INT_MAX, "INT_MAX", Signed, int);
1150 #else
1151 missing("INT_MAX");
1152 #endif
1153 #ifdef INT_MIN
1154 checktype(INT_MIN, "INT_MIN", Signed, int);
1155 #else
1156 missing("INT_MIN");
1157 #endif
1158 #ifdef LONG_MAX
1159 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1160 #else
1161 missing("LONG_MAX");
1162 #endif
1163 #ifdef LONG_MIN
1164 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1165 #else
1166 missing("LONG_MIN");
1167 #endif
1168 #ifdef USHRT_MAX
1169 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1170 #else
1171 missing("USHRT_MAX");
1172 #endif
1173 #ifdef UINT_MAX
1174 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1175 #else
1176 missing("UINT_MAX");
1177 #endif
1178 #ifdef ULONG_MAX
1179 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1180 #else
1181 missing("ULONG_MAX");
1182 #endif
1183 } /* if (L) */
1184
1185 if (F) {
1186 #ifdef FLT_RADIX
1187 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1188 #else
1189 fmissing("FLT_RADIX");
1190 #endif
1191 #ifdef FLT_MANT_DIG
1192 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1193 #else
1194 fmissing("FLT_MANT_DIG");
1195 #endif
1196 #ifdef FLT_DIG
1197 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1198 #else
1199 fmissing("FLT_DIG");
1200 #endif
1201 #ifdef FLT_ROUNDS
1202 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1203 #else
1204 fmissing("FLT_ROUNDS");
1205 #endif
1206 #ifdef FLT_EPSILON
1207 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1208 #else
1209 fmissing("FLT_EPSILON");
1210 #endif
1211 #ifdef FLT_MIN_EXP
1212 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1213 #else
1214 fmissing("FLT_MIN_EXP");
1215 #endif
1216 #ifdef FLT_MIN
1217 fchecktype(FLT_MIN, "FLT_MIN", float);
1218 #else
1219 fmissing("FLT_MIN");
1220 #endif
1221 #ifdef FLT_MIN_10_EXP
1222 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1223 #else
1224 fmissing("FLT_MIN_10_EXP");
1225 #endif
1226 #ifdef FLT_MAX_EXP
1227 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1228 #else
1229 fmissing("FLT_MAX_EXP");
1230 #endif
1231 #ifdef FLT_MAX
1232 fchecktype(FLT_MAX, "FLT_MAX", float);
1233 #else
1234 fmissing("FLT_MAX");
1235 #endif
1236 #ifdef FLT_MAX_10_EXP
1237 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1238 #else
1239 fmissing("FLT_MAX_10_EXP");
1240 #endif
1241 #ifdef DBL_MANT_DIG
1242 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1243 #else
1244 fmissing("DBL_MANT_DIG");
1245 #endif
1246 #ifdef DBL_DIG
1247 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1248 #else
1249 fmissing("DBL_DIG");
1250 #endif
1251 #ifdef DBL_EPSILON
1252 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1253 #else
1254 fmissing("DBL_EPSILON");
1255 #endif
1256 #ifdef DBL_MIN_EXP
1257 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1258 #else
1259 fmissing("DBL_MIN_EXP");
1260 #endif
1261 #ifdef DBL_MIN
1262 fchecktype(DBL_MIN, "DBL_MIN", double);
1263 #else
1264 fmissing("DBL_MIN");
1265 #endif
1266 #ifdef DBL_MIN_10_EXP
1267 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1268 #else
1269 fmissing("DBL_MIN_10_EXP");
1270 #endif
1271 #ifdef DBL_MAX_EXP
1272 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1273 #else
1274 fmissing("DBL_MAX_EXP");
1275 #endif
1276 #ifdef DBL_MAX
1277 fchecktype(DBL_MAX, "DBL_MAX", double);
1278 #else
1279 fmissing("DBL_MAX");
1280 #endif
1281 #ifdef DBL_MAX_10_EXP
1282 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1283 #else
1284 fmissing("DBL_MAX_10_EXP");
1285 #endif
1286 #ifdef STDC
1287 #ifdef LDBL_MANT_DIG
1288 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1289 #else
1290 fmissing("LDBL_MANT_DIG");
1291 #endif
1292 #ifdef LDBL_DIG
1293 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1294 #else
1295 fmissing("LDBL_DIG");
1296 #endif
1297 #ifdef LDBL_EPSILON
1298 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1299 #else
1300 fmissing("LDBL_EPSILON");
1301 #endif
1302 #ifdef LDBL_MIN_EXP
1303 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1304 #else
1305 fmissing("LDBL_MIN_EXP");
1306 #endif
1307 #ifdef LDBL_MIN
1308 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1309 #else
1310 fmissing("LDBL_MIN");
1311 #endif
1312 #ifdef LDBL_MIN_10_EXP
1313 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1314 #else
1315 fmissing("LDBL_MIN_10_EXP");
1316 #endif
1317 #ifdef LDBL_MAX_EXP
1318 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1319 #else
1320 fmissing("LDBL_MAX_EXP");
1321 #endif
1322 #ifdef LDBL_MAX
1323 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1324 #else
1325 fmissing("LDBL_MAX");
1326 #endif
1327 #ifdef LDBL_MAX_10_EXP
1328 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1329 #else
1330 fmissing("LDBL_MAX_10_EXP");
1331 #endif
1332 #endif /* STDC */
1333 } /* if (F) */
1334 #endif /* VERIFY */
1335 }
1336
1337 #ifdef VERIFY
1338 #ifndef SCHAR_MAX
1339 #define SCHAR_MAX char_max
1340 #endif
1341 #ifndef SCHAR_MIN
1342 #define SCHAR_MIN char_min
1343 #endif
1344 #ifndef UCHAR_MAX
1345 #define UCHAR_MAX char_max
1346 #endif
1347 #endif /* VERIFY */
1348
1349 #ifndef CHAR_BIT
1350 #define CHAR_BIT char_bit
1351 #endif
1352 #ifndef CHAR_MAX
1353 #define CHAR_MAX char_max
1354 #endif
1355 #ifndef CHAR_MIN
1356 #define CHAR_MIN char_min
1357 #endif
1358 #ifndef SCHAR_MAX
1359 #define SCHAR_MAX char_max
1360 #endif
1361 #ifndef SCHAR_MIN
1362 #define SCHAR_MIN char_min
1363 #endif
1364 #ifndef UCHAR_MAX
1365 #define UCHAR_MAX char_max
1366 #endif
1367
1368 int cprop() {
1369 /* Properties of type char */
1370 Volatile char c, char_max, char_min;
1371 Volatile int bits_per_byte, c_signed;
1372 long char_bit;
1373
1374 Unexpected(2);
1375
1376 /* Calculate number of bits per character *************************/
1377 c=1; bits_per_byte=0;
1378 do { c=c<<1; bits_per_byte++; } while(c!=0);
1379 c= (char)(-1);
1380 if (((int)c)<0) c_signed=1;
1381 else c_signed=0;
1382 Vprintf("%schar = %d bits, %ssigned%s\n",
1383 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1384 char_bit=(long)(sizeof(c)*bits_per_byte);
1385 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1386 char_bit, 0L, (long) CHAR_BIT, "");
1387
1388 c=0; char_max=0;
1389 c++;
1390 if (setjmp(lab)==0) { /* Yields char_max */
1391 while (c>char_max) {
1392 char_max=c;
1393 c++;
1394 }
1395 } else {
1396 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1397 }
1398 c=0; char_min=0;
1399 c--;
1400 if (setjmp(lab)==0) { /* Yields char_min */
1401 while (c<char_min) {
1402 char_min=c;
1403 c--;
1404 }
1405 }
1406 if (c_signed && char_min == 0) {
1407 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1408 Vprintf("%s %s%s%s\n",
1409 "They contain only nonnegative values, ",
1410 "but sign extend when used as integers.", co, oc);
1411 }
1412 Unexpected(3);
1413
1414 if (L) {
1415 /* Because of the integer promotions, you must use a U after
1416 the MAX_CHARS in the following cases */
1417 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1418 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1419 (long) char_max,
1420 (long) CHAR_MAX, "");
1421 } else {
1422 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1423 (long) char_max, 0L,
1424 (long) CHAR_MAX, "");
1425 }
1426 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1427 (long) char_min, (long) maxint,
1428 (long) CHAR_MIN, "");
1429 if (c_signed) {
1430 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1431 (long) char_max, 0L,
1432 (long) SCHAR_MAX, "");
1433 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1434 (long) char_min, (long) maxint,
1435 (long) SCHAR_MIN, "");
1436 } else {
1437 if (sizeof(char) == sizeof(int)) {
1438 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1439 (long) char_max,
1440 (long) UCHAR_MAX, "");
1441 } else {
1442 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1443 (long) char_max, 0L,
1444 (long) UCHAR_MAX, "");
1445 }
1446 }
1447
1448 if (c_signed) {
1449 #ifndef NO_UC
1450 Volatile unsigned char c, char_max;
1451 c=0; char_max=0;
1452 c++;
1453 if (setjmp(lab)==0) { /* Yields char_max */
1454 while (c>char_max) {
1455 char_max=c;
1456 c++;
1457 }
1458 }
1459 Unexpected(4);
1460 if (sizeof(char) == sizeof(int)) {
1461 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1462 (long) char_max,
1463 (long) UCHAR_MAX, "");
1464 } else {
1465 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1466 (long) char_max, 0L,
1467 (long) UCHAR_MAX, "");
1468 }
1469 #endif
1470 } else {
1471 #ifndef NO_SC
1472 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1473 c=0; char_max=0;
1474 c++;
1475 if (setjmp(lab)==0) { /* Yields char_max */
1476 while (c>char_max) {
1477 char_max=c;
1478 c++;
1479 }
1480 }
1481 c=0; char_min=0;
1482 c--;
1483 if (setjmp(lab)==0) { /* Yields char_min */
1484 while (c<char_min) {
1485 char_min=c;
1486 c--;
1487 }
1488 }
1489 Unexpected(5);
1490 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1491 (long) char_min, (long) maxint,
1492 (long) SCHAR_MIN, "");
1493 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1494 (long) char_max, 0L,
1495 (long) SCHAR_MAX, "");
1496 #endif /* NO_SC */
1497 }
1498 }
1499 return bits_per_byte;
1500 }
1501
1502 int basic() {
1503 /* The properties of the basic types.
1504 Returns number of bits per sizeof unit */
1505 Volatile int bits_per_byte;
1506 typedef int function ();
1507 int variable;
1508 int *p, *q;
1509
1510 Vprintf("%sSIZES%s\n", co, oc);
1511 bits_per_byte= cprop();
1512
1513 /* Shorts, ints and longs *****************************************/
1514 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1515 co,
1516 (int) sizeof(short)*bits_per_byte,
1517 (int) sizeof(int)*bits_per_byte,
1518 (int) sizeof(long)*bits_per_byte,
1519 (int) sizeof(float)*bits_per_byte,
1520 (int) sizeof(double)*bits_per_byte, oc);
1521 if (stdc) {
1522 Vprintf("%slong double=%d bits%s\n",
1523 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1524 }
1525 Vprintf("%schar*=%d bits%s%s\n",
1526 co, (int)sizeof(char *)*bits_per_byte,
1527 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1528 oc);
1529 Vprintf("%sint* =%d bits%s%s\n",
1530 co, (int)sizeof(int *)*bits_per_byte,
1531 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1532 oc);
1533 Vprintf("%sfunc*=%d bits%s%s\n",
1534 co, (int)sizeof(function *)*bits_per_byte,
1535 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1536 oc);
1537 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1538 ((((false()?( sizeof(int)):(-1)) < 0) )?
1539 "signed":"unsigned") ,
1540 type_of(sizeof(
1541 sizeof(int)+0
1542 )
1543 ),
1544 oc);
1545 showtype("Type size_t is", sizeof(0));
1546
1547 /* Alignment constants ********************************************/
1548
1549 #define alignment(TYPE) \
1550 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1551
1552 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1553
1554 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1555 co,
1556 alignment(char), alignment(short),
1557 alignment(int), alignment(long),
1558 oc);
1559
1560 Vprintf("%sfloat=%ld double=%ld%s\n",
1561 co,
1562 alignment(float), alignment(double),
1563 oc);
1564
1565 if (stdc) {
1566 Vprintf("%slong double=%ld%s\n",
1567 co,
1568 alignment(Long_double),
1569 oc);
1570 }
1571 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1572 co,
1573 alignment(char *), alignment(int *), alignment(function *),
1574 oc);
1575
1576 Vprintf("\n");
1577
1578 /* Ten little endians *********************************************/
1579
1580 endian(bits_per_byte);
1581
1582 /* Pointers *******************************************************/
1583
1584 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1585
1586 if ((long) (char *) &variable == (long) (int *) &variable)
1587 Vprintf("%sChar and int pointer formats seem identical%s\n",
1588 co, oc);
1589 else
1590 Vprintf("%sChar and int pointer formats are different%s\n",
1591 co, oc);
1592 if ((long) (char *) &variable == (long) (function *) &variable)
1593 Vprintf("%sChar and function pointer formats seem identical%s\n",
1594 co, oc);
1595 else
1596 Vprintf("%sChar and function pointer formats are different%s\n",
1597 co, oc);
1598
1599 if (V) {
1600 if ("abcd"=="abcd")
1601 printf("%sStrings are shared%s\n", co, oc);
1602 else printf("%sStrings are not shared%s\n", co, oc);
1603 }
1604
1605 p=0; q=0;
1606 showtype("Type ptrdiff_t is", p-q);
1607
1608 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1609
1610 sprop();
1611 iprop();
1612 lprop();
1613 usprop();
1614 uiprop();
1615 ulprop();
1616
1617 promotions();
1618
1619 Unexpected(6);
1620
1621 return bits_per_byte;
1622 }
1623
1624 #else /* not PASS0 */
1625
1626 #ifdef SEP
1627 extern jmp_buf lab;
1628 extern int V, L, F, bugs, bits_per_byte;
1629 extern char co[], oc[];
1630 extern char *f_rep();
1631 #endif /* SEP */
1632 #endif /* ifdef PASS0 */
1633
1634 /* As I said, I apologise for the contortions below. The functions are
1635 expanded by the preprocessor twice or three times (for float and double,
1636 and maybe for long double, and for short, int and long). That way,
1637 I never make a change to one that I forget to make to the other.
1638 You can look on it as C's fault for not supporting multi-line macro's.
1639 This whole file is read 3 times by the preprocessor, with PASSn set for
1640 n=1, 2 or 3, to decide which parts to reprocess.
1641 */
1642
1643 /* #undef on an already undefined thing is (wrongly) flagged as an error
1644 by some compilers, therefore the #ifdef that follows:
1645 */
1646 #ifdef Number
1647 #undef Number
1648 #undef THING
1649 #undef Thing
1650 #undef thing
1651 #undef FPROP
1652 #undef Fname
1653 #undef Store
1654 #undef Sum
1655 #undef Diff
1656 #undef Mul
1657 #undef Div
1658 #undef ZERO
1659 #undef HALF
1660 #undef ONE
1661 #undef TWO
1662 #undef THREE
1663 #undef FOUR
1664 #undef Self
1665 #undef F_check
1666 #undef Validate
1667 #undef EPROP
1668 #undef MARK
1669
1670 /* These are the float.h constants */
1671 #undef F_RADIX
1672 #undef F_MANT_DIG
1673 #undef F_DIG
1674 #undef F_ROUNDS
1675 #undef F_EPSILON
1676 #undef F_MIN_EXP
1677 #undef F_MIN
1678 #undef F_MIN_10_EXP
1679 #undef F_MAX_EXP
1680 #undef F_MAX
1681 #undef F_MAX_10_EXP
1682 #endif
1683
1684 #ifdef Integer
1685 #undef Integer
1686 #undef INT
1687 #undef IPROP
1688 #undef Iname
1689 #undef UPROP
1690 #undef Uname
1691 #undef OK_UI
1692 #undef IMARK
1693
1694 #undef I_MAX
1695 #undef I_MIN
1696 #undef U_MAX
1697 #endif
1698
1699 #ifdef PASS1
1700
1701 /* Define the things we're going to use this pass */
1702
1703 #define Number float
1704 #define THING "FLOAT"
1705 #define Thing "Float"
1706 #define thing "float"
1707 #define Fname "FLT"
1708 #define FPROP fprop
1709 #define Store fStore
1710 #define Sum fSum
1711 #define Diff fDiff
1712 #define Mul fMul
1713 #define Div fDiv
1714 #define ZERO 0.0
1715 #define HALF 0.5
1716 #define ONE 1.0
1717 #define TWO 2.0
1718 #define THREE 3.0
1719 #define FOUR 4.0
1720 #define Self fSelf
1721 #define F_check fCheck
1722 #define MARK "F"
1723 #ifdef VERIFY
1724 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1725 #endif
1726
1727 #define EPROP efprop
1728
1729 #define Integer short
1730 #define INT "short"
1731 #define IPROP sprop
1732 #define Iname "SHRT"
1733 #ifndef NO_UI
1734 #define OK_UI 1
1735 #endif
1736 #define IMARK ""
1737
1738 #define UPROP usprop
1739 #define Uname "USHRT"
1740
1741 #ifdef VERIFY
1742 #ifdef SHRT_MAX
1743 #define I_MAX SHRT_MAX
1744 #endif
1745 #ifdef SHRT_MIN
1746 #define I_MIN SHRT_MIN
1747 #endif
1748 #ifdef USHRT_MAX
1749 #define U_MAX USHRT_MAX
1750 #endif
1751
1752 #ifdef FLT_RADIX
1753 #define F_RADIX FLT_RADIX
1754 #endif
1755 #ifdef FLT_MANT_DIG
1756 #define F_MANT_DIG FLT_MANT_DIG
1757 #endif
1758 #ifdef FLT_DIG
1759 #define F_DIG FLT_DIG
1760 #endif
1761 #ifdef FLT_ROUNDS
1762 #define F_ROUNDS FLT_ROUNDS
1763 #endif
1764 #ifdef FLT_EPSILON
1765 #define F_EPSILON FLT_EPSILON
1766 #endif
1767 #ifdef FLT_MIN_EXP
1768 #define F_MIN_EXP FLT_MIN_EXP
1769 #endif
1770 #ifdef FLT_MIN
1771 #define F_MIN FLT_MIN
1772 #endif
1773 #ifdef FLT_MIN_10_EXP
1774 #define F_MIN_10_EXP FLT_MIN_10_EXP
1775 #endif
1776 #ifdef FLT_MAX_EXP
1777 #define F_MAX_EXP FLT_MAX_EXP
1778 #endif
1779 #ifdef FLT_MAX
1780 #define F_MAX FLT_MAX
1781 #endif
1782 #ifdef FLT_MAX_10_EXP
1783 #define F_MAX_10_EXP FLT_MAX_10_EXP
1784 #endif
1785 #endif /* VERIFY */
1786
1787 #endif /* PASS1 */
1788
1789 #ifdef PASS2
1790
1791 #define Number double
1792 #define THING "DOUBLE"
1793 #define Thing "Double"
1794 #define thing "double"
1795 #define Fname "DBL"
1796 #define FPROP dprop
1797 #define Store dStore
1798 #define Sum dSum
1799 #define Diff dDiff
1800 #define Mul dMul
1801 #define Div dDiv
1802 #define ZERO 0.0
1803 #define HALF 0.5
1804 #define ONE 1.0
1805 #define TWO 2.0
1806 #define THREE 3.0
1807 #define FOUR 4.0
1808 #define Self dSelf
1809 #define F_check dCheck
1810 #define MARK ""
1811 #ifdef VERIFY
1812 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1813 #endif
1814
1815 #define EPROP edprop
1816
1817 #define Integer int
1818 #define INT "int"
1819 #define IPROP iprop
1820 #define Iname "INT"
1821 #define OK_UI 1 /* Unsigned int is always possible */
1822 #define IMARK ""
1823
1824 #define UPROP uiprop
1825 #define Uname "UINT"
1826
1827 #ifdef VERIFY
1828 #ifdef INT_MAX
1829 #define I_MAX INT_MAX
1830 #endif
1831 #ifdef INT_MIN
1832 #define I_MIN INT_MIN
1833 #endif
1834 #ifdef UINT_MAX
1835 #define U_MAX UINT_MAX
1836 #endif
1837
1838 #ifdef DBL_MANT_DIG
1839 #define F_MANT_DIG DBL_MANT_DIG
1840 #endif
1841 #ifdef DBL_DIG
1842 #define F_DIG DBL_DIG
1843 #endif
1844 #ifdef DBL_EPSILON
1845 #define F_EPSILON DBL_EPSILON
1846 #endif
1847 #ifdef DBL_MIN_EXP
1848 #define F_MIN_EXP DBL_MIN_EXP
1849 #endif
1850 #ifdef DBL_MIN
1851 #define F_MIN DBL_MIN
1852 #endif
1853 #ifdef DBL_MIN_10_EXP
1854 #define F_MIN_10_EXP DBL_MIN_10_EXP
1855 #endif
1856 #ifdef DBL_MAX_EXP
1857 #define F_MAX_EXP DBL_MAX_EXP
1858 #endif
1859 #ifdef DBL_MAX
1860 #define F_MAX DBL_MAX
1861 #endif
1862 #ifdef DBL_MAX_10_EXP
1863 #define F_MAX_10_EXP DBL_MAX_10_EXP
1864 #endif
1865 #endif /* VERIFY */
1866
1867 #endif /* PASS2 */
1868
1869 #ifdef PASS3
1870
1871 #ifdef STDC
1872 #define Number long double
1873
1874 #define ZERO 0.0L
1875 #define HALF 0.5L
1876 #define ONE 1.0L
1877 #define TWO 2.0L
1878 #define THREE 3.0L
1879 #define FOUR 4.0L
1880 #endif
1881
1882 #define THING "LONG DOUBLE"
1883 #define Thing "Long double"
1884 #define thing "long double"
1885 #define Fname "LDBL"
1886 #define FPROP ldprop
1887 #define Store ldStore
1888 #define Sum ldSum
1889 #define Diff ldDiff
1890 #define Mul ldMul
1891 #define Div ldDiv
1892 #define Self ldSelf
1893 #define F_check ldCheck
1894 #define MARK "L"
1895 #ifdef VERIFY
1896 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1897 #endif
1898
1899 #define EPROP eldprop
1900
1901 #define Integer long
1902 #define INT "long"
1903 #define IPROP lprop
1904 #define Iname "LONG"
1905 #ifndef NO_UI
1906 #define OK_UI 1
1907 #endif
1908 #define IMARK "L"
1909
1910 #define UPROP ulprop
1911 #define Uname "ULONG"
1912
1913 #ifdef VERIFY
1914 #ifdef LONG_MAX
1915 #define I_MAX LONG_MAX
1916 #endif
1917 #ifdef LONG_MIN
1918 #define I_MIN LONG_MIN
1919 #endif
1920 #ifdef ULONG_MAX
1921 #define U_MAX ULONG_MAX
1922 #endif
1923
1924 #ifdef LDBL_MANT_DIG
1925 #define F_MANT_DIG LDBL_MANT_DIG
1926 #endif
1927 #ifdef LDBL_DIG
1928 #define F_DIG LDBL_DIG
1929 #endif
1930 #ifdef LDBL_EPSILON
1931 #define F_EPSILON LDBL_EPSILON
1932 #endif
1933 #ifdef LDBL_MIN_EXP
1934 #define F_MIN_EXP LDBL_MIN_EXP
1935 #endif
1936 #ifdef LDBL_MIN
1937 #define F_MIN LDBL_MIN
1938 #endif
1939 #ifdef LDBL_MIN_10_EXP
1940 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1941 #endif
1942 #ifdef LDBL_MAX_EXP
1943 #define F_MAX_EXP LDBL_MAX_EXP
1944 #endif
1945 #ifdef LDBL_MAX
1946 #define F_MAX LDBL_MAX
1947 #endif
1948 #ifdef LDBL_MAX_10_EXP
1949 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1950 #endif
1951 #endif /* VERIFY */
1952
1953 #endif /* PASS3 */
1954
1955 #ifndef I_MAX
1956 #define I_MAX int_max
1957 #endif
1958 #ifndef I_MIN
1959 #define I_MIN int_min
1960 #endif
1961 #ifndef U_MAX
1962 #define U_MAX u_max
1963 #endif
1964
1965 #ifndef F_RADIX
1966 #define F_RADIX f_radix
1967 #endif
1968 #ifndef F_MANT_DIG
1969 #define F_MANT_DIG f_mant_dig
1970 #endif
1971 #ifndef F_DIG
1972 #define F_DIG f_dig
1973 #endif
1974 #ifndef F_ROUNDS
1975 #define F_ROUNDS f_rounds
1976 #endif
1977 #ifndef F_EPSILON
1978 #define F_EPSILON f_epsilon
1979 #endif
1980 #ifndef F_MIN_EXP
1981 #define F_MIN_EXP f_min_exp
1982 #endif
1983 #ifndef F_MIN
1984 #define F_MIN f_min
1985 #endif
1986 #ifndef F_MIN_10_EXP
1987 #define F_MIN_10_EXP f_min_10_exp
1988 #endif
1989 #ifndef F_MAX_EXP
1990 #define F_MAX_EXP f_max_exp
1991 #endif
1992 #ifndef F_MAX
1993 #define F_MAX f_max
1994 #endif
1995 #ifndef F_MAX_10_EXP
1996 #define F_MAX_10_EXP f_max_10_exp
1997 #endif
1998
1999 #ifndef VERIFY
2000 #define Validate(prec, val, req, same) {;}
2001 #endif
2002
2003 #ifdef Integer
2004
2005 Procedure IPROP() {
2006 /* the properties of short, int, and long */
2007 Volatile Integer newi, int_max, maxeri, int_min, minneri;
2008 Volatile int ibits, ipower, two=2;
2009
2010 /* Calculate max short/int/long ***********************************/
2011 /* Calculate 2**n-1 until overflow - then use the previous value */
2012
2013 newi=1; int_max=0;
2014
2015 if (setjmp(lab)==0) { /* Yields int_max */
2016 for(ipower=0; newi>int_max; ipower++) {
2017 int_max=newi;
2018 newi=newi*two+1;
2019 }
2020 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2021 co, INT[0]=='i'?"n":"", INT, oc);
2022 } else {
2023 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2024 co, INT[0]=='i'?"n":"", INT, oc);
2025 }
2026 Unexpected(7);
2027
2028 /* Minimum value: assume either two's or one's complement *********/
2029 int_min= -int_max;
2030 if (setjmp(lab)==0) { /* Yields int_min */
2031 if (int_min-1 < int_min) int_min--;
2032 }
2033 Unexpected(8);
2034
2035 /* Now for those daft Cybers */
2036
2037 maxeri=0; newi=int_max;
2038
2039 if (setjmp(lab)==0) { /* Yields maxeri */
2040 for(ibits=ipower; newi>maxeri; ibits++) {
2041 maxeri=newi;
2042 newi=newi+newi+1;
2043 }
2044 }
2045 Unexpected(9);
2046
2047 minneri= -maxeri;
2048 if (setjmp(lab)==0) { /* Yields minneri */
2049 if (minneri-1 < minneri) minneri--;
2050 }
2051 Unexpected(10);
2052
2053 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2054 co, INT, (long)int_max, ipower, oc);
2055 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
2056
2057 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
2058 (long) int_max, 0L,
2059 (long) I_MAX, IMARK);
2060 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
2061 (long) int_min, (long) (PASS==1?maxint:int_max),
2062 (long) I_MIN, IMARK);
2063
2064 if(int_max < 0) { /* It has happened */
2065 eek_a_bug("signed integral comparison faulty?");
2066 }
2067
2068 if (maxeri>int_max) {
2069 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2070 co, INT, (long)maxeri, ibits,
2071 "but only for addition, not multiplication",
2072 "(I smell a Cyber!)",
2073 oc);
2074 }
2075
2076 if (minneri<int_min) {
2077 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2078 co, INT, (long)minneri,
2079 "but only for addition, not multiplication",
2080 "(I smell a Cyber!)",
2081 oc);
2082 }
2083 }
2084
2085 Procedure UPROP () {
2086 /* The properties of unsigned short/int/long */
2087 #ifdef OK_UI
2088 Volatile unsigned Integer u_max, newi, two;
2089 newi=1; u_max=0; two=2;
2090
2091 if (setjmp(lab)==0) { /* Yields u_max */
2092 while(newi>u_max) {
2093 u_max=newi;
2094 newi=newi*two+1;
2095 }
2096 }
2097 Unexpected(11);
2098 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2099 co, INT, (unsigned long) u_max, oc);
2100
2101 /* Oh woe: new standard C defines value preserving promotions */
2102 if (L) {
2103 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2104 /* Special only for short */
2105 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2106 (unsigned long) u_max, 0L,
2107 (unsigned long) U_MAX, IMARK);
2108 } else {
2109 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2110 (unsigned long) u_max,
2111 (unsigned long) U_MAX, IMARK);
2112 }
2113 }
2114 #endif
2115 }
2116
2117 #endif /* Integer */
2118
2119 #ifdef Number
2120
2121 /* The following routines are intended to defeat any attempt at optimisation
2122 or use of extended precision, and to defeat faulty narrowing casts.
2123 The weird prototypes are because of widening incompatibilities.
2124 */
2125 #ifdef STDC
2126 #define ARGS1(atype, a) (atype a)
2127 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2128 #else
2129 #define ARGS1(atype, a) (a) atype a;
2130 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2131 #endif
2132
2133 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2134 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2135 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2136 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2137 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2138 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2139
2140 Procedure F_check ARGS((int precision, Long_double val1));
2141
2142 Procedure F_check(precision, val1) int precision; Long_double val1; {
2143 /* You don't think I'm going to go to all the trouble of writing
2144 a program that works out what all sorts of values are, only to
2145 have printf go and print the wrong values out, do you?
2146 No, you're right, so this function tries to see if printf
2147 has written the right value, by reading it back again.
2148 This introduces a new problem of course: suppose printf writes
2149 the correct value, and scanf reads it back wrong... oh well.
2150 But I'm adamant about this: the precision given is enough
2151 to uniquely identify the printed number, therefore I insist
2152 that sscanf read the number back identically. Harsh yes, but
2153 sometimes you've got to be cruel to be kind.
2154 */
2155 Number val, new, diff;
2156 double rem;
2157 int e;
2158 char *rep;
2159 char *f2;
2160
2161 #ifdef NO_LONG_DOUBLE_IO
2162 double new1;
2163 /* On the Sun 3, sscanf clobbers 4 words,
2164 which leads to a crash when this function tries to return. */
2165 f2= "%le"; /* Input */
2166 /* It is no use checking long doubles if we can't
2167 read and write them. */
2168 if (sizeof (Number) > sizeof(double))
2169 return;
2170 #else
2171 Long_double new1;
2172 if (sizeof(double) == sizeof(Long_double)) {
2173 /* Assume they're the same, and use non-stdc format */
2174 /* This is for stdc compilers using non-stdc libraries */
2175 f2= "%le"; /* Input */
2176 } else {
2177 /* It had better support Le then */
2178 f2= "%Le";
2179 }
2180 #endif
2181 val= val1;
2182 rep= f_rep(precision, (Long_double) val);
2183 if (setjmp(lab)==0) {
2184 sscanf(rep, f2, &new1);
2185 } else {
2186 eek_a_bug("sscanf caused a trap");
2187 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2188 Unexpected(12);
2189 return;
2190 }
2191
2192 if (setjmp(lab)==0) { /* See if new is usable */
2193 new= new1;
2194 if (new != 0.0) {
2195 diff= val/new - 1.0;
2196 if (diff < 0.1) diff= 1.0;
2197 /* That should be enough to generate a trap */
2198 }
2199 } else {
2200 eek_a_bug("sscanf returned an unusable number");
2201 printf("%s scanning: %s with format: %s%s\n\n",
2202 co, rep, f2, oc);
2203 Unexpected(13);
2204 return;
2205 }
2206
2207 Unexpected(14);
2208 if (new != val) {
2209 eek_a_bug("Possibly bad output from printf above");
2210 if (!exponent((Long_double)val, &rem, &e)) {
2211 printf("%s but value was an unusable number%s\n\n",
2212 co, oc);
2213 return;
2214 }
2215 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2216 co, precision, rem, e);
2217 bitpattern((char *) &val, (unsigned)sizeof(val));
2218 printf ("%s\n", oc);
2219 printf("%s sscanf gave %s, bit pattern:\n ",
2220 co, f_rep(precision, (Long_double) new));
2221 bitpattern((char *) &new, (unsigned)sizeof(new));
2222 printf ("%s\n", oc);
2223 if (setjmp(lab) == 0) {
2224 diff= val-new;
2225 printf("%s difference= %s%s\n\n",
2226 co, f_rep(precision, (Long_double) diff), oc);
2227 } /* else forget it */
2228 Unexpected(15);
2229 }
2230 }
2231
2232 #ifdef VERIFY
2233 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2234 /* Check that the compiler has read a #define value correctly */
2235 Unexpected(16);
2236 if (!same) {
2237 printf("%s*** Verify failed for above #define!\n", co);
2238 if (setjmp(lab) == 0) { /* for the case that req == nan */
2239 printf(" Compiler has %s for value%s\n",
2240 f_rep(prec, req), oc);
2241 } else {
2242 printf(" Compiler has %s for value%s\n",
2243 "an unusable number", oc);
2244 }
2245 if (setjmp(lab) == 0) {
2246 F_check(prec, (Long_double) req);
2247 } /*else forget it*/
2248 if (setjmp(lab) == 0) {
2249 if (req > 0.0 && val > 0.0) {
2250 printf("%s difference= %s%s\n",
2251 co, f_rep(prec, val-req), oc);
2252 }
2253 } /*else forget it*/
2254 Unexpected(17);
2255 printf("\n");
2256 bugs++;
2257 } else if (val != req) {
2258 if (stdc) eek_a_bug("constant has the wrong precision");
2259 else eek_a_bug("the cast didn't work");
2260 printf("\n");
2261 }
2262 }
2263 #endif /* VERIFY */
2264
2265 int FPROP(bits_per_byte) int bits_per_byte; {
2266 /* Properties of floating types, using algorithms by Cody and Waite
2267 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2268 Further extended by S Pemberton.
2269
2270 Returns the number of digits in the fraction.
2271 */
2272
2273 Volatile int
2274 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2275 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2276 mantbits, digs, f_dig, trap,
2277 hidden, normal, f_min_10_exp, f_max_10_exp;
2278 Volatile Number
2279 a, b, base, basein, basem1, f_epsilon, epsneg,
2280 eps, epsp1, etop, ebot,
2281 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2282
2283 Unexpected(18);
2284
2285 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2286
2287 /* Base and size of significand **************************************/
2288 /* First repeatedly double until adding 1 has no effect. */
2289 /* For instance, if base is 10, with 3 significant digits */
2290 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2291 /* since 1024 is only representable as 1020. */
2292 a=1.0;
2293 if (setjmp(lab)==0) { /* inexact trap? */
2294 do { a=Sum(a, a); }
2295 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2296 } else {
2297 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2298 /* And supporting those is just TOO much trouble! */
2299 farewell(bugs+1);
2300 }
2301 Unexpected(19);
2302 /* Now double until you find a number that can be added to the */
2303 /* above number. For 1020 this is 8 or 16, depending whether the */
2304 /* result is rounded or truncated. */
2305 /* In either case the result is 1030. 1030-1020= the base, 10. */
2306 b=1.0;
2307 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2308 f_radix=base;
2309 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2310
2311 /* Sanity check; if base<2, I can't guarantee the rest will work */
2312 if (f_radix < 2) {
2313 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2314 printf("\n");
2315 return(0);
2316 }
2317
2318 if (PASS == 1) { /* only for FLT */
2319 flt_radix= f_radix;
2320 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2321 (long) f_radix, 0L, (long) F_RADIX, "");
2322 } else if (f_radix != flt_radix) {
2323 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2324 co, thing, "arithmetic has a different radix",
2325 f_radix, "from float", oc);
2326 bugs++;
2327 }
2328
2329 /* Now the number of digits precision */
2330 f_mant_dig=0; b=1.0;
2331 do { f_mant_dig++; b=Mul(b, base); }
2332 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2333 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2334 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2335 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2336 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2337 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2338 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2339 (long) f_dig, 0L, (long) F_DIG, "");
2340 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2341
2342 /* Rounding *******************************************************/
2343 basem1=Diff(base, HALF);
2344 if (Diff(Sum(a, basem1), a) != ZERO) {
2345 if (f_radix == 2) basem1=0.375;
2346 else basem1=1.0;
2347 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2348 else irnd=1; /* to nearest */
2349 } else irnd=0; /* towards 0 */
2350
2351 basem1=Diff(base, HALF);
2352
2353 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2354 if (f_radix == 2) basem1=0.375;
2355 else basem1=1.0;
2356 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2357 else mrnd=1; /* to nearest */
2358 } else mrnd=0; /* towards 0 */
2359
2360 f_rounds= -1; /* Unknown rounding */
2361 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2362 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2363 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2364 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2365
2366 if (f_rounds != -1) {
2367 Vprintf("%sArithmetic rounds towards ", co);
2368 switch (f_rounds) {
2369 case 0: Vprintf("zero (i.e. it chops)"); break;
2370 case 1: Vprintf("nearest"); break;
2371 case 2: Vprintf("+infinity"); break;
2372 case 3: Vprintf("-infinity"); break;
2373 default: Vprintf("???"); break;
2374 }
2375 Vprintf("%s\n", oc);
2376 } else { /* Hmm, try to give some help here */
2377 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2378 Vprintf("%s Negative numbers %s%s\n",
2379 co, mrnd==0 ? "towards zero" :
2380 mrnd==1 ? "to nearest" :
2381 "away from zero",
2382 oc);
2383 Vprintf("%s Positive numbers %s%s\n",
2384 co, irnd==0 ? "towards zero" :
2385 irnd==1 ? "to nearest" :
2386 "away from zero",
2387 oc);
2388 }
2389 /* An extra goody */
2390 if (f_radix == 2 && f_rounds == 1) {
2391 if (Diff(Sum(a, ONE), a) != ZERO) {
2392 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2393 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2394 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2395 } else {
2396 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2397 }
2398 }
2399 if (PASS == 1) { /* only for FLT */
2400 flt_rounds= f_rounds;
2401 if (F)
2402 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2403 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2404 } else if (f_rounds != flt_rounds) {
2405 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2406 co, thing, "arithmetic rounds differently",
2407 f_rounds, "from float", oc);
2408 bugs++;
2409 }
2410
2411 /* Various flavours of epsilon ************************************/
2412 negeps=f_mant_dig+f_mant_dig;
2413 basein=1.0/base;
2414 a=1.0;
2415 for(i=1; i<=negeps; i++) a*=basein;
2416
2417 b=a;
2418 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2419 a*=base;
2420 negeps--;
2421 }
2422 negeps= -negeps;
2423 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2424 co, negeps, oc);
2425
2426 etop = ONE;
2427 ebot = ZERO;
2428 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2429 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2430 ebot and etop are the current bounds */
2431 while (eps != ebot && eps != etop) {
2432 epsp1 = Diff(ONE, eps);
2433 if (epsp1 < ONE) etop = eps;
2434 else ebot = eps;
2435 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2436 }
2437 eps= etop;
2438 /* Sanity check */
2439 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2440 eek_a_bug("internal error calculating epsneg");
2441 }
2442 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2443 co, f_rep(digs, (Long_double) eps), oc);
2444 if (V) F_check(digs, (Long_double) eps);
2445
2446 epsneg=a;
2447 if ((f_radix!=2) && irnd) {
2448 /* a=(a*(1.0+a))/(1.0+1.0); => */
2449 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2450 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2451 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2452 }
2453 /* epsneg is used later */
2454 Unexpected(20);
2455
2456 machep= -f_mant_dig-f_mant_dig;
2457 a=b;
2458 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2459 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2460 co, machep, oc);
2461
2462 etop = ONE;
2463 ebot = ZERO;
2464 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2465 /* find the smallest eps (1+eps != 1) by binary search.
2466 ebot and etop are the current bounds */
2467 while (eps != ebot && eps != etop) {
2468 epsp1 = Sum(ONE, eps);
2469 if (epsp1 > ONE) etop = eps;
2470 else ebot = eps;
2471 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2472 }
2473 /* Sanity check */
2474 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2475 eek_a_bug("internal error calculating eps");
2476 }
2477 f_epsilon=etop;
2478
2479 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2480 co, f_rep(digs, (Long_double) f_epsilon), oc);
2481
2482 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2483 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2484 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2485
2486 /* Possible loss of precision warnings here from non-stdc compilers */
2487 if (F) f_define(D_EPSILON, thing,
2488 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2489 if (V || F) F_check(digs, (Long_double) f_epsilon);
2490 Unexpected(21);
2491 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2492 f_epsilon == Self(F_EPSILON));
2493 Unexpected(22);
2494
2495 /* Extra chop info *************************************************/
2496 if (f_rounds == 0) {
2497 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2498 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2499 }
2500 }
2501
2502 /* Size of and minimum normalised exponent ************************/
2503 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2504
2505 /* Coarse search for the largest power of two */
2506 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2507 do {
2508 y=z; y1=z1;
2509 z=Mul(y,y); z1=Mul(z1, y);
2510 a=Mul(z,ONE);
2511 z2=Div(z1,y);
2512 if (z2 != y1) break;
2513 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2514 i++;
2515 k+=k;
2516 } while(1);
2517 } else {
2518 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2519 }
2520 Unexpected(23);
2521
2522 if (f_radix != 10) {
2523 iexp=i+1; /* for the sign */
2524 mx=k+k;
2525 } else {
2526 iexp=2;
2527 iz=f_radix;
2528 while (k >= iz) { iz*=f_radix; iexp++; }
2529 mx=iz+iz-1;
2530 }
2531
2532 /* Fine tune starting with y and y1 */
2533 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2534 do {
2535 f_min=y; z1=y1;
2536 y=Div(y,base); y1=Div(y1,base);
2537 a=Mul(y,ONE);
2538 z2=Mul(y1,base);
2539 if (z2 != z1) break;
2540 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2541 k++;
2542 } while (1);
2543 }
2544 Unexpected(24);
2545
2546 f_min_exp=(-k)+1;
2547
2548 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2549 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2550 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2551 if (F)
2552 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2553 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2554
2555 if (setjmp(lab)==0) {
2556 Vprintf("%sMinimum normalised positive number = %s%s\n",
2557 co, f_rep(digs, (Long_double) f_min), oc);
2558 } else {
2559 eek_a_bug("printf can't print the smallest normalised number");
2560 printf("\n");
2561 }
2562 Unexpected(25);
2563 /* Possible loss of precision warnings here from non-stdc compilers */
2564 if (setjmp(lab) == 0) {
2565 if (F) f_define(D_MIN, thing,
2566 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2567 if (V || F) F_check(digs, (Long_double) f_min);
2568 } else {
2569 eek_a_bug("xxx_MIN caused a trap");
2570 printf("\n");
2571 }
2572
2573 if (setjmp(lab) == 0) {
2574 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2575 f_min == Self(F_MIN));
2576 } else {
2577 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2578 co, "Compiler has an unusable number for value", oc);
2579 bugs++;
2580 }
2581 Unexpected(26);
2582
2583 a=1.0; f_min_10_exp=0;
2584 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2585 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2586 (long) f_min_10_exp, (long) maxint,
2587 (long) F_MIN_10_EXP, "");
2588
2589 /* Minimum exponent ************************************************/
2590 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2591 do {
2592 xminner=y;
2593 y=Div(y,base);
2594 a=Mul(y,ONE);
2595 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2596 } while (1);
2597 }
2598 Unexpected(27);
2599
2600 if (xminner != 0.0 && xminner != f_min) {
2601 normal= 0;
2602 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2603 co, oc);
2604 if (setjmp(lab)==0) {
2605 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2606 co, f_rep(digs, (Long_double) xminner), oc);
2607 if (V) F_check(digs, (Long_double) xminner);
2608 } else {
2609 eek_a_bug("printf can't print the smallest unnormalised number.");
2610 printf("\n");
2611 }
2612 Unexpected(28);
2613 } else {
2614 normal= 1;
2615 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2616 }
2617
2618 /* Maximum exponent ************************************************/
2619 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2620 inf=0; trap=0;
2621 while (f_max<newxmax) {
2622 f_max=newxmax;
2623 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2624 newxmax=Mul(newxmax, base);
2625 } else {
2626 trap=1;
2627 break;
2628 }
2629 if (Div(newxmax, base) != f_max) {
2630 inf=1; /* ieee infinity */
2631 break;
2632 }
2633 f_max_exp++;
2634 }
2635 Unexpected(29);
2636 if (trap) {
2637 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2638 }
2639
2640 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2641 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2642 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2643 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2644
2645 /* Largest number ***************************************************/
2646 f_max=Diff(ONE, epsneg);
2647 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2648 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2649
2650 if (setjmp(lab)==0) {
2651 Vprintf("%sMaximum number = %s%s\n",
2652 co, f_rep(digs, (Long_double) f_max), oc);
2653 } else {
2654 eek_a_bug("printf can't print the largest double.");
2655 printf("\n");
2656 }
2657 if (setjmp(lab)==0) {
2658 /* Possible loss of precision warnings here from non-stdc compilers */
2659 if (F) f_define(D_MAX, thing,
2660 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2661 if (V || F) F_check(digs, (Long_double) f_max);
2662 } else {
2663 eek_a_bug("xxx_MAX caused a trap");
2664 printf("\n");
2665 }
2666 if (setjmp(lab)==0) {
2667 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2668 f_max == Self(F_MAX));
2669 } else {
2670 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2671 co, "Compiler has an unusable number for value", oc);
2672 bugs++;
2673 }
2674 Unexpected(30);
2675
2676 a=1.0; f_max_10_exp=0;
2677 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2678 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2679 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2680
2681 /* Hidden bit + sanity check ****************************************/
2682 if (f_radix != 10) {
2683 hidden=0;
2684 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2685 if (mantbits == 64
2686 && iexp == 15
2687 && f_max_exp+f_min_exp > 0 /* ??? f_min_exp may be wrong. */
2688 && mantbits+iexp+17 == (int)sizeof(Number)*bits_per_byte) {
2689 Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co, oc);
2690 Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co, oc);
2691 goto is_extended;
2692 }
2693 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2694 hidden=1;
2695 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2696 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2697 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2698 co, oc);
2699 } else {
2700 printf("\n%s%s\n %s %s %s!%s\n\n",
2701 co,
2702 "*** Something fishy here!",
2703 "Exponent size + significand size doesn't match",
2704 "with the size of a", thing,
2705 oc);
2706 }
2707 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2708 Vprintf("%sIt looks like %s length IEEE format%s\n",
2709 co, f_mant_dig==24 ? "single" :
2710 f_mant_dig==53 ? "double" :
2711 f_mant_dig >53 ? "extended" :
2712 "some", oc);
2713 is_extended:
2714 if (f_rounds != 1 || normal) {
2715 Vprintf("%s though ", co);
2716 if (f_rounds != 1) {
2717 Vprintf("the rounding is unusual");
2718 if (normal) Vprintf(" and ");
2719 }
2720 if (normal) Vprintf("the normalisation is unusual");
2721 Vprintf("%s\n", oc);
2722 }
2723 } else {
2724 Vprintf("%sIt doesn't look like IEEE format%s\n",
2725 co, oc);
2726 }
2727 }
2728 printf("\n"); /* regardless of verbosity */
2729 return f_mant_dig;
2730 }
2731
2732 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2733 /* See if expressions are evaluated in extended precision.
2734 Some compilers optimise even if you don't want it,
2735 and then this function fails to produce the right result.
2736 We try to diagnose this if it happens.
2737 */
2738 Volatile int eprec;
2739 Volatile double a, b, base, old;
2740 Volatile Number d, oldd, dbase, one, zero;
2741 Volatile int bad=0;
2742
2743 /* Size of significand **************************************/
2744 a=1.0;
2745 if (setjmp(lab) == 0) { /* Yields nothing */
2746 do { old=a; a=a+a; }
2747 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2748 } else bad=1;
2749
2750 /* Avoid the comparison if bad is set,
2751 to avoid trouble on the convex. */
2752 if (!bad && (a <= old)) bad=1;
2753
2754 if (!bad) {
2755 b=1.0;
2756 if (setjmp(lab) == 0) { /* Yields nothing */
2757 do { old=b; b=b+b; }
2758 while ((base=((a+b)-a)) == 0.0 && b>old);
2759 if (b <= old) bad=1;
2760 } else bad=1;
2761 }
2762
2763 if (!bad) {
2764 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2765 if (setjmp(lab) == 0) { /* Yields nothing */
2766 do { eprec++; oldd=d; d=d*dbase; }
2767 while ((((d+one)-d)-one) == zero && d>oldd);
2768 if (d <= oldd) bad=1;
2769 } else bad=1;
2770 }
2771
2772 Unexpected(31);
2773
2774 if (bad) {
2775 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2776 co, thing, " check that you compiled without optimisation!",
2777 oc);
2778 } else if (eprec==dprec) {
2779 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2780 co, Thing, oc);
2781 } else if (eprec==fprec) {
2782 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2783 co, Thing, oc);
2784 } else if (eprec==lprec) {
2785 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2786 co, Thing, oc);
2787 } else {
2788 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2789 co, Thing, eprec>dprec ? "higher" : "lower",
2790 "precision than double,\n using",
2791 eprec, "base digits",
2792 oc);
2793 }
2794 }
2795
2796 #else /* not Number */
2797
2798 #ifdef FPROP /* Then create dummy routines for long double */
2799 /* ARGSUSED */
2800 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2801 #endif
2802 #ifdef EPROP
2803 /* ARGSUSED */
2804 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2805 #endif
2806
2807 #endif /* ifdef Number */
2808
2809 /* Increment the pass number */
2810 #undef PASS
2811
2812 #ifdef PASS2
2813 #undef PASS2
2814 #define PASS 3
2815 #define PASS3 1
2816 #endif
2817
2818 #ifdef PASS1
2819 #undef PASS1
2820 #define PASS 2
2821 #define PASS2 1
2822 #endif
2823
2824 #ifdef PASS0
2825 #undef PASS0
2826 #endif
2827
2828 #ifdef PASS /* then rescan this file */
2829 #ifdef NO_FILE
2830 #include "enquire.c"
2831 #else
2832 #include FILENAME /* if this line fails to compile, define NO_FILE */
2833 #endif
2834 #endif /* PASS */
2835
This page took 0.17068 seconds and 6 git commands to generate.