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.
20 With luck and a following wind, just the following will work:
21 cc enquire.c -o enquire
22 You may get some messages about unreachable code, which you can ignore.
24 If your compiler doesn't support: add flag:
25 signed char (eg pcc) -DNO_SC
27 unsigned short and long -DNO_UI
29 signal(), or setjmp/longjmp() -DNO_SIG
31 Try to compile first with no flags, and see if you get any errors -
32 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
33 Some compilers need a -f flag for floating point.
35 Don't use any optimisation flags: the program may not work if you do.
36 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
37 optimiser, to a floating-point unit there's a world of difference.
39 Some compilers offer various flags for different floating point
40 modes; it's worth trying all possible combinations of these.
42 Add -DID=\"name\" if you want the machine/flags identified in the output.
45 Because of bugs and/or inadequacies, some compilers need the following
48 If your C preprocessor doesn't have the predefined __FILE__ macro, and
49 you don't want to call this file enquire.c but, say, tell.c, add the
50 flag -DFILENAME=\"tell.c\" .
52 Some compilers won't accept the line "#include FILENAME".
53 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
55 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
56 or -DNO_FILE as above.
58 Some naughty compilers define __STDC__, but don't really support it.
59 Some define it as 0, in which case we treat it as undefined.
60 But if your compiler defines it, and isn't really ANSI C,
61 add flag -DNO_STDC. (To those compiler writers: for shame).
63 Some naughty compilers define __STDC__, but don't have the stddef.h
64 include file. Add flag -DNO_STDDEF.
66 Summary of naughty-compiler flags:
67 If your compiler doesn't support: add flag:
68 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
69 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
70 #include FILENAME -DNO_FILE
71 __STDC__ (properly) -DNO_STDC
74 Some systems crash when you try to malloc all store. To save users of
75 such defective systems too much grief, they may compile with -DNO_MEM,
76 which ignores that bit of the code.
78 While it is not our policy to support defective compilers, pity has been
79 taken on people with compilers that can't produce object files bigger than
80 32k (especially since it was an easy addition). Compile the program
81 into separate parts like this:
82 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
83 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
84 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
85 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
86 cc -o enquire p0.o p1.o p2.o p3.o
89 You may possibly need to add some calls to signal() for other sorts of
90 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
91 #ifdef SIGxxx in main() (and communicate the differences to me!).
94 Run without argument to get the information as English text. If run
95 with argument -l (e.g. enquire -l), output is a series of #define's for
96 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
97 with argument -f, output is a series of #define's for the ANSI standard
98 float.h include file (according to ANSI C Draft of Dec 7, 1988).
99 Flag -v gives verbose output: output includes the English text above
100 as C comments. The program exit(0)'s if everything went ok, otherwise
101 it exits with a positive number, telling how many problems there were.
103 VERIFYING THE COMPILER
104 If, having produced the float.h and limits.h header files, you want to
105 verify that the compiler reads them back correctly (there are a lot of
106 boundary cases, of course, like minimum and maximum numbers), you can
107 recompile enquire.c with -DVERIFY set (plus the other flags that you used
108 when compiling the version that produced the header files). This then
109 recompiles the program so that it #includes "limits.h" and "float.h",
110 and checks that the constants it finds there are the same as the
111 constants it produces. Run the resulting program with enquire -fl.
112 Very few compilers have passed without error.
113 NB: You *must* recompile with the same compiler and flags, otherwise
114 you may get odd results.
116 You can also use this option if your compiler already has both files,
117 and you want to confirm that this program produces the right results.
120 This program is now quite trustworthy, and suspicious and wrong output
121 may well be caused by bugs in the compiler, not in the program (however
122 of course, this is not guaranteed, and no responsibility can be
125 The program only works if overflows are ignored by the C system or
126 are catchable with signal().
128 If the program fails to run to completion (often with the error message
129 "Unexpected signal at point x"), this often turns out to be a bug in the
130 C compiler's run-time system. Check what was about to be printed, and
131 try to narrow the problem down.
133 Another possible problem is that you have compiled the program to produce
134 loss-of-precision arithmetic traps. The program cannot cope with these,
135 and you should re-compile without them. (They should never be the default).
137 Make sure you compiled with optimisation turned off.
139 Output preceded by *** WARNING: identifies behaviour of the C system
140 deemed incorrect by the program. Likely problems are that printf or
141 scanf don't cope properly with certain boundary numbers: this program
142 goes to a lot of trouble to calculate its values, and these values
143 are mostly boundary numbers. Experience has shown that often printf
144 cannot cope with these values, and so in an attempt to increase
145 confidence in the output, for each float and double that is printed,
146 the printed value is checked by using sscanf to read it back.
147 Care is taken that numbers are printed with enough digits to uniquely
148 identify them, and therefore that they can be read back identically.
149 If the number read back is different, then there is probably a bug in
150 printf or sscanf, and the program prints the warning message.
151 If the two numbers in the warning look identical, then printf is more
152 than likely rounding the last digit(s) incorrectly. To put you at ease
153 that the two really are different, the bit patterns of the two numbers
154 are also printed. The difference is very likely in the last bit.
155 Many scanf's read the minimum double back as 0.0, and similarly cause
156 overflow when reading the maximum double. This program quite ruthlessly
157 declares all these behaviours faulty. The point is that if you get
158 one of these warnings, the output may be wrong, so you should check
159 the result carefully if you intend to use the results. Of course, printf
160 and sscanf may both be wrong, and cancel each other out, so you should
161 check the output carefully anyway.
163 The warning that "a cast didn't work" refers to cases like this:
166 #define C 1.234567890123456789
168 if (f != (float) C) printf ("Wrong!");
170 A faulty compiler will widen f to double and ignore the cast to float,
171 and because there is more accuracy in a double than a float, fail to
172 recognise that they are the same. In the actual case in point, f and C
173 are passed as parameters to a function that discovers they are not equal,
174 so it's just possible that the error was in the parameter passing,
175 not in the cast (see function Validate()).
176 For ANSI C, which has float constants, the error message is "constant has
180 If the program doesn't work for you for any reason that can't be
181 narrowed down to a problem in the C compiler, or it has to be changed in
182 order to get it to compile, or it produces suspicious output (like a very
183 low maximum float, for instance), please mail the problem and an example
184 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
185 improvements can be worked into future versions; cwi.nl is the European
186 backbone, and is connected to uunet and other fine hosts.
188 The program tries to catch and diagnose bugs in the compiler/run-time
189 system. I would be especially pleased to have reports of failures so
190 that I can improve this service.
192 I apologise unreservedly for the contorted use of the preprocessor...
195 You may copy and distribute verbatim copies of this source file.
197 You may modify this source file, and copy and distribute such
198 modified versions, provided that you leave the copyright notice
199 at the top of the file and also cause the modified file to carry
200 prominent notices stating that you changed the files and the date
201 of any change; and cause the whole of any work that you distribute
202 or publish, that in whole or in part contains or is a derivative of
203 this program or any part thereof, to be licensed at no charge to
204 all third parties on terms identical to those here.
206 If you do have a fix to any problem, please send it to me, so that
207 other people can have the benefits.
209 While every effort has been taken to make this program as reliable as
210 possible, no responsibility can be taken for the correctness of the
211 output, nor suitability for any particular use.
213 This program is an offshoot of a project funded by public funds.
214 If you use this program for research or commercial use (i.e. more
215 than just for the fun of knowing about your compiler) mailing a short
216 note of acknowledgement may help keep enquire.c supported.
219 Many people have given time and ideas to making this program what it is.
220 To all of them thanks, and apologies for not mentioning them by name.
223 Originally started as a program to generate configuration constants
224 for a large piece of software we were writing, which later took on
226 1.0 Length 6658!; end 1984?
227 Unix only. Only printed a dozen maximum int/double values.
228 2.0 Length 10535; Spring 1985
229 Prints values as #defines (about 20 of them)
230 More extensive floating point, using Cody and Waite
231 Handles signals better
232 Programs around optimisations
234 3.0 Length 12648; Aug 1987; prints about 42 values
235 Added PASS stuff, so treats float as well as double
236 4.0 Length 33891; Feb 1989; prints around 85 values
237 First GNU version (for gcc, where they call it hard-params.c)
238 Generates float.h and limits.h files
240 Generates warnings for dubious output
241 4.1 Length 47738; April 1989
242 Added VERIFY and TEST
243 4.2 Length 63442; Feb 1990
246 Added check for pseudo-unsigned chars
247 Added description for each #define output
248 Added check for absence of defines during verify
250 Added NO_STDC and NO_FILE
251 Fixed alignments output
252 4.3 Length 75000; Oct 1990; around 114 lines of output
253 Function xmalloc defined, Richard Stallman, June 89.
254 Alignments computed from member offsets rather than structure sizes,
255 Richard Stallman, Oct 89.
256 Print whether char* and int* pointers have the same format;
257 also char * and function *.
258 Update to Draft C version Dec 7, 1988
259 - types of constants produced in limits.h
260 (whether to put a U after unsigned shorts and chars and
261 whether to output -1024 as (-1023-1))
262 - values of SCHAR_MIN/MAX
263 - values of *_EPSILON (not the smallest but the effective smallest)
264 Added FILENAME, since standard C doesn't allow #define __FILE__
265 Renamed from config.c to enquire.c
266 Added size_t and ptrdiff_t enquiries
267 Added promotion enquiries
268 Added type checks of #defines
270 Changed endian to allow for cases where not all bits are used
271 Sanity check for max integrals
272 Fixed definition of setjmp for -DNO_SIG
273 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
277 /* Set FILENAME to the name of this file */
280 #define FILENAME "enquire.c"
282 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
283 #define FILENAME __FILE__
285 #define FILENAME "enquire.c"
286 #endif /* __FILE__ */
288 #endif /* FILENAME */
290 /* If PASS isn't defined, then this is the first pass over this file. */
298 /* A description of the ANSI constants */
299 #define D_CHAR_BIT "Number of bits in a storage unit"
300 #define D_CHAR_MAX "Maximum char"
301 #define D_CHAR_MIN "Minimum char"
302 #define D_SCHAR_MAX "Maximum signed char"
303 #define D_SCHAR_MIN "Minimum signed char"
304 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
306 #define D_INT_MAX "Maximum %s"
307 #define D_INT_MIN "Minimum %s"
308 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
310 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
311 #define D_FLT_RADIX "Radix of exponent representation"
312 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
313 #define D_DIG "Number of decimal digits of precision in a %s"
314 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
315 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
316 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
317 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
318 #define D_MAX "Maximum %s"
319 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
320 #define D_MIN "Minimum normalised %s"
322 /* Procedure just marks the functions that don't return a result */
324 #define Procedure int
326 #define Procedure void
329 /* Some bad compilers define __STDC__, when they don't support it.
330 Compile with -DNO_STDC to get round this.
334 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
340 /* Stuff different for ANSI C, and old C:
341 ARGS and NOARGS are used for function prototypes.
342 Volatile is used to reduce the chance of optimisation,
343 and to prevent variables being put in registers (when setjmp/longjmp
344 wouldn't work as we want)
345 Long_double is the longest floating point type available.
346 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
347 U is output after unsigned constants.
352 #define NOARGS (void)
353 #define Volatile volatile
354 #define Long_double long double
358 #else /* Old style C */
362 #define Volatile static
363 #define Long_double double
374 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
385 /* Kludge around the possiblity that <stdio.h> includes <limits.h> */
401 #define Vprintf if (V) printf
402 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
403 #define fabs(x) (((x)<0.0)?(-x):(x))
409 /* Prototypes for what's to come: */
414 char *malloc (); /* Old style prototype */
416 char *malloc ARGS((size_t size));
419 Procedure exit ARGS((int status));
421 char *f_rep ARGS((int precision, Long_double val));
423 int maximum_int NOARGS;
426 Procedure sprop NOARGS;
427 Procedure iprop NOARGS;
428 Procedure lprop NOARGS;
429 Procedure usprop NOARGS;
430 Procedure uiprop NOARGS;
431 Procedure ulprop NOARGS;
432 int fprop ARGS((int bits_per_byte));
433 int dprop ARGS((int bits_per_byte));
434 int ldprop ARGS((int bits_per_byte));
435 Procedure efprop ARGS((int fprec, int dprec, int lprec));
436 Procedure edprop ARGS((int fprec, int dprec, int lprec));
437 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
439 int setmode ARGS((char *s));
440 Procedure farewell ARGS((int bugs));
441 Procedure describe ARGS((char *description, char *extra));
442 Procedure missing ARGS((char *s));
443 Procedure fmissing ARGS((char *s));
444 Procedure check_defines NOARGS;
445 Procedure bitpattern ARGS((char *p, unsigned int size));
446 int ceil_log ARGS((int base, Long_double x));
447 Procedure croak ARGS((int place));
448 Procedure eek_a_bug ARGS((char *problem));
449 Procedure endian ARGS((int bits_per_byte));
450 int exponent ARGS((Long_double x, double *fract, int *exp));
451 int floor_log ARGS((int base, Long_double x));
452 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
453 int prec, Long_double val, char *mark));
454 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
455 long val, long lim, long req, char *mark));
456 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
457 unsigned long val, unsigned long req, char *mark));
459 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
461 /* Dummy routines instead */
463 int setjmp ARGS((int lab));
466 int setjmp(lab) int lab; { return(0); }
467 Procedure signal(i, p) int i, (*p)(); {}
471 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
472 signal(sig, overflow);
478 int V= 0, /* verbose */
479 L= 0, /* produce limits.h */
480 F= 0, /* produce float.h */
481 bugs=0; /* The number of (possible) bugs in the output */
483 char co[4], oc[4]; /* Comment starter and ender symbols */
485 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
486 int flt_rounds; /* The calculated value of FLT_ROUNDS */
487 int flt_radix; /* The calculated value of FLT_RADIX */
490 /* Set the fp modes on a SUN with 68881 chip, to check that different
491 rounding modes etc. get properly detected.
492 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
493 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
494 register to hex-number
497 /* Bits 0x30 = rounding mode */
498 #define ROUND_BITS 0x30
499 #define TO_NEAREST 0x00
501 #define TO_MINUS_INF 0x20
502 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
504 /* Bits 0xc0 = extended rounding */
505 #define EXT_BITS 0xc0
506 #define ROUND_EXTENDED 0x00
507 #define ROUND_SINGLE 0x40
508 #define ROUND_DOUBLE 0x80
511 #define EXE_INEX1 0x100
512 #define EXE_INEX2 0x200
514 #define EXE_UNFL 0x800
515 #define EXE_OVFL 0x1000
516 #define EXE_OPERR 0x2000
517 #define EXE_SNAN 0x4000
518 #define EXE_BSUN 0x8000
520 /* Only used for testing, on a Sun with 68881 chip */
521 /* Print the FP mode */
522 printmode(new) unsigned new; {
524 printf("New fp mode:\n");
525 printf(" Round toward ");
526 switch (new & ROUND_BITS) {
527 case TO_NEAREST: printf("nearest"); break;
528 case TO_ZERO: printf("zero"); break;
529 case TO_MINUS_INF: printf("minus infinity"); break;
530 case TO_PLUS_INF: printf("plus infinity"); break;
531 default: printf("???"); break;
534 printf("\n Extended rounding precision: ");
536 switch (new & EXT_BITS) {
537 case ROUND_EXTENDED: printf("extended"); break;
538 case ROUND_SINGLE: printf("single"); break;
539 case ROUND_DOUBLE: printf("double"); break;
540 default: printf("???"); break;
543 printf("\n Enabled exceptions:");
544 if (new & (unsigned) EXE_INEX1) printf(" inex1");
545 if (new & (unsigned) EXE_INEX2) printf(" inex2");
546 if (new & (unsigned) EXE_DZ) printf(" dz");
547 if (new & (unsigned) EXE_UNFL) printf(" unfl");
548 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
549 if (new & (unsigned) EXE_OPERR) printf(" operr");
550 if (new & (unsigned) EXE_SNAN) printf(" snan");
551 if (new & (unsigned) EXE_BSUN) printf(" bsun");
555 /* Only used for testing, on a Sun with 68881 chip */
556 /* Set the FP mode */
557 int setmode(s) char *s; {
558 unsigned mode=0, dig;
563 if (c>='0' && c<='9') dig= c-'0';
564 else if (c>='a' && c<='f') dig= c-'a'+10;
565 else if (c>='A' && c<='F') dig= c-'A'+10;
574 int setmode(s) char *s; {
575 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
580 Procedure farewell(bugs) int bugs; {
581 if (bugs == 0) exit(0);
582 printf("\n%sFor hints on dealing with the ", co);
583 if (bugs == 1) printf("problem");
584 else printf("%d problems", bugs);
585 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
586 printf("%s%s\n", FILENAME, oc);
590 /* The program has received a signal where it wasn't expecting one */
591 Procedure croak(place) int place; {
592 printf("*** Unexpected signal at point %d\n", place);
593 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
596 /* This is here in case alloca.c is used, which calls this. */
597 char *xmalloc(size) unsigned size; {
598 char *value = (char *)malloc(size);
600 fprintf(stderr, "Virtual memory exceeded\n");
609 /* Find the maximum integer */
610 Volatile int newi, int_max, two=2;
612 /* Calculate maxint ***********************************/
613 /* Calculate 2**n-1 until overflow - then use the previous value */
617 if (setjmp(lab)==0) { /* Yields int_max */
618 while(newi>int_max) {
627 int main(argc, argv) int argc; char *argv[]; {
628 int dprec, fprec, lprec;
631 int i; char *s; int bad;
634 signal(SIGFPE, overflow);
637 signal(SIGOVER, overflow);
639 /* Add more calls as necessary */
644 for (i=1; i < argc; i++) {
650 case 'v': V=1; break;
651 case 'l': L=1; break;
652 case 'f': F=1; break;
653 default: bad=1; break;
656 } else if (*s == '+') {
663 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
668 co[0]= '/'; oc[0]= ' ';
669 co[1]= '*'; oc[1]= '*';
670 co[2]= ' '; oc[2]= '/';
671 co[3]= '\0'; oc[3]= '\0';
673 co[0]= '\0'; oc[0]= '\0';
677 if (L) printf("%slimits.h%s\n", co, oc);
678 if (F) printf("%sfloat.h%s\n", co, oc);
680 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
681 co, ID, VERSION, oc);
683 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
688 printf("%sVerification phase%s\n", co, oc);
692 Vprintf("%sCompiled without signal(): %s%s\n",
694 "there's nothing that can be done if overflow occurs",
698 Vprintf("%sCompiled without signed char%s\n", co, oc);
701 Vprintf("%Compiled without unsigned char%s\n", co, oc);
704 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
707 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
710 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
715 maxint= maximum_int();
716 bits_per_byte= basic();
719 fprec= fprop(bits_per_byte);
720 dprec= dprop(bits_per_byte);
721 lprec= ldprop(bits_per_byte);
722 efprop(fprec, dprec, lprec);
723 edprop(fprec, dprec, lprec);
724 eldprop(fprec, dprec, lprec);
728 /* An extra goody: the approximate amount of data-space */
729 /* Allocate store until no more available */
730 /* Different implementations have a different argument type
731 to malloc. Here we assume that it's the same type as
732 that which sizeof() returns */
733 size=1<<((bits_per_byte*sizeof(int))-2);
736 while ( malloc((false()?sizeof(int):size)) !=
744 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
745 co, (total+511)/512, oc);
749 return bugs; /* To keep compilers and lint happy */
752 Procedure eek_a_bug(problem) char *problem; {
753 /* The program has discovered a problem */
754 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
758 Procedure describe(description, extra) char *description, *extra; {
759 /* Produce the description for a #define */
761 printf(description, extra);
765 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
766 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
767 /* Produce a #define for a signed int type */
768 describe(desc, extra);
770 printf("#define %s%s %ld%s\n", sort, name, val, mark);
771 } else if (val + lim < 0) {
772 /* We may not produce a constant like -1024 if the max
773 allowable value is 1023. It has then to be output as
774 -1023-1. lim is the max allowable value. */
775 printf("#define %s%s (%ld%s%ld%s)\n",
776 sort, name, -lim, mark, val+lim, mark);
778 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
780 /* If VERIFY is not set, val and req are just the same value;
781 if it is set, val is the value as calculated, and req is
782 the #defined constant
785 printf("%s*** Verify failed for above #define!\n", co);
786 printf(" Compiler has %ld for value%s\n\n", req, oc);
792 Procedure u_define(desc, extra, sort, name, val, req, mark)
793 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
794 /* Produce a #define for an unsigned value */
795 describe(desc, extra);
796 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
798 printf("%s*** Verify failed for above #define!\n", co);
799 printf(" Compiler has %lu for value%s\n\n", req, oc);
805 Procedure f_define(desc, extra, sort, name, precision, val, mark)
806 char *desc, *extra, *sort, *name; int precision;
807 Long_double val; char *mark; {
808 /* Produce a #define for a float/double/long double */
809 describe(desc, extra);
811 printf("#define %s%s %s%s\n",
812 sort, name, f_rep(precision, val), mark);
813 } else if (*mark == 'F') {
814 /* non-ANSI C has no float constants, so cast the constant */
815 printf("#define %s%s ((float)%s)\n",
816 sort, name, f_rep(precision, val));
818 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
823 int floor_log(base, x) int base; Long_double x; {
824 /* return floor(log base(x)) */
826 while (x>=base) { r++; x/=base; }
830 int ceil_log(base, x) int base; Long_double x; {
832 while (x>1.0) { r++; x/=base; }
836 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
837 /* Split x into a fraction and a power of ten;
838 returns 0 if x is unusable, 1 otherwise.
839 Only used for error messages about faulty output.
848 if (x==0.0) return 1;
852 if (old==x) return 0;
857 if (old==x) return 0;
860 if (neg) *fract= (double) -x;
861 else *fract=(double) x;
866 char *f_rep(precision, val) int precision; Long_double val; {
867 /* Return the floating representation of val */
868 static char buf[1024];
870 if (sizeof(double) == sizeof(Long_double)) {
871 /* Assume they're the same, and use non-stdc format */
872 /* This is for stdc compilers using non-stdc libraries */
875 /* It had better support Le then */
878 sprintf(buf, f1, precision, val);
882 Procedure bitpattern(p, size) char *p; unsigned int size; {
883 /* Printf the bit-pattern of p */
887 for (i=1; i<=size; i++) {
890 for (j=bits_per_byte-1; j>=0; j--)
891 printf("%c", (c>>j)&1 ? '1' : '0');
892 if (i!=size) printf(" ");
896 #define Order(x, px, mode)\
897 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
898 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
899 putchar(c==0 ? '?' : (char)c); }\
902 Procedure endian(bits_per_byte) int bits_per_byte; {
903 /* Printf the byte-order used on this machine */
904 /*unsigned*/ short s=0;
905 /*unsigned*/ int j=0;
906 /*unsigned*/ long l=0;
908 char *ps= (char *) &s,
911 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
912 unsigned int mask, i, c;
915 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
918 printf("%sCHARACTER ORDER%s\n", co, oc);
919 Order(s, ps, "short:");
920 Order(j, pj, "int: ");
921 Order(l, pl, "long: ");
925 Procedure missing(s) char *s; {
926 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
930 Procedure fmissing(s) char *s; {
931 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
935 /* To try and fool optimisers */
936 int false() { return 0; }
938 #define Promoted(x) (false()?(x):(-1))
939 #define is_signed(x) (Promoted(x) < 0)
940 #define sign_of(x) ((x)?"signed":"unsigned")
943 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
945 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
947 char *type_of(x) int x; {
948 if (x == sizeof(char)) {
949 if (sizeof(char) == sizeof(int)) return "char/short/int";
950 if (sizeof(char) == sizeof(short)) return "char/short";
953 if (x == sizeof(short)) {
954 if (sizeof(short) == sizeof(int)) return "short/int";
957 if (x == sizeof(int)) {
958 if (sizeof(int) == sizeof(long)) return "int/long";
961 if (x == sizeof(long)) return "long";
962 return "unknown-type";
965 char *ftype_of(x) int x; {
966 if (x == sizeof(float)) {
969 if (x == sizeof(double)) {
970 if (sizeof(double) == sizeof(Long_double))
971 return "(long)double";
974 if (x == sizeof(Long_double)) {
975 return "long double";
977 return "unknown-type";
980 Procedure typerr(name, esign, esize, sign, size)
981 char *name; int esign, esize, sign, size;
983 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
984 name, sign_of(esign), type_of(esize),
985 sign_of(sign), type_of(size));
988 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
989 Vprintf("*** %s has wrong type: expected %s, found %s\n",
990 name, ftype_of(esize), ftype_of(size));
995 unsigned int ui; unsigned long ul;
996 short ss; unsigned short us;
998 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1001 /* Possible warnings here; no problem */
1002 (sizeof(Promoted(si)) != sizeof(int)) ||
1003 (sizeof(Promoted(sl)) != sizeof(long)) ||
1004 (sizeof(Promoted(ss)) != sizeof(int)) ||
1005 (sizeof(Promoted(ui)) != sizeof(int)) ||
1006 (sizeof(Promoted(ul)) != sizeof(long)) ||
1007 (sizeof(Promoted(us)) != sizeof(int)) ||
1008 is_signed(ui) || is_signed(ul) ||
1009 !is_signed(si) || !is_signed(sl)
1012 eek_a_bug("promotions don't work properly in conditional expressions\n");
1015 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1016 showtype("long+unsigned gives", sl+ui);
1019 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1021 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1023 Procedure check_defines() {
1024 /* ensure that all #defines are present and have the correct type */
1031 /* Implementations promote unsigned short differently */
1032 usign= is_signed((unsigned short)0);
1037 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1039 missing("CHAR_BIT");
1042 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1044 missing("CHAR_MAX");
1047 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1049 missing("CHAR_MIN");
1052 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1054 missing("SCHAR_MAX");
1057 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1059 missing("SCHAR_MIN");
1062 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1064 missing("UCHAR_MAX");
1067 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1069 missing("SHRT_MAX");
1072 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1074 missing("SHRT_MIN");
1077 checktype(INT_MAX, "INT_MAX", Signed, int);
1082 checktype(INT_MIN, "INT_MIN", Signed, int);
1087 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1089 missing("LONG_MAX");
1092 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1094 missing("LONG_MIN");
1097 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1099 missing("USHRT_MAX");
1102 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1104 missing("UINT_MAX");
1107 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1109 missing("ULONG_MAX");
1115 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1117 fmissing("FLT_RADIX");
1120 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1122 fmissing("FLT_MANT_DIG");
1125 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1127 fmissing("FLT_DIG");
1130 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1132 fmissing("FLT_ROUNDS");
1135 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1137 fmissing("FLT_EPSILON");
1140 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1142 fmissing("FLT_MIN_EXP");
1145 fchecktype(FLT_MIN, "FLT_MIN", float);
1147 fmissing("FLT_MIN");
1149 #ifdef FLT_MIN_10_EXP
1150 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1152 fmissing("FLT_MIN_10_EXP");
1155 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1157 fmissing("FLT_MAX_EXP");
1160 fchecktype(FLT_MAX, "FLT_MAX", float);
1162 fmissing("FLT_MAX");
1164 #ifdef FLT_MAX_10_EXP
1165 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1167 fmissing("FLT_MAX_10_EXP");
1170 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1172 fmissing("DBL_MANT_DIG");
1175 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1177 fmissing("DBL_DIG");
1180 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1182 fmissing("DBL_EPSILON");
1185 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1187 fmissing("DBL_MIN_EXP");
1190 fchecktype(DBL_MIN, "DBL_MIN", double);
1192 fmissing("DBL_MIN");
1194 #ifdef DBL_MIN_10_EXP
1195 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1197 fmissing("DBL_MIN_10_EXP");
1200 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1202 fmissing("DBL_MAX_EXP");
1205 fchecktype(DBL_MAX, "DBL_MAX", double);
1207 fmissing("DBL_MAX");
1209 #ifdef DBL_MAX_10_EXP
1210 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1212 fmissing("DBL_MAX_10_EXP");
1215 #ifdef LDBL_MANT_DIG
1216 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1218 fmissing("LDBL_MANT_DIG");
1221 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1223 fmissing("LDBL_DIG");
1226 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1228 fmissing("LDBL_EPSILON");
1231 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1233 fmissing("LDBL_MIN_EXP");
1236 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1238 fmissing("LDBL_MIN");
1240 #ifdef LDBL_MIN_10_EXP
1241 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1243 fmissing("LDBL_MIN_10_EXP");
1246 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1248 fmissing("LDBL_MAX_EXP");
1251 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1253 fmissing("LDBL_MAX");
1255 #ifdef LDBL_MAX_10_EXP
1256 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1258 fmissing("LDBL_MAX_10_EXP");
1267 #define SCHAR_MAX char_max
1270 #define SCHAR_MIN char_min
1273 #define UCHAR_MAX char_max
1278 #define CHAR_BIT char_bit
1281 #define CHAR_MAX char_max
1284 #define CHAR_MIN char_min
1287 #define SCHAR_MAX char_max
1290 #define SCHAR_MIN char_min
1293 #define UCHAR_MAX char_max
1297 /* Properties of type char */
1298 Volatile char c, char_max, char_min;
1299 Volatile int bits_per_byte, c_signed;
1304 /* Calculate number of bits per character *************************/
1305 c=1; bits_per_byte=0;
1306 do { c=c<<1; bits_per_byte++; } while(c!=0);
1308 if (((int)c)<0) c_signed=1;
1310 Vprintf("%schar = %d bits, %ssigned%s\n",
1311 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1312 char_bit=(long)(sizeof(c)*bits_per_byte);
1313 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1314 char_bit, 0L, (long) CHAR_BIT, "");
1318 if (setjmp(lab)==0) { /* Yields char_max */
1319 while (c>char_max) {
1324 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1328 if (setjmp(lab)==0) { /* Yields char_min */
1329 while (c<char_min) {
1334 if (c_signed && char_min == 0) {
1335 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1336 Vprintf("%s %s%s%s\n",
1337 "They contain only nonnegative values, ",
1338 "but sign extend when used as integers.", co, oc);
1343 /* Because of the integer promotions, you must use a U after
1344 the MAX_CHARS in the following cases */
1345 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1346 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1348 (long) CHAR_MAX, "");
1350 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1351 (long) char_max, 0L,
1352 (long) CHAR_MAX, "");
1354 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1355 (long) char_min, (long) maxint,
1356 (long) CHAR_MIN, "");
1358 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1359 (long) char_max, 0L,
1360 (long) SCHAR_MAX, "");
1361 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1362 (long) char_min, (long) maxint,
1363 (long) SCHAR_MIN, "");
1365 if (sizeof(char) == sizeof(int)) {
1366 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1368 (long) UCHAR_MAX, "");
1370 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1371 (long) char_max, 0L,
1372 (long) UCHAR_MAX, "");
1378 Volatile unsigned char c, char_max;
1381 if (setjmp(lab)==0) { /* Yields char_max */
1382 while (c>char_max) {
1388 if (sizeof(char) == sizeof(int)) {
1389 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1391 (long) UCHAR_MAX, "");
1393 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1394 (long) char_max, 0L,
1395 (long) UCHAR_MAX, "");
1400 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1403 if (setjmp(lab)==0) { /* Yields char_max */
1404 while (c>char_max) {
1411 if (setjmp(lab)==0) { /* Yields char_min */
1412 while (c<char_min) {
1418 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1419 (long) char_min, (long) maxint,
1420 (long) SCHAR_MIN, "");
1421 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1422 (long) char_max, 0L,
1423 (long) SCHAR_MAX, "");
1427 return bits_per_byte;
1431 /* The properties of the basic types.
1432 Returns number of bits per sizeof unit */
1433 Volatile int bits_per_byte;
1434 typedef int function ();
1438 Vprintf("%sSIZES%s\n", co, oc);
1439 bits_per_byte= cprop();
1441 /* Shorts, ints and longs *****************************************/
1442 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1444 (int) sizeof(short)*bits_per_byte,
1445 (int) sizeof(int)*bits_per_byte,
1446 (int) sizeof(long)*bits_per_byte,
1447 (int) sizeof(float)*bits_per_byte,
1448 (int) sizeof(double)*bits_per_byte, oc);
1450 Vprintf("%slong double=%d bits%s\n",
1451 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1453 Vprintf("%schar*=%d bits%s%s\n",
1454 co, (int)sizeof(char *)*bits_per_byte,
1455 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1457 Vprintf("%sint* =%d bits%s%s\n",
1458 co, (int)sizeof(int *)*bits_per_byte,
1459 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1461 Vprintf("%sfunc*=%d bits%s%s\n",
1462 co, (int)sizeof(function *)*bits_per_byte,
1463 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1465 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1466 ((((false()?( sizeof(int)):(-1)) < 0) )?
1467 "signed":"unsigned") ,
1473 showtype("Type size_t is", sizeof(0));
1475 /* Alignment constants ********************************************/
1477 #define alignment(TYPE) \
1478 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1480 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1482 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1484 alignment(char), alignment(short),
1485 alignment(int), alignment(long),
1488 Vprintf("%sfloat=%ld double=%ld%s\n",
1490 alignment(float), alignment(double),
1494 Vprintf("%slong double=%ld%s\n",
1496 alignment(Long_double),
1499 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1501 alignment(char *), alignment(int *), alignment(function *),
1506 /* Ten little endians *********************************************/
1508 endian(bits_per_byte);
1510 /* Pointers *******************************************************/
1512 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1514 if ((long) (char *) &variable == (long) (int *) &variable)
1515 Vprintf("%sChar and int pointer formats seem identical%s\n",
1518 Vprintf("%sChar and int pointer formats are different%s\n",
1520 if ((long) (char *) &variable == (long) (function *) &variable)
1521 Vprintf("%sChar and function pointer formats seem identical%s\n",
1524 Vprintf("%sChar and function pointer formats are different%s\n",
1529 printf("%sStrings are shared%s\n", co, oc);
1530 else printf("%sStrings are not shared%s\n", co, oc);
1534 showtype("Type ptrdiff_t is", p-q);
1536 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1549 return bits_per_byte;
1552 #else /* not PASS0 */
1556 extern int V, L, F, bugs, bits_per_byte;
1557 extern char co[], oc[];
1558 extern char *f_rep();
1560 #endif /* ifdef PASS0 */
1562 /* As I said, I apologise for the contortions below. The functions are
1563 expanded by the preprocessor twice or three times (for float and double,
1564 and maybe for long double, and for short, int and long). That way,
1565 I never make a change to one that I forget to make to the other.
1566 You can look on it as C's fault for not supporting multi-line macro's.
1567 This whole file is read 3 times by the preprocessor, with PASSn set for
1568 n=1, 2 or 3, to decide which parts to reprocess.
1571 /* #undef on an already undefined thing is (wrongly) flagged as an error
1572 by some compilers, therefore the #ifdef that follows:
1598 /* These are the float.h constants */
1629 /* Define the things we're going to use this pass */
1631 #define Number float
1632 #define THING "FLOAT"
1633 #define Thing "Float"
1634 #define thing "float"
1637 #define Store fStore
1649 #define F_check fCheck
1652 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1655 #define EPROP efprop
1657 #define Integer short
1660 #define Iname "SHRT"
1666 #define UPROP usprop
1667 #define Uname "USHRT"
1671 #define I_MAX SHRT_MAX
1674 #define I_MIN SHRT_MIN
1677 #define U_MAX USHRT_MAX
1681 #define F_RADIX FLT_RADIX
1684 #define F_MANT_DIG FLT_MANT_DIG
1687 #define F_DIG FLT_DIG
1690 #define F_ROUNDS FLT_ROUNDS
1693 #define F_EPSILON FLT_EPSILON
1696 #define F_MIN_EXP FLT_MIN_EXP
1699 #define F_MIN FLT_MIN
1701 #ifdef FLT_MIN_10_EXP
1702 #define F_MIN_10_EXP FLT_MIN_10_EXP
1705 #define F_MAX_EXP FLT_MAX_EXP
1708 #define F_MAX FLT_MAX
1710 #ifdef FLT_MAX_10_EXP
1711 #define F_MAX_10_EXP FLT_MAX_10_EXP
1719 #define Number double
1720 #define THING "DOUBLE"
1721 #define Thing "Double"
1722 #define thing "double"
1725 #define Store dStore
1737 #define F_check dCheck
1740 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1743 #define EPROP edprop
1749 #define OK_UI 1 /* Unsigned int is always possible */
1752 #define UPROP uiprop
1753 #define Uname "UINT"
1757 #define I_MAX INT_MAX
1760 #define I_MIN INT_MIN
1763 #define U_MAX UINT_MAX
1767 #define F_MANT_DIG DBL_MANT_DIG
1770 #define F_DIG DBL_DIG
1773 #define F_EPSILON DBL_EPSILON
1776 #define F_MIN_EXP DBL_MIN_EXP
1779 #define F_MIN DBL_MIN
1781 #ifdef DBL_MIN_10_EXP
1782 #define F_MIN_10_EXP DBL_MIN_10_EXP
1785 #define F_MAX_EXP DBL_MAX_EXP
1788 #define F_MAX DBL_MAX
1790 #ifdef DBL_MAX_10_EXP
1791 #define F_MAX_10_EXP DBL_MAX_10_EXP
1800 #define Number long double
1810 #define THING "LONG DOUBLE"
1811 #define Thing "Long double"
1812 #define thing "long double"
1813 #define Fname "LDBL"
1814 #define FPROP ldprop
1815 #define Store ldStore
1821 #define F_check ldCheck
1824 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1827 #define EPROP eldprop
1829 #define Integer long
1832 #define Iname "LONG"
1838 #define UPROP ulprop
1839 #define Uname "ULONG"
1843 #define I_MAX LONG_MAX
1846 #define I_MIN LONG_MIN
1849 #define U_MAX ULONG_MAX
1852 #ifdef LDBL_MANT_DIG
1853 #define F_MANT_DIG LDBL_MANT_DIG
1856 #define F_DIG LDBL_DIG
1859 #define F_EPSILON LDBL_EPSILON
1862 #define F_MIN_EXP LDBL_MIN_EXP
1865 #define F_MIN LDBL_MIN
1867 #ifdef LDBL_MIN_10_EXP
1868 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1871 #define F_MAX_EXP LDBL_MAX_EXP
1874 #define F_MAX LDBL_MAX
1876 #ifdef LDBL_MAX_10_EXP
1877 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1884 #define I_MAX int_max
1887 #define I_MIN int_min
1894 #define F_RADIX f_radix
1897 #define F_MANT_DIG f_mant_dig
1903 #define F_ROUNDS f_rounds
1906 #define F_EPSILON f_epsilon
1909 #define F_MIN_EXP f_min_exp
1914 #ifndef F_MIN_10_EXP
1915 #define F_MIN_10_EXP f_min_10_exp
1918 #define F_MAX_EXP f_max_exp
1923 #ifndef F_MAX_10_EXP
1924 #define F_MAX_10_EXP f_max_10_exp
1928 #define Validate(prec, val, req, same) {;}
1934 /* the properties of short, int, and long */
1935 Volatile Integer newi, int_max, maxeri, int_min, minneri;
1936 Volatile int ibits, ipower, two=2;
1938 /* Calculate max short/int/long ***********************************/
1939 /* Calculate 2**n-1 until overflow - then use the previous value */
1943 if (setjmp(lab)==0) { /* Yields int_max */
1944 for(ipower=0; newi>int_max; ipower++) {
1948 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
1949 co, INT[0]=='i'?"n":"", INT, oc);
1951 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
1952 co, INT[0]=='i'?"n":"", INT, oc);
1956 /* Minimum value: assume either two's or one's complement *********/
1958 if (setjmp(lab)==0) { /* Yields int_min */
1959 if (int_min-1 < int_min) int_min--;
1963 /* Now for those daft Cybers */
1965 maxeri=0; newi=int_max;
1967 if (setjmp(lab)==0) { /* Yields maxeri */
1968 for(ibits=ipower; newi>maxeri; ibits++) {
1976 if (setjmp(lab)==0) { /* Yields minneri */
1977 if (minneri-1 < minneri) minneri--;
1981 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
1982 co, INT, (long)int_max, ipower, oc);
1983 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
1985 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
1987 (long) I_MAX, IMARK);
1988 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
1989 (long) int_min, (long) (PASS==1?maxint:int_max),
1990 (long) I_MIN, IMARK);
1992 if(int_max < 0) { /* It has happened */
1993 eek_a_bug("signed integral comparison faulty?");
1996 if (maxeri>int_max) {
1997 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
1998 co, INT, (long)maxeri, ibits,
1999 "but only for addition, not multiplication",
2000 "(I smell a Cyber!)",
2004 if (minneri<int_min) {
2005 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2006 co, INT, (long)minneri,
2007 "but only for addition, not multiplication",
2008 "(I smell a Cyber!)",
2013 Procedure UPROP () {
2014 /* The properties of unsigned short/int/long */
2016 Volatile unsigned Integer u_max, newi, two;
2017 newi=1; u_max=0; two=2;
2019 if (setjmp(lab)==0) { /* Yields u_max */
2026 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2027 co, INT, (unsigned long) u_max, oc);
2029 /* Oh woe: new standard C defines value preserving promotions */
2031 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2032 /* Special only for short */
2033 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2034 (unsigned long) u_max, 0L,
2035 (unsigned long) U_MAX, IMARK);
2037 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2038 (unsigned long) u_max,
2039 (unsigned long) U_MAX, IMARK);
2045 #endif /* Integer */
2049 /* The following routines are intended to defeat any attempt at optimisation
2050 or use of extended precision, and to defeat faulty narrowing casts.
2051 The weird prototypes are because of widening incompatibilities.
2054 #define ARGS1(atype, a) (atype a)
2055 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2057 #define ARGS1(atype, a) (a) atype a;
2058 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2061 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2062 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2063 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2064 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2065 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2066 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2068 Procedure F_check ARGS((int precision, Long_double val1));
2070 Procedure F_check(precision, val1) int precision; Long_double val1; {
2071 /* You don't think I'm going to go to all the trouble of writing
2072 a program that works out what all sorts of values are, only to
2073 have printf go and print the wrong values out, do you?
2074 No, you're right, so this function tries to see if printf
2075 has written the right value, by reading it back again.
2076 This introduces a new problem of course: suppose printf writes
2077 the correct value, and scanf reads it back wrong... oh well.
2078 But I'm adamant about this: the precision given is enough
2079 to uniquely identify the printed number, therefore I insist
2080 that sscanf read the number back identically. Harsh yes, but
2081 sometimes you've got to be cruel to be kind.
2084 Number val, new, diff;
2090 if (sizeof(double) == sizeof(Long_double)) {
2091 /* Assume they're the same, and use non-stdc format */
2092 /* This is for stdc compilers using non-stdc libraries */
2093 f2= "%le"; /* Input */
2095 /* It had better support Le then */
2099 rep= f_rep(precision, (Long_double) val);
2100 if (setjmp(lab)==0) {
2101 sscanf(rep, f2, &new1);
2103 eek_a_bug("sscanf caused a trap");
2104 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2109 if (setjmp(lab)==0) { /* See if new is usable */
2112 diff= val/new - 1.0;
2113 if (diff < 0.1) diff= 1.0;
2114 /* That should be enough to generate a trap */
2117 eek_a_bug("sscanf returned an unusable number");
2118 printf("%s scanning: %s with format: %s%s\n\n",
2126 eek_a_bug("Possibly bad output from printf above");
2127 if (!exponent((Long_double)val, &rem, &e)) {
2128 printf("%s but value was an unusable number%s\n\n",
2132 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2133 co, precision, rem, e);
2134 bitpattern((char *) &val, (unsigned)sizeof(val));
2135 printf ("%s\n", oc);
2136 printf("%s sscanf gave %s, bit pattern:\n ",
2137 co, f_rep(precision, (Long_double) new));
2138 bitpattern((char *) &new, (unsigned)sizeof(new));
2139 printf ("%s\n", oc);
2140 if (setjmp(lab) == 0) {
2142 printf("%s difference= %s%s\n\n",
2143 co, f_rep(precision, (Long_double) diff), oc);
2144 } /* else forget it */
2150 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2151 /* Check that the compiler has read a #define value correctly */
2154 printf("%s*** Verify failed for above #define!\n", co);
2155 if (setjmp(lab) == 0) { /* for the case that req == nan */
2156 printf(" Compiler has %s for value%s\n",
2157 f_rep(prec, req), oc);
2159 printf(" Compiler has %s for value%s\n",
2160 "an unusable number", oc);
2162 if (setjmp(lab) == 0) {
2163 F_check(prec, (Long_double) req);
2164 } /*else forget it*/
2165 if (setjmp(lab) == 0) {
2166 if (req > 0.0 && val > 0.0) {
2167 printf("%s difference= %s%s\n",
2168 co, f_rep(prec, val-req), oc);
2170 } /*else forget it*/
2174 } else if (val != req) {
2175 if (stdc) eek_a_bug("constant has the wrong precision");
2176 else eek_a_bug("the cast didn't work");
2182 int FPROP(bits_per_byte) int bits_per_byte; {
2183 /* Properties of floating types, using algorithms by Cody and Waite
2184 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2185 Further extended by S Pemberton.
2187 Returns the number of digits in the fraction.
2191 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2192 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2193 mantbits, digs, f_dig, trap,
2194 hidden, normal, f_min_10_exp, f_max_10_exp;
2196 a, b, base, basein, basem1, f_epsilon, epsneg,
2197 eps, epsp1, etop, ebot,
2198 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2202 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2204 /* Base and size of significand **************************************/
2205 /* First repeatedly double until adding 1 has no effect. */
2206 /* For instance, if base is 10, with 3 significant digits */
2207 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2208 /* since 1024 is only representable as 1020. */
2210 if (setjmp(lab)==0) { /* inexact trap? */
2212 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2214 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2215 /* And supporting those is just TOO much trouble! */
2219 /* Now double until you find a number that can be added to the */
2220 /* above number. For 1020 this is 8 or 16, depending whether the */
2221 /* result is rounded or truncated. */
2222 /* In either case the result is 1030. 1030-1020= the base, 10. */
2224 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2226 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2228 /* Sanity check; if base<2, I can't guarantee the rest will work */
2230 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2235 if (PASS == 1) { /* only for FLT */
2237 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2238 (long) f_radix, 0L, (long) F_RADIX, "");
2239 } else if (f_radix != flt_radix) {
2240 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2241 co, thing, "arithmetic has a different radix",
2242 f_radix, "from float", oc);
2246 /* Now the number of digits precision */
2247 f_mant_dig=0; b=1.0;
2248 do { f_mant_dig++; b=Mul(b, base); }
2249 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2250 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2251 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2252 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2253 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2254 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2255 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2256 (long) f_dig, 0L, (long) F_DIG, "");
2257 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2259 /* Rounding *******************************************************/
2260 basem1=Diff(base, HALF);
2261 if (Diff(Sum(a, basem1), a) != ZERO) {
2262 if (f_radix == 2) basem1=0.375;
2264 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2265 else irnd=1; /* to nearest */
2266 } else irnd=0; /* towards 0 */
2268 basem1=Diff(base, HALF);
2270 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2271 if (f_radix == 2) basem1=0.375;
2273 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2274 else mrnd=1; /* to nearest */
2275 } else mrnd=0; /* towards 0 */
2277 f_rounds= -1; /* Unknown rounding */
2278 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2279 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2280 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2281 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2283 if (f_rounds != -1) {
2284 Vprintf("%sArithmetic rounds towards ", co);
2286 case 0: Vprintf("zero (i.e. it chops)"); break;
2287 case 1: Vprintf("nearest"); break;
2288 case 2: Vprintf("+infinity"); break;
2289 case 3: Vprintf("-infinity"); break;
2290 default: Vprintf("???"); break;
2292 Vprintf("%s\n", oc);
2293 } else { /* Hmm, try to give some help here */
2294 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2295 Vprintf("%s Negative numbers %s%s\n",
2296 co, mrnd==0 ? "towards zero" :
2297 mrnd==1 ? "to nearest" :
2300 Vprintf("%s Positive numbers %s%s\n",
2301 co, irnd==0 ? "towards zero" :
2302 irnd==1 ? "to nearest" :
2306 /* An extra goody */
2307 if (f_radix == 2 && f_rounds == 1) {
2308 if (Diff(Sum(a, ONE), a) != ZERO) {
2309 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2310 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2311 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2313 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2316 if (PASS == 1) { /* only for FLT */
2317 flt_rounds= f_rounds;
2319 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2320 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2321 } else if (f_rounds != flt_rounds) {
2322 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2323 co, thing, "arithmetic rounds differently",
2324 f_rounds, "from float", oc);
2328 /* Various flavours of epsilon ************************************/
2329 negeps=f_mant_dig+f_mant_dig;
2332 for(i=1; i<=negeps; i++) a*=basein;
2335 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2340 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2345 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2346 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2347 ebot and etop are the current bounds */
2348 while (eps != ebot && eps != etop) {
2349 epsp1 = Diff(ONE, eps);
2350 if (epsp1 < ONE) etop = eps;
2352 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2356 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2357 eek_a_bug("internal error calculating epsneg");
2359 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2360 co, f_rep(digs, (Long_double) eps), oc);
2361 if (V) F_check(digs, (Long_double) eps);
2364 if ((f_radix!=2) && irnd) {
2365 /* a=(a*(1.0+a))/(1.0+1.0); => */
2366 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2367 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2368 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2370 /* epsneg is used later */
2373 machep= -f_mant_dig-f_mant_dig;
2375 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2376 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2381 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2382 /* find the smallest eps (1+eps != 1) by binary search.
2383 ebot and etop are the current bounds */
2384 while (eps != ebot && eps != etop) {
2385 epsp1 = Sum(ONE, eps);
2386 if (epsp1 > ONE) etop = eps;
2388 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2391 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2392 eek_a_bug("internal error calculating eps");
2396 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2397 co, f_rep(digs, (Long_double) f_epsilon), oc);
2399 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2400 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2401 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2403 /* Possible loss of precision warnings here from non-stdc compilers */
2404 if (F) f_define(D_EPSILON, thing,
2405 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2406 if (V || F) F_check(digs, (Long_double) f_epsilon);
2408 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2409 f_epsilon == Self(F_EPSILON));
2412 /* Extra chop info *************************************************/
2413 if (f_rounds == 0) {
2414 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2415 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2419 /* Size of and minimum normalised exponent ************************/
2420 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2422 /* Coarse search for the largest power of two */
2423 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2426 z=Mul(y,y); z1=Mul(z1, y);
2429 if (z2 != y1) break;
2430 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2435 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2439 if (f_radix != 10) {
2440 iexp=i+1; /* for the sign */
2445 while (k >= iz) { iz*=f_radix; iexp++; }
2449 /* Fine tune starting with y and y1 */
2450 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2453 y=Div(y,base); y1=Div(y1,base);
2456 if (z2 != z1) break;
2457 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2465 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2466 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2467 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2469 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2470 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2472 if (setjmp(lab)==0) {
2473 Vprintf("%sMinimum normalised positive number = %s%s\n",
2474 co, f_rep(digs, (Long_double) f_min), oc);
2476 eek_a_bug("printf can't print the smallest normalised number");
2480 /* Possible loss of precision warnings here from non-stdc compilers */
2481 if (setjmp(lab) == 0) {
2482 if (F) f_define(D_MIN, thing,
2483 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2484 if (V || F) F_check(digs, (Long_double) f_min);
2486 eek_a_bug("xxx_MIN caused a trap");
2490 if (setjmp(lab) == 0) {
2491 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2492 f_min == Self(F_MIN));
2494 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2495 co, "Compiler has an unusable number for value", oc);
2500 a=1.0; f_min_10_exp=0;
2501 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2502 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2503 (long) f_min_10_exp, (long) maxint,
2504 (long) F_MIN_10_EXP, "");
2506 /* Minimum exponent ************************************************/
2507 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2512 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2517 if (xminner != 0.0 && xminner != f_min) {
2519 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2521 if (setjmp(lab)==0) {
2522 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2523 co, f_rep(digs, (Long_double) xminner), oc);
2524 if (V) F_check(digs, (Long_double) xminner);
2526 eek_a_bug("printf can't print the smallest unnormalised number.");
2532 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2535 /* Maximum exponent ************************************************/
2536 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2538 while (f_max<newxmax) {
2540 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2541 newxmax=Mul(newxmax, base);
2546 if (Div(newxmax, base) != f_max) {
2547 inf=1; /* ieee infinity */
2554 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2557 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2558 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2559 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2560 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2562 /* Largest number ***************************************************/
2563 f_max=Diff(ONE, epsneg);
2564 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2565 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2567 if (setjmp(lab)==0) {
2568 Vprintf("%sMaximum number = %s%s\n",
2569 co, f_rep(digs, (Long_double) f_max), oc);
2571 eek_a_bug("printf can't print the largest double.");
2574 if (setjmp(lab)==0) {
2575 /* Possible loss of precision warnings here from non-stdc compilers */
2576 if (F) f_define(D_MAX, thing,
2577 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2578 if (V || F) F_check(digs, (Long_double) f_max);
2580 eek_a_bug("xxx_MAX caused a trap");
2583 if (setjmp(lab)==0) {
2584 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2585 f_max == Self(F_MAX));
2587 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2588 co, "Compiler has an unusable number for value", oc);
2593 a=1.0; f_max_10_exp=0;
2594 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2595 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2596 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2598 /* Hidden bit + sanity check ****************************************/
2599 if (f_radix != 10) {
2601 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2602 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2604 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2605 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2606 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2609 printf("\n%s%s\n %s %s %s!%s\n\n",
2611 "*** Something fishy here!",
2612 "Exponent size + significand size doesn't match",
2613 "with the size of a", thing,
2616 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2617 Vprintf("%sIt looks like %s length IEEE format%s\n",
2618 co, f_mant_dig==24 ? "single" :
2619 f_mant_dig==53 ? "double" :
2620 f_mant_dig >53 ? "extended" :
2622 if (f_rounds != 1 || normal) {
2623 Vprintf("%s though ", co);
2624 if (f_rounds != 1) {
2625 Vprintf("the rounding is unusual");
2626 if (normal) Vprintf(" and ");
2628 if (normal) Vprintf("the normalisation is unusual");
2629 Vprintf("%s\n", oc);
2632 Vprintf("%sIt doesn't look like IEEE format%s\n",
2636 printf("\n"); /* regardless of verbosity */
2640 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2641 /* See if expressions are evaluated in extended precision.
2642 Some compilers optimise even if you don't want it,
2643 and then this function fails to produce the right result.
2644 We try to diagnose this if it happens.
2647 Volatile double a, b, base, old;
2648 Volatile Number d, oldd, dbase, one, zero;
2651 /* Size of significand **************************************/
2653 if (setjmp(lab) == 0) { /* Yields nothing */
2654 do { old=a; a=a+a; }
2655 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2658 /* Avoid the comparison if bad is set,
2659 to avoid trouble on the convex. */
2660 if (!bad && (a <= old)) bad=1;
2664 if (setjmp(lab) == 0) { /* Yields nothing */
2665 do { old=b; b=b+b; }
2666 while ((base=((a+b)-a)) == 0.0 && b>old);
2667 if (b <= old) bad=1;
2672 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2673 if (setjmp(lab) == 0) { /* Yields nothing */
2674 do { eprec++; oldd=d; d=d*dbase; }
2675 while ((((d+one)-d)-one) == zero && d>oldd);
2676 if (d <= oldd) bad=1;
2683 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2684 co, thing, " check that you compiled without optimisation!",
2686 } else if (eprec==dprec) {
2687 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2689 } else if (eprec==fprec) {
2690 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2692 } else if (eprec==lprec) {
2693 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2696 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2697 co, Thing, eprec>dprec ? "higher" : "lower",
2698 "precision than double,\n using",
2699 eprec, "base digits",
2704 #else /* not Number */
2706 #ifdef FPROP /* Then create dummy routines for long double */
2708 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2712 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2715 #endif /* ifdef Number */
2717 /* Increment the pass number */
2736 #ifdef PASS /* then rescan this file */
2738 #include "enquire.c"
2740 #include FILENAME /* if this line fails to compile, define NO_FILE */