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.
22 Add #undef before every #define, Jim Wilson, Dec 92.
25 With luck and a following wind, just the following will work:
26 cc enquire.c -o enquire
27 You may get some messages about unreachable code, which you can ignore.
29 If your compiler doesn't support: add flag:
30 signed char (eg pcc) -DNO_SC
32 unsigned short and long -DNO_UI
34 signal(), or setjmp/longjmp() -DNO_SIG
35 %Lf in printf -DNO_LONG_DOUBLE_IO
37 Try to compile first with no flags, and see if you get any errors -
38 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
39 Some compilers need a -f flag for floating point.
41 Don't use any optimisation flags: the program may not work if you do.
42 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
43 optimiser, to a floating-point unit there's a world of difference.
45 Some compilers offer various flags for different floating point
46 modes; it's worth trying all possible combinations of these.
48 Add -DID=\"name\" if you want the machine/flags identified in the output.
51 Because of bugs and/or inadequacies, some compilers need the following
54 If your C preprocessor doesn't have the predefined __FILE__ macro, and
55 you don't want to call this file enquire.c but, say, tell.c, add the
56 flag -DFILENAME=\"tell.c\" .
58 Some compilers won't accept the line "#include FILENAME".
59 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
61 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
62 or -DNO_FILE as above.
64 Some naughty compilers define __STDC__, but don't really support it.
65 Some define it as 0, in which case we treat it as undefined.
66 But if your compiler defines it, and isn't really ANSI C,
67 add flag -DNO_STDC. (To those compiler writers: for shame).
69 Some naughty compilers define __STDC__, but don't have the stddef.h
70 include file. Add flag -DNO_STDDEF.
72 Summary of naughty-compiler flags:
73 If your compiler doesn't support: add flag:
74 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
75 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
76 #include FILENAME -DNO_FILE
77 __STDC__ (properly) -DNO_STDC
80 Some systems crash when you try to malloc all store. To save users of
81 such defective systems too much grief, they may compile with -DNO_MEM,
82 which ignores that bit of the code.
84 While it is not our policy to support defective compilers, pity has been
85 taken on people with compilers that can't produce object files bigger than
86 32k (especially since it was an easy addition). Compile the program
87 into separate parts like this:
88 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
89 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
90 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
91 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
92 cc -o enquire p0.o p1.o p2.o p3.o
95 You may possibly need to add some calls to signal() for other sorts of
96 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
97 #ifdef SIGxxx in main() (and communicate the differences to me!).
100 Run without argument to get the information as English text. If run
101 with argument -l (e.g. enquire -l), output is a series of #define's for
102 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
103 with argument -f, output is a series of #define's for the ANSI standard
104 float.h include file (according to ANSI C Draft of Dec 7, 1988).
105 Flag -v gives verbose output: output includes the English text above
106 as C comments. The program exit(0)'s if everything went ok, otherwise
107 it exits with a positive number, telling how many problems there were.
109 VERIFYING THE COMPILER
110 If, having produced the float.h and limits.h header files, you want to
111 verify that the compiler reads them back correctly (there are a lot of
112 boundary cases, of course, like minimum and maximum numbers), you can
113 recompile enquire.c with -DVERIFY set (plus the other flags that you used
114 when compiling the version that produced the header files). This then
115 recompiles the program so that it #includes "limits.h" and "float.h",
116 and checks that the constants it finds there are the same as the
117 constants it produces. Run the resulting program with enquire -fl.
118 Very few compilers have passed without error.
119 NB: You *must* recompile with the same compiler and flags, otherwise
120 you may get odd results.
122 You can also use this option if your compiler already has both files,
123 and you want to confirm that this program produces the right results.
126 This program is now quite trustworthy, and suspicious and wrong output
127 may well be caused by bugs in the compiler, not in the program (however
128 of course, this is not guaranteed, and no responsibility can be
131 The program only works if overflows are ignored by the C system or
132 are catchable with signal().
134 If the program fails to run to completion (often with the error message
135 "Unexpected signal at point x"), this often turns out to be a bug in the
136 C compiler's run-time system. Check what was about to be printed, and
137 try to narrow the problem down.
139 Another possible problem is that you have compiled the program to produce
140 loss-of-precision arithmetic traps. The program cannot cope with these,
141 and you should re-compile without them. (They should never be the default).
143 Make sure you compiled with optimisation turned off.
145 Output preceded by *** WARNING: identifies behaviour of the C system
146 deemed incorrect by the program. Likely problems are that printf or
147 scanf don't cope properly with certain boundary numbers: this program
148 goes to a lot of trouble to calculate its values, and these values
149 are mostly boundary numbers. Experience has shown that often printf
150 cannot cope with these values, and so in an attempt to increase
151 confidence in the output, for each float and double that is printed,
152 the printed value is checked by using sscanf to read it back.
153 Care is taken that numbers are printed with enough digits to uniquely
154 identify them, and therefore that they can be read back identically.
155 If the number read back is different, then there is probably a bug in
156 printf or sscanf, and the program prints the warning message.
157 If the two numbers in the warning look identical, then printf is more
158 than likely rounding the last digit(s) incorrectly. To put you at ease
159 that the two really are different, the bit patterns of the two numbers
160 are also printed. The difference is very likely in the last bit.
161 Many scanf's read the minimum double back as 0.0, and similarly cause
162 overflow when reading the maximum double. This program quite ruthlessly
163 declares all these behaviours faulty. The point is that if you get
164 one of these warnings, the output may be wrong, so you should check
165 the result carefully if you intend to use the results. Of course, printf
166 and sscanf may both be wrong, and cancel each other out, so you should
167 check the output carefully anyway.
169 The warning that "a cast didn't work" refers to cases like this:
172 #define C 1.234567890123456789
174 if (f != (float) C) printf ("Wrong!");
176 A faulty compiler will widen f to double and ignore the cast to float,
177 and because there is more accuracy in a double than a float, fail to
178 recognise that they are the same. In the actual case in point, f and C
179 are passed as parameters to a function that discovers they are not equal,
180 so it's just possible that the error was in the parameter passing,
181 not in the cast (see function Validate()).
182 For ANSI C, which has float constants, the error message is "constant has
186 If the program doesn't work for you for any reason that can't be
187 narrowed down to a problem in the C compiler, or it has to be changed in
188 order to get it to compile, or it produces suspicious output (like a very
189 low maximum float, for instance), please mail the problem and an example
190 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
191 improvements can be worked into future versions; cwi.nl is the European
192 backbone, and is connected to uunet and other fine hosts.
194 The program tries to catch and diagnose bugs in the compiler/run-time
195 system. I would be especially pleased to have reports of failures so
196 that I can improve this service.
198 I apologise unreservedly for the contorted use of the preprocessor...
201 You may copy and distribute verbatim copies of this source file.
203 You may modify this source file, and copy and distribute such
204 modified versions, provided that you leave the copyright notice
205 at the top of the file and also cause the modified file to carry
206 prominent notices stating that you changed the files and the date
207 of any change; and cause the whole of any work that you distribute
208 or publish, that in whole or in part contains or is a derivative of
209 this program or any part thereof, to be licensed at no charge to
210 all third parties on terms identical to those here.
212 If you do have a fix to any problem, please send it to me, so that
213 other people can have the benefits.
215 While every effort has been taken to make this program as reliable as
216 possible, no responsibility can be taken for the correctness of the
217 output, nor suitability for any particular use.
219 This program is an offshoot of a project funded by public funds.
220 If you use this program for research or commercial use (i.e. more
221 than just for the fun of knowing about your compiler) mailing a short
222 note of acknowledgement may help keep enquire.c supported.
225 Many people have given time and ideas to making this program what it is.
226 To all of them thanks, and apologies for not mentioning them by name.
229 Originally started as a program to generate configuration constants
230 for a large piece of software we were writing, which later took on
232 1.0 Length 6658!; end 1984?
233 Unix only. Only printed a dozen maximum int/double values.
234 2.0 Length 10535; Spring 1985
235 Prints values as #defines (about 20 of them)
236 More extensive floating point, using Cody and Waite
237 Handles signals better
238 Programs around optimisations
240 3.0 Length 12648; Aug 1987; prints about 42 values
241 Added PASS stuff, so treats float as well as double
242 4.0 Length 33891; Feb 1989; prints around 85 values
243 First GNU version (for gcc, where they call it hard-params.c)
244 Generates float.h and limits.h files
246 Generates warnings for dubious output
247 4.1 Length 47738; April 1989
248 Added VERIFY and TEST
249 4.2 Length 63442; Feb 1990
252 Added check for pseudo-unsigned chars
253 Added description for each #define output
254 Added check for absence of defines during verify
256 Added NO_STDC and NO_FILE
257 Fixed alignments output
258 4.3 Length 75000; Oct 1990; around 114 lines of output
259 Function xmalloc defined, Richard Stallman, June 89.
260 Alignments computed from member offsets rather than structure sizes,
261 Richard Stallman, Oct 89.
262 Print whether char* and int* pointers have the same format;
263 also char * and function *.
264 Update to Draft C version Dec 7, 1988
265 - types of constants produced in limits.h
266 (whether to put a U after unsigned shorts and chars and
267 whether to output -1024 as (-1023-1))
268 - values of SCHAR_MIN/MAX
269 - values of *_EPSILON (not the smallest but the effective smallest)
270 Added FILENAME, since standard C doesn't allow #define __FILE__
271 Renamed from config.c to enquire.c
272 Added size_t and ptrdiff_t enquiries
273 Added promotion enquiries
274 Added type checks of #defines
276 Changed endian to allow for cases where not all bits are used
277 Sanity check for max integrals
278 Fixed definition of setjmp for -DNO_SIG
279 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
283 /* Set FILENAME to the name of this file */
286 #define FILENAME "enquire.c"
288 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
289 #define FILENAME __FILE__
291 #define FILENAME "enquire.c"
292 #endif /* __FILE__ */
294 #endif /* FILENAME */
296 /* If PASS isn't defined, then this is the first pass over this file. */
304 /* A description of the ANSI constants */
305 #define D_CHAR_BIT "Number of bits in a storage unit"
306 #define D_CHAR_MAX "Maximum char"
307 #define D_CHAR_MIN "Minimum char"
308 #define D_SCHAR_MAX "Maximum signed char"
309 #define D_SCHAR_MIN "Minimum signed char"
310 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
312 #define D_INT_MAX "Maximum %s"
313 #define D_INT_MIN "Minimum %s"
314 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
316 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
317 #define D_FLT_RADIX "Radix of exponent representation"
318 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
319 #define D_DIG "Number of decimal digits of precision in a %s"
320 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
321 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
322 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
323 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
324 #define D_MAX "Maximum %s"
325 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
326 #define D_MIN "Minimum normalised %s"
328 /* Procedure just marks the functions that don't return a result */
330 #define Procedure int
332 #define Procedure void
335 /* Some bad compilers define __STDC__, when they don't support it.
336 Compile with -DNO_STDC to get round this.
340 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
346 /* Stuff different for ANSI C, and old C:
347 ARGS and NOARGS are used for function prototypes.
348 Volatile is used to reduce the chance of optimisation,
349 and to prevent variables being put in registers (when setjmp/longjmp
350 wouldn't work as we want)
351 Long_double is the longest floating point type available.
352 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
353 U is output after unsigned constants.
358 #define NOARGS (void)
359 #define Volatile volatile
360 #define Long_double long double
364 #else /* Old style C */
368 #define Volatile static
369 #define Long_double double
380 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
387 #include <sys/types.h>
392 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
408 #define Vprintf if (V) printf
409 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
410 #define fabs(x) (((x)<0.0)?(-x):(x))
416 /* Prototypes for what's to come: */
421 char *malloc (); /* Old style prototype */
423 char *malloc ARGS((size_t size));
426 Procedure exit ARGS((int status));
428 char *f_rep ARGS((int precision, Long_double val));
429 char *fake_f_rep ARGS((char *type, Long_double val));
431 int maximum_int NOARGS;
434 Procedure sprop NOARGS;
435 Procedure iprop NOARGS;
436 Procedure lprop NOARGS;
437 Procedure usprop NOARGS;
438 Procedure uiprop NOARGS;
439 Procedure ulprop NOARGS;
440 int fprop ARGS((int bits_per_byte));
441 int dprop ARGS((int bits_per_byte));
442 int ldprop ARGS((int bits_per_byte));
443 Procedure efprop ARGS((int fprec, int dprec, int lprec));
444 Procedure edprop ARGS((int fprec, int dprec, int lprec));
445 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
447 int setmode ARGS((char *s));
448 Procedure farewell ARGS((int bugs));
449 Procedure describe ARGS((char *description, char *extra));
450 Procedure missing ARGS((char *s));
451 Procedure fmissing ARGS((char *s));
452 Procedure check_defines NOARGS;
453 Procedure bitpattern ARGS((char *p, unsigned int size));
454 int ceil_log ARGS((int base, Long_double x));
455 Procedure croak ARGS((int place));
456 Procedure eek_a_bug ARGS((char *problem));
457 Procedure endian ARGS((int bits_per_byte));
458 int exponent ARGS((Long_double x, double *fract, int *exp));
459 int floor_log ARGS((int base, Long_double x));
460 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
461 int prec, Long_double val, char *mark));
462 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
463 long val, long lim, long req, char *mark));
464 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
465 unsigned long val, unsigned long req, char *mark));
467 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
469 /* Dummy routines instead */
471 int setjmp ARGS((int lab));
474 int setjmp(lab) int lab; { return(0); }
475 Procedure signal(i, p) int i, (*p)(); {}
479 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
480 signal(sig, overflow);
486 int V= 0, /* verbose */
487 L= 0, /* produce limits.h */
488 F= 0, /* produce float.h */
489 bugs=0; /* The number of (possible) bugs in the output */
491 char co[4], oc[4]; /* Comment starter and ender symbols */
493 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
494 int flt_rounds; /* The calculated value of FLT_ROUNDS */
495 int flt_radix; /* The calculated value of FLT_RADIX */
498 /* Set the fp modes on a SUN with 68881 chip, to check that different
499 rounding modes etc. get properly detected.
500 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
501 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
502 register to hex-number
505 /* Bits 0x30 = rounding mode */
506 #define ROUND_BITS 0x30
507 #define TO_NEAREST 0x00
509 #define TO_MINUS_INF 0x20
510 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
512 /* Bits 0xc0 = extended rounding */
513 #define EXT_BITS 0xc0
514 #define ROUND_EXTENDED 0x00
515 #define ROUND_SINGLE 0x40
516 #define ROUND_DOUBLE 0x80
519 #define EXE_INEX1 0x100
520 #define EXE_INEX2 0x200
522 #define EXE_UNFL 0x800
523 #define EXE_OVFL 0x1000
524 #define EXE_OPERR 0x2000
525 #define EXE_SNAN 0x4000
526 #define EXE_BSUN 0x8000
528 /* Only used for testing, on a Sun with 68881 chip */
529 /* Print the FP mode */
530 printmode(new) unsigned new; {
532 printf("New fp mode:\n");
533 printf(" Round toward ");
534 switch (new & ROUND_BITS) {
535 case TO_NEAREST: printf("nearest"); break;
536 case TO_ZERO: printf("zero"); break;
537 case TO_MINUS_INF: printf("minus infinity"); break;
538 case TO_PLUS_INF: printf("plus infinity"); break;
539 default: printf("???"); break;
542 printf("\n Extended rounding precision: ");
544 switch (new & EXT_BITS) {
545 case ROUND_EXTENDED: printf("extended"); break;
546 case ROUND_SINGLE: printf("single"); break;
547 case ROUND_DOUBLE: printf("double"); break;
548 default: printf("???"); break;
551 printf("\n Enabled exceptions:");
552 if (new & (unsigned) EXE_INEX1) printf(" inex1");
553 if (new & (unsigned) EXE_INEX2) printf(" inex2");
554 if (new & (unsigned) EXE_DZ) printf(" dz");
555 if (new & (unsigned) EXE_UNFL) printf(" unfl");
556 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
557 if (new & (unsigned) EXE_OPERR) printf(" operr");
558 if (new & (unsigned) EXE_SNAN) printf(" snan");
559 if (new & (unsigned) EXE_BSUN) printf(" bsun");
563 /* Only used for testing, on a Sun with 68881 chip */
564 /* Set the FP mode */
565 int setmode(s) char *s; {
566 unsigned mode=0, dig;
571 if (c>='0' && c<='9') dig= c-'0';
572 else if (c>='a' && c<='f') dig= c-'a'+10;
573 else if (c>='A' && c<='F') dig= c-'A'+10;
582 int setmode(s) char *s; {
583 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
588 Procedure farewell(bugs) int bugs; {
589 if (bugs == 0) exit(0);
590 printf("\n%sFor hints on dealing with the ", co);
591 if (bugs == 1) printf("problem");
592 else printf("%d problems", bugs);
593 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
594 printf("%s%s\n", FILENAME, oc);
598 /* The program has received a signal where it wasn't expecting one */
599 Procedure croak(place) int place; {
600 printf("*** Unexpected signal at point %d\n", place);
601 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
604 /* This is here in case alloca.c is used, which calls this. */
605 char *xmalloc(size) unsigned size; {
606 char *value = (char *)malloc(size);
608 fprintf(stderr, "Virtual memory exceeded\n");
617 /* Find the maximum integer */
618 Volatile int newi, int_max, two=2;
620 /* Calculate maxint ***********************************/
621 /* Calculate 2**n-1 until overflow - then use the previous value */
625 if (setjmp(lab)==0) { /* Yields int_max */
626 while(newi>int_max) {
635 int main(argc, argv) int argc; char *argv[]; {
636 int dprec, fprec, lprec;
639 int i; char *s; int bad;
642 signal(SIGFPE, overflow);
645 signal(SIGOVER, overflow);
647 /* Add more calls as necessary */
652 for (i=1; i < argc; i++) {
658 case 'v': V=1; break;
659 case 'l': L=1; break;
660 case 'f': F=1; break;
661 default: bad=1; break;
664 } else if (*s == '+') {
671 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
676 co[0]= '/'; oc[0]= ' ';
677 co[1]= '*'; oc[1]= '*';
678 co[2]= ' '; oc[2]= '/';
679 co[3]= '\0'; oc[3]= '\0';
681 co[0]= '\0'; oc[0]= '\0';
685 if (L) printf("%slimits.h%s\n", co, oc);
686 if (F) printf("%sfloat.h%s\n", co, oc);
688 printf ("#ifndef _FLOAT_H___\n");
689 printf ("#define _FLOAT_H___\n");
692 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
693 co, ID, VERSION, oc);
695 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
700 printf("%sVerification phase%s\n", co, oc);
704 Vprintf("%sCompiled without signal(): %s%s\n",
706 "there's nothing that can be done if overflow occurs",
710 Vprintf("%sCompiled without signed char%s\n", co, oc);
713 Vprintf("%Compiled without unsigned char%s\n", co, oc);
716 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
719 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
722 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
727 maxint= maximum_int();
728 bits_per_byte= basic();
731 fprec= fprop(bits_per_byte);
732 dprec= dprop(bits_per_byte);
733 lprec= ldprop(bits_per_byte);
734 efprop(fprec, dprec, lprec);
735 edprop(fprec, dprec, lprec);
736 eldprop(fprec, dprec, lprec);
740 /* An extra goody: the approximate amount of data-space */
741 /* Allocate store until no more available */
742 /* Different implementations have a different argument type
743 to malloc. Here we assume that it's the same type as
744 that which sizeof() returns */
745 size=1<<((bits_per_byte*sizeof(int))-2);
748 while ( malloc((false()?sizeof(int):size)) !=
756 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
757 co, (total+511)/512, oc);
761 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
764 return bugs; /* To keep compilers and lint happy */
767 Procedure eek_a_bug(problem) char *problem; {
768 /* The program has discovered a problem */
769 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
773 Procedure describe(description, extra) char *description, *extra; {
774 /* Produce the description for a #define */
776 printf(description, extra);
780 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
781 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
782 /* Produce a #define for a signed int type */
783 describe(desc, extra);
784 printf("#undef %s%s\n", sort, name);
786 printf("#define %s%s %ld%s\n", sort, name, val, mark);
787 } else if (val + lim < 0) {
788 /* We may not produce a constant like -1024 if the max
789 allowable value is 1023. It has then to be output as
790 -1023-1. lim is the max allowable value. */
791 printf("#define %s%s (%ld%s%ld%s)\n",
792 sort, name, -lim, mark, val+lim, mark);
794 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
796 /* If VERIFY is not set, val and req are just the same value;
797 if it is set, val is the value as calculated, and req is
798 the #defined constant
801 printf("%s*** Verify failed for above #define!\n", co);
802 printf(" Compiler has %ld for value%s\n\n", req, oc);
808 Procedure u_define(desc, extra, sort, name, val, req, mark)
809 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
810 /* Produce a #define for an unsigned value */
811 describe(desc, extra);
812 printf("#undef %s%s\n", sort, name);
813 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
815 printf("%s*** Verify failed for above #define!\n", co);
816 printf(" Compiler has %lu for value%s\n\n", req, oc);
822 Procedure f_define(desc, extra, sort, name, precision, val, mark)
823 char *desc, *extra, *sort, *name; int precision;
824 Long_double val; char *mark; {
825 /* Produce a #define for a float/double/long double */
826 describe(desc, extra);
827 printf ("#undef %s%s\n", sort, name);
829 #ifdef NO_LONG_DOUBLE_IO
830 static int union_defined = 0;
831 if (!strcmp(sort, "LDBL")) {
832 if (!union_defined) {
833 printf("#ifndef __LDBL_UNION__\n");
834 printf("#define __LDBL_UNION__\n");
835 printf("union __convert_long_double {\n");
836 printf(" int __convert_long_double_i[4];\n");
837 printf(" long double __convert_long_double_d;\n");
842 printf("#define %s%s %s\n",
843 sort, name, fake_f_rep("long double", val));
845 printf("#define %s%s %s%s\n",
846 sort, name, f_rep(precision, val), mark);
849 printf("#define %s%s %s%s\n",
850 sort, name, f_rep(precision, val), mark);
852 } else if (*mark == 'F') {
853 /* non-ANSI C has no float constants, so cast the constant */
854 printf("#define %s%s ((float)%s)\n",
855 sort, name, f_rep(precision, val));
857 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
862 int floor_log(base, x) int base; Long_double x; {
863 /* return floor(log base(x)) */
865 while (x>=base) { r++; x/=base; }
869 int ceil_log(base, x) int base; Long_double x; {
871 while (x>1.0) { r++; x/=base; }
875 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
876 /* Split x into a fraction and a power of ten;
877 returns 0 if x is unusable, 1 otherwise.
878 Only used for error messages about faulty output.
887 if (x==0.0) return 1;
891 if (old==x) return 0;
896 if (old==x) return 0;
899 if (neg) *fract= (double) -x;
900 else *fract=(double) x;
905 /* Print a value of type TYPE with value VAL,
906 assuming that sprintf can't handle this type properly (without truncation).
907 We create an expression that uses type casting to create the value from
910 char *fake_f_rep(type, val) char *type; Long_double val; {
911 static char buf[1024];
912 union { int i[4]; Long_double ld;} u;
914 sprintf(buf, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
915 u.i[0], u.i[1], u.i[2], u.i[3]);
919 char *f_rep(precision, val) int precision; Long_double val; {
920 /* Return the floating representation of val */
921 static char buf[1024];
923 #ifdef NO_LONG_DOUBLE_IO
926 if (sizeof(double) == sizeof(Long_double))
930 /* Assume they're the same, and use non-stdc format */
931 /* This is for stdc compilers using non-stdc libraries */
932 sprintf(buf, "%.*e", precision, d);
934 /* It had better support Le then */
935 sprintf(buf, "%.*Le", precision, val);
940 Procedure bitpattern(p, size) char *p; unsigned int size; {
941 /* Printf the bit-pattern of p */
945 for (i=1; i<=size; i++) {
948 for (j=bits_per_byte-1; j>=0; j--)
949 printf("%c", (c>>j)&1 ? '1' : '0');
950 if (i!=size) printf(" ");
954 #define Order(x, px, mode)\
955 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
956 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
957 putchar(c==0 ? '?' : (char)c); }\
960 Procedure endian(bits_per_byte) int bits_per_byte; {
961 /* Printf the byte-order used on this machine */
962 /*unsigned*/ short s=0;
963 /*unsigned*/ int j=0;
964 /*unsigned*/ long l=0;
966 char *ps= (char *) &s,
969 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
970 unsigned int mask, i, c;
973 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
976 printf("%sCHARACTER ORDER%s\n", co, oc);
977 Order(s, ps, "short:");
978 Order(j, pj, "int: ");
979 Order(l, pl, "long: ");
983 Procedure missing(s) char *s; {
984 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
988 Procedure fmissing(s) char *s; {
989 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
993 /* To try and fool optimisers */
994 int false() { return 0; }
996 #define Promoted(x) (false()?(x):(-1))
997 #define is_signed(x) (Promoted(x) < 0)
998 #define sign_of(x) ((x)?"signed":"unsigned")
1001 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1003 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1005 char *type_of(x) int x; {
1006 if (x == sizeof(char)) {
1007 if (sizeof(char) == sizeof(int)) return "char/short/int";
1008 if (sizeof(char) == sizeof(short)) return "char/short";
1011 if (x == sizeof(short)) {
1012 if (sizeof(short) == sizeof(int)) return "short/int";
1015 if (x == sizeof(int)) {
1016 if (sizeof(int) == sizeof(long)) return "int/long";
1019 if (x == sizeof(long)) return "long";
1020 return "unknown-type";
1023 char *ftype_of(x) int x; {
1024 if (x == sizeof(float)) {
1027 if (x == sizeof(double)) {
1028 if (sizeof(double) == sizeof(Long_double))
1029 return "(long)double";
1032 if (x == sizeof(Long_double)) {
1033 return "long double";
1035 return "unknown-type";
1038 Procedure typerr(name, esign, esize, sign, size)
1039 char *name; int esign, esize, sign, size;
1041 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1042 name, sign_of(esign), type_of(esize),
1043 sign_of(sign), type_of(size));
1046 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
1047 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1048 name, ftype_of(esize), ftype_of(size));
1053 unsigned int ui; unsigned long ul;
1054 short ss; unsigned short us;
1056 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1059 /* Possible warnings here; no problem */
1060 (sizeof(Promoted(si)) != sizeof(int)) ||
1061 (sizeof(Promoted(sl)) != sizeof(long)) ||
1062 (sizeof(Promoted(ss)) != sizeof(int)) ||
1063 (sizeof(Promoted(ui)) != sizeof(int)) ||
1064 (sizeof(Promoted(ul)) != sizeof(long)) ||
1065 (sizeof(Promoted(us)) != sizeof(int)) ||
1066 is_signed(ui) || is_signed(ul) ||
1067 !is_signed(si) || !is_signed(sl)
1070 eek_a_bug("promotions don't work properly in conditional expressions\n");
1073 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1074 showtype("long+unsigned gives", sl+ui);
1077 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1079 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1081 Procedure check_defines() {
1082 /* ensure that all #defines are present and have the correct type */
1089 /* Implementations promote unsigned short differently */
1090 usign= is_signed((unsigned short)0);
1095 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1097 missing("CHAR_BIT");
1100 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1102 missing("CHAR_MAX");
1105 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1107 missing("CHAR_MIN");
1110 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1112 missing("SCHAR_MAX");
1115 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1117 missing("SCHAR_MIN");
1120 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1122 missing("UCHAR_MAX");
1125 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1127 missing("SHRT_MAX");
1130 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1132 missing("SHRT_MIN");
1135 checktype(INT_MAX, "INT_MAX", Signed, int);
1140 checktype(INT_MIN, "INT_MIN", Signed, int);
1145 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1147 missing("LONG_MAX");
1150 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1152 missing("LONG_MIN");
1155 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1157 missing("USHRT_MAX");
1160 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1162 missing("UINT_MAX");
1165 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1167 missing("ULONG_MAX");
1173 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1175 fmissing("FLT_RADIX");
1178 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1180 fmissing("FLT_MANT_DIG");
1183 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1185 fmissing("FLT_DIG");
1188 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1190 fmissing("FLT_ROUNDS");
1193 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1195 fmissing("FLT_EPSILON");
1198 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1200 fmissing("FLT_MIN_EXP");
1203 fchecktype(FLT_MIN, "FLT_MIN", float);
1205 fmissing("FLT_MIN");
1207 #ifdef FLT_MIN_10_EXP
1208 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1210 fmissing("FLT_MIN_10_EXP");
1213 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1215 fmissing("FLT_MAX_EXP");
1218 fchecktype(FLT_MAX, "FLT_MAX", float);
1220 fmissing("FLT_MAX");
1222 #ifdef FLT_MAX_10_EXP
1223 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1225 fmissing("FLT_MAX_10_EXP");
1228 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1230 fmissing("DBL_MANT_DIG");
1233 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1235 fmissing("DBL_DIG");
1238 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1240 fmissing("DBL_EPSILON");
1243 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1245 fmissing("DBL_MIN_EXP");
1248 fchecktype(DBL_MIN, "DBL_MIN", double);
1250 fmissing("DBL_MIN");
1252 #ifdef DBL_MIN_10_EXP
1253 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1255 fmissing("DBL_MIN_10_EXP");
1258 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1260 fmissing("DBL_MAX_EXP");
1263 fchecktype(DBL_MAX, "DBL_MAX", double);
1265 fmissing("DBL_MAX");
1267 #ifdef DBL_MAX_10_EXP
1268 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1270 fmissing("DBL_MAX_10_EXP");
1273 #ifdef LDBL_MANT_DIG
1274 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1276 fmissing("LDBL_MANT_DIG");
1279 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1281 fmissing("LDBL_DIG");
1284 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1286 fmissing("LDBL_EPSILON");
1289 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1291 fmissing("LDBL_MIN_EXP");
1294 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1296 fmissing("LDBL_MIN");
1298 #ifdef LDBL_MIN_10_EXP
1299 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1301 fmissing("LDBL_MIN_10_EXP");
1304 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1306 fmissing("LDBL_MAX_EXP");
1309 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1311 fmissing("LDBL_MAX");
1313 #ifdef LDBL_MAX_10_EXP
1314 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1316 fmissing("LDBL_MAX_10_EXP");
1325 #define SCHAR_MAX char_max
1328 #define SCHAR_MIN char_min
1331 #define UCHAR_MAX char_max
1336 #define CHAR_BIT char_bit
1339 #define CHAR_MAX char_max
1342 #define CHAR_MIN char_min
1345 #define SCHAR_MAX char_max
1348 #define SCHAR_MIN char_min
1351 #define UCHAR_MAX char_max
1355 /* Properties of type char */
1356 Volatile char c, char_max, char_min;
1357 Volatile int bits_per_byte, c_signed;
1362 /* Calculate number of bits per character *************************/
1363 c=1; bits_per_byte=0;
1364 do { c=c<<1; bits_per_byte++; } while(c!=0);
1366 if (((int)c)<0) c_signed=1;
1368 Vprintf("%schar = %d bits, %ssigned%s\n",
1369 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1370 char_bit=(long)(sizeof(c)*bits_per_byte);
1371 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1372 char_bit, 0L, (long) CHAR_BIT, "");
1376 if (setjmp(lab)==0) { /* Yields char_max */
1377 while (c>char_max) {
1382 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1386 if (setjmp(lab)==0) { /* Yields char_min */
1387 while (c<char_min) {
1392 if (c_signed && char_min == 0) {
1393 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1394 Vprintf("%s %s%s%s\n",
1395 "They contain only nonnegative values, ",
1396 "but sign extend when used as integers.", co, oc);
1401 /* Because of the integer promotions, you must use a U after
1402 the MAX_CHARS in the following cases */
1403 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1404 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1406 (long) CHAR_MAX, "");
1408 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1409 (long) char_max, 0L,
1410 (long) CHAR_MAX, "");
1412 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1413 (long) char_min, (long) maxint,
1414 (long) CHAR_MIN, "");
1416 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1417 (long) char_max, 0L,
1418 (long) SCHAR_MAX, "");
1419 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1420 (long) char_min, (long) maxint,
1421 (long) SCHAR_MIN, "");
1423 if (sizeof(char) == sizeof(int)) {
1424 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1426 (long) UCHAR_MAX, "");
1428 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1429 (long) char_max, 0L,
1430 (long) UCHAR_MAX, "");
1436 Volatile unsigned char c, char_max;
1439 if (setjmp(lab)==0) { /* Yields char_max */
1440 while (c>char_max) {
1446 if (sizeof(char) == sizeof(int)) {
1447 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1449 (long) UCHAR_MAX, "");
1451 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1452 (long) char_max, 0L,
1453 (long) UCHAR_MAX, "");
1458 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1461 if (setjmp(lab)==0) { /* Yields char_max */
1462 while (c>char_max) {
1469 if (setjmp(lab)==0) { /* Yields char_min */
1470 while (c<char_min) {
1476 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1477 (long) char_min, (long) maxint,
1478 (long) SCHAR_MIN, "");
1479 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1480 (long) char_max, 0L,
1481 (long) SCHAR_MAX, "");
1485 return bits_per_byte;
1489 /* The properties of the basic types.
1490 Returns number of bits per sizeof unit */
1491 Volatile int bits_per_byte;
1492 typedef int function ();
1496 Vprintf("%sSIZES%s\n", co, oc);
1497 bits_per_byte= cprop();
1499 /* Shorts, ints and longs *****************************************/
1500 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1502 (int) sizeof(short)*bits_per_byte,
1503 (int) sizeof(int)*bits_per_byte,
1504 (int) sizeof(long)*bits_per_byte,
1505 (int) sizeof(float)*bits_per_byte,
1506 (int) sizeof(double)*bits_per_byte, oc);
1508 Vprintf("%slong double=%d bits%s\n",
1509 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1511 Vprintf("%schar*=%d bits%s%s\n",
1512 co, (int)sizeof(char *)*bits_per_byte,
1513 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1515 Vprintf("%sint* =%d bits%s%s\n",
1516 co, (int)sizeof(int *)*bits_per_byte,
1517 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1519 Vprintf("%sfunc*=%d bits%s%s\n",
1520 co, (int)sizeof(function *)*bits_per_byte,
1521 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1523 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1524 ((((false()?( sizeof(int)):(-1)) < 0) )?
1525 "signed":"unsigned") ,
1531 showtype("Type size_t is", sizeof(0));
1533 /* Alignment constants ********************************************/
1535 #define alignment(TYPE) \
1536 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1538 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1540 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1542 alignment(char), alignment(short),
1543 alignment(int), alignment(long),
1546 Vprintf("%sfloat=%ld double=%ld%s\n",
1548 alignment(float), alignment(double),
1552 Vprintf("%slong double=%ld%s\n",
1554 alignment(Long_double),
1557 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1559 alignment(char *), alignment(int *), alignment(function *),
1564 /* Ten little endians *********************************************/
1566 endian(bits_per_byte);
1568 /* Pointers *******************************************************/
1570 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1572 if ((long) (char *) &variable == (long) (int *) &variable)
1573 Vprintf("%sChar and int pointer formats seem identical%s\n",
1576 Vprintf("%sChar and int pointer formats are different%s\n",
1578 if ((long) (char *) &variable == (long) (function *) &variable)
1579 Vprintf("%sChar and function pointer formats seem identical%s\n",
1582 Vprintf("%sChar and function pointer formats are different%s\n",
1587 printf("%sStrings are shared%s\n", co, oc);
1588 else printf("%sStrings are not shared%s\n", co, oc);
1592 showtype("Type ptrdiff_t is", p-q);
1594 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1607 return bits_per_byte;
1610 #else /* not PASS0 */
1614 extern int V, L, F, bugs, bits_per_byte;
1615 extern char co[], oc[];
1616 extern char *f_rep();
1618 #endif /* ifdef PASS0 */
1620 /* As I said, I apologise for the contortions below. The functions are
1621 expanded by the preprocessor twice or three times (for float and double,
1622 and maybe for long double, and for short, int and long). That way,
1623 I never make a change to one that I forget to make to the other.
1624 You can look on it as C's fault for not supporting multi-line macro's.
1625 This whole file is read 3 times by the preprocessor, with PASSn set for
1626 n=1, 2 or 3, to decide which parts to reprocess.
1629 /* #undef on an already undefined thing is (wrongly) flagged as an error
1630 by some compilers, therefore the #ifdef that follows:
1656 /* These are the float.h constants */
1687 /* Define the things we're going to use this pass */
1689 #define Number float
1690 #define THING "FLOAT"
1691 #define Thing "Float"
1692 #define thing "float"
1695 #define Store fStore
1707 #define F_check fCheck
1710 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1713 #define EPROP efprop
1715 #define Integer short
1718 #define Iname "SHRT"
1724 #define UPROP usprop
1725 #define Uname "USHRT"
1729 #define I_MAX SHRT_MAX
1732 #define I_MIN SHRT_MIN
1735 #define U_MAX USHRT_MAX
1739 #define F_RADIX FLT_RADIX
1742 #define F_MANT_DIG FLT_MANT_DIG
1745 #define F_DIG FLT_DIG
1748 #define F_ROUNDS FLT_ROUNDS
1751 #define F_EPSILON FLT_EPSILON
1754 #define F_MIN_EXP FLT_MIN_EXP
1757 #define F_MIN FLT_MIN
1759 #ifdef FLT_MIN_10_EXP
1760 #define F_MIN_10_EXP FLT_MIN_10_EXP
1763 #define F_MAX_EXP FLT_MAX_EXP
1766 #define F_MAX FLT_MAX
1768 #ifdef FLT_MAX_10_EXP
1769 #define F_MAX_10_EXP FLT_MAX_10_EXP
1777 #define Number double
1778 #define THING "DOUBLE"
1779 #define Thing "Double"
1780 #define thing "double"
1783 #define Store dStore
1795 #define F_check dCheck
1798 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1801 #define EPROP edprop
1807 #define OK_UI 1 /* Unsigned int is always possible */
1810 #define UPROP uiprop
1811 #define Uname "UINT"
1815 #define I_MAX INT_MAX
1818 #define I_MIN INT_MIN
1821 #define U_MAX UINT_MAX
1825 #define F_MANT_DIG DBL_MANT_DIG
1828 #define F_DIG DBL_DIG
1831 #define F_EPSILON DBL_EPSILON
1834 #define F_MIN_EXP DBL_MIN_EXP
1837 #define F_MIN DBL_MIN
1839 #ifdef DBL_MIN_10_EXP
1840 #define F_MIN_10_EXP DBL_MIN_10_EXP
1843 #define F_MAX_EXP DBL_MAX_EXP
1846 #define F_MAX DBL_MAX
1848 #ifdef DBL_MAX_10_EXP
1849 #define F_MAX_10_EXP DBL_MAX_10_EXP
1858 #define Number long double
1868 #define THING "LONG DOUBLE"
1869 #define Thing "Long double"
1870 #define thing "long double"
1871 #define Fname "LDBL"
1872 #define FPROP ldprop
1873 #define Store ldStore
1879 #define F_check ldCheck
1882 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1885 #define EPROP eldprop
1887 #define Integer long
1890 #define Iname "LONG"
1896 #define UPROP ulprop
1897 #define Uname "ULONG"
1901 #define I_MAX LONG_MAX
1904 #define I_MIN LONG_MIN
1907 #define U_MAX ULONG_MAX
1910 #ifdef LDBL_MANT_DIG
1911 #define F_MANT_DIG LDBL_MANT_DIG
1914 #define F_DIG LDBL_DIG
1917 #define F_EPSILON LDBL_EPSILON
1920 #define F_MIN_EXP LDBL_MIN_EXP
1923 #define F_MIN LDBL_MIN
1925 #ifdef LDBL_MIN_10_EXP
1926 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1929 #define F_MAX_EXP LDBL_MAX_EXP
1932 #define F_MAX LDBL_MAX
1934 #ifdef LDBL_MAX_10_EXP
1935 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1942 #define I_MAX int_max
1945 #define I_MIN int_min
1952 #define F_RADIX f_radix
1955 #define F_MANT_DIG f_mant_dig
1961 #define F_ROUNDS f_rounds
1964 #define F_EPSILON f_epsilon
1967 #define F_MIN_EXP f_min_exp
1972 #ifndef F_MIN_10_EXP
1973 #define F_MIN_10_EXP f_min_10_exp
1976 #define F_MAX_EXP f_max_exp
1981 #ifndef F_MAX_10_EXP
1982 #define F_MAX_10_EXP f_max_10_exp
1986 #define Validate(prec, val, req, same) {;}
1992 /* the properties of short, int, and long */
1993 Volatile Integer newi, int_max, maxeri, int_min, minneri;
1994 Volatile int ibits, ipower, two=2;
1996 /* Calculate max short/int/long ***********************************/
1997 /* Calculate 2**n-1 until overflow - then use the previous value */
2001 if (setjmp(lab)==0) { /* Yields int_max */
2002 for(ipower=0; newi>int_max; ipower++) {
2006 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2007 co, INT[0]=='i'?"n":"", INT, oc);
2009 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2010 co, INT[0]=='i'?"n":"", INT, oc);
2014 /* Minimum value: assume either two's or one's complement *********/
2016 if (setjmp(lab)==0) { /* Yields int_min */
2017 if (int_min-1 < int_min) int_min--;
2021 /* Now for those daft Cybers */
2023 maxeri=0; newi=int_max;
2025 if (setjmp(lab)==0) { /* Yields maxeri */
2026 for(ibits=ipower; newi>maxeri; ibits++) {
2034 if (setjmp(lab)==0) { /* Yields minneri */
2035 if (minneri-1 < minneri) minneri--;
2039 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2040 co, INT, (long)int_max, ipower, oc);
2041 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
2043 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
2045 (long) I_MAX, IMARK);
2046 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
2047 (long) int_min, (long) (PASS==1?maxint:int_max),
2048 (long) I_MIN, IMARK);
2050 if(int_max < 0) { /* It has happened */
2051 eek_a_bug("signed integral comparison faulty?");
2054 if (maxeri>int_max) {
2055 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2056 co, INT, (long)maxeri, ibits,
2057 "but only for addition, not multiplication",
2058 "(I smell a Cyber!)",
2062 if (minneri<int_min) {
2063 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2064 co, INT, (long)minneri,
2065 "but only for addition, not multiplication",
2066 "(I smell a Cyber!)",
2071 Procedure UPROP () {
2072 /* The properties of unsigned short/int/long */
2074 Volatile unsigned Integer u_max, newi, two;
2075 newi=1; u_max=0; two=2;
2077 if (setjmp(lab)==0) { /* Yields u_max */
2084 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2085 co, INT, (unsigned long) u_max, oc);
2087 /* Oh woe: new standard C defines value preserving promotions */
2089 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2090 /* Special only for short */
2091 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2092 (unsigned long) u_max, 0L,
2093 (unsigned long) U_MAX, IMARK);
2095 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2096 (unsigned long) u_max,
2097 (unsigned long) U_MAX, IMARK);
2103 #endif /* Integer */
2107 /* The following routines are intended to defeat any attempt at optimisation
2108 or use of extended precision, and to defeat faulty narrowing casts.
2109 The weird prototypes are because of widening incompatibilities.
2112 #define ARGS1(atype, a) (atype a)
2113 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2115 #define ARGS1(atype, a) (a) atype a;
2116 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2119 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2120 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2121 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2122 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2123 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2124 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2126 Procedure F_check ARGS((int precision, Long_double val1));
2128 Procedure F_check(precision, val1) int precision; Long_double val1; {
2129 /* You don't think I'm going to go to all the trouble of writing
2130 a program that works out what all sorts of values are, only to
2131 have printf go and print the wrong values out, do you?
2132 No, you're right, so this function tries to see if printf
2133 has written the right value, by reading it back again.
2134 This introduces a new problem of course: suppose printf writes
2135 the correct value, and scanf reads it back wrong... oh well.
2136 But I'm adamant about this: the precision given is enough
2137 to uniquely identify the printed number, therefore I insist
2138 that sscanf read the number back identically. Harsh yes, but
2139 sometimes you've got to be cruel to be kind.
2142 Number val, new, diff;
2148 if (sizeof(double) == sizeof(Long_double)) {
2149 /* Assume they're the same, and use non-stdc format */
2150 /* This is for stdc compilers using non-stdc libraries */
2151 f2= "%le"; /* Input */
2153 /* It had better support Le then */
2157 rep= f_rep(precision, (Long_double) val);
2158 if (setjmp(lab)==0) {
2159 sscanf(rep, f2, &new1);
2161 eek_a_bug("sscanf caused a trap");
2162 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2167 if (setjmp(lab)==0) { /* See if new is usable */
2170 diff= val/new - 1.0;
2171 if (diff < 0.1) diff= 1.0;
2172 /* That should be enough to generate a trap */
2175 eek_a_bug("sscanf returned an unusable number");
2176 printf("%s scanning: %s with format: %s%s\n\n",
2184 eek_a_bug("Possibly bad output from printf above");
2185 if (!exponent((Long_double)val, &rem, &e)) {
2186 printf("%s but value was an unusable number%s\n\n",
2190 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2191 co, precision, rem, e);
2192 bitpattern((char *) &val, (unsigned)sizeof(val));
2193 printf ("%s\n", oc);
2194 printf("%s sscanf gave %s, bit pattern:\n ",
2195 co, f_rep(precision, (Long_double) new));
2196 bitpattern((char *) &new, (unsigned)sizeof(new));
2197 printf ("%s\n", oc);
2198 if (setjmp(lab) == 0) {
2200 printf("%s difference= %s%s\n\n",
2201 co, f_rep(precision, (Long_double) diff), oc);
2202 } /* else forget it */
2208 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2209 /* Check that the compiler has read a #define value correctly */
2212 printf("%s*** Verify failed for above #define!\n", co);
2213 if (setjmp(lab) == 0) { /* for the case that req == nan */
2214 printf(" Compiler has %s for value%s\n",
2215 f_rep(prec, req), oc);
2217 printf(" Compiler has %s for value%s\n",
2218 "an unusable number", oc);
2220 if (setjmp(lab) == 0) {
2221 F_check(prec, (Long_double) req);
2222 } /*else forget it*/
2223 if (setjmp(lab) == 0) {
2224 if (req > 0.0 && val > 0.0) {
2225 printf("%s difference= %s%s\n",
2226 co, f_rep(prec, val-req), oc);
2228 } /*else forget it*/
2232 } else if (val != req) {
2233 if (stdc) eek_a_bug("constant has the wrong precision");
2234 else eek_a_bug("the cast didn't work");
2240 int FPROP(bits_per_byte) int bits_per_byte; {
2241 /* Properties of floating types, using algorithms by Cody and Waite
2242 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2243 Further extended by S Pemberton.
2245 Returns the number of digits in the fraction.
2249 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2250 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2251 mantbits, digs, f_dig, trap,
2252 hidden, normal, f_min_10_exp, f_max_10_exp;
2254 a, b, base, basein, basem1, f_epsilon, epsneg,
2255 eps, epsp1, etop, ebot,
2256 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2260 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2262 /* Base and size of significand **************************************/
2263 /* First repeatedly double until adding 1 has no effect. */
2264 /* For instance, if base is 10, with 3 significant digits */
2265 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2266 /* since 1024 is only representable as 1020. */
2268 if (setjmp(lab)==0) { /* inexact trap? */
2270 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2272 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2273 /* And supporting those is just TOO much trouble! */
2277 /* Now double until you find a number that can be added to the */
2278 /* above number. For 1020 this is 8 or 16, depending whether the */
2279 /* result is rounded or truncated. */
2280 /* In either case the result is 1030. 1030-1020= the base, 10. */
2282 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2284 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2286 /* Sanity check; if base<2, I can't guarantee the rest will work */
2288 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2293 if (PASS == 1) { /* only for FLT */
2295 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2296 (long) f_radix, 0L, (long) F_RADIX, "");
2297 } else if (f_radix != flt_radix) {
2298 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2299 co, thing, "arithmetic has a different radix",
2300 f_radix, "from float", oc);
2304 /* Now the number of digits precision */
2305 f_mant_dig=0; b=1.0;
2306 do { f_mant_dig++; b=Mul(b, base); }
2307 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2308 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2309 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2310 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2311 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2312 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2313 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2314 (long) f_dig, 0L, (long) F_DIG, "");
2315 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2317 /* Rounding *******************************************************/
2318 basem1=Diff(base, HALF);
2319 if (Diff(Sum(a, basem1), a) != ZERO) {
2320 if (f_radix == 2) basem1=0.375;
2322 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2323 else irnd=1; /* to nearest */
2324 } else irnd=0; /* towards 0 */
2326 basem1=Diff(base, HALF);
2328 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2329 if (f_radix == 2) basem1=0.375;
2331 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2332 else mrnd=1; /* to nearest */
2333 } else mrnd=0; /* towards 0 */
2335 f_rounds= -1; /* Unknown rounding */
2336 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2337 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2338 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2339 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2341 if (f_rounds != -1) {
2342 Vprintf("%sArithmetic rounds towards ", co);
2344 case 0: Vprintf("zero (i.e. it chops)"); break;
2345 case 1: Vprintf("nearest"); break;
2346 case 2: Vprintf("+infinity"); break;
2347 case 3: Vprintf("-infinity"); break;
2348 default: Vprintf("???"); break;
2350 Vprintf("%s\n", oc);
2351 } else { /* Hmm, try to give some help here */
2352 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2353 Vprintf("%s Negative numbers %s%s\n",
2354 co, mrnd==0 ? "towards zero" :
2355 mrnd==1 ? "to nearest" :
2358 Vprintf("%s Positive numbers %s%s\n",
2359 co, irnd==0 ? "towards zero" :
2360 irnd==1 ? "to nearest" :
2364 /* An extra goody */
2365 if (f_radix == 2 && f_rounds == 1) {
2366 if (Diff(Sum(a, ONE), a) != ZERO) {
2367 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2368 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2369 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2371 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2374 if (PASS == 1) { /* only for FLT */
2375 flt_rounds= f_rounds;
2377 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2378 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2379 } else if (f_rounds != flt_rounds) {
2380 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2381 co, thing, "arithmetic rounds differently",
2382 f_rounds, "from float", oc);
2386 /* Various flavours of epsilon ************************************/
2387 negeps=f_mant_dig+f_mant_dig;
2390 for(i=1; i<=negeps; i++) a*=basein;
2393 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2398 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2403 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2404 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2405 ebot and etop are the current bounds */
2406 while (eps != ebot && eps != etop) {
2407 epsp1 = Diff(ONE, eps);
2408 if (epsp1 < ONE) etop = eps;
2410 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2414 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2415 eek_a_bug("internal error calculating epsneg");
2417 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2418 co, f_rep(digs, (Long_double) eps), oc);
2419 if (V) F_check(digs, (Long_double) eps);
2422 if ((f_radix!=2) && irnd) {
2423 /* a=(a*(1.0+a))/(1.0+1.0); => */
2424 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2425 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2426 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2428 /* epsneg is used later */
2431 machep= -f_mant_dig-f_mant_dig;
2433 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2434 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2439 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2440 /* find the smallest eps (1+eps != 1) by binary search.
2441 ebot and etop are the current bounds */
2442 while (eps != ebot && eps != etop) {
2443 epsp1 = Sum(ONE, eps);
2444 if (epsp1 > ONE) etop = eps;
2446 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2449 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2450 eek_a_bug("internal error calculating eps");
2454 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2455 co, f_rep(digs, (Long_double) f_epsilon), oc);
2457 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2458 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2459 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2461 /* Possible loss of precision warnings here from non-stdc compilers */
2462 if (F) f_define(D_EPSILON, thing,
2463 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2464 if (V || F) F_check(digs, (Long_double) f_epsilon);
2466 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2467 f_epsilon == Self(F_EPSILON));
2470 /* Extra chop info *************************************************/
2471 if (f_rounds == 0) {
2472 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2473 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2477 /* Size of and minimum normalised exponent ************************/
2478 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2480 /* Coarse search for the largest power of two */
2481 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2484 z=Mul(y,y); z1=Mul(z1, y);
2487 if (z2 != y1) break;
2488 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2493 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2497 if (f_radix != 10) {
2498 iexp=i+1; /* for the sign */
2503 while (k >= iz) { iz*=f_radix; iexp++; }
2507 /* Fine tune starting with y and y1 */
2508 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2511 y=Div(y,base); y1=Div(y1,base);
2514 if (z2 != z1) break;
2515 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2523 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2524 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2525 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2527 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2528 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2530 if (setjmp(lab)==0) {
2531 Vprintf("%sMinimum normalised positive number = %s%s\n",
2532 co, f_rep(digs, (Long_double) f_min), oc);
2534 eek_a_bug("printf can't print the smallest normalised number");
2538 /* Possible loss of precision warnings here from non-stdc compilers */
2539 if (setjmp(lab) == 0) {
2540 if (F) f_define(D_MIN, thing,
2541 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2542 if (V || F) F_check(digs, (Long_double) f_min);
2544 eek_a_bug("xxx_MIN caused a trap");
2548 if (setjmp(lab) == 0) {
2549 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2550 f_min == Self(F_MIN));
2552 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2553 co, "Compiler has an unusable number for value", oc);
2558 a=1.0; f_min_10_exp=0;
2559 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2560 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2561 (long) f_min_10_exp, (long) maxint,
2562 (long) F_MIN_10_EXP, "");
2564 /* Minimum exponent ************************************************/
2565 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2570 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2575 if (xminner != 0.0 && xminner != f_min) {
2577 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2579 if (setjmp(lab)==0) {
2580 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2581 co, f_rep(digs, (Long_double) xminner), oc);
2582 if (V) F_check(digs, (Long_double) xminner);
2584 eek_a_bug("printf can't print the smallest unnormalised number.");
2590 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2593 /* Maximum exponent ************************************************/
2594 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2596 while (f_max<newxmax) {
2598 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2599 newxmax=Mul(newxmax, base);
2604 if (Div(newxmax, base) != f_max) {
2605 inf=1; /* ieee infinity */
2612 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2615 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2616 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2617 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2618 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2620 /* Largest number ***************************************************/
2621 f_max=Diff(ONE, epsneg);
2622 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2623 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2625 if (setjmp(lab)==0) {
2626 Vprintf("%sMaximum number = %s%s\n",
2627 co, f_rep(digs, (Long_double) f_max), oc);
2629 eek_a_bug("printf can't print the largest double.");
2632 if (setjmp(lab)==0) {
2633 /* Possible loss of precision warnings here from non-stdc compilers */
2634 if (F) f_define(D_MAX, thing,
2635 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2636 if (V || F) F_check(digs, (Long_double) f_max);
2638 eek_a_bug("xxx_MAX caused a trap");
2641 if (setjmp(lab)==0) {
2642 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2643 f_max == Self(F_MAX));
2645 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2646 co, "Compiler has an unusable number for value", oc);
2651 a=1.0; f_max_10_exp=0;
2652 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2653 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2654 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2656 /* Hidden bit + sanity check ****************************************/
2657 if (f_radix != 10) {
2659 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2660 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2662 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2663 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2664 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2667 printf("\n%s%s\n %s %s %s!%s\n\n",
2669 "*** Something fishy here!",
2670 "Exponent size + significand size doesn't match",
2671 "with the size of a", thing,
2674 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2675 Vprintf("%sIt looks like %s length IEEE format%s\n",
2676 co, f_mant_dig==24 ? "single" :
2677 f_mant_dig==53 ? "double" :
2678 f_mant_dig >53 ? "extended" :
2680 if (f_rounds != 1 || normal) {
2681 Vprintf("%s though ", co);
2682 if (f_rounds != 1) {
2683 Vprintf("the rounding is unusual");
2684 if (normal) Vprintf(" and ");
2686 if (normal) Vprintf("the normalisation is unusual");
2687 Vprintf("%s\n", oc);
2690 Vprintf("%sIt doesn't look like IEEE format%s\n",
2694 printf("\n"); /* regardless of verbosity */
2698 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2699 /* See if expressions are evaluated in extended precision.
2700 Some compilers optimise even if you don't want it,
2701 and then this function fails to produce the right result.
2702 We try to diagnose this if it happens.
2705 Volatile double a, b, base, old;
2706 Volatile Number d, oldd, dbase, one, zero;
2709 /* Size of significand **************************************/
2711 if (setjmp(lab) == 0) { /* Yields nothing */
2712 do { old=a; a=a+a; }
2713 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2716 /* Avoid the comparison if bad is set,
2717 to avoid trouble on the convex. */
2718 if (!bad && (a <= old)) bad=1;
2722 if (setjmp(lab) == 0) { /* Yields nothing */
2723 do { old=b; b=b+b; }
2724 while ((base=((a+b)-a)) == 0.0 && b>old);
2725 if (b <= old) bad=1;
2730 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2731 if (setjmp(lab) == 0) { /* Yields nothing */
2732 do { eprec++; oldd=d; d=d*dbase; }
2733 while ((((d+one)-d)-one) == zero && d>oldd);
2734 if (d <= oldd) bad=1;
2741 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2742 co, thing, " check that you compiled without optimisation!",
2744 } else if (eprec==dprec) {
2745 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2747 } else if (eprec==fprec) {
2748 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2750 } else if (eprec==lprec) {
2751 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2754 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2755 co, Thing, eprec>dprec ? "higher" : "lower",
2756 "precision than double,\n using",
2757 eprec, "base digits",
2762 #else /* not Number */
2764 #ifdef FPROP /* Then create dummy routines for long double */
2766 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2770 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2773 #endif /* ifdef Number */
2775 /* Increment the pass number */
2794 #ifdef PASS /* then rescan this file */
2796 #include "enquire.c"
2798 #include FILENAME /* if this line fails to compile, define NO_FILE */