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 Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
15 In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
16 Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
17 Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
18 Include sys/types.h before signal.h, Apr 92.
21 With luck and a following wind, just the following will work:
22 cc enquire.c -o enquire
23 You may get some messages about unreachable code, which you can ignore.
25 If your compiler doesn't support: add flag:
26 signed char (eg pcc) -DNO_SC
28 unsigned short and long -DNO_UI
30 signal(), or setjmp/longjmp() -DNO_SIG
32 Try to compile first with no flags, and see if you get any errors -
33 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
34 Some compilers need a -f flag for floating point.
36 Don't use any optimisation flags: the program may not work if you do.
37 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
38 optimiser, to a floating-point unit there's a world of difference.
40 Some compilers offer various flags for different floating point
41 modes; it's worth trying all possible combinations of these.
43 Add -DID=\"name\" if you want the machine/flags identified in the output.
46 Because of bugs and/or inadequacies, some compilers need the following
49 If your C preprocessor doesn't have the predefined __FILE__ macro, and
50 you don't want to call this file enquire.c but, say, tell.c, add the
51 flag -DFILENAME=\"tell.c\" .
53 Some compilers won't accept the line "#include FILENAME".
54 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
56 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
57 or -DNO_FILE as above.
59 Some naughty compilers define __STDC__, but don't really support it.
60 Some define it as 0, in which case we treat it as undefined.
61 But if your compiler defines it, and isn't really ANSI C,
62 add flag -DNO_STDC. (To those compiler writers: for shame).
64 Some naughty compilers define __STDC__, but don't have the stddef.h
65 include file. Add flag -DNO_STDDEF.
67 Summary of naughty-compiler flags:
68 If your compiler doesn't support: add flag:
69 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
70 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
71 #include FILENAME -DNO_FILE
72 __STDC__ (properly) -DNO_STDC
75 Some systems crash when you try to malloc all store. To save users of
76 such defective systems too much grief, they may compile with -DNO_MEM,
77 which ignores that bit of the code.
79 While it is not our policy to support defective compilers, pity has been
80 taken on people with compilers that can't produce object files bigger than
81 32k (especially since it was an easy addition). Compile the program
82 into separate parts like this:
83 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
84 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
85 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
86 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
87 cc -o enquire p0.o p1.o p2.o p3.o
90 You may possibly need to add some calls to signal() for other sorts of
91 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
92 #ifdef SIGxxx in main() (and communicate the differences to me!).
95 Run without argument to get the information as English text. If run
96 with argument -l (e.g. enquire -l), output is a series of #define's for
97 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
98 with argument -f, output is a series of #define's for the ANSI standard
99 float.h include file (according to ANSI C Draft of Dec 7, 1988).
100 Flag -v gives verbose output: output includes the English text above
101 as C comments. The program exit(0)'s if everything went ok, otherwise
102 it exits with a positive number, telling how many problems there were.
104 VERIFYING THE COMPILER
105 If, having produced the float.h and limits.h header files, you want to
106 verify that the compiler reads them back correctly (there are a lot of
107 boundary cases, of course, like minimum and maximum numbers), you can
108 recompile enquire.c with -DVERIFY set (plus the other flags that you used
109 when compiling the version that produced the header files). This then
110 recompiles the program so that it #includes "limits.h" and "float.h",
111 and checks that the constants it finds there are the same as the
112 constants it produces. Run the resulting program with enquire -fl.
113 Very few compilers have passed without error.
114 NB: You *must* recompile with the same compiler and flags, otherwise
115 you may get odd results.
117 You can also use this option if your compiler already has both files,
118 and you want to confirm that this program produces the right results.
121 This program is now quite trustworthy, and suspicious and wrong output
122 may well be caused by bugs in the compiler, not in the program (however
123 of course, this is not guaranteed, and no responsibility can be
126 The program only works if overflows are ignored by the C system or
127 are catchable with signal().
129 If the program fails to run to completion (often with the error message
130 "Unexpected signal at point x"), this often turns out to be a bug in the
131 C compiler's run-time system. Check what was about to be printed, and
132 try to narrow the problem down.
134 Another possible problem is that you have compiled the program to produce
135 loss-of-precision arithmetic traps. The program cannot cope with these,
136 and you should re-compile without them. (They should never be the default).
138 Make sure you compiled with optimisation turned off.
140 Output preceded by *** WARNING: identifies behaviour of the C system
141 deemed incorrect by the program. Likely problems are that printf or
142 scanf don't cope properly with certain boundary numbers: this program
143 goes to a lot of trouble to calculate its values, and these values
144 are mostly boundary numbers. Experience has shown that often printf
145 cannot cope with these values, and so in an attempt to increase
146 confidence in the output, for each float and double that is printed,
147 the printed value is checked by using sscanf to read it back.
148 Care is taken that numbers are printed with enough digits to uniquely
149 identify them, and therefore that they can be read back identically.
150 If the number read back is different, then there is probably a bug in
151 printf or sscanf, and the program prints the warning message.
152 If the two numbers in the warning look identical, then printf is more
153 than likely rounding the last digit(s) incorrectly. To put you at ease
154 that the two really are different, the bit patterns of the two numbers
155 are also printed. The difference is very likely in the last bit.
156 Many scanf's read the minimum double back as 0.0, and similarly cause
157 overflow when reading the maximum double. This program quite ruthlessly
158 declares all these behaviours faulty. The point is that if you get
159 one of these warnings, the output may be wrong, so you should check
160 the result carefully if you intend to use the results. Of course, printf
161 and sscanf may both be wrong, and cancel each other out, so you should
162 check the output carefully anyway.
164 The warning that "a cast didn't work" refers to cases like this:
167 #define C 1.234567890123456789
169 if (f != (float) C) printf ("Wrong!");
171 A faulty compiler will widen f to double and ignore the cast to float,
172 and because there is more accuracy in a double than a float, fail to
173 recognise that they are the same. In the actual case in point, f and C
174 are passed as parameters to a function that discovers they are not equal,
175 so it's just possible that the error was in the parameter passing,
176 not in the cast (see function Validate()).
177 For ANSI C, which has float constants, the error message is "constant has
181 If the program doesn't work for you for any reason that can't be
182 narrowed down to a problem in the C compiler, or it has to be changed in
183 order to get it to compile, or it produces suspicious output (like a very
184 low maximum float, for instance), please mail the problem and an example
185 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
186 improvements can be worked into future versions; cwi.nl is the European
187 backbone, and is connected to uunet and other fine hosts.
189 The program tries to catch and diagnose bugs in the compiler/run-time
190 system. I would be especially pleased to have reports of failures so
191 that I can improve this service.
193 I apologise unreservedly for the contorted use of the preprocessor...
196 You may copy and distribute verbatim copies of this source file.
198 You may modify this source file, and copy and distribute such
199 modified versions, provided that you leave the copyright notice
200 at the top of the file and also cause the modified file to carry
201 prominent notices stating that you changed the files and the date
202 of any change; and cause the whole of any work that you distribute
203 or publish, that in whole or in part contains or is a derivative of
204 this program or any part thereof, to be licensed at no charge to
205 all third parties on terms identical to those here.
207 If you do have a fix to any problem, please send it to me, so that
208 other people can have the benefits.
210 While every effort has been taken to make this program as reliable as
211 possible, no responsibility can be taken for the correctness of the
212 output, nor suitability for any particular use.
214 This program is an offshoot of a project funded by public funds.
215 If you use this program for research or commercial use (i.e. more
216 than just for the fun of knowing about your compiler) mailing a short
217 note of acknowledgement may help keep enquire.c supported.
220 Many people have given time and ideas to making this program what it is.
221 To all of them thanks, and apologies for not mentioning them by name.
224 Originally started as a program to generate configuration constants
225 for a large piece of software we were writing, which later took on
227 1.0 Length 6658!; end 1984?
228 Unix only. Only printed a dozen maximum int/double values.
229 2.0 Length 10535; Spring 1985
230 Prints values as #defines (about 20 of them)
231 More extensive floating point, using Cody and Waite
232 Handles signals better
233 Programs around optimisations
235 3.0 Length 12648; Aug 1987; prints about 42 values
236 Added PASS stuff, so treats float as well as double
237 4.0 Length 33891; Feb 1989; prints around 85 values
238 First GNU version (for gcc, where they call it hard-params.c)
239 Generates float.h and limits.h files
241 Generates warnings for dubious output
242 4.1 Length 47738; April 1989
243 Added VERIFY and TEST
244 4.2 Length 63442; Feb 1990
247 Added check for pseudo-unsigned chars
248 Added description for each #define output
249 Added check for absence of defines during verify
251 Added NO_STDC and NO_FILE
252 Fixed alignments output
253 4.3 Length 75000; Oct 1990; around 114 lines of output
254 Function xmalloc defined, Richard Stallman, June 89.
255 Alignments computed from member offsets rather than structure sizes,
256 Richard Stallman, Oct 89.
257 Print whether char* and int* pointers have the same format;
258 also char * and function *.
259 Update to Draft C version Dec 7, 1988
260 - types of constants produced in limits.h
261 (whether to put a U after unsigned shorts and chars and
262 whether to output -1024 as (-1023-1))
263 - values of SCHAR_MIN/MAX
264 - values of *_EPSILON (not the smallest but the effective smallest)
265 Added FILENAME, since standard C doesn't allow #define __FILE__
266 Renamed from config.c to enquire.c
267 Added size_t and ptrdiff_t enquiries
268 Added promotion enquiries
269 Added type checks of #defines
271 Changed endian to allow for cases where not all bits are used
272 Sanity check for max integrals
273 Fixed definition of setjmp for -DNO_SIG
274 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
278 /* Set FILENAME to the name of this file */
281 #define FILENAME "enquire.c"
283 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
284 #define FILENAME __FILE__
286 #define FILENAME "enquire.c"
287 #endif /* __FILE__ */
289 #endif /* FILENAME */
291 /* If PASS isn't defined, then this is the first pass over this file. */
299 /* A description of the ANSI constants */
300 #define D_CHAR_BIT "Number of bits in a storage unit"
301 #define D_CHAR_MAX "Maximum char"
302 #define D_CHAR_MIN "Minimum char"
303 #define D_SCHAR_MAX "Maximum signed char"
304 #define D_SCHAR_MIN "Minimum signed char"
305 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
307 #define D_INT_MAX "Maximum %s"
308 #define D_INT_MIN "Minimum %s"
309 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
311 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
312 #define D_FLT_RADIX "Radix of exponent representation"
313 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
314 #define D_DIG "Number of decimal digits of precision in a %s"
315 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
316 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
317 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
318 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
319 #define D_MAX "Maximum %s"
320 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
321 #define D_MIN "Minimum normalised %s"
323 /* Procedure just marks the functions that don't return a result */
325 #define Procedure int
327 #define Procedure void
330 /* Some bad compilers define __STDC__, when they don't support it.
331 Compile with -DNO_STDC to get round this.
335 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
341 /* Stuff different for ANSI C, and old C:
342 ARGS and NOARGS are used for function prototypes.
343 Volatile is used to reduce the chance of optimisation,
344 and to prevent variables being put in registers (when setjmp/longjmp
345 wouldn't work as we want)
346 Long_double is the longest floating point type available.
347 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
348 U is output after unsigned constants.
353 #define NOARGS (void)
354 #define Volatile volatile
355 #define Long_double long double
359 #else /* Old style C */
363 #define Volatile static
364 #define Long_double double
375 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
382 #include <sys/types.h>
387 /* Kludge around the possiblity that <stdio.h> includes <limits.h> */
403 #define Vprintf if (V) printf
404 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
405 #define fabs(x) (((x)<0.0)?(-x):(x))
411 /* Prototypes for what's to come: */
416 char *malloc (); /* Old style prototype */
418 char *malloc ARGS((size_t size));
421 Procedure exit ARGS((int status));
423 char *f_rep ARGS((int precision, Long_double val));
425 int maximum_int NOARGS;
428 Procedure sprop NOARGS;
429 Procedure iprop NOARGS;
430 Procedure lprop NOARGS;
431 Procedure usprop NOARGS;
432 Procedure uiprop NOARGS;
433 Procedure ulprop NOARGS;
434 int fprop ARGS((int bits_per_byte));
435 int dprop ARGS((int bits_per_byte));
436 int ldprop ARGS((int bits_per_byte));
437 Procedure efprop ARGS((int fprec, int dprec, int lprec));
438 Procedure edprop ARGS((int fprec, int dprec, int lprec));
439 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
441 int setmode ARGS((char *s));
442 Procedure farewell ARGS((int bugs));
443 Procedure describe ARGS((char *description, char *extra));
444 Procedure missing ARGS((char *s));
445 Procedure fmissing ARGS((char *s));
446 Procedure check_defines NOARGS;
447 Procedure bitpattern ARGS((char *p, unsigned int size));
448 int ceil_log ARGS((int base, Long_double x));
449 Procedure croak ARGS((int place));
450 Procedure eek_a_bug ARGS((char *problem));
451 Procedure endian ARGS((int bits_per_byte));
452 int exponent ARGS((Long_double x, double *fract, int *exp));
453 int floor_log ARGS((int base, Long_double x));
454 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
455 int prec, Long_double val, char *mark));
456 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
457 long val, long lim, long req, char *mark));
458 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
459 unsigned long val, unsigned long req, char *mark));
461 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
463 /* Dummy routines instead */
465 int setjmp ARGS((int lab));
468 int setjmp(lab) int lab; { return(0); }
469 Procedure signal(i, p) int i, (*p)(); {}
473 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
474 signal(sig, overflow);
480 int V= 0, /* verbose */
481 L= 0, /* produce limits.h */
482 F= 0, /* produce float.h */
483 bugs=0; /* The number of (possible) bugs in the output */
485 char co[4], oc[4]; /* Comment starter and ender symbols */
487 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
488 int flt_rounds; /* The calculated value of FLT_ROUNDS */
489 int flt_radix; /* The calculated value of FLT_RADIX */
492 /* Set the fp modes on a SUN with 68881 chip, to check that different
493 rounding modes etc. get properly detected.
494 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
495 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
496 register to hex-number
499 /* Bits 0x30 = rounding mode */
500 #define ROUND_BITS 0x30
501 #define TO_NEAREST 0x00
503 #define TO_MINUS_INF 0x20
504 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
506 /* Bits 0xc0 = extended rounding */
507 #define EXT_BITS 0xc0
508 #define ROUND_EXTENDED 0x00
509 #define ROUND_SINGLE 0x40
510 #define ROUND_DOUBLE 0x80
513 #define EXE_INEX1 0x100
514 #define EXE_INEX2 0x200
516 #define EXE_UNFL 0x800
517 #define EXE_OVFL 0x1000
518 #define EXE_OPERR 0x2000
519 #define EXE_SNAN 0x4000
520 #define EXE_BSUN 0x8000
522 /* Only used for testing, on a Sun with 68881 chip */
523 /* Print the FP mode */
524 printmode(new) unsigned new; {
526 printf("New fp mode:\n");
527 printf(" Round toward ");
528 switch (new & ROUND_BITS) {
529 case TO_NEAREST: printf("nearest"); break;
530 case TO_ZERO: printf("zero"); break;
531 case TO_MINUS_INF: printf("minus infinity"); break;
532 case TO_PLUS_INF: printf("plus infinity"); break;
533 default: printf("???"); break;
536 printf("\n Extended rounding precision: ");
538 switch (new & EXT_BITS) {
539 case ROUND_EXTENDED: printf("extended"); break;
540 case ROUND_SINGLE: printf("single"); break;
541 case ROUND_DOUBLE: printf("double"); break;
542 default: printf("???"); break;
545 printf("\n Enabled exceptions:");
546 if (new & (unsigned) EXE_INEX1) printf(" inex1");
547 if (new & (unsigned) EXE_INEX2) printf(" inex2");
548 if (new & (unsigned) EXE_DZ) printf(" dz");
549 if (new & (unsigned) EXE_UNFL) printf(" unfl");
550 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
551 if (new & (unsigned) EXE_OPERR) printf(" operr");
552 if (new & (unsigned) EXE_SNAN) printf(" snan");
553 if (new & (unsigned) EXE_BSUN) printf(" bsun");
557 /* Only used for testing, on a Sun with 68881 chip */
558 /* Set the FP mode */
559 int setmode(s) char *s; {
560 unsigned mode=0, dig;
565 if (c>='0' && c<='9') dig= c-'0';
566 else if (c>='a' && c<='f') dig= c-'a'+10;
567 else if (c>='A' && c<='F') dig= c-'A'+10;
576 int setmode(s) char *s; {
577 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
582 Procedure farewell(bugs) int bugs; {
583 if (bugs == 0) exit(0);
584 printf("\n%sFor hints on dealing with the ", co);
585 if (bugs == 1) printf("problem");
586 else printf("%d problems", bugs);
587 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
588 printf("%s%s\n", FILENAME, oc);
592 /* The program has received a signal where it wasn't expecting one */
593 Procedure croak(place) int place; {
594 printf("*** Unexpected signal at point %d\n", place);
595 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
598 /* This is here in case alloca.c is used, which calls this. */
599 char *xmalloc(size) unsigned size; {
600 char *value = (char *)malloc(size);
602 fprintf(stderr, "Virtual memory exceeded\n");
611 /* Find the maximum integer */
612 Volatile int newi, int_max, two=2;
614 /* Calculate maxint ***********************************/
615 /* Calculate 2**n-1 until overflow - then use the previous value */
619 if (setjmp(lab)==0) { /* Yields int_max */
620 while(newi>int_max) {
629 int main(argc, argv) int argc; char *argv[]; {
630 int dprec, fprec, lprec;
633 int i; char *s; int bad;
636 signal(SIGFPE, overflow);
639 signal(SIGOVER, overflow);
641 /* Add more calls as necessary */
646 for (i=1; i < argc; i++) {
652 case 'v': V=1; break;
653 case 'l': L=1; break;
654 case 'f': F=1; break;
655 default: bad=1; break;
658 } else if (*s == '+') {
665 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
670 co[0]= '/'; oc[0]= ' ';
671 co[1]= '*'; oc[1]= '*';
672 co[2]= ' '; oc[2]= '/';
673 co[3]= '\0'; oc[3]= '\0';
675 co[0]= '\0'; oc[0]= '\0';
679 if (L) printf("%slimits.h%s\n", co, oc);
680 if (F) printf("%sfloat.h%s\n", co, oc);
682 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
683 co, ID, VERSION, oc);
685 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
690 printf("%sVerification phase%s\n", co, oc);
694 Vprintf("%sCompiled without signal(): %s%s\n",
696 "there's nothing that can be done if overflow occurs",
700 Vprintf("%sCompiled without signed char%s\n", co, oc);
703 Vprintf("%Compiled without unsigned char%s\n", co, oc);
706 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
709 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
712 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
717 maxint= maximum_int();
718 bits_per_byte= basic();
721 fprec= fprop(bits_per_byte);
722 dprec= dprop(bits_per_byte);
723 lprec= ldprop(bits_per_byte);
724 efprop(fprec, dprec, lprec);
725 edprop(fprec, dprec, lprec);
726 eldprop(fprec, dprec, lprec);
730 /* An extra goody: the approximate amount of data-space */
731 /* Allocate store until no more available */
732 /* Different implementations have a different argument type
733 to malloc. Here we assume that it's the same type as
734 that which sizeof() returns */
735 size=1<<((bits_per_byte*sizeof(int))-2);
738 while ( malloc((false()?sizeof(int):size)) !=
746 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
747 co, (total+511)/512, oc);
751 return bugs; /* To keep compilers and lint happy */
754 Procedure eek_a_bug(problem) char *problem; {
755 /* The program has discovered a problem */
756 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
760 Procedure describe(description, extra) char *description, *extra; {
761 /* Produce the description for a #define */
763 printf(description, extra);
767 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
768 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
769 /* Produce a #define for a signed int type */
770 describe(desc, extra);
772 printf("#define %s%s %ld%s\n", sort, name, val, mark);
773 } else if (val + lim < 0) {
774 /* We may not produce a constant like -1024 if the max
775 allowable value is 1023. It has then to be output as
776 -1023-1. lim is the max allowable value. */
777 printf("#define %s%s (%ld%s%ld%s)\n",
778 sort, name, -lim, mark, val+lim, mark);
780 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
782 /* If VERIFY is not set, val and req are just the same value;
783 if it is set, val is the value as calculated, and req is
784 the #defined constant
787 printf("%s*** Verify failed for above #define!\n", co);
788 printf(" Compiler has %ld for value%s\n\n", req, oc);
794 Procedure u_define(desc, extra, sort, name, val, req, mark)
795 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
796 /* Produce a #define for an unsigned value */
797 describe(desc, extra);
798 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
800 printf("%s*** Verify failed for above #define!\n", co);
801 printf(" Compiler has %lu for value%s\n\n", req, oc);
807 Procedure f_define(desc, extra, sort, name, precision, val, mark)
808 char *desc, *extra, *sort, *name; int precision;
809 Long_double val; char *mark; {
810 /* Produce a #define for a float/double/long double */
811 describe(desc, extra);
813 printf("#define %s%s %s%s\n",
814 sort, name, f_rep(precision, val), mark);
815 } else if (*mark == 'F') {
816 /* non-ANSI C has no float constants, so cast the constant */
817 printf("#define %s%s ((float)%s)\n",
818 sort, name, f_rep(precision, val));
820 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
825 int floor_log(base, x) int base; Long_double x; {
826 /* return floor(log base(x)) */
828 while (x>=base) { r++; x/=base; }
832 int ceil_log(base, x) int base; Long_double x; {
834 while (x>1.0) { r++; x/=base; }
838 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
839 /* Split x into a fraction and a power of ten;
840 returns 0 if x is unusable, 1 otherwise.
841 Only used for error messages about faulty output.
850 if (x==0.0) return 1;
854 if (old==x) return 0;
859 if (old==x) return 0;
862 if (neg) *fract= (double) -x;
863 else *fract=(double) x;
868 char *f_rep(precision, val) int precision; Long_double val; {
869 /* Return the floating representation of val */
870 static char buf[1024];
872 if (sizeof(double) == sizeof(Long_double)) {
873 /* Assume they're the same, and use non-stdc format */
874 /* This is for stdc compilers using non-stdc libraries */
877 /* It had better support Le then */
880 sprintf(buf, f1, precision, val);
884 Procedure bitpattern(p, size) char *p; unsigned int size; {
885 /* Printf the bit-pattern of p */
889 for (i=1; i<=size; i++) {
892 for (j=bits_per_byte-1; j>=0; j--)
893 printf("%c", (c>>j)&1 ? '1' : '0');
894 if (i!=size) printf(" ");
898 #define Order(x, px, mode)\
899 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
900 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
901 putchar(c==0 ? '?' : (char)c); }\
904 Procedure endian(bits_per_byte) int bits_per_byte; {
905 /* Printf the byte-order used on this machine */
906 /*unsigned*/ short s=0;
907 /*unsigned*/ int j=0;
908 /*unsigned*/ long l=0;
910 char *ps= (char *) &s,
913 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
914 unsigned int mask, i, c;
917 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
920 printf("%sCHARACTER ORDER%s\n", co, oc);
921 Order(s, ps, "short:");
922 Order(j, pj, "int: ");
923 Order(l, pl, "long: ");
927 Procedure missing(s) char *s; {
928 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
932 Procedure fmissing(s) char *s; {
933 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
937 /* To try and fool optimisers */
938 int false() { return 0; }
940 #define Promoted(x) (false()?(x):(-1))
941 #define is_signed(x) (Promoted(x) < 0)
942 #define sign_of(x) ((x)?"signed":"unsigned")
945 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
947 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
949 char *type_of(x) int x; {
950 if (x == sizeof(char)) {
951 if (sizeof(char) == sizeof(int)) return "char/short/int";
952 if (sizeof(char) == sizeof(short)) return "char/short";
955 if (x == sizeof(short)) {
956 if (sizeof(short) == sizeof(int)) return "short/int";
959 if (x == sizeof(int)) {
960 if (sizeof(int) == sizeof(long)) return "int/long";
963 if (x == sizeof(long)) return "long";
964 return "unknown-type";
967 char *ftype_of(x) int x; {
968 if (x == sizeof(float)) {
971 if (x == sizeof(double)) {
972 if (sizeof(double) == sizeof(Long_double))
973 return "(long)double";
976 if (x == sizeof(Long_double)) {
977 return "long double";
979 return "unknown-type";
982 Procedure typerr(name, esign, esize, sign, size)
983 char *name; int esign, esize, sign, size;
985 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
986 name, sign_of(esign), type_of(esize),
987 sign_of(sign), type_of(size));
990 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
991 Vprintf("*** %s has wrong type: expected %s, found %s\n",
992 name, ftype_of(esize), ftype_of(size));
997 unsigned int ui; unsigned long ul;
998 short ss; unsigned short us;
1000 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1003 /* Possible warnings here; no problem */
1004 (sizeof(Promoted(si)) != sizeof(int)) ||
1005 (sizeof(Promoted(sl)) != sizeof(long)) ||
1006 (sizeof(Promoted(ss)) != sizeof(int)) ||
1007 (sizeof(Promoted(ui)) != sizeof(int)) ||
1008 (sizeof(Promoted(ul)) != sizeof(long)) ||
1009 (sizeof(Promoted(us)) != sizeof(int)) ||
1010 is_signed(ui) || is_signed(ul) ||
1011 !is_signed(si) || !is_signed(sl)
1014 eek_a_bug("promotions don't work properly in conditional expressions\n");
1017 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1018 showtype("long+unsigned gives", sl+ui);
1021 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1023 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1025 Procedure check_defines() {
1026 /* ensure that all #defines are present and have the correct type */
1033 /* Implementations promote unsigned short differently */
1034 usign= is_signed((unsigned short)0);
1039 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1041 missing("CHAR_BIT");
1044 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1046 missing("CHAR_MAX");
1049 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1051 missing("CHAR_MIN");
1054 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1056 missing("SCHAR_MAX");
1059 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1061 missing("SCHAR_MIN");
1064 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1066 missing("UCHAR_MAX");
1069 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1071 missing("SHRT_MAX");
1074 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1076 missing("SHRT_MIN");
1079 checktype(INT_MAX, "INT_MAX", Signed, int);
1084 checktype(INT_MIN, "INT_MIN", Signed, int);
1089 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1091 missing("LONG_MAX");
1094 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1096 missing("LONG_MIN");
1099 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1101 missing("USHRT_MAX");
1104 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1106 missing("UINT_MAX");
1109 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1111 missing("ULONG_MAX");
1117 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1119 fmissing("FLT_RADIX");
1122 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1124 fmissing("FLT_MANT_DIG");
1127 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1129 fmissing("FLT_DIG");
1132 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1134 fmissing("FLT_ROUNDS");
1137 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1139 fmissing("FLT_EPSILON");
1142 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1144 fmissing("FLT_MIN_EXP");
1147 fchecktype(FLT_MIN, "FLT_MIN", float);
1149 fmissing("FLT_MIN");
1151 #ifdef FLT_MIN_10_EXP
1152 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1154 fmissing("FLT_MIN_10_EXP");
1157 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1159 fmissing("FLT_MAX_EXP");
1162 fchecktype(FLT_MAX, "FLT_MAX", float);
1164 fmissing("FLT_MAX");
1166 #ifdef FLT_MAX_10_EXP
1167 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1169 fmissing("FLT_MAX_10_EXP");
1172 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1174 fmissing("DBL_MANT_DIG");
1177 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1179 fmissing("DBL_DIG");
1182 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1184 fmissing("DBL_EPSILON");
1187 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1189 fmissing("DBL_MIN_EXP");
1192 fchecktype(DBL_MIN, "DBL_MIN", double);
1194 fmissing("DBL_MIN");
1196 #ifdef DBL_MIN_10_EXP
1197 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1199 fmissing("DBL_MIN_10_EXP");
1202 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1204 fmissing("DBL_MAX_EXP");
1207 fchecktype(DBL_MAX, "DBL_MAX", double);
1209 fmissing("DBL_MAX");
1211 #ifdef DBL_MAX_10_EXP
1212 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1214 fmissing("DBL_MAX_10_EXP");
1217 #ifdef LDBL_MANT_DIG
1218 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1220 fmissing("LDBL_MANT_DIG");
1223 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1225 fmissing("LDBL_DIG");
1228 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1230 fmissing("LDBL_EPSILON");
1233 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1235 fmissing("LDBL_MIN_EXP");
1238 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1240 fmissing("LDBL_MIN");
1242 #ifdef LDBL_MIN_10_EXP
1243 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1245 fmissing("LDBL_MIN_10_EXP");
1248 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1250 fmissing("LDBL_MAX_EXP");
1253 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1255 fmissing("LDBL_MAX");
1257 #ifdef LDBL_MAX_10_EXP
1258 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1260 fmissing("LDBL_MAX_10_EXP");
1269 #define SCHAR_MAX char_max
1272 #define SCHAR_MIN char_min
1275 #define UCHAR_MAX char_max
1280 #define CHAR_BIT char_bit
1283 #define CHAR_MAX char_max
1286 #define CHAR_MIN char_min
1289 #define SCHAR_MAX char_max
1292 #define SCHAR_MIN char_min
1295 #define UCHAR_MAX char_max
1299 /* Properties of type char */
1300 Volatile char c, char_max, char_min;
1301 Volatile int bits_per_byte, c_signed;
1306 /* Calculate number of bits per character *************************/
1307 c=1; bits_per_byte=0;
1308 do { c=c<<1; bits_per_byte++; } while(c!=0);
1310 if (((int)c)<0) c_signed=1;
1312 Vprintf("%schar = %d bits, %ssigned%s\n",
1313 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1314 char_bit=(long)(sizeof(c)*bits_per_byte);
1315 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1316 char_bit, 0L, (long) CHAR_BIT, "");
1320 if (setjmp(lab)==0) { /* Yields char_max */
1321 while (c>char_max) {
1326 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1330 if (setjmp(lab)==0) { /* Yields char_min */
1331 while (c<char_min) {
1336 if (c_signed && char_min == 0) {
1337 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1338 Vprintf("%s %s%s%s\n",
1339 "They contain only nonnegative values, ",
1340 "but sign extend when used as integers.", co, oc);
1345 /* Because of the integer promotions, you must use a U after
1346 the MAX_CHARS in the following cases */
1347 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1348 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1350 (long) CHAR_MAX, "");
1352 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1353 (long) char_max, 0L,
1354 (long) CHAR_MAX, "");
1356 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1357 (long) char_min, (long) maxint,
1358 (long) CHAR_MIN, "");
1360 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1361 (long) char_max, 0L,
1362 (long) SCHAR_MAX, "");
1363 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1364 (long) char_min, (long) maxint,
1365 (long) SCHAR_MIN, "");
1367 if (sizeof(char) == sizeof(int)) {
1368 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1370 (long) UCHAR_MAX, "");
1372 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1373 (long) char_max, 0L,
1374 (long) UCHAR_MAX, "");
1380 Volatile unsigned char c, char_max;
1383 if (setjmp(lab)==0) { /* Yields char_max */
1384 while (c>char_max) {
1390 if (sizeof(char) == sizeof(int)) {
1391 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1393 (long) UCHAR_MAX, "");
1395 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1396 (long) char_max, 0L,
1397 (long) UCHAR_MAX, "");
1402 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1405 if (setjmp(lab)==0) { /* Yields char_max */
1406 while (c>char_max) {
1413 if (setjmp(lab)==0) { /* Yields char_min */
1414 while (c<char_min) {
1420 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1421 (long) char_min, (long) maxint,
1422 (long) SCHAR_MIN, "");
1423 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1424 (long) char_max, 0L,
1425 (long) SCHAR_MAX, "");
1429 return bits_per_byte;
1433 /* The properties of the basic types.
1434 Returns number of bits per sizeof unit */
1435 Volatile int bits_per_byte;
1436 typedef int function ();
1440 Vprintf("%sSIZES%s\n", co, oc);
1441 bits_per_byte= cprop();
1443 /* Shorts, ints and longs *****************************************/
1444 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1446 (int) sizeof(short)*bits_per_byte,
1447 (int) sizeof(int)*bits_per_byte,
1448 (int) sizeof(long)*bits_per_byte,
1449 (int) sizeof(float)*bits_per_byte,
1450 (int) sizeof(double)*bits_per_byte, oc);
1452 Vprintf("%slong double=%d bits%s\n",
1453 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1455 Vprintf("%schar*=%d bits%s%s\n",
1456 co, (int)sizeof(char *)*bits_per_byte,
1457 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1459 Vprintf("%sint* =%d bits%s%s\n",
1460 co, (int)sizeof(int *)*bits_per_byte,
1461 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1463 Vprintf("%sfunc*=%d bits%s%s\n",
1464 co, (int)sizeof(function *)*bits_per_byte,
1465 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1467 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1468 ((((false()?( sizeof(int)):(-1)) < 0) )?
1469 "signed":"unsigned") ,
1475 showtype("Type size_t is", sizeof(0));
1477 /* Alignment constants ********************************************/
1479 #define alignment(TYPE) \
1480 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1482 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1484 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1486 alignment(char), alignment(short),
1487 alignment(int), alignment(long),
1490 Vprintf("%sfloat=%ld double=%ld%s\n",
1492 alignment(float), alignment(double),
1496 Vprintf("%slong double=%ld%s\n",
1498 alignment(Long_double),
1501 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1503 alignment(char *), alignment(int *), alignment(function *),
1508 /* Ten little endians *********************************************/
1510 endian(bits_per_byte);
1512 /* Pointers *******************************************************/
1514 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1516 if ((long) (char *) &variable == (long) (int *) &variable)
1517 Vprintf("%sChar and int pointer formats seem identical%s\n",
1520 Vprintf("%sChar and int pointer formats are different%s\n",
1522 if ((long) (char *) &variable == (long) (function *) &variable)
1523 Vprintf("%sChar and function pointer formats seem identical%s\n",
1526 Vprintf("%sChar and function pointer formats are different%s\n",
1531 printf("%sStrings are shared%s\n", co, oc);
1532 else printf("%sStrings are not shared%s\n", co, oc);
1536 showtype("Type ptrdiff_t is", p-q);
1538 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1551 return bits_per_byte;
1554 #else /* not PASS0 */
1558 extern int V, L, F, bugs, bits_per_byte;
1559 extern char co[], oc[];
1560 extern char *f_rep();
1562 #endif /* ifdef PASS0 */
1564 /* As I said, I apologise for the contortions below. The functions are
1565 expanded by the preprocessor twice or three times (for float and double,
1566 and maybe for long double, and for short, int and long). That way,
1567 I never make a change to one that I forget to make to the other.
1568 You can look on it as C's fault for not supporting multi-line macro's.
1569 This whole file is read 3 times by the preprocessor, with PASSn set for
1570 n=1, 2 or 3, to decide which parts to reprocess.
1573 /* #undef on an already undefined thing is (wrongly) flagged as an error
1574 by some compilers, therefore the #ifdef that follows:
1600 /* These are the float.h constants */
1631 /* Define the things we're going to use this pass */
1633 #define Number float
1634 #define THING "FLOAT"
1635 #define Thing "Float"
1636 #define thing "float"
1639 #define Store fStore
1651 #define F_check fCheck
1654 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1657 #define EPROP efprop
1659 #define Integer short
1662 #define Iname "SHRT"
1668 #define UPROP usprop
1669 #define Uname "USHRT"
1673 #define I_MAX SHRT_MAX
1676 #define I_MIN SHRT_MIN
1679 #define U_MAX USHRT_MAX
1683 #define F_RADIX FLT_RADIX
1686 #define F_MANT_DIG FLT_MANT_DIG
1689 #define F_DIG FLT_DIG
1692 #define F_ROUNDS FLT_ROUNDS
1695 #define F_EPSILON FLT_EPSILON
1698 #define F_MIN_EXP FLT_MIN_EXP
1701 #define F_MIN FLT_MIN
1703 #ifdef FLT_MIN_10_EXP
1704 #define F_MIN_10_EXP FLT_MIN_10_EXP
1707 #define F_MAX_EXP FLT_MAX_EXP
1710 #define F_MAX FLT_MAX
1712 #ifdef FLT_MAX_10_EXP
1713 #define F_MAX_10_EXP FLT_MAX_10_EXP
1721 #define Number double
1722 #define THING "DOUBLE"
1723 #define Thing "Double"
1724 #define thing "double"
1727 #define Store dStore
1739 #define F_check dCheck
1742 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1745 #define EPROP edprop
1751 #define OK_UI 1 /* Unsigned int is always possible */
1754 #define UPROP uiprop
1755 #define Uname "UINT"
1759 #define I_MAX INT_MAX
1762 #define I_MIN INT_MIN
1765 #define U_MAX UINT_MAX
1769 #define F_MANT_DIG DBL_MANT_DIG
1772 #define F_DIG DBL_DIG
1775 #define F_EPSILON DBL_EPSILON
1778 #define F_MIN_EXP DBL_MIN_EXP
1781 #define F_MIN DBL_MIN
1783 #ifdef DBL_MIN_10_EXP
1784 #define F_MIN_10_EXP DBL_MIN_10_EXP
1787 #define F_MAX_EXP DBL_MAX_EXP
1790 #define F_MAX DBL_MAX
1792 #ifdef DBL_MAX_10_EXP
1793 #define F_MAX_10_EXP DBL_MAX_10_EXP
1802 #define Number long double
1812 #define THING "LONG DOUBLE"
1813 #define Thing "Long double"
1814 #define thing "long double"
1815 #define Fname "LDBL"
1816 #define FPROP ldprop
1817 #define Store ldStore
1823 #define F_check ldCheck
1826 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1829 #define EPROP eldprop
1831 #define Integer long
1834 #define Iname "LONG"
1840 #define UPROP ulprop
1841 #define Uname "ULONG"
1845 #define I_MAX LONG_MAX
1848 #define I_MIN LONG_MIN
1851 #define U_MAX ULONG_MAX
1854 #ifdef LDBL_MANT_DIG
1855 #define F_MANT_DIG LDBL_MANT_DIG
1858 #define F_DIG LDBL_DIG
1861 #define F_EPSILON LDBL_EPSILON
1864 #define F_MIN_EXP LDBL_MIN_EXP
1867 #define F_MIN LDBL_MIN
1869 #ifdef LDBL_MIN_10_EXP
1870 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1873 #define F_MAX_EXP LDBL_MAX_EXP
1876 #define F_MAX LDBL_MAX
1878 #ifdef LDBL_MAX_10_EXP
1879 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1886 #define I_MAX int_max
1889 #define I_MIN int_min
1896 #define F_RADIX f_radix
1899 #define F_MANT_DIG f_mant_dig
1905 #define F_ROUNDS f_rounds
1908 #define F_EPSILON f_epsilon
1911 #define F_MIN_EXP f_min_exp
1916 #ifndef F_MIN_10_EXP
1917 #define F_MIN_10_EXP f_min_10_exp
1920 #define F_MAX_EXP f_max_exp
1925 #ifndef F_MAX_10_EXP
1926 #define F_MAX_10_EXP f_max_10_exp
1930 #define Validate(prec, val, req, same) {;}
1936 /* the properties of short, int, and long */
1937 Volatile Integer newi, int_max, maxeri, int_min, minneri;
1938 Volatile int ibits, ipower, two=2;
1940 /* Calculate max short/int/long ***********************************/
1941 /* Calculate 2**n-1 until overflow - then use the previous value */
1945 if (setjmp(lab)==0) { /* Yields int_max */
1946 for(ipower=0; newi>int_max; ipower++) {
1950 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
1951 co, INT[0]=='i'?"n":"", INT, oc);
1953 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
1954 co, INT[0]=='i'?"n":"", INT, oc);
1958 /* Minimum value: assume either two's or one's complement *********/
1960 if (setjmp(lab)==0) { /* Yields int_min */
1961 if (int_min-1 < int_min) int_min--;
1965 /* Now for those daft Cybers */
1967 maxeri=0; newi=int_max;
1969 if (setjmp(lab)==0) { /* Yields maxeri */
1970 for(ibits=ipower; newi>maxeri; ibits++) {
1978 if (setjmp(lab)==0) { /* Yields minneri */
1979 if (minneri-1 < minneri) minneri--;
1983 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
1984 co, INT, (long)int_max, ipower, oc);
1985 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
1987 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
1989 (long) I_MAX, IMARK);
1990 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
1991 (long) int_min, (long) (PASS==1?maxint:int_max),
1992 (long) I_MIN, IMARK);
1994 if(int_max < 0) { /* It has happened */
1995 eek_a_bug("signed integral comparison faulty?");
1998 if (maxeri>int_max) {
1999 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2000 co, INT, (long)maxeri, ibits,
2001 "but only for addition, not multiplication",
2002 "(I smell a Cyber!)",
2006 if (minneri<int_min) {
2007 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2008 co, INT, (long)minneri,
2009 "but only for addition, not multiplication",
2010 "(I smell a Cyber!)",
2015 Procedure UPROP () {
2016 /* The properties of unsigned short/int/long */
2018 Volatile unsigned Integer u_max, newi, two;
2019 newi=1; u_max=0; two=2;
2021 if (setjmp(lab)==0) { /* Yields u_max */
2028 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2029 co, INT, (unsigned long) u_max, oc);
2031 /* Oh woe: new standard C defines value preserving promotions */
2033 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2034 /* Special only for short */
2035 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2036 (unsigned long) u_max, 0L,
2037 (unsigned long) U_MAX, IMARK);
2039 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2040 (unsigned long) u_max,
2041 (unsigned long) U_MAX, IMARK);
2047 #endif /* Integer */
2051 /* The following routines are intended to defeat any attempt at optimisation
2052 or use of extended precision, and to defeat faulty narrowing casts.
2053 The weird prototypes are because of widening incompatibilities.
2056 #define ARGS1(atype, a) (atype a)
2057 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2059 #define ARGS1(atype, a) (a) atype a;
2060 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2063 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2064 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2065 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2066 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2067 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2068 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2070 Procedure F_check ARGS((int precision, Long_double val1));
2072 Procedure F_check(precision, val1) int precision; Long_double val1; {
2073 /* You don't think I'm going to go to all the trouble of writing
2074 a program that works out what all sorts of values are, only to
2075 have printf go and print the wrong values out, do you?
2076 No, you're right, so this function tries to see if printf
2077 has written the right value, by reading it back again.
2078 This introduces a new problem of course: suppose printf writes
2079 the correct value, and scanf reads it back wrong... oh well.
2080 But I'm adamant about this: the precision given is enough
2081 to uniquely identify the printed number, therefore I insist
2082 that sscanf read the number back identically. Harsh yes, but
2083 sometimes you've got to be cruel to be kind.
2086 Number val, new, diff;
2092 if (sizeof(double) == sizeof(Long_double)) {
2093 /* Assume they're the same, and use non-stdc format */
2094 /* This is for stdc compilers using non-stdc libraries */
2095 f2= "%le"; /* Input */
2097 /* It had better support Le then */
2101 rep= f_rep(precision, (Long_double) val);
2102 if (setjmp(lab)==0) {
2103 sscanf(rep, f2, &new1);
2105 eek_a_bug("sscanf caused a trap");
2106 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2111 if (setjmp(lab)==0) { /* See if new is usable */
2114 diff= val/new - 1.0;
2115 if (diff < 0.1) diff= 1.0;
2116 /* That should be enough to generate a trap */
2119 eek_a_bug("sscanf returned an unusable number");
2120 printf("%s scanning: %s with format: %s%s\n\n",
2128 eek_a_bug("Possibly bad output from printf above");
2129 if (!exponent((Long_double)val, &rem, &e)) {
2130 printf("%s but value was an unusable number%s\n\n",
2134 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2135 co, precision, rem, e);
2136 bitpattern((char *) &val, (unsigned)sizeof(val));
2137 printf ("%s\n", oc);
2138 printf("%s sscanf gave %s, bit pattern:\n ",
2139 co, f_rep(precision, (Long_double) new));
2140 bitpattern((char *) &new, (unsigned)sizeof(new));
2141 printf ("%s\n", oc);
2142 if (setjmp(lab) == 0) {
2144 printf("%s difference= %s%s\n\n",
2145 co, f_rep(precision, (Long_double) diff), oc);
2146 } /* else forget it */
2152 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2153 /* Check that the compiler has read a #define value correctly */
2156 printf("%s*** Verify failed for above #define!\n", co);
2157 if (setjmp(lab) == 0) { /* for the case that req == nan */
2158 printf(" Compiler has %s for value%s\n",
2159 f_rep(prec, req), oc);
2161 printf(" Compiler has %s for value%s\n",
2162 "an unusable number", oc);
2164 if (setjmp(lab) == 0) {
2165 F_check(prec, (Long_double) req);
2166 } /*else forget it*/
2167 if (setjmp(lab) == 0) {
2168 if (req > 0.0 && val > 0.0) {
2169 printf("%s difference= %s%s\n",
2170 co, f_rep(prec, val-req), oc);
2172 } /*else forget it*/
2176 } else if (val != req) {
2177 if (stdc) eek_a_bug("constant has the wrong precision");
2178 else eek_a_bug("the cast didn't work");
2184 int FPROP(bits_per_byte) int bits_per_byte; {
2185 /* Properties of floating types, using algorithms by Cody and Waite
2186 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2187 Further extended by S Pemberton.
2189 Returns the number of digits in the fraction.
2193 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2194 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2195 mantbits, digs, f_dig, trap,
2196 hidden, normal, f_min_10_exp, f_max_10_exp;
2198 a, b, base, basein, basem1, f_epsilon, epsneg,
2199 eps, epsp1, etop, ebot,
2200 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2204 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2206 /* Base and size of significand **************************************/
2207 /* First repeatedly double until adding 1 has no effect. */
2208 /* For instance, if base is 10, with 3 significant digits */
2209 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2210 /* since 1024 is only representable as 1020. */
2212 if (setjmp(lab)==0) { /* inexact trap? */
2214 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2216 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2217 /* And supporting those is just TOO much trouble! */
2221 /* Now double until you find a number that can be added to the */
2222 /* above number. For 1020 this is 8 or 16, depending whether the */
2223 /* result is rounded or truncated. */
2224 /* In either case the result is 1030. 1030-1020= the base, 10. */
2226 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2228 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2230 /* Sanity check; if base<2, I can't guarantee the rest will work */
2232 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2237 if (PASS == 1) { /* only for FLT */
2239 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2240 (long) f_radix, 0L, (long) F_RADIX, "");
2241 } else if (f_radix != flt_radix) {
2242 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2243 co, thing, "arithmetic has a different radix",
2244 f_radix, "from float", oc);
2248 /* Now the number of digits precision */
2249 f_mant_dig=0; b=1.0;
2250 do { f_mant_dig++; b=Mul(b, base); }
2251 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2252 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2253 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2254 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2255 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2256 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2257 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2258 (long) f_dig, 0L, (long) F_DIG, "");
2259 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2261 /* Rounding *******************************************************/
2262 basem1=Diff(base, HALF);
2263 if (Diff(Sum(a, basem1), a) != ZERO) {
2264 if (f_radix == 2) basem1=0.375;
2266 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2267 else irnd=1; /* to nearest */
2268 } else irnd=0; /* towards 0 */
2270 basem1=Diff(base, HALF);
2272 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2273 if (f_radix == 2) basem1=0.375;
2275 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2276 else mrnd=1; /* to nearest */
2277 } else mrnd=0; /* towards 0 */
2279 f_rounds= -1; /* Unknown rounding */
2280 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2281 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2282 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2283 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2285 if (f_rounds != -1) {
2286 Vprintf("%sArithmetic rounds towards ", co);
2288 case 0: Vprintf("zero (i.e. it chops)"); break;
2289 case 1: Vprintf("nearest"); break;
2290 case 2: Vprintf("+infinity"); break;
2291 case 3: Vprintf("-infinity"); break;
2292 default: Vprintf("???"); break;
2294 Vprintf("%s\n", oc);
2295 } else { /* Hmm, try to give some help here */
2296 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2297 Vprintf("%s Negative numbers %s%s\n",
2298 co, mrnd==0 ? "towards zero" :
2299 mrnd==1 ? "to nearest" :
2302 Vprintf("%s Positive numbers %s%s\n",
2303 co, irnd==0 ? "towards zero" :
2304 irnd==1 ? "to nearest" :
2308 /* An extra goody */
2309 if (f_radix == 2 && f_rounds == 1) {
2310 if (Diff(Sum(a, ONE), a) != ZERO) {
2311 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2312 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2313 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2315 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2318 if (PASS == 1) { /* only for FLT */
2319 flt_rounds= f_rounds;
2321 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2322 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2323 } else if (f_rounds != flt_rounds) {
2324 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2325 co, thing, "arithmetic rounds differently",
2326 f_rounds, "from float", oc);
2330 /* Various flavours of epsilon ************************************/
2331 negeps=f_mant_dig+f_mant_dig;
2334 for(i=1; i<=negeps; i++) a*=basein;
2337 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2342 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2347 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2348 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2349 ebot and etop are the current bounds */
2350 while (eps != ebot && eps != etop) {
2351 epsp1 = Diff(ONE, eps);
2352 if (epsp1 < ONE) etop = eps;
2354 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2358 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2359 eek_a_bug("internal error calculating epsneg");
2361 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2362 co, f_rep(digs, (Long_double) eps), oc);
2363 if (V) F_check(digs, (Long_double) eps);
2366 if ((f_radix!=2) && irnd) {
2367 /* a=(a*(1.0+a))/(1.0+1.0); => */
2368 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2369 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2370 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2372 /* epsneg is used later */
2375 machep= -f_mant_dig-f_mant_dig;
2377 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2378 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2383 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2384 /* find the smallest eps (1+eps != 1) by binary search.
2385 ebot and etop are the current bounds */
2386 while (eps != ebot && eps != etop) {
2387 epsp1 = Sum(ONE, eps);
2388 if (epsp1 > ONE) etop = eps;
2390 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2393 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2394 eek_a_bug("internal error calculating eps");
2398 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2399 co, f_rep(digs, (Long_double) f_epsilon), oc);
2401 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2402 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2403 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2405 /* Possible loss of precision warnings here from non-stdc compilers */
2406 if (F) f_define(D_EPSILON, thing,
2407 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2408 if (V || F) F_check(digs, (Long_double) f_epsilon);
2410 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2411 f_epsilon == Self(F_EPSILON));
2414 /* Extra chop info *************************************************/
2415 if (f_rounds == 0) {
2416 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2417 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2421 /* Size of and minimum normalised exponent ************************/
2422 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2424 /* Coarse search for the largest power of two */
2425 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2428 z=Mul(y,y); z1=Mul(z1, y);
2431 if (z2 != y1) break;
2432 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2437 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2441 if (f_radix != 10) {
2442 iexp=i+1; /* for the sign */
2447 while (k >= iz) { iz*=f_radix; iexp++; }
2451 /* Fine tune starting with y and y1 */
2452 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2455 y=Div(y,base); y1=Div(y1,base);
2458 if (z2 != z1) break;
2459 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2467 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2468 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2469 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2471 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2472 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2474 if (setjmp(lab)==0) {
2475 Vprintf("%sMinimum normalised positive number = %s%s\n",
2476 co, f_rep(digs, (Long_double) f_min), oc);
2478 eek_a_bug("printf can't print the smallest normalised number");
2482 /* Possible loss of precision warnings here from non-stdc compilers */
2483 if (setjmp(lab) == 0) {
2484 if (F) f_define(D_MIN, thing,
2485 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2486 if (V || F) F_check(digs, (Long_double) f_min);
2488 eek_a_bug("xxx_MIN caused a trap");
2492 if (setjmp(lab) == 0) {
2493 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2494 f_min == Self(F_MIN));
2496 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2497 co, "Compiler has an unusable number for value", oc);
2502 a=1.0; f_min_10_exp=0;
2503 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2504 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2505 (long) f_min_10_exp, (long) maxint,
2506 (long) F_MIN_10_EXP, "");
2508 /* Minimum exponent ************************************************/
2509 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2514 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2519 if (xminner != 0.0 && xminner != f_min) {
2521 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2523 if (setjmp(lab)==0) {
2524 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2525 co, f_rep(digs, (Long_double) xminner), oc);
2526 if (V) F_check(digs, (Long_double) xminner);
2528 eek_a_bug("printf can't print the smallest unnormalised number.");
2534 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2537 /* Maximum exponent ************************************************/
2538 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2540 while (f_max<newxmax) {
2542 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2543 newxmax=Mul(newxmax, base);
2548 if (Div(newxmax, base) != f_max) {
2549 inf=1; /* ieee infinity */
2556 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2559 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2560 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2561 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2562 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2564 /* Largest number ***************************************************/
2565 f_max=Diff(ONE, epsneg);
2566 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2567 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2569 if (setjmp(lab)==0) {
2570 Vprintf("%sMaximum number = %s%s\n",
2571 co, f_rep(digs, (Long_double) f_max), oc);
2573 eek_a_bug("printf can't print the largest double.");
2576 if (setjmp(lab)==0) {
2577 /* Possible loss of precision warnings here from non-stdc compilers */
2578 if (F) f_define(D_MAX, thing,
2579 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2580 if (V || F) F_check(digs, (Long_double) f_max);
2582 eek_a_bug("xxx_MAX caused a trap");
2585 if (setjmp(lab)==0) {
2586 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2587 f_max == Self(F_MAX));
2589 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2590 co, "Compiler has an unusable number for value", oc);
2595 a=1.0; f_max_10_exp=0;
2596 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2597 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2598 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2600 /* Hidden bit + sanity check ****************************************/
2601 if (f_radix != 10) {
2603 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2604 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2606 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2607 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2608 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2611 printf("\n%s%s\n %s %s %s!%s\n\n",
2613 "*** Something fishy here!",
2614 "Exponent size + significand size doesn't match",
2615 "with the size of a", thing,
2618 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2619 Vprintf("%sIt looks like %s length IEEE format%s\n",
2620 co, f_mant_dig==24 ? "single" :
2621 f_mant_dig==53 ? "double" :
2622 f_mant_dig >53 ? "extended" :
2624 if (f_rounds != 1 || normal) {
2625 Vprintf("%s though ", co);
2626 if (f_rounds != 1) {
2627 Vprintf("the rounding is unusual");
2628 if (normal) Vprintf(" and ");
2630 if (normal) Vprintf("the normalisation is unusual");
2631 Vprintf("%s\n", oc);
2634 Vprintf("%sIt doesn't look like IEEE format%s\n",
2638 printf("\n"); /* regardless of verbosity */
2642 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2643 /* See if expressions are evaluated in extended precision.
2644 Some compilers optimise even if you don't want it,
2645 and then this function fails to produce the right result.
2646 We try to diagnose this if it happens.
2649 Volatile double a, b, base, old;
2650 Volatile Number d, oldd, dbase, one, zero;
2653 /* Size of significand **************************************/
2655 if (setjmp(lab) == 0) { /* Yields nothing */
2656 do { old=a; a=a+a; }
2657 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2660 /* Avoid the comparison if bad is set,
2661 to avoid trouble on the convex. */
2662 if (!bad && (a <= old)) bad=1;
2666 if (setjmp(lab) == 0) { /* Yields nothing */
2667 do { old=b; b=b+b; }
2668 while ((base=((a+b)-a)) == 0.0 && b>old);
2669 if (b <= old) bad=1;
2674 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2675 if (setjmp(lab) == 0) { /* Yields nothing */
2676 do { eprec++; oldd=d; d=d*dbase; }
2677 while ((((d+one)-d)-one) == zero && d>oldd);
2678 if (d <= oldd) bad=1;
2685 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2686 co, thing, " check that you compiled without optimisation!",
2688 } else if (eprec==dprec) {
2689 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2691 } else if (eprec==fprec) {
2692 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2694 } else if (eprec==lprec) {
2695 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2698 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2699 co, Thing, eprec>dprec ? "higher" : "lower",
2700 "precision than double,\n using",
2701 eprec, "base digits",
2706 #else /* not Number */
2708 #ifdef FPROP /* Then create dummy routines for long double */
2710 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2714 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2717 #endif /* ifdef Number */
2719 /* Increment the pass number */
2738 #ifdef PASS /* then rescan this file */
2740 #include "enquire.c"
2742 #include FILENAME /* if this line fails to compile, define NO_FILE */