1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9 Bugfixes and upgrades gratefully received.
11 Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
14 Changes by Richard Stallman:
15 Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
16 In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
17 Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
18 Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
19 Include sys/types.h before signal.h, Apr 92.
20 Support NO_LONG_DOUBLE_IO in f_define and f_rep; new fn fake_f_rep, Apr 92.
21 Enclose -f output in #ifndef _FLOAT_H___, Richard Stallman, May 92.
23 Add #undef before every #define, Jim Wilson, Dec 92.
25 Changes by Paul Eggert, installed Feb 93:
26 (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
27 (f_define): Use ordinary constants for long double
28 if it's same width as double. Make __convert_long_double_i unsigned.
29 Richard Stallman, May 93:
30 In F_check, check NO_LONG_DOUBLE_IO.
33 With luck and a following wind, just the following will work:
34 cc enquire.c -o enquire
35 You may get some messages about unreachable code, which you can ignore.
37 If your compiler doesn't support: add flag:
38 signed char (eg pcc) -DNO_SC
40 unsigned short and long -DNO_UI
42 signal(), or setjmp/longjmp() -DNO_SIG
43 %Lf in printf -DNO_LONG_DOUBLE_IO
45 Try to compile first with no flags, and see if you get any errors -
46 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
47 Some compilers need a -f flag for floating point.
49 Don't use any optimisation flags: the program may not work if you do.
50 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
51 optimiser, to a floating-point unit there's a world of difference.
53 Some compilers offer various flags for different floating point
54 modes; it's worth trying all possible combinations of these.
56 Add -DID=\"name\" if you want the machine/flags identified in the output.
59 Because of bugs and/or inadequacies, some compilers need the following
62 If your C preprocessor doesn't have the predefined __FILE__ macro, and
63 you don't want to call this file enquire.c but, say, tell.c, add the
64 flag -DFILENAME=\"tell.c\" .
66 Some compilers won't accept the line "#include FILENAME".
67 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
69 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
70 or -DNO_FILE as above.
72 Some naughty compilers define __STDC__, but don't really support it.
73 Some define it as 0, in which case we treat it as undefined.
74 But if your compiler defines it, and isn't really ANSI C,
75 add flag -DNO_STDC. (To those compiler writers: for shame).
77 Some naughty compilers define __STDC__, but don't have the stddef.h
78 include file. Add flag -DNO_STDDEF.
80 Summary of naughty-compiler flags:
81 If your compiler doesn't support: add flag:
82 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
83 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
84 #include FILENAME -DNO_FILE
85 __STDC__ (properly) -DNO_STDC
88 Some systems crash when you try to malloc all store. To save users of
89 such defective systems too much grief, they may compile with -DNO_MEM,
90 which ignores that bit of the code.
92 While it is not our policy to support defective compilers, pity has been
93 taken on people with compilers that can't produce object files bigger than
94 32k (especially since it was an easy addition). Compile the program
95 into separate parts like this:
96 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
97 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
98 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
99 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
100 cc -o enquire p0.o p1.o p2.o p3.o
103 You may possibly need to add some calls to signal() for other sorts of
104 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
105 #ifdef SIGxxx in main() (and communicate the differences to me!).
108 Run without argument to get the information as English text. If run
109 with argument -l (e.g. enquire -l), output is a series of #define's for
110 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
111 with argument -f, output is a series of #define's for the ANSI standard
112 float.h include file (according to ANSI C Draft of Dec 7, 1988).
113 Flag -v gives verbose output: output includes the English text above
114 as C comments. The program exit(0)'s if everything went ok, otherwise
115 it exits with a positive number, telling how many problems there were.
117 VERIFYING THE COMPILER
118 If, having produced the float.h and limits.h header files, you want to
119 verify that the compiler reads them back correctly (there are a lot of
120 boundary cases, of course, like minimum and maximum numbers), you can
121 recompile enquire.c with -DVERIFY set (plus the other flags that you used
122 when compiling the version that produced the header files). This then
123 recompiles the program so that it #includes "limits.h" and "float.h",
124 and checks that the constants it finds there are the same as the
125 constants it produces. Run the resulting program with enquire -fl.
126 Very few compilers have passed without error.
127 NB: You *must* recompile with the same compiler and flags, otherwise
128 you may get odd results.
130 You can also use this option if your compiler already has both files,
131 and you want to confirm that this program produces the right results.
134 This program is now quite trustworthy, and suspicious and wrong output
135 may well be caused by bugs in the compiler, not in the program (however
136 of course, this is not guaranteed, and no responsibility can be
139 The program only works if overflows are ignored by the C system or
140 are catchable with signal().
142 If the program fails to run to completion (often with the error message
143 "Unexpected signal at point x"), this often turns out to be a bug in the
144 C compiler's run-time system. Check what was about to be printed, and
145 try to narrow the problem down.
147 Another possible problem is that you have compiled the program to produce
148 loss-of-precision arithmetic traps. The program cannot cope with these,
149 and you should re-compile without them. (They should never be the default).
151 Make sure you compiled with optimisation turned off.
153 Output preceded by *** WARNING: identifies behaviour of the C system
154 deemed incorrect by the program. Likely problems are that printf or
155 scanf don't cope properly with certain boundary numbers: this program
156 goes to a lot of trouble to calculate its values, and these values
157 are mostly boundary numbers. Experience has shown that often printf
158 cannot cope with these values, and so in an attempt to increase
159 confidence in the output, for each float and double that is printed,
160 the printed value is checked by using sscanf to read it back.
161 Care is taken that numbers are printed with enough digits to uniquely
162 identify them, and therefore that they can be read back identically.
163 If the number read back is different, then there is probably a bug in
164 printf or sscanf, and the program prints the warning message.
165 If the two numbers in the warning look identical, then printf is more
166 than likely rounding the last digit(s) incorrectly. To put you at ease
167 that the two really are different, the bit patterns of the two numbers
168 are also printed. The difference is very likely in the last bit.
169 Many scanf's read the minimum double back as 0.0, and similarly cause
170 overflow when reading the maximum double. This program quite ruthlessly
171 declares all these behaviours faulty. The point is that if you get
172 one of these warnings, the output may be wrong, so you should check
173 the result carefully if you intend to use the results. Of course, printf
174 and sscanf may both be wrong, and cancel each other out, so you should
175 check the output carefully anyway.
177 The warning that "a cast didn't work" refers to cases like this:
180 #define C 1.234567890123456789
182 if (f != (float) C) printf ("Wrong!");
184 A faulty compiler will widen f to double and ignore the cast to float,
185 and because there is more accuracy in a double than a float, fail to
186 recognise that they are the same. In the actual case in point, f and C
187 are passed as parameters to a function that discovers they are not equal,
188 so it's just possible that the error was in the parameter passing,
189 not in the cast (see function Validate()).
190 For ANSI C, which has float constants, the error message is "constant has
194 If the program doesn't work for you for any reason that can't be
195 narrowed down to a problem in the C compiler, or it has to be changed in
196 order to get it to compile, or it produces suspicious output (like a very
197 low maximum float, for instance), please mail the problem and an example
198 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
199 improvements can be worked into future versions; cwi.nl is the European
200 backbone, and is connected to uunet and other fine hosts.
202 The program tries to catch and diagnose bugs in the compiler/run-time
203 system. I would be especially pleased to have reports of failures so
204 that I can improve this service.
206 I apologise unreservedly for the contorted use of the preprocessor...
209 You may copy and distribute verbatim copies of this source file.
211 You may modify this source file, and copy and distribute such
212 modified versions, provided that you leave the copyright notice
213 at the top of the file and also cause the modified file to carry
214 prominent notices stating that you changed the files and the date
215 of any change; and cause the whole of any work that you distribute
216 or publish, that in whole or in part contains or is a derivative of
217 this program or any part thereof, to be licensed at no charge to
218 all third parties on terms identical to those here.
220 If you do have a fix to any problem, please send it to me, so that
221 other people can have the benefits.
223 While every effort has been taken to make this program as reliable as
224 possible, no responsibility can be taken for the correctness of the
225 output, nor suitability for any particular use.
227 This program is an offshoot of a project funded by public funds.
228 If you use this program for research or commercial use (i.e. more
229 than just for the fun of knowing about your compiler) mailing a short
230 note of acknowledgement may help keep enquire.c supported.
233 Many people have given time and ideas to making this program what it is.
234 To all of them thanks, and apologies for not mentioning them by name.
237 Originally started as a program to generate configuration constants
238 for a large piece of software we were writing, which later took on
240 1.0 Length 6658!; end 1984?
241 Unix only. Only printed a dozen maximum int/double values.
242 2.0 Length 10535; Spring 1985
243 Prints values as #defines (about 20 of them)
244 More extensive floating point, using Cody and Waite
245 Handles signals better
246 Programs around optimisations
248 3.0 Length 12648; Aug 1987; prints about 42 values
249 Added PASS stuff, so treats float as well as double
250 4.0 Length 33891; Feb 1989; prints around 85 values
251 First GNU version (for gcc, where they call it hard-params.c)
252 Generates float.h and limits.h files
254 Generates warnings for dubious output
255 4.1 Length 47738; April 1989
256 Added VERIFY and TEST
257 4.2 Length 63442; Feb 1990
260 Added check for pseudo-unsigned chars
261 Added description for each #define output
262 Added check for absence of defines during verify
264 Added NO_STDC and NO_FILE
265 Fixed alignments output
266 4.3 Length 75000; Oct 1990; around 114 lines of output
267 Function xmalloc defined, Richard Stallman, June 89.
268 Alignments computed from member offsets rather than structure sizes,
269 Richard Stallman, Oct 89.
270 Print whether char* and int* pointers have the same format;
271 also char * and function *.
272 Update to Draft C version Dec 7, 1988
273 - types of constants produced in limits.h
274 (whether to put a U after unsigned shorts and chars and
275 whether to output -1024 as (-1023-1))
276 - values of SCHAR_MIN/MAX
277 - values of *_EPSILON (not the smallest but the effective smallest)
278 Added FILENAME, since standard C doesn't allow #define __FILE__
279 Renamed from config.c to enquire.c
280 Added size_t and ptrdiff_t enquiries
281 Added promotion enquiries
282 Added type checks of #defines
284 Changed endian to allow for cases where not all bits are used
285 Sanity check for max integrals
286 Fixed definition of setjmp for -DNO_SIG
287 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
291 /* Set FILENAME to the name of this file */
294 #define FILENAME "enquire.c"
296 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
297 #define FILENAME __FILE__
299 #define FILENAME "enquire.c"
300 #endif /* __FILE__ */
302 #endif /* FILENAME */
304 /* If PASS isn't defined, then this is the first pass over this file. */
312 /* A description of the ANSI constants */
313 #define D_CHAR_BIT "Number of bits in a storage unit"
314 #define D_CHAR_MAX "Maximum char"
315 #define D_CHAR_MIN "Minimum char"
316 #define D_SCHAR_MAX "Maximum signed char"
317 #define D_SCHAR_MIN "Minimum signed char"
318 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
320 #define D_INT_MAX "Maximum %s"
321 #define D_INT_MIN "Minimum %s"
322 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
324 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
325 #define D_FLT_RADIX "Radix of exponent representation"
326 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
327 #define D_DIG "Number of decimal digits of precision in a %s"
328 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
329 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
330 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
331 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
332 #define D_MAX "Maximum %s"
333 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
334 #define D_MIN "Minimum normalised %s"
336 /* Procedure just marks the functions that don't return a result */
338 #define Procedure int
340 #define Procedure void
343 /* Some bad compilers define __STDC__, when they don't support it.
344 Compile with -DNO_STDC to get round this.
348 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
354 /* Stuff different for ANSI C, and old C:
355 ARGS and NOARGS are used for function prototypes.
356 Volatile is used to reduce the chance of optimisation,
357 and to prevent variables being put in registers (when setjmp/longjmp
358 wouldn't work as we want)
359 Long_double is the longest floating point type available.
360 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
361 U is output after unsigned constants.
366 #define NOARGS (void)
367 #define Volatile volatile
368 #define Long_double long double
372 #else /* Old style C */
376 #define Volatile static
377 #define Long_double double
388 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
395 #include <sys/types.h>
400 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
416 #define Vprintf if (V) printf
417 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
418 #define fabs(x) (((x)<0.0)?(-x):(x))
424 /* Prototypes for what's to come: */
429 char *malloc (); /* Old style prototype */
431 char *malloc ARGS((size_t size));
434 Procedure exit ARGS((int status));
436 char *f_rep ARGS((int precision, Long_double val));
437 char *fake_f_rep ARGS((char *type, Long_double val));
439 int maximum_int NOARGS;
442 Procedure sprop NOARGS;
443 Procedure iprop NOARGS;
444 Procedure lprop NOARGS;
445 Procedure usprop NOARGS;
446 Procedure uiprop NOARGS;
447 Procedure ulprop NOARGS;
448 int fprop ARGS((int bits_per_byte));
449 int dprop ARGS((int bits_per_byte));
450 int ldprop ARGS((int bits_per_byte));
451 Procedure efprop ARGS((int fprec, int dprec, int lprec));
452 Procedure edprop ARGS((int fprec, int dprec, int lprec));
453 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
455 int setmode ARGS((char *s));
456 Procedure farewell ARGS((int bugs));
457 Procedure describe ARGS((char *description, char *extra));
458 Procedure missing ARGS((char *s));
459 Procedure fmissing ARGS((char *s));
460 Procedure check_defines NOARGS;
461 Procedure bitpattern ARGS((char *p, unsigned int size));
462 int ceil_log ARGS((int base, Long_double x));
463 Procedure croak ARGS((int place));
464 Procedure eek_a_bug ARGS((char *problem));
465 Procedure endian ARGS((int bits_per_byte));
466 int exponent ARGS((Long_double x, double *fract, int *exp));
467 int floor_log ARGS((int base, Long_double x));
468 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
469 int prec, Long_double val, char *mark));
470 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
471 long val, long lim, long req, char *mark));
472 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
473 unsigned long val, unsigned long req, char *mark));
475 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
477 /* Dummy routines instead */
479 int setjmp ARGS((int lab));
482 int setjmp(lab) int lab; { return(0); }
483 Procedure signal(i, p) int i, (*p)(); {}
487 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
488 signal(sig, overflow);
494 int V= 0, /* verbose */
495 L= 0, /* produce limits.h */
496 F= 0, /* produce float.h */
497 bugs=0; /* The number of (possible) bugs in the output */
499 char co[4], oc[4]; /* Comment starter and ender symbols */
501 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
502 int flt_rounds; /* The calculated value of FLT_ROUNDS */
503 int flt_radix; /* The calculated value of FLT_RADIX */
506 /* Set the fp modes on a SUN with 68881 chip, to check that different
507 rounding modes etc. get properly detected.
508 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
509 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
510 register to hex-number
513 /* Bits 0x30 = rounding mode */
514 #define ROUND_BITS 0x30
515 #define TO_NEAREST 0x00
517 #define TO_MINUS_INF 0x20
518 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
520 /* Bits 0xc0 = extended rounding */
521 #define EXT_BITS 0xc0
522 #define ROUND_EXTENDED 0x00
523 #define ROUND_SINGLE 0x40
524 #define ROUND_DOUBLE 0x80
527 #define EXE_INEX1 0x100
528 #define EXE_INEX2 0x200
530 #define EXE_UNFL 0x800
531 #define EXE_OVFL 0x1000
532 #define EXE_OPERR 0x2000
533 #define EXE_SNAN 0x4000
534 #define EXE_BSUN 0x8000
536 /* Only used for testing, on a Sun with 68881 chip */
537 /* Print the FP mode */
538 printmode(new) unsigned new; {
540 printf("New fp mode:\n");
541 printf(" Round toward ");
542 switch (new & ROUND_BITS) {
543 case TO_NEAREST: printf("nearest"); break;
544 case TO_ZERO: printf("zero"); break;
545 case TO_MINUS_INF: printf("minus infinity"); break;
546 case TO_PLUS_INF: printf("plus infinity"); break;
547 default: printf("???"); break;
550 printf("\n Extended rounding precision: ");
552 switch (new & EXT_BITS) {
553 case ROUND_EXTENDED: printf("extended"); break;
554 case ROUND_SINGLE: printf("single"); break;
555 case ROUND_DOUBLE: printf("double"); break;
556 default: printf("???"); break;
559 printf("\n Enabled exceptions:");
560 if (new & (unsigned) EXE_INEX1) printf(" inex1");
561 if (new & (unsigned) EXE_INEX2) printf(" inex2");
562 if (new & (unsigned) EXE_DZ) printf(" dz");
563 if (new & (unsigned) EXE_UNFL) printf(" unfl");
564 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
565 if (new & (unsigned) EXE_OPERR) printf(" operr");
566 if (new & (unsigned) EXE_SNAN) printf(" snan");
567 if (new & (unsigned) EXE_BSUN) printf(" bsun");
571 /* Only used for testing, on a Sun with 68881 chip */
572 /* Set the FP mode */
573 int setmode(s) char *s; {
574 unsigned mode=0, dig;
579 if (c>='0' && c<='9') dig= c-'0';
580 else if (c>='a' && c<='f') dig= c-'a'+10;
581 else if (c>='A' && c<='F') dig= c-'A'+10;
590 int setmode(s) char *s; {
591 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
596 Procedure farewell(bugs) int bugs; {
597 if (bugs == 0) exit(0);
598 printf("\n%sFor hints on dealing with the ", co);
599 if (bugs == 1) printf("problem");
600 else printf("%d problems", bugs);
601 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
602 printf("%s%s\n", FILENAME, oc);
606 /* The program has received a signal where it wasn't expecting one */
607 Procedure croak(place) int place; {
608 printf("*** Unexpected signal at point %d\n", place);
609 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
612 /* This is here in case alloca.c is used, which calls this. */
613 char *xmalloc(size) unsigned size; {
614 char *value = (char *)malloc(size);
616 fprintf(stderr, "Virtual memory exceeded\n");
625 /* Find the maximum integer */
626 Volatile int newi, int_max, two=2;
628 /* Calculate maxint ***********************************/
629 /* Calculate 2**n-1 until overflow - then use the previous value */
633 if (setjmp(lab)==0) { /* Yields int_max */
634 while(newi>int_max) {
643 int main(argc, argv) int argc; char *argv[]; {
644 int dprec, fprec, lprec;
647 int i; char *s; int bad;
650 signal(SIGFPE, overflow);
653 signal(SIGOVER, overflow);
655 /* Add more calls as necessary */
660 for (i=1; i < argc; i++) {
666 case 'v': V=1; break;
667 case 'l': L=1; break;
668 case 'f': F=1; break;
669 default: bad=1; break;
672 } else if (*s == '+') {
679 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
684 co[0]= '/'; oc[0]= ' ';
685 co[1]= '*'; oc[1]= '*';
686 co[2]= ' '; oc[2]= '/';
687 co[3]= '\0'; oc[3]= '\0';
689 co[0]= '\0'; oc[0]= '\0';
693 if (L) printf("%slimits.h%s\n", co, oc);
694 if (F) printf("%sfloat.h%s\n", co, oc);
696 printf ("#ifndef _FLOAT_H___\n");
697 printf ("#define _FLOAT_H___\n");
700 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
701 co, ID, VERSION, oc);
703 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
708 printf("%sVerification phase%s\n", co, oc);
712 Vprintf("%sCompiled without signal(): %s%s\n",
714 "there's nothing that can be done if overflow occurs",
718 Vprintf("%sCompiled without signed char%s\n", co, oc);
721 Vprintf("%Compiled without unsigned char%s\n", co, oc);
724 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
727 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
730 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
735 maxint= maximum_int();
736 bits_per_byte= basic();
739 fprec= fprop(bits_per_byte);
740 dprec= dprop(bits_per_byte);
741 lprec= ldprop(bits_per_byte);
742 efprop(fprec, dprec, lprec);
743 edprop(fprec, dprec, lprec);
744 eldprop(fprec, dprec, lprec);
748 /* An extra goody: the approximate amount of data-space */
749 /* Allocate store until no more available */
750 /* Different implementations have a different argument type
751 to malloc. Here we assume that it's the same type as
752 that which sizeof() returns */
753 size=1<<((bits_per_byte*sizeof(int))-2);
756 while ( malloc((false()?sizeof(int):size)) !=
764 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
765 co, (total+511)/512, oc);
769 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
772 return bugs; /* To keep compilers and lint happy */
775 Procedure eek_a_bug(problem) char *problem; {
776 /* The program has discovered a problem */
777 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
781 Procedure describe(description, extra) char *description, *extra; {
782 /* Produce the description for a #define */
784 printf(description, extra);
788 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
789 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
790 /* Produce a #define for a signed int type */
791 describe(desc, extra);
792 printf("#undef %s%s\n", sort, name);
794 printf("#define %s%s %ld%s\n", sort, name, val, mark);
795 } else if (val + lim < 0) {
796 /* We may not produce a constant like -1024 if the max
797 allowable value is 1023. It has then to be output as
798 -1023-1. lim is the max allowable value. */
799 printf("#define %s%s (%ld%s%ld%s)\n",
800 sort, name, -lim, mark, val+lim, mark);
802 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
804 /* If VERIFY is not set, val and req are just the same value;
805 if it is set, val is the value as calculated, and req is
806 the #defined constant
809 printf("%s*** Verify failed for above #define!\n", co);
810 printf(" Compiler has %ld for value%s\n\n", req, oc);
816 Procedure u_define(desc, extra, sort, name, val, req, mark)
817 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
818 /* Produce a #define for an unsigned value */
819 describe(desc, extra);
820 printf("#undef %s%s\n", sort, name);
821 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
823 printf("%s*** Verify failed for above #define!\n", co);
824 printf(" Compiler has %lu for value%s\n\n", req, oc);
830 Procedure f_define(desc, extra, sort, name, precision, val, mark)
831 char *desc, *extra, *sort, *name; int precision;
832 Long_double val; char *mark; {
833 /* Produce a #define for a float/double/long double */
834 describe(desc, extra);
835 printf ("#undef %s%s\n", sort, name);
837 #ifdef NO_LONG_DOUBLE_IO
838 static int union_defined = 0;
839 if (sizeof(double) != sizeof(Long_double)
840 && !strcmp(sort, "LDBL")) {
841 if (!union_defined) {
842 printf("#ifndef __LDBL_UNION__\n");
843 printf("#define __LDBL_UNION__\n");
844 printf("union __convert_long_double {\n");
845 printf(" unsigned __convert_long_double_i[4];\n");
846 printf(" long double __convert_long_double_d;\n");
851 printf("#define %s%s %s\n",
852 sort, name, fake_f_rep("long double", val));
854 printf("#define %s%s %s%s\n",
855 sort, name, f_rep(precision, val), mark);
858 printf("#define %s%s %s%s\n",
859 sort, name, f_rep(precision, val), mark);
861 } else if (*mark == 'F') {
862 /* non-ANSI C has no float constants, so cast the constant */
863 printf("#define %s%s ((float)%s)\n",
864 sort, name, f_rep(precision, val));
866 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
871 int floor_log(base, x) int base; Long_double x; {
872 /* return floor(log base(x)) */
874 while (x>=base) { r++; x/=base; }
878 int ceil_log(base, x) int base; Long_double x; {
880 while (x>1.0) { r++; x/=base; }
884 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
885 /* Split x into a fraction and a power of ten;
886 returns 0 if x is unusable, 1 otherwise.
887 Only used for error messages about faulty output.
896 if (x==0.0) return 1;
900 if (old==x) return 0;
905 if (old==x) return 0;
908 if (neg) *fract= (double) -x;
909 else *fract=(double) x;
914 /* Print a value of type TYPE with value VAL,
915 assuming that sprintf can't handle this type properly (without truncation).
916 We create an expression that uses type casting to create the value from
919 char *fake_f_rep(type, val) char *type; Long_double val; {
920 static char buf[1024];
921 union { unsigned int i[4]; Long_double ld;} u;
922 u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
924 sprintf(buf, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
925 u.i[0], u.i[1], u.i[2], u.i[3]);
929 char *f_rep(precision, val) int precision; Long_double val; {
930 /* Return the floating representation of val */
931 static char buf[1024];
933 #ifdef NO_LONG_DOUBLE_IO
936 if (sizeof(double) == sizeof(Long_double))
940 /* Assume they're the same, and use non-stdc format */
941 /* This is for stdc compilers using non-stdc libraries */
942 sprintf(buf, "%.*e", precision, d);
944 /* It had better support Le then */
945 sprintf(buf, "%.*Le", precision, val);
950 Procedure bitpattern(p, size) char *p; unsigned int size; {
951 /* Printf the bit-pattern of p */
955 for (i=1; i<=size; i++) {
958 for (j=bits_per_byte-1; j>=0; j--)
959 printf("%c", (c>>j)&1 ? '1' : '0');
960 if (i!=size) printf(" ");
964 #define Order(x, px, mode)\
965 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
966 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
967 putchar(c==0 ? '?' : (char)c); }\
970 Procedure endian(bits_per_byte) int bits_per_byte; {
971 /* Printf the byte-order used on this machine */
972 /*unsigned*/ short s=0;
973 /*unsigned*/ int j=0;
974 /*unsigned*/ long l=0;
976 char *ps= (char *) &s,
979 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
980 unsigned int mask, i, c;
983 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
986 printf("%sCHARACTER ORDER%s\n", co, oc);
987 Order(s, ps, "short:");
988 Order(j, pj, "int: ");
989 Order(l, pl, "long: ");
993 Procedure missing(s) char *s; {
994 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
998 Procedure fmissing(s) char *s; {
999 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
1003 /* To try and fool optimisers */
1004 int false() { return 0; }
1006 #define Promoted(x) (false()?(x):(-1))
1007 #define is_signed(x) (Promoted(x) < 0)
1008 #define sign_of(x) ((x)?"signed":"unsigned")
1011 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1013 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1015 char *type_of(x) int x; {
1016 if (x == sizeof(char)) {
1017 if (sizeof(char) == sizeof(int)) return "char/short/int";
1018 if (sizeof(char) == sizeof(short)) return "char/short";
1021 if (x == sizeof(short)) {
1022 if (sizeof(short) == sizeof(int)) return "short/int";
1025 if (x == sizeof(int)) {
1026 if (sizeof(int) == sizeof(long)) return "int/long";
1029 if (x == sizeof(long)) return "long";
1030 return "unknown-type";
1033 char *ftype_of(x) int x; {
1034 if (x == sizeof(float)) {
1037 if (x == sizeof(double)) {
1038 if (sizeof(double) == sizeof(Long_double))
1039 return "(long)double";
1042 if (x == sizeof(Long_double)) {
1043 return "long double";
1045 return "unknown-type";
1048 Procedure typerr(name, esign, esize, sign, size)
1049 char *name; int esign, esize, sign, size;
1051 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1052 name, sign_of(esign), type_of(esize),
1053 sign_of(sign), type_of(size));
1056 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
1057 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1058 name, ftype_of(esize), ftype_of(size));
1063 unsigned int ui; unsigned long ul;
1064 short ss; unsigned short us;
1066 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1069 /* Possible warnings here; no problem */
1070 (sizeof(Promoted(si)) != sizeof(int)) ||
1071 (sizeof(Promoted(sl)) != sizeof(long)) ||
1072 (sizeof(Promoted(ss)) != sizeof(int)) ||
1073 (sizeof(Promoted(ui)) != sizeof(int)) ||
1074 (sizeof(Promoted(ul)) != sizeof(long)) ||
1075 (sizeof(Promoted(us)) != sizeof(int)) ||
1076 is_signed(ui) || is_signed(ul) ||
1077 !is_signed(si) || !is_signed(sl)
1080 eek_a_bug("promotions don't work properly in conditional expressions\n");
1083 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1084 showtype("long+unsigned gives", sl+ui);
1087 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1089 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1091 Procedure check_defines() {
1092 /* ensure that all #defines are present and have the correct type */
1099 /* Implementations promote unsigned short differently */
1100 usign= is_signed((unsigned short)0);
1105 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1107 missing("CHAR_BIT");
1110 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1112 missing("CHAR_MAX");
1115 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1117 missing("CHAR_MIN");
1120 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1122 missing("SCHAR_MAX");
1125 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1127 missing("SCHAR_MIN");
1130 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1132 missing("UCHAR_MAX");
1135 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1137 missing("SHRT_MAX");
1140 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1142 missing("SHRT_MIN");
1145 checktype(INT_MAX, "INT_MAX", Signed, int);
1150 checktype(INT_MIN, "INT_MIN", Signed, int);
1155 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1157 missing("LONG_MAX");
1160 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1162 missing("LONG_MIN");
1165 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1167 missing("USHRT_MAX");
1170 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1172 missing("UINT_MAX");
1175 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1177 missing("ULONG_MAX");
1183 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1185 fmissing("FLT_RADIX");
1188 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1190 fmissing("FLT_MANT_DIG");
1193 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1195 fmissing("FLT_DIG");
1198 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1200 fmissing("FLT_ROUNDS");
1203 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1205 fmissing("FLT_EPSILON");
1208 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1210 fmissing("FLT_MIN_EXP");
1213 fchecktype(FLT_MIN, "FLT_MIN", float);
1215 fmissing("FLT_MIN");
1217 #ifdef FLT_MIN_10_EXP
1218 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1220 fmissing("FLT_MIN_10_EXP");
1223 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1225 fmissing("FLT_MAX_EXP");
1228 fchecktype(FLT_MAX, "FLT_MAX", float);
1230 fmissing("FLT_MAX");
1232 #ifdef FLT_MAX_10_EXP
1233 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1235 fmissing("FLT_MAX_10_EXP");
1238 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1240 fmissing("DBL_MANT_DIG");
1243 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1245 fmissing("DBL_DIG");
1248 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1250 fmissing("DBL_EPSILON");
1253 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1255 fmissing("DBL_MIN_EXP");
1258 fchecktype(DBL_MIN, "DBL_MIN", double);
1260 fmissing("DBL_MIN");
1262 #ifdef DBL_MIN_10_EXP
1263 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1265 fmissing("DBL_MIN_10_EXP");
1268 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1270 fmissing("DBL_MAX_EXP");
1273 fchecktype(DBL_MAX, "DBL_MAX", double);
1275 fmissing("DBL_MAX");
1277 #ifdef DBL_MAX_10_EXP
1278 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1280 fmissing("DBL_MAX_10_EXP");
1283 #ifdef LDBL_MANT_DIG
1284 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1286 fmissing("LDBL_MANT_DIG");
1289 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1291 fmissing("LDBL_DIG");
1294 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1296 fmissing("LDBL_EPSILON");
1299 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1301 fmissing("LDBL_MIN_EXP");
1304 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1306 fmissing("LDBL_MIN");
1308 #ifdef LDBL_MIN_10_EXP
1309 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1311 fmissing("LDBL_MIN_10_EXP");
1314 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1316 fmissing("LDBL_MAX_EXP");
1319 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1321 fmissing("LDBL_MAX");
1323 #ifdef LDBL_MAX_10_EXP
1324 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1326 fmissing("LDBL_MAX_10_EXP");
1335 #define SCHAR_MAX char_max
1338 #define SCHAR_MIN char_min
1341 #define UCHAR_MAX char_max
1346 #define CHAR_BIT char_bit
1349 #define CHAR_MAX char_max
1352 #define CHAR_MIN char_min
1355 #define SCHAR_MAX char_max
1358 #define SCHAR_MIN char_min
1361 #define UCHAR_MAX char_max
1365 /* Properties of type char */
1366 Volatile char c, char_max, char_min;
1367 Volatile int bits_per_byte, c_signed;
1372 /* Calculate number of bits per character *************************/
1373 c=1; bits_per_byte=0;
1374 do { c=c<<1; bits_per_byte++; } while(c!=0);
1376 if (((int)c)<0) c_signed=1;
1378 Vprintf("%schar = %d bits, %ssigned%s\n",
1379 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1380 char_bit=(long)(sizeof(c)*bits_per_byte);
1381 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1382 char_bit, 0L, (long) CHAR_BIT, "");
1386 if (setjmp(lab)==0) { /* Yields char_max */
1387 while (c>char_max) {
1392 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1396 if (setjmp(lab)==0) { /* Yields char_min */
1397 while (c<char_min) {
1402 if (c_signed && char_min == 0) {
1403 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1404 Vprintf("%s %s%s%s\n",
1405 "They contain only nonnegative values, ",
1406 "but sign extend when used as integers.", co, oc);
1411 /* Because of the integer promotions, you must use a U after
1412 the MAX_CHARS in the following cases */
1413 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1414 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1416 (long) CHAR_MAX, "");
1418 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1419 (long) char_max, 0L,
1420 (long) CHAR_MAX, "");
1422 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1423 (long) char_min, (long) maxint,
1424 (long) CHAR_MIN, "");
1426 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1427 (long) char_max, 0L,
1428 (long) SCHAR_MAX, "");
1429 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1430 (long) char_min, (long) maxint,
1431 (long) SCHAR_MIN, "");
1433 if (sizeof(char) == sizeof(int)) {
1434 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1436 (long) UCHAR_MAX, "");
1438 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1439 (long) char_max, 0L,
1440 (long) UCHAR_MAX, "");
1446 Volatile unsigned char c, char_max;
1449 if (setjmp(lab)==0) { /* Yields char_max */
1450 while (c>char_max) {
1456 if (sizeof(char) == sizeof(int)) {
1457 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1459 (long) UCHAR_MAX, "");
1461 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1462 (long) char_max, 0L,
1463 (long) UCHAR_MAX, "");
1468 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1471 if (setjmp(lab)==0) { /* Yields char_max */
1472 while (c>char_max) {
1479 if (setjmp(lab)==0) { /* Yields char_min */
1480 while (c<char_min) {
1486 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1487 (long) char_min, (long) maxint,
1488 (long) SCHAR_MIN, "");
1489 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1490 (long) char_max, 0L,
1491 (long) SCHAR_MAX, "");
1495 return bits_per_byte;
1499 /* The properties of the basic types.
1500 Returns number of bits per sizeof unit */
1501 Volatile int bits_per_byte;
1502 typedef int function ();
1506 Vprintf("%sSIZES%s\n", co, oc);
1507 bits_per_byte= cprop();
1509 /* Shorts, ints and longs *****************************************/
1510 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1512 (int) sizeof(short)*bits_per_byte,
1513 (int) sizeof(int)*bits_per_byte,
1514 (int) sizeof(long)*bits_per_byte,
1515 (int) sizeof(float)*bits_per_byte,
1516 (int) sizeof(double)*bits_per_byte, oc);
1518 Vprintf("%slong double=%d bits%s\n",
1519 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1521 Vprintf("%schar*=%d bits%s%s\n",
1522 co, (int)sizeof(char *)*bits_per_byte,
1523 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1525 Vprintf("%sint* =%d bits%s%s\n",
1526 co, (int)sizeof(int *)*bits_per_byte,
1527 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1529 Vprintf("%sfunc*=%d bits%s%s\n",
1530 co, (int)sizeof(function *)*bits_per_byte,
1531 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1533 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1534 ((((false()?( sizeof(int)):(-1)) < 0) )?
1535 "signed":"unsigned") ,
1541 showtype("Type size_t is", sizeof(0));
1543 /* Alignment constants ********************************************/
1545 #define alignment(TYPE) \
1546 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1548 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1550 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1552 alignment(char), alignment(short),
1553 alignment(int), alignment(long),
1556 Vprintf("%sfloat=%ld double=%ld%s\n",
1558 alignment(float), alignment(double),
1562 Vprintf("%slong double=%ld%s\n",
1564 alignment(Long_double),
1567 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1569 alignment(char *), alignment(int *), alignment(function *),
1574 /* Ten little endians *********************************************/
1576 endian(bits_per_byte);
1578 /* Pointers *******************************************************/
1580 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1582 if ((long) (char *) &variable == (long) (int *) &variable)
1583 Vprintf("%sChar and int pointer formats seem identical%s\n",
1586 Vprintf("%sChar and int pointer formats are different%s\n",
1588 if ((long) (char *) &variable == (long) (function *) &variable)
1589 Vprintf("%sChar and function pointer formats seem identical%s\n",
1592 Vprintf("%sChar and function pointer formats are different%s\n",
1597 printf("%sStrings are shared%s\n", co, oc);
1598 else printf("%sStrings are not shared%s\n", co, oc);
1602 showtype("Type ptrdiff_t is", p-q);
1604 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1617 return bits_per_byte;
1620 #else /* not PASS0 */
1624 extern int V, L, F, bugs, bits_per_byte;
1625 extern char co[], oc[];
1626 extern char *f_rep();
1628 #endif /* ifdef PASS0 */
1630 /* As I said, I apologise for the contortions below. The functions are
1631 expanded by the preprocessor twice or three times (for float and double,
1632 and maybe for long double, and for short, int and long). That way,
1633 I never make a change to one that I forget to make to the other.
1634 You can look on it as C's fault for not supporting multi-line macro's.
1635 This whole file is read 3 times by the preprocessor, with PASSn set for
1636 n=1, 2 or 3, to decide which parts to reprocess.
1639 /* #undef on an already undefined thing is (wrongly) flagged as an error
1640 by some compilers, therefore the #ifdef that follows:
1666 /* These are the float.h constants */
1697 /* Define the things we're going to use this pass */
1699 #define Number float
1700 #define THING "FLOAT"
1701 #define Thing "Float"
1702 #define thing "float"
1705 #define Store fStore
1717 #define F_check fCheck
1720 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1723 #define EPROP efprop
1725 #define Integer short
1728 #define Iname "SHRT"
1734 #define UPROP usprop
1735 #define Uname "USHRT"
1739 #define I_MAX SHRT_MAX
1742 #define I_MIN SHRT_MIN
1745 #define U_MAX USHRT_MAX
1749 #define F_RADIX FLT_RADIX
1752 #define F_MANT_DIG FLT_MANT_DIG
1755 #define F_DIG FLT_DIG
1758 #define F_ROUNDS FLT_ROUNDS
1761 #define F_EPSILON FLT_EPSILON
1764 #define F_MIN_EXP FLT_MIN_EXP
1767 #define F_MIN FLT_MIN
1769 #ifdef FLT_MIN_10_EXP
1770 #define F_MIN_10_EXP FLT_MIN_10_EXP
1773 #define F_MAX_EXP FLT_MAX_EXP
1776 #define F_MAX FLT_MAX
1778 #ifdef FLT_MAX_10_EXP
1779 #define F_MAX_10_EXP FLT_MAX_10_EXP
1787 #define Number double
1788 #define THING "DOUBLE"
1789 #define Thing "Double"
1790 #define thing "double"
1793 #define Store dStore
1805 #define F_check dCheck
1808 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1811 #define EPROP edprop
1817 #define OK_UI 1 /* Unsigned int is always possible */
1820 #define UPROP uiprop
1821 #define Uname "UINT"
1825 #define I_MAX INT_MAX
1828 #define I_MIN INT_MIN
1831 #define U_MAX UINT_MAX
1835 #define F_MANT_DIG DBL_MANT_DIG
1838 #define F_DIG DBL_DIG
1841 #define F_EPSILON DBL_EPSILON
1844 #define F_MIN_EXP DBL_MIN_EXP
1847 #define F_MIN DBL_MIN
1849 #ifdef DBL_MIN_10_EXP
1850 #define F_MIN_10_EXP DBL_MIN_10_EXP
1853 #define F_MAX_EXP DBL_MAX_EXP
1856 #define F_MAX DBL_MAX
1858 #ifdef DBL_MAX_10_EXP
1859 #define F_MAX_10_EXP DBL_MAX_10_EXP
1868 #define Number long double
1878 #define THING "LONG DOUBLE"
1879 #define Thing "Long double"
1880 #define thing "long double"
1881 #define Fname "LDBL"
1882 #define FPROP ldprop
1883 #define Store ldStore
1889 #define F_check ldCheck
1892 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1895 #define EPROP eldprop
1897 #define Integer long
1900 #define Iname "LONG"
1906 #define UPROP ulprop
1907 #define Uname "ULONG"
1911 #define I_MAX LONG_MAX
1914 #define I_MIN LONG_MIN
1917 #define U_MAX ULONG_MAX
1920 #ifdef LDBL_MANT_DIG
1921 #define F_MANT_DIG LDBL_MANT_DIG
1924 #define F_DIG LDBL_DIG
1927 #define F_EPSILON LDBL_EPSILON
1930 #define F_MIN_EXP LDBL_MIN_EXP
1933 #define F_MIN LDBL_MIN
1935 #ifdef LDBL_MIN_10_EXP
1936 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1939 #define F_MAX_EXP LDBL_MAX_EXP
1942 #define F_MAX LDBL_MAX
1944 #ifdef LDBL_MAX_10_EXP
1945 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1952 #define I_MAX int_max
1955 #define I_MIN int_min
1962 #define F_RADIX f_radix
1965 #define F_MANT_DIG f_mant_dig
1971 #define F_ROUNDS f_rounds
1974 #define F_EPSILON f_epsilon
1977 #define F_MIN_EXP f_min_exp
1982 #ifndef F_MIN_10_EXP
1983 #define F_MIN_10_EXP f_min_10_exp
1986 #define F_MAX_EXP f_max_exp
1991 #ifndef F_MAX_10_EXP
1992 #define F_MAX_10_EXP f_max_10_exp
1996 #define Validate(prec, val, req, same) {;}
2002 /* the properties of short, int, and long */
2003 Volatile Integer newi, int_max, maxeri, int_min, minneri;
2004 Volatile int ibits, ipower, two=2;
2006 /* Calculate max short/int/long ***********************************/
2007 /* Calculate 2**n-1 until overflow - then use the previous value */
2011 if (setjmp(lab)==0) { /* Yields int_max */
2012 for(ipower=0; newi>int_max; ipower++) {
2016 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2017 co, INT[0]=='i'?"n":"", INT, oc);
2019 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2020 co, INT[0]=='i'?"n":"", INT, oc);
2024 /* Minimum value: assume either two's or one's complement *********/
2026 if (setjmp(lab)==0) { /* Yields int_min */
2027 if (int_min-1 < int_min) int_min--;
2031 /* Now for those daft Cybers */
2033 maxeri=0; newi=int_max;
2035 if (setjmp(lab)==0) { /* Yields maxeri */
2036 for(ibits=ipower; newi>maxeri; ibits++) {
2044 if (setjmp(lab)==0) { /* Yields minneri */
2045 if (minneri-1 < minneri) minneri--;
2049 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2050 co, INT, (long)int_max, ipower, oc);
2051 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
2053 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
2055 (long) I_MAX, IMARK);
2056 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
2057 (long) int_min, (long) (PASS==1?maxint:int_max),
2058 (long) I_MIN, IMARK);
2060 if(int_max < 0) { /* It has happened */
2061 eek_a_bug("signed integral comparison faulty?");
2064 if (maxeri>int_max) {
2065 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2066 co, INT, (long)maxeri, ibits,
2067 "but only for addition, not multiplication",
2068 "(I smell a Cyber!)",
2072 if (minneri<int_min) {
2073 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2074 co, INT, (long)minneri,
2075 "but only for addition, not multiplication",
2076 "(I smell a Cyber!)",
2081 Procedure UPROP () {
2082 /* The properties of unsigned short/int/long */
2084 Volatile unsigned Integer u_max, newi, two;
2085 newi=1; u_max=0; two=2;
2087 if (setjmp(lab)==0) { /* Yields u_max */
2094 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2095 co, INT, (unsigned long) u_max, oc);
2097 /* Oh woe: new standard C defines value preserving promotions */
2099 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2100 /* Special only for short */
2101 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2102 (unsigned long) u_max, 0L,
2103 (unsigned long) U_MAX, IMARK);
2105 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2106 (unsigned long) u_max,
2107 (unsigned long) U_MAX, IMARK);
2113 #endif /* Integer */
2117 /* The following routines are intended to defeat any attempt at optimisation
2118 or use of extended precision, and to defeat faulty narrowing casts.
2119 The weird prototypes are because of widening incompatibilities.
2122 #define ARGS1(atype, a) (atype a)
2123 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2125 #define ARGS1(atype, a) (a) atype a;
2126 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2129 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2130 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2131 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2132 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2133 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2134 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2136 Procedure F_check ARGS((int precision, Long_double val1));
2138 Procedure F_check(precision, val1) int precision; Long_double val1; {
2139 /* You don't think I'm going to go to all the trouble of writing
2140 a program that works out what all sorts of values are, only to
2141 have printf go and print the wrong values out, do you?
2142 No, you're right, so this function tries to see if printf
2143 has written the right value, by reading it back again.
2144 This introduces a new problem of course: suppose printf writes
2145 the correct value, and scanf reads it back wrong... oh well.
2146 But I'm adamant about this: the precision given is enough
2147 to uniquely identify the printed number, therefore I insist
2148 that sscanf read the number back identically. Harsh yes, but
2149 sometimes you've got to be cruel to be kind.
2151 Number val, new, diff;
2157 #ifdef NO_LONG_DOUBLE_IO
2159 /* On the Sun 3, sscanf clobbers 4 words,
2160 which leads to a crash when this function tries to return. */
2161 f2= "%le"; /* Input */
2162 /* It is no use checking long doubles if we can't
2163 read and write them. */
2164 if (sizeof (Number) > sizeof(double))
2168 if (sizeof(double) == sizeof(Long_double)) {
2169 /* Assume they're the same, and use non-stdc format */
2170 /* This is for stdc compilers using non-stdc libraries */
2171 f2= "%le"; /* Input */
2173 /* It had better support Le then */
2178 rep= f_rep(precision, (Long_double) val);
2179 if (setjmp(lab)==0) {
2180 sscanf(rep, f2, &new1);
2182 eek_a_bug("sscanf caused a trap");
2183 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2188 if (setjmp(lab)==0) { /* See if new is usable */
2191 diff= val/new - 1.0;
2192 if (diff < 0.1) diff= 1.0;
2193 /* That should be enough to generate a trap */
2196 eek_a_bug("sscanf returned an unusable number");
2197 printf("%s scanning: %s with format: %s%s\n\n",
2205 eek_a_bug("Possibly bad output from printf above");
2206 if (!exponent((Long_double)val, &rem, &e)) {
2207 printf("%s but value was an unusable number%s\n\n",
2211 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2212 co, precision, rem, e);
2213 bitpattern((char *) &val, (unsigned)sizeof(val));
2214 printf ("%s\n", oc);
2215 printf("%s sscanf gave %s, bit pattern:\n ",
2216 co, f_rep(precision, (Long_double) new));
2217 bitpattern((char *) &new, (unsigned)sizeof(new));
2218 printf ("%s\n", oc);
2219 if (setjmp(lab) == 0) {
2221 printf("%s difference= %s%s\n\n",
2222 co, f_rep(precision, (Long_double) diff), oc);
2223 } /* else forget it */
2229 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2230 /* Check that the compiler has read a #define value correctly */
2233 printf("%s*** Verify failed for above #define!\n", co);
2234 if (setjmp(lab) == 0) { /* for the case that req == nan */
2235 printf(" Compiler has %s for value%s\n",
2236 f_rep(prec, req), oc);
2238 printf(" Compiler has %s for value%s\n",
2239 "an unusable number", oc);
2241 if (setjmp(lab) == 0) {
2242 F_check(prec, (Long_double) req);
2243 } /*else forget it*/
2244 if (setjmp(lab) == 0) {
2245 if (req > 0.0 && val > 0.0) {
2246 printf("%s difference= %s%s\n",
2247 co, f_rep(prec, val-req), oc);
2249 } /*else forget it*/
2253 } else if (val != req) {
2254 if (stdc) eek_a_bug("constant has the wrong precision");
2255 else eek_a_bug("the cast didn't work");
2261 int FPROP(bits_per_byte) int bits_per_byte; {
2262 /* Properties of floating types, using algorithms by Cody and Waite
2263 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2264 Further extended by S Pemberton.
2266 Returns the number of digits in the fraction.
2270 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2271 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2272 mantbits, digs, f_dig, trap,
2273 hidden, normal, f_min_10_exp, f_max_10_exp;
2275 a, b, base, basein, basem1, f_epsilon, epsneg,
2276 eps, epsp1, etop, ebot,
2277 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2281 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2283 /* Base and size of significand **************************************/
2284 /* First repeatedly double until adding 1 has no effect. */
2285 /* For instance, if base is 10, with 3 significant digits */
2286 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2287 /* since 1024 is only representable as 1020. */
2289 if (setjmp(lab)==0) { /* inexact trap? */
2291 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2293 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2294 /* And supporting those is just TOO much trouble! */
2298 /* Now double until you find a number that can be added to the */
2299 /* above number. For 1020 this is 8 or 16, depending whether the */
2300 /* result is rounded or truncated. */
2301 /* In either case the result is 1030. 1030-1020= the base, 10. */
2303 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2305 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2307 /* Sanity check; if base<2, I can't guarantee the rest will work */
2309 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2314 if (PASS == 1) { /* only for FLT */
2316 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2317 (long) f_radix, 0L, (long) F_RADIX, "");
2318 } else if (f_radix != flt_radix) {
2319 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2320 co, thing, "arithmetic has a different radix",
2321 f_radix, "from float", oc);
2325 /* Now the number of digits precision */
2326 f_mant_dig=0; b=1.0;
2327 do { f_mant_dig++; b=Mul(b, base); }
2328 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2329 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2330 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2331 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2332 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2333 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2334 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2335 (long) f_dig, 0L, (long) F_DIG, "");
2336 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2338 /* Rounding *******************************************************/
2339 basem1=Diff(base, HALF);
2340 if (Diff(Sum(a, basem1), a) != ZERO) {
2341 if (f_radix == 2) basem1=0.375;
2343 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2344 else irnd=1; /* to nearest */
2345 } else irnd=0; /* towards 0 */
2347 basem1=Diff(base, HALF);
2349 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2350 if (f_radix == 2) basem1=0.375;
2352 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2353 else mrnd=1; /* to nearest */
2354 } else mrnd=0; /* towards 0 */
2356 f_rounds= -1; /* Unknown rounding */
2357 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2358 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2359 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2360 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2362 if (f_rounds != -1) {
2363 Vprintf("%sArithmetic rounds towards ", co);
2365 case 0: Vprintf("zero (i.e. it chops)"); break;
2366 case 1: Vprintf("nearest"); break;
2367 case 2: Vprintf("+infinity"); break;
2368 case 3: Vprintf("-infinity"); break;
2369 default: Vprintf("???"); break;
2371 Vprintf("%s\n", oc);
2372 } else { /* Hmm, try to give some help here */
2373 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2374 Vprintf("%s Negative numbers %s%s\n",
2375 co, mrnd==0 ? "towards zero" :
2376 mrnd==1 ? "to nearest" :
2379 Vprintf("%s Positive numbers %s%s\n",
2380 co, irnd==0 ? "towards zero" :
2381 irnd==1 ? "to nearest" :
2385 /* An extra goody */
2386 if (f_radix == 2 && f_rounds == 1) {
2387 if (Diff(Sum(a, ONE), a) != ZERO) {
2388 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2389 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2390 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2392 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2395 if (PASS == 1) { /* only for FLT */
2396 flt_rounds= f_rounds;
2398 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2399 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2400 } else if (f_rounds != flt_rounds) {
2401 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2402 co, thing, "arithmetic rounds differently",
2403 f_rounds, "from float", oc);
2407 /* Various flavours of epsilon ************************************/
2408 negeps=f_mant_dig+f_mant_dig;
2411 for(i=1; i<=negeps; i++) a*=basein;
2414 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2419 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2424 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2425 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2426 ebot and etop are the current bounds */
2427 while (eps != ebot && eps != etop) {
2428 epsp1 = Diff(ONE, eps);
2429 if (epsp1 < ONE) etop = eps;
2431 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2435 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2436 eek_a_bug("internal error calculating epsneg");
2438 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2439 co, f_rep(digs, (Long_double) eps), oc);
2440 if (V) F_check(digs, (Long_double) eps);
2443 if ((f_radix!=2) && irnd) {
2444 /* a=(a*(1.0+a))/(1.0+1.0); => */
2445 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2446 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2447 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2449 /* epsneg is used later */
2452 machep= -f_mant_dig-f_mant_dig;
2454 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2455 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2460 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2461 /* find the smallest eps (1+eps != 1) by binary search.
2462 ebot and etop are the current bounds */
2463 while (eps != ebot && eps != etop) {
2464 epsp1 = Sum(ONE, eps);
2465 if (epsp1 > ONE) etop = eps;
2467 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2470 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2471 eek_a_bug("internal error calculating eps");
2475 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2476 co, f_rep(digs, (Long_double) f_epsilon), oc);
2478 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2479 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2480 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2482 /* Possible loss of precision warnings here from non-stdc compilers */
2483 if (F) f_define(D_EPSILON, thing,
2484 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2485 if (V || F) F_check(digs, (Long_double) f_epsilon);
2487 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2488 f_epsilon == Self(F_EPSILON));
2491 /* Extra chop info *************************************************/
2492 if (f_rounds == 0) {
2493 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2494 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2498 /* Size of and minimum normalised exponent ************************/
2499 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2501 /* Coarse search for the largest power of two */
2502 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2505 z=Mul(y,y); z1=Mul(z1, y);
2508 if (z2 != y1) break;
2509 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2514 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2518 if (f_radix != 10) {
2519 iexp=i+1; /* for the sign */
2524 while (k >= iz) { iz*=f_radix; iexp++; }
2528 /* Fine tune starting with y and y1 */
2529 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2532 y=Div(y,base); y1=Div(y1,base);
2535 if (z2 != z1) break;
2536 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2544 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2545 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2546 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2548 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2549 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2551 if (setjmp(lab)==0) {
2552 Vprintf("%sMinimum normalised positive number = %s%s\n",
2553 co, f_rep(digs, (Long_double) f_min), oc);
2555 eek_a_bug("printf can't print the smallest normalised number");
2559 /* Possible loss of precision warnings here from non-stdc compilers */
2560 if (setjmp(lab) == 0) {
2561 if (F) f_define(D_MIN, thing,
2562 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2563 if (V || F) F_check(digs, (Long_double) f_min);
2565 eek_a_bug("xxx_MIN caused a trap");
2569 if (setjmp(lab) == 0) {
2570 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2571 f_min == Self(F_MIN));
2573 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2574 co, "Compiler has an unusable number for value", oc);
2579 a=1.0; f_min_10_exp=0;
2580 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2581 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2582 (long) f_min_10_exp, (long) maxint,
2583 (long) F_MIN_10_EXP, "");
2585 /* Minimum exponent ************************************************/
2586 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2591 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2596 if (xminner != 0.0 && xminner != f_min) {
2598 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2600 if (setjmp(lab)==0) {
2601 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2602 co, f_rep(digs, (Long_double) xminner), oc);
2603 if (V) F_check(digs, (Long_double) xminner);
2605 eek_a_bug("printf can't print the smallest unnormalised number.");
2611 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2614 /* Maximum exponent ************************************************/
2615 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2617 while (f_max<newxmax) {
2619 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2620 newxmax=Mul(newxmax, base);
2625 if (Div(newxmax, base) != f_max) {
2626 inf=1; /* ieee infinity */
2633 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2636 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2637 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2638 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2639 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2641 /* Largest number ***************************************************/
2642 f_max=Diff(ONE, epsneg);
2643 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2644 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2646 if (setjmp(lab)==0) {
2647 Vprintf("%sMaximum number = %s%s\n",
2648 co, f_rep(digs, (Long_double) f_max), oc);
2650 eek_a_bug("printf can't print the largest double.");
2653 if (setjmp(lab)==0) {
2654 /* Possible loss of precision warnings here from non-stdc compilers */
2655 if (F) f_define(D_MAX, thing,
2656 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2657 if (V || F) F_check(digs, (Long_double) f_max);
2659 eek_a_bug("xxx_MAX caused a trap");
2662 if (setjmp(lab)==0) {
2663 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2664 f_max == Self(F_MAX));
2666 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2667 co, "Compiler has an unusable number for value", oc);
2672 a=1.0; f_max_10_exp=0;
2673 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2674 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2675 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2677 /* Hidden bit + sanity check ****************************************/
2678 if (f_radix != 10) {
2680 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2681 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2683 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2684 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2685 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2688 printf("\n%s%s\n %s %s %s!%s\n\n",
2690 "*** Something fishy here!",
2691 "Exponent size + significand size doesn't match",
2692 "with the size of a", thing,
2695 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2696 Vprintf("%sIt looks like %s length IEEE format%s\n",
2697 co, f_mant_dig==24 ? "single" :
2698 f_mant_dig==53 ? "double" :
2699 f_mant_dig >53 ? "extended" :
2701 if (f_rounds != 1 || normal) {
2702 Vprintf("%s though ", co);
2703 if (f_rounds != 1) {
2704 Vprintf("the rounding is unusual");
2705 if (normal) Vprintf(" and ");
2707 if (normal) Vprintf("the normalisation is unusual");
2708 Vprintf("%s\n", oc);
2711 Vprintf("%sIt doesn't look like IEEE format%s\n",
2715 printf("\n"); /* regardless of verbosity */
2719 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2720 /* See if expressions are evaluated in extended precision.
2721 Some compilers optimise even if you don't want it,
2722 and then this function fails to produce the right result.
2723 We try to diagnose this if it happens.
2726 Volatile double a, b, base, old;
2727 Volatile Number d, oldd, dbase, one, zero;
2730 /* Size of significand **************************************/
2732 if (setjmp(lab) == 0) { /* Yields nothing */
2733 do { old=a; a=a+a; }
2734 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2737 /* Avoid the comparison if bad is set,
2738 to avoid trouble on the convex. */
2739 if (!bad && (a <= old)) bad=1;
2743 if (setjmp(lab) == 0) { /* Yields nothing */
2744 do { old=b; b=b+b; }
2745 while ((base=((a+b)-a)) == 0.0 && b>old);
2746 if (b <= old) bad=1;
2751 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2752 if (setjmp(lab) == 0) { /* Yields nothing */
2753 do { eprec++; oldd=d; d=d*dbase; }
2754 while ((((d+one)-d)-one) == zero && d>oldd);
2755 if (d <= oldd) bad=1;
2762 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2763 co, thing, " check that you compiled without optimisation!",
2765 } else if (eprec==dprec) {
2766 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2768 } else if (eprec==fprec) {
2769 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2771 } else if (eprec==lprec) {
2772 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2775 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2776 co, Thing, eprec>dprec ? "higher" : "lower",
2777 "precision than double,\n using",
2778 eprec, "base digits",
2783 #else /* not Number */
2785 #ifdef FPROP /* Then create dummy routines for long double */
2787 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2791 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2794 #endif /* ifdef Number */
2796 /* Increment the pass number */
2815 #ifdef PASS /* then rescan this file */
2817 #include "enquire.c"
2819 #include FILENAME /* if this line fails to compile, define NO_FILE */