1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9 Bugfixes and upgrades gratefully received.
11 Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
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.
23 Add #undef before every #define, Jim Wilson, Dec 92.
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.
32 Changes by Stephen Moshier, installed Sep 93:
33 (FPROP): Recognize 80387 or 68881 XFmode format.
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.
41 If your compiler doesn't support: add flag:
42 signed char (eg pcc) -DNO_SC
44 unsigned short and long -DNO_UI
46 signal(), or setjmp/longjmp() -DNO_SIG
47 %Lf in printf -DNO_LONG_DOUBLE_IO
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.
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.
57 Some compilers offer various flags for different floating point
58 modes; it's worth trying all possible combinations of these.
60 Add -DID=\"name\" if you want the machine/flags identified in the output.
63 Because of bugs and/or inadequacies, some compilers need the following
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\" .
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.
73 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
74 or -DNO_FILE as above.
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).
81 Some naughty compilers define __STDC__, but don't have the stddef.h
82 include file. Add flag -DNO_STDDEF.
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
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.
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
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!).
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.
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.
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.
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
143 The program only works if overflows are ignored by the C system or
144 are catchable with signal().
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.
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).
155 Make sure you compiled with optimisation turned off.
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.
181 The warning that "a cast didn't work" refers to cases like this:
184 #define C 1.234567890123456789
186 if (f != (float) C) printf ("Wrong!");
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
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.
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.
210 I apologise unreservedly for the contorted use of the preprocessor...
213 You may copy and distribute verbatim copies of this source file.
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.
224 If you do have a fix to any problem, please send it to me, so that
225 other people can have the benefits.
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.
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.
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.
241 Originally started as a program to generate configuration constants
242 for a large piece of software we were writing, which later took on
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
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
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
264 Added check for pseudo-unsigned chars
265 Added description for each #define output
266 Added check for absence of defines during verify
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
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
295 /* Set FILENAME to the name of this file */
298 #define FILENAME "enquire.c"
300 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
301 #define FILENAME __FILE__
303 #define FILENAME "enquire.c"
304 #endif /* __FILE__ */
306 #endif /* FILENAME */
308 /* If PASS isn't defined, then this is the first pass over this file. */
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)"
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)"
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"
340 /* Procedure just marks the functions that don't return a result */
342 #define Procedure int
344 #define Procedure void
347 /* Some bad compilers define __STDC__, when they don't support it.
348 Compile with -DNO_STDC to get round this.
352 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
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.
370 #define NOARGS (void)
371 #define Volatile volatile
372 #define Long_double long double
376 #else /* Old style C */
380 #define Volatile static
381 #define Long_double double
392 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
399 #include <sys/types.h>
404 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
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))
428 /* Prototypes for what's to come: */
433 char *malloc (); /* Old style prototype */
435 char *malloc ARGS((size_t size));
438 Procedure exit ARGS((int status));
440 char *f_rep ARGS((int precision, Long_double val));
441 char *fake_f_rep ARGS((char *type, Long_double val));
443 int maximum_int 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));
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));
479 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
481 /* Dummy routines instead */
483 int setjmp ARGS((int lab));
486 int setjmp(lab) int lab; { return(0); }
487 Procedure signal(i, p) int i, (*p)(); {}
491 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
492 signal(sig, overflow);
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 */
503 char co[4], oc[4]; /* Comment starter and ender symbols */
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 */
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
517 /* Bits 0x30 = rounding mode */
518 #define ROUND_BITS 0x30
519 #define TO_NEAREST 0x00
521 #define TO_MINUS_INF 0x20
522 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
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
531 #define EXE_INEX1 0x100
532 #define EXE_INEX2 0x200
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
540 /* Only used for testing, on a Sun with 68881 chip */
541 /* Print the FP mode */
542 printmode(new) unsigned 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;
554 printf("\n Extended rounding precision: ");
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;
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");
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;
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;
594 int setmode(s) char *s; {
595 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
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);
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 */
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);
620 fprintf(stderr, "Virtual memory exceeded\n");
629 /* Find the maximum integer */
630 Volatile int newi, int_max, two=2;
632 /* Calculate maxint ***********************************/
633 /* Calculate 2**n-1 until overflow - then use the previous value */
637 if (setjmp(lab)==0) { /* Yields int_max */
638 while(newi>int_max) {
647 int main(argc, argv) int argc; char *argv[]; {
648 int dprec, fprec, lprec;
651 int i; char *s; int bad;
654 signal(SIGFPE, overflow);
657 signal(SIGOVER, overflow);
659 /* Add more calls as necessary */
664 for (i=1; i < argc; i++) {
670 case 'v': V=1; break;
671 case 'l': L=1; break;
672 case 'f': F=1; break;
673 default: bad=1; break;
676 } else if (*s == '+') {
683 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
688 co[0]= '/'; oc[0]= ' ';
689 co[1]= '*'; oc[1]= '*';
690 co[2]= ' '; oc[2]= '/';
691 co[3]= '\0'; oc[3]= '\0';
693 co[0]= '\0'; oc[0]= '\0';
697 if (L) printf("%slimits.h%s\n", co, oc);
698 if (F) printf("%sfloat.h%s\n", co, oc);
700 printf ("#ifndef _FLOAT_H___\n");
701 printf ("#define _FLOAT_H___\n");
704 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
705 co, ID, VERSION, oc);
707 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
712 printf("%sVerification phase%s\n", co, oc);
716 Vprintf("%sCompiled without signal(): %s%s\n",
718 "there's nothing that can be done if overflow occurs",
722 Vprintf("%sCompiled without signed char%s\n", co, oc);
725 Vprintf("%Compiled without unsigned char%s\n", co, oc);
728 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
731 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
734 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
739 maxint= maximum_int();
740 bits_per_byte= basic();
743 fprec= fprop(bits_per_byte);
744 dprec= dprop(bits_per_byte);
745 lprec= ldprop(bits_per_byte);
746 efprop(fprec, dprec, lprec);
747 edprop(fprec, dprec, lprec);
748 eldprop(fprec, dprec, lprec);
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);
760 while ( malloc((false()?sizeof(int):size)) !=
768 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
769 co, (total+511)/512, oc);
773 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
776 return bugs; /* To keep compilers and lint happy */
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);
785 Procedure describe(description, extra) char *description, *extra; {
786 /* Produce the description for a #define */
788 printf(description, extra);
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);
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);
806 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
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
813 printf("%s*** Verify failed for above #define!\n", co);
814 printf(" Compiler has %ld for value%s\n\n", req, oc);
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);
827 printf("%s*** Verify failed for above #define!\n", co);
828 printf(" Compiler has %lu for value%s\n\n", req, oc);
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);
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");
855 printf("#define %s%s %s\n",
856 sort, name, fake_f_rep("long double", val));
858 printf("#define %s%s %s%s\n",
859 sort, name, f_rep(precision, val), mark);
862 printf("#define %s%s %s%s\n",
863 sort, name, f_rep(precision, val), mark);
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));
870 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
875 int floor_log(base, x) int base; Long_double x; {
876 /* return floor(log base(x)) */
878 while (x>=base) { r++; x/=base; }
882 int ceil_log(base, x) int base; Long_double x; {
884 while (x>1.0) { r++; x/=base; }
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.
900 if (x==0.0) return 1;
904 if (old==x) return 0;
909 if (old==x) return 0;
912 if (neg) *fract= (double) -x;
913 else *fract=(double) x;
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
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;
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]);
933 char *f_rep(precision, val) int precision; Long_double val; {
934 /* Return the floating representation of val */
935 static char buf[1024];
937 #ifdef NO_LONG_DOUBLE_IO
940 if (sizeof(double) == sizeof(Long_double))
944 /* Assume they're the same, and use non-stdc format */
945 /* This is for stdc compilers using non-stdc libraries */
946 sprintf(buf, "%.*e", precision, d);
948 /* It had better support Le then */
949 sprintf(buf, "%.*Le", precision, val);
954 Procedure bitpattern(p, size) char *p; unsigned int size; {
955 /* Printf the bit-pattern of p */
959 for (i=1; i<=size; i++) {
962 for (j=bits_per_byte-1; j>=0; j--)
963 printf("%c", (c>>j)&1 ? '1' : '0');
964 if (i!=size) printf(" ");
968 #define Order(x, px, mode)\
969 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
970 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
971 putchar(c==0 ? '?' : (char)c); }\
974 Procedure endian(bits_per_byte) int bits_per_byte; {
975 /* Printf the byte-order used on this machine */
976 /*unsigned*/ short s=0;
977 /*unsigned*/ int j=0;
978 /*unsigned*/ long l=0;
980 char *ps= (char *) &s,
983 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
984 unsigned int mask, i, c;
987 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
990 printf("%sCHARACTER ORDER%s\n", co, oc);
991 Order(s, ps, "short:");
992 Order(j, pj, "int: ");
993 Order(l, pl, "long: ");
997 Procedure missing(s) char *s; {
998 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
1002 Procedure fmissing(s) char *s; {
1003 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
1007 /* To try and fool optimisers */
1008 int false() { return 0; }
1010 #define Promoted(x) (false()?(x):(-1))
1011 #define is_signed(x) (Promoted(x) < 0)
1012 #define sign_of(x) ((x)?"signed":"unsigned")
1015 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1017 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1019 char *type_of(x) int x; {
1020 if (x == sizeof(char)) {
1021 if (sizeof(char) == sizeof(int)) return "char/short/int";
1022 if (sizeof(char) == sizeof(short)) return "char/short";
1025 if (x == sizeof(short)) {
1026 if (sizeof(short) == sizeof(int)) return "short/int";
1029 if (x == sizeof(int)) {
1030 if (sizeof(int) == sizeof(long)) return "int/long";
1033 if (x == sizeof(long)) return "long";
1034 return "unknown-type";
1037 char *ftype_of(x) int x; {
1038 if (x == sizeof(float)) {
1041 if (x == sizeof(double)) {
1042 if (sizeof(double) == sizeof(Long_double))
1043 return "(long)double";
1046 if (x == sizeof(Long_double)) {
1047 return "long double";
1049 return "unknown-type";
1052 Procedure typerr(name, esign, esize, sign, size)
1053 char *name; int esign, esize, sign, size;
1055 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1056 name, sign_of(esign), type_of(esize),
1057 sign_of(sign), type_of(size));
1060 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
1061 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1062 name, ftype_of(esize), ftype_of(size));
1067 unsigned int ui; unsigned long ul;
1068 short ss; unsigned short us;
1070 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1073 /* Possible warnings here; no problem */
1074 (sizeof(Promoted(si)) != sizeof(int)) ||
1075 (sizeof(Promoted(sl)) != sizeof(long)) ||
1076 (sizeof(Promoted(ss)) != sizeof(int)) ||
1077 (sizeof(Promoted(ui)) != sizeof(int)) ||
1078 (sizeof(Promoted(ul)) != sizeof(long)) ||
1079 (sizeof(Promoted(us)) != sizeof(int)) ||
1080 is_signed(ui) || is_signed(ul) ||
1081 !is_signed(si) || !is_signed(sl)
1084 eek_a_bug("promotions don't work properly in conditional expressions\n");
1087 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1088 showtype("long+unsigned gives", sl+ui);
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));
1093 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1095 Procedure check_defines() {
1096 /* ensure that all #defines are present and have the correct type */
1103 /* Implementations promote unsigned short differently */
1104 usign= is_signed((unsigned short)0);
1109 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1111 missing("CHAR_BIT");
1114 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1116 missing("CHAR_MAX");
1119 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1121 missing("CHAR_MIN");
1124 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1126 missing("SCHAR_MAX");
1129 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1131 missing("SCHAR_MIN");
1134 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1136 missing("UCHAR_MAX");
1139 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1141 missing("SHRT_MAX");
1144 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1146 missing("SHRT_MIN");
1149 checktype(INT_MAX, "INT_MAX", Signed, int);
1154 checktype(INT_MIN, "INT_MIN", Signed, int);
1159 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1161 missing("LONG_MAX");
1164 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1166 missing("LONG_MIN");
1169 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1171 missing("USHRT_MAX");
1174 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1176 missing("UINT_MAX");
1179 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1181 missing("ULONG_MAX");
1187 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1189 fmissing("FLT_RADIX");
1192 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1194 fmissing("FLT_MANT_DIG");
1197 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1199 fmissing("FLT_DIG");
1202 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1204 fmissing("FLT_ROUNDS");
1207 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1209 fmissing("FLT_EPSILON");
1212 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1214 fmissing("FLT_MIN_EXP");
1217 fchecktype(FLT_MIN, "FLT_MIN", float);
1219 fmissing("FLT_MIN");
1221 #ifdef FLT_MIN_10_EXP
1222 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1224 fmissing("FLT_MIN_10_EXP");
1227 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1229 fmissing("FLT_MAX_EXP");
1232 fchecktype(FLT_MAX, "FLT_MAX", float);
1234 fmissing("FLT_MAX");
1236 #ifdef FLT_MAX_10_EXP
1237 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1239 fmissing("FLT_MAX_10_EXP");
1242 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1244 fmissing("DBL_MANT_DIG");
1247 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1249 fmissing("DBL_DIG");
1252 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1254 fmissing("DBL_EPSILON");
1257 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1259 fmissing("DBL_MIN_EXP");
1262 fchecktype(DBL_MIN, "DBL_MIN", double);
1264 fmissing("DBL_MIN");
1266 #ifdef DBL_MIN_10_EXP
1267 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1269 fmissing("DBL_MIN_10_EXP");
1272 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1274 fmissing("DBL_MAX_EXP");
1277 fchecktype(DBL_MAX, "DBL_MAX", double);
1279 fmissing("DBL_MAX");
1281 #ifdef DBL_MAX_10_EXP
1282 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1284 fmissing("DBL_MAX_10_EXP");
1287 #ifdef LDBL_MANT_DIG
1288 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1290 fmissing("LDBL_MANT_DIG");
1293 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1295 fmissing("LDBL_DIG");
1298 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1300 fmissing("LDBL_EPSILON");
1303 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1305 fmissing("LDBL_MIN_EXP");
1308 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1310 fmissing("LDBL_MIN");
1312 #ifdef LDBL_MIN_10_EXP
1313 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1315 fmissing("LDBL_MIN_10_EXP");
1318 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1320 fmissing("LDBL_MAX_EXP");
1323 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1325 fmissing("LDBL_MAX");
1327 #ifdef LDBL_MAX_10_EXP
1328 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1330 fmissing("LDBL_MAX_10_EXP");
1339 #define SCHAR_MAX char_max
1342 #define SCHAR_MIN char_min
1345 #define UCHAR_MAX char_max
1350 #define CHAR_BIT char_bit
1353 #define CHAR_MAX char_max
1356 #define CHAR_MIN char_min
1359 #define SCHAR_MAX char_max
1362 #define SCHAR_MIN char_min
1365 #define UCHAR_MAX char_max
1369 /* Properties of type char */
1370 Volatile char c, char_max, char_min;
1371 Volatile int bits_per_byte, c_signed;
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);
1380 if (((int)c)<0) c_signed=1;
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, "");
1390 if (setjmp(lab)==0) { /* Yields char_max */
1391 while (c>char_max) {
1396 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1400 if (setjmp(lab)==0) { /* Yields char_min */
1401 while (c<char_min) {
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);
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",
1420 (long) CHAR_MAX, "");
1422 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1423 (long) char_max, 0L,
1424 (long) CHAR_MAX, "");
1426 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1427 (long) char_min, (long) maxint,
1428 (long) CHAR_MIN, "");
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, "");
1437 if (sizeof(char) == sizeof(int)) {
1438 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1440 (long) UCHAR_MAX, "");
1442 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1443 (long) char_max, 0L,
1444 (long) UCHAR_MAX, "");
1450 Volatile unsigned char c, char_max;
1453 if (setjmp(lab)==0) { /* Yields char_max */
1454 while (c>char_max) {
1460 if (sizeof(char) == sizeof(int)) {
1461 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1463 (long) UCHAR_MAX, "");
1465 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1466 (long) char_max, 0L,
1467 (long) UCHAR_MAX, "");
1472 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1475 if (setjmp(lab)==0) { /* Yields char_max */
1476 while (c>char_max) {
1483 if (setjmp(lab)==0) { /* Yields char_min */
1484 while (c<char_min) {
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, "");
1499 return bits_per_byte;
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 ();
1510 Vprintf("%sSIZES%s\n", co, oc);
1511 bits_per_byte= cprop();
1513 /* Shorts, ints and longs *****************************************/
1514 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
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);
1522 Vprintf("%slong double=%d bits%s\n",
1523 co, (int) sizeof(Long_double)*bits_per_byte, oc);
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!":"",
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!":"",
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!":"",
1537 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1538 ((((false()?( sizeof(int)):(-1)) < 0) )?
1539 "signed":"unsigned") ,
1545 showtype("Type size_t is", sizeof(0));
1547 /* Alignment constants ********************************************/
1549 #define alignment(TYPE) \
1550 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1552 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1554 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1556 alignment(char), alignment(short),
1557 alignment(int), alignment(long),
1560 Vprintf("%sfloat=%ld double=%ld%s\n",
1562 alignment(float), alignment(double),
1566 Vprintf("%slong double=%ld%s\n",
1568 alignment(Long_double),
1571 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1573 alignment(char *), alignment(int *), alignment(function *),
1578 /* Ten little endians *********************************************/
1580 endian(bits_per_byte);
1582 /* Pointers *******************************************************/
1584 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1586 if ((long) (char *) &variable == (long) (int *) &variable)
1587 Vprintf("%sChar and int pointer formats seem identical%s\n",
1590 Vprintf("%sChar and int pointer formats are different%s\n",
1592 if ((long) (char *) &variable == (long) (function *) &variable)
1593 Vprintf("%sChar and function pointer formats seem identical%s\n",
1596 Vprintf("%sChar and function pointer formats are different%s\n",
1601 printf("%sStrings are shared%s\n", co, oc);
1602 else printf("%sStrings are not shared%s\n", co, oc);
1606 showtype("Type ptrdiff_t is", p-q);
1608 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1621 return bits_per_byte;
1624 #else /* not PASS0 */
1628 extern int V, L, F, bugs, bits_per_byte;
1629 extern char co[], oc[];
1630 extern char *f_rep();
1632 #endif /* ifdef PASS0 */
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.
1643 /* #undef on an already undefined thing is (wrongly) flagged as an error
1644 by some compilers, therefore the #ifdef that follows:
1670 /* These are the float.h constants */
1701 /* Define the things we're going to use this pass */
1703 #define Number float
1704 #define THING "FLOAT"
1705 #define Thing "Float"
1706 #define thing "float"
1709 #define Store fStore
1721 #define F_check fCheck
1724 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1727 #define EPROP efprop
1729 #define Integer short
1732 #define Iname "SHRT"
1738 #define UPROP usprop
1739 #define Uname "USHRT"
1743 #define I_MAX SHRT_MAX
1746 #define I_MIN SHRT_MIN
1749 #define U_MAX USHRT_MAX
1753 #define F_RADIX FLT_RADIX
1756 #define F_MANT_DIG FLT_MANT_DIG
1759 #define F_DIG FLT_DIG
1762 #define F_ROUNDS FLT_ROUNDS
1765 #define F_EPSILON FLT_EPSILON
1768 #define F_MIN_EXP FLT_MIN_EXP
1771 #define F_MIN FLT_MIN
1773 #ifdef FLT_MIN_10_EXP
1774 #define F_MIN_10_EXP FLT_MIN_10_EXP
1777 #define F_MAX_EXP FLT_MAX_EXP
1780 #define F_MAX FLT_MAX
1782 #ifdef FLT_MAX_10_EXP
1783 #define F_MAX_10_EXP FLT_MAX_10_EXP
1791 #define Number double
1792 #define THING "DOUBLE"
1793 #define Thing "Double"
1794 #define thing "double"
1797 #define Store dStore
1809 #define F_check dCheck
1812 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1815 #define EPROP edprop
1821 #define OK_UI 1 /* Unsigned int is always possible */
1824 #define UPROP uiprop
1825 #define Uname "UINT"
1829 #define I_MAX INT_MAX
1832 #define I_MIN INT_MIN
1835 #define U_MAX UINT_MAX
1839 #define F_MANT_DIG DBL_MANT_DIG
1842 #define F_DIG DBL_DIG
1845 #define F_EPSILON DBL_EPSILON
1848 #define F_MIN_EXP DBL_MIN_EXP
1851 #define F_MIN DBL_MIN
1853 #ifdef DBL_MIN_10_EXP
1854 #define F_MIN_10_EXP DBL_MIN_10_EXP
1857 #define F_MAX_EXP DBL_MAX_EXP
1860 #define F_MAX DBL_MAX
1862 #ifdef DBL_MAX_10_EXP
1863 #define F_MAX_10_EXP DBL_MAX_10_EXP
1872 #define Number long double
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
1893 #define F_check ldCheck
1896 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1899 #define EPROP eldprop
1901 #define Integer long
1904 #define Iname "LONG"
1910 #define UPROP ulprop
1911 #define Uname "ULONG"
1915 #define I_MAX LONG_MAX
1918 #define I_MIN LONG_MIN
1921 #define U_MAX ULONG_MAX
1924 #ifdef LDBL_MANT_DIG
1925 #define F_MANT_DIG LDBL_MANT_DIG
1928 #define F_DIG LDBL_DIG
1931 #define F_EPSILON LDBL_EPSILON
1934 #define F_MIN_EXP LDBL_MIN_EXP
1937 #define F_MIN LDBL_MIN
1939 #ifdef LDBL_MIN_10_EXP
1940 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1943 #define F_MAX_EXP LDBL_MAX_EXP
1946 #define F_MAX LDBL_MAX
1948 #ifdef LDBL_MAX_10_EXP
1949 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1956 #define I_MAX int_max
1959 #define I_MIN int_min
1966 #define F_RADIX f_radix
1969 #define F_MANT_DIG f_mant_dig
1975 #define F_ROUNDS f_rounds
1978 #define F_EPSILON f_epsilon
1981 #define F_MIN_EXP f_min_exp
1986 #ifndef F_MIN_10_EXP
1987 #define F_MIN_10_EXP f_min_10_exp
1990 #define F_MAX_EXP f_max_exp
1995 #ifndef F_MAX_10_EXP
1996 #define F_MAX_10_EXP f_max_10_exp
2000 #define Validate(prec, val, req, same) {;}
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;
2010 /* Calculate max short/int/long ***********************************/
2011 /* Calculate 2**n-1 until overflow - then use the previous value */
2015 if (setjmp(lab)==0) { /* Yields int_max */
2016 for(ipower=0; newi>int_max; ipower++) {
2020 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2021 co, INT[0]=='i'?"n":"", INT, oc);
2023 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2024 co, INT[0]=='i'?"n":"", INT, oc);
2028 /* Minimum value: assume either two's or one's complement *********/
2030 if (setjmp(lab)==0) { /* Yields int_min */
2031 if (int_min-1 < int_min) int_min--;
2035 /* Now for those daft Cybers */
2037 maxeri=0; newi=int_max;
2039 if (setjmp(lab)==0) { /* Yields maxeri */
2040 for(ibits=ipower; newi>maxeri; ibits++) {
2048 if (setjmp(lab)==0) { /* Yields minneri */
2049 if (minneri-1 < minneri) minneri--;
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);
2057 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
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);
2064 if(int_max < 0) { /* It has happened */
2065 eek_a_bug("signed integral comparison faulty?");
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!)",
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!)",
2085 Procedure UPROP () {
2086 /* The properties of unsigned short/int/long */
2088 Volatile unsigned Integer u_max, newi, two;
2089 newi=1; u_max=0; two=2;
2091 if (setjmp(lab)==0) { /* Yields u_max */
2098 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2099 co, INT, (unsigned long) u_max, oc);
2101 /* Oh woe: new standard C defines value preserving promotions */
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);
2109 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2110 (unsigned long) u_max,
2111 (unsigned long) U_MAX, IMARK);
2117 #endif /* Integer */
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.
2126 #define ARGS1(atype, a) (atype a)
2127 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2129 #define ARGS1(atype, a) (a) atype a;
2130 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
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); }
2140 Procedure F_check ARGS((int precision, Long_double val1));
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.
2155 Number val, new, diff;
2161 #ifdef NO_LONG_DOUBLE_IO
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))
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 */
2177 /* It had better support Le then */
2182 rep= f_rep(precision, (Long_double) val);
2183 if (setjmp(lab)==0) {
2184 sscanf(rep, f2, &new1);
2186 eek_a_bug("sscanf caused a trap");
2187 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2192 if (setjmp(lab)==0) { /* See if new is usable */
2195 diff= val/new - 1.0;
2196 if (diff < 0.1) diff= 1.0;
2197 /* That should be enough to generate a trap */
2200 eek_a_bug("sscanf returned an unusable number");
2201 printf("%s scanning: %s with format: %s%s\n\n",
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",
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) {
2225 printf("%s difference= %s%s\n\n",
2226 co, f_rep(precision, (Long_double) diff), oc);
2227 } /* else forget it */
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 */
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);
2242 printf(" Compiler has %s for value%s\n",
2243 "an unusable number", oc);
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);
2253 } /*else forget it*/
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");
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.
2270 Returns the number of digits in the fraction.
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;
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;
2285 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
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. */
2293 if (setjmp(lab)==0) { /* inexact trap? */
2295 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2297 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2298 /* And supporting those is just TOO much trouble! */
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. */
2307 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2309 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2311 /* Sanity check; if base<2, I can't guarantee the rest will work */
2313 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2318 if (PASS == 1) { /* only for FLT */
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);
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 */
2342 /* Rounding *******************************************************/
2343 basem1=Diff(base, HALF);
2344 if (Diff(Sum(a, basem1), a) != ZERO) {
2345 if (f_radix == 2) basem1=0.375;
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 */
2351 basem1=Diff(base, HALF);
2353 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2354 if (f_radix == 2) basem1=0.375;
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 */
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 */
2366 if (f_rounds != -1) {
2367 Vprintf("%sArithmetic rounds towards ", co);
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;
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" :
2383 Vprintf("%s Positive numbers %s%s\n",
2384 co, irnd==0 ? "towards zero" :
2385 irnd==1 ? "to nearest" :
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);
2396 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2399 if (PASS == 1) { /* only for FLT */
2400 flt_rounds= f_rounds;
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);
2411 /* Various flavours of epsilon ************************************/
2412 negeps=f_mant_dig+f_mant_dig;
2415 for(i=1; i<=negeps; i++) a*=basein;
2418 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2423 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
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;
2435 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2439 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2440 eek_a_bug("internal error calculating epsneg");
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);
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;
2453 /* epsneg is used later */
2456 machep= -f_mant_dig-f_mant_dig;
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",
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;
2471 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2474 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2475 eek_a_bug("internal error calculating eps");
2479 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2480 co, f_rep(digs, (Long_double) f_epsilon), oc);
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);
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);
2491 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2492 f_epsilon == Self(F_EPSILON));
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);
2502 /* Size of and minimum normalised exponent ************************/
2503 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2505 /* Coarse search for the largest power of two */
2506 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2509 z=Mul(y,y); z1=Mul(z1, y);
2512 if (z2 != y1) break;
2513 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2518 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2522 if (f_radix != 10) {
2523 iexp=i+1; /* for the sign */
2528 while (k >= iz) { iz*=f_radix; iexp++; }
2532 /* Fine tune starting with y and y1 */
2533 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2536 y=Div(y,base); y1=Div(y1,base);
2539 if (z2 != z1) break;
2540 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
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);
2552 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2553 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2555 if (setjmp(lab)==0) {
2556 Vprintf("%sMinimum normalised positive number = %s%s\n",
2557 co, f_rep(digs, (Long_double) f_min), oc);
2559 eek_a_bug("printf can't print the smallest normalised number");
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);
2569 eek_a_bug("xxx_MIN caused a trap");
2573 if (setjmp(lab) == 0) {
2574 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2575 f_min == Self(F_MIN));
2577 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2578 co, "Compiler has an unusable number for value", oc);
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, "");
2589 /* Minimum exponent ************************************************/
2590 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2595 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2600 if (xminner != 0.0 && xminner != f_min) {
2602 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
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);
2609 eek_a_bug("printf can't print the smallest unnormalised number.");
2615 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2618 /* Maximum exponent ************************************************/
2619 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2621 while (f_max<newxmax) {
2623 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2624 newxmax=Mul(newxmax, base);
2629 if (Div(newxmax, base) != f_max) {
2630 inf=1; /* ieee infinity */
2637 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
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, "");
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);
2650 if (setjmp(lab)==0) {
2651 Vprintf("%sMaximum number = %s%s\n",
2652 co, f_rep(digs, (Long_double) f_max), oc);
2654 eek_a_bug("printf can't print the largest double.");
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);
2663 eek_a_bug("xxx_MAX caused a trap");
2666 if (setjmp(lab)==0) {
2667 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2668 f_max == Self(F_MAX));
2670 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2671 co, "Compiler has an unusable number for value", oc);
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, "");
2681 /* Hidden bit + sanity check ****************************************/
2682 if (f_radix != 10) {
2684 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
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);
2693 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
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",
2700 printf("\n%s%s\n %s %s %s!%s\n\n",
2702 "*** Something fishy here!",
2703 "Exponent size + significand size doesn't match",
2704 "with the size of a", thing,
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" :
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 ");
2720 if (normal) Vprintf("the normalisation is unusual");
2721 Vprintf("%s\n", oc);
2724 Vprintf("%sIt doesn't look like IEEE format%s\n",
2728 printf("\n"); /* regardless of verbosity */
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.
2739 Volatile double a, b, base, old;
2740 Volatile Number d, oldd, dbase, one, zero;
2743 /* Size of significand **************************************/
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);
2750 /* Avoid the comparison if bad is set,
2751 to avoid trouble on the convex. */
2752 if (!bad && (a <= old)) bad=1;
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;
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;
2775 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2776 co, thing, " check that you compiled without optimisation!",
2778 } else if (eprec==dprec) {
2779 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2781 } else if (eprec==fprec) {
2782 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2784 } else if (eprec==lprec) {
2785 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
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",
2796 #else /* not Number */
2798 #ifdef FPROP /* Then create dummy routines for long double */
2800 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2804 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2807 #endif /* ifdef Number */
2809 /* Increment the pass number */
2828 #ifdef PASS /* then rescan this file */
2830 #include "enquire.c"
2832 #include FILENAME /* if this line fails to compile, define NO_FILE */