Initial revision
[official-gcc.git] / gcc / enquire.c
blob763b1a44c9d300c2e4d3da89d2b35f08519572a4
1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
4 #ifndef VERSION
5 #define VERSION "4.3"
6 #endif
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.
12 All rights reserved.
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 Change by Jim Wilson:
24 Add #undef before every #define, Dec 92.
25 Use stddef.h not gstddef.h, Mar 94.
27 Changes by Paul Eggert, installed Feb 93:
28 (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
29 (f_define): Use ordinary constants for long double
30 if it's same width as double. Make __convert_long_double_i unsigned.
31 Richard Stallman, May 93:
32 In F_check, check NO_LONG_DOUBLE_IO.
34 Changes by Stephen Moshier, installed Sep 93:
35 (FPROP): Recognize 80387 or 68881 XFmode format.
38 COMPILING
39 With luck and a following wind, just the following will work:
40 cc enquire.c -o enquire
41 You may get some messages about unreachable code, which you can ignore.
43 If your compiler doesn't support: add flag:
44 signed char (eg pcc) -DNO_SC
45 unsigned char -DNO_UC
46 unsigned short and long -DNO_UI
47 void -DNO_VOID
48 signal(), or setjmp/longjmp() -DNO_SIG
49 %Lf in printf -DNO_LONG_DOUBLE_IO
51 Try to compile first with no flags, and see if you get any errors -
52 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
53 Some compilers need a -f flag for floating point.
55 Don't use any optimisation flags: the program may not work if you do.
56 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
57 optimiser, to a floating-point unit there's a world of difference.
59 Some compilers offer various flags for different floating point
60 modes; it's worth trying all possible combinations of these.
62 Add -DID=\"name\" if you want the machine/flags identified in the output.
64 FAULTY COMPILERS
65 Because of bugs and/or inadequacies, some compilers need the following
66 defines:
68 If your C preprocessor doesn't have the predefined __FILE__ macro, and
69 you don't want to call this file enquire.c but, say, tell.c, add the
70 flag -DFILENAME=\"tell.c\" .
72 Some compilers won't accept the line "#include FILENAME".
73 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
75 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
76 or -DNO_FILE as above.
78 Some naughty compilers define __STDC__, but don't really support it.
79 Some define it as 0, in which case we treat it as undefined.
80 But if your compiler defines it, and isn't really ANSI C,
81 add flag -DNO_STDC. (To those compiler writers: for shame).
83 Some naughty compilers define __STDC__, but don't have the stddef.h
84 include file. Add flag -DNO_STDDEF.
86 Summary of naughty-compiler flags:
87 If your compiler doesn't support: add flag:
88 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
89 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
90 #include FILENAME -DNO_FILE
91 __STDC__ (properly) -DNO_STDC
92 stddef.h -DNO_STDDEF
94 Some systems crash when you try to malloc all store. To save users of
95 such defective systems too much grief, they may compile with -DNO_MEM,
96 which ignores that bit of the code.
98 While it is not our policy to support defective compilers, pity has been
99 taken on people with compilers that can't produce object files bigger than
100 32k (especially since it was an easy addition). Compile the program
101 into separate parts like this:
102 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
103 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
104 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
105 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
106 cc -o enquire p0.o p1.o p2.o p3.o
108 SYSTEM DEPENDENCIES
109 You may possibly need to add some calls to signal() for other sorts of
110 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
111 #ifdef SIGxxx in main() (and communicate the differences to me!).
113 OUTPUT
114 Run without argument to get the information as English text. If run
115 with argument -l (e.g. enquire -l), output is a series of #define's for
116 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
117 with argument -f, output is a series of #define's for the ANSI standard
118 float.h include file (according to ANSI C Draft of Dec 7, 1988).
119 Flag -v gives verbose output: output includes the English text above
120 as C comments. The program exit(0)'s if everything went ok, otherwise
121 it exits with a positive number, telling how many problems there were.
123 VERIFYING THE COMPILER
124 If, having produced the float.h and limits.h header files, you want to
125 verify that the compiler reads them back correctly (there are a lot of
126 boundary cases, of course, like minimum and maximum numbers), you can
127 recompile enquire.c with -DVERIFY set (plus the other flags that you used
128 when compiling the version that produced the header files). This then
129 recompiles the program so that it #includes "limits.h" and "float.h",
130 and checks that the constants it finds there are the same as the
131 constants it produces. Run the resulting program with enquire -fl.
132 Very few compilers have passed without error.
133 NB: You *must* recompile with the same compiler and flags, otherwise
134 you may get odd results.
136 You can also use this option if your compiler already has both files,
137 and you want to confirm that this program produces the right results.
139 TROUBLESHOOTING.
140 This program is now quite trustworthy, and suspicious and wrong output
141 may well be caused by bugs in the compiler, not in the program (however
142 of course, this is not guaranteed, and no responsibility can be
143 accepted, etc.)
145 The program only works if overflows are ignored by the C system or
146 are catchable with signal().
148 If the program fails to run to completion (often with the error message
149 "Unexpected signal at point x"), this often turns out to be a bug in the
150 C compiler's run-time system. Check what was about to be printed, and
151 try to narrow the problem down.
153 Another possible problem is that you have compiled the program to produce
154 loss-of-precision arithmetic traps. The program cannot cope with these,
155 and you should re-compile without them. (They should never be the default).
157 Make sure you compiled with optimisation turned off.
159 Output preceded by *** WARNING: identifies behaviour of the C system
160 deemed incorrect by the program. Likely problems are that printf or
161 scanf don't cope properly with certain boundary numbers: this program
162 goes to a lot of trouble to calculate its values, and these values
163 are mostly boundary numbers. Experience has shown that often printf
164 cannot cope with these values, and so in an attempt to increase
165 confidence in the output, for each float and double that is printed,
166 the printed value is checked by using sscanf to read it back.
167 Care is taken that numbers are printed with enough digits to uniquely
168 identify them, and therefore that they can be read back identically.
169 If the number read back is different, then there is probably a bug in
170 printf or sscanf, and the program prints the warning message.
171 If the two numbers in the warning look identical, then printf is more
172 than likely rounding the last digit(s) incorrectly. To put you at ease
173 that the two really are different, the bit patterns of the two numbers
174 are also printed. The difference is very likely in the last bit.
175 Many scanf's read the minimum double back as 0.0, and similarly cause
176 overflow when reading the maximum double. This program quite ruthlessly
177 declares all these behaviours faulty. The point is that if you get
178 one of these warnings, the output may be wrong, so you should check
179 the result carefully if you intend to use the results. Of course, printf
180 and sscanf may both be wrong, and cancel each other out, so you should
181 check the output carefully anyway.
183 The warning that "a cast didn't work" refers to cases like this:
185 float f;
186 #define C 1.234567890123456789
187 f= C;
188 if (f != (float) C) printf ("Wrong!");
190 A faulty compiler will widen f to double and ignore the cast to float,
191 and because there is more accuracy in a double than a float, fail to
192 recognise that they are the same. In the actual case in point, f and C
193 are passed as parameters to a function that discovers they are not equal,
194 so it's just possible that the error was in the parameter passing,
195 not in the cast (see function Validate()).
196 For ANSI C, which has float constants, the error message is "constant has
197 wrong precision".
199 REPORTING PROBLEMS
200 If the program doesn't work for you for any reason that can't be
201 narrowed down to a problem in the C compiler, or it has to be changed in
202 order to get it to compile, or it produces suspicious output (like a very
203 low maximum float, for instance), please mail the problem and an example
204 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
205 improvements can be worked into future versions; cwi.nl is the European
206 backbone, and is connected to uunet and other fine hosts.
208 The program tries to catch and diagnose bugs in the compiler/run-time
209 system. I would be especially pleased to have reports of failures so
210 that I can improve this service.
212 I apologise unreservedly for the contorted use of the preprocessor...
214 THE SMALL PRINT
215 You may copy and distribute verbatim copies of this source file.
217 You may modify this source file, and copy and distribute such
218 modified versions, provided that you leave the copyright notice
219 at the top of the file and also cause the modified file to carry
220 prominent notices stating that you changed the files and the date
221 of any change; and cause the whole of any work that you distribute
222 or publish, that in whole or in part contains or is a derivative of
223 this program or any part thereof, to be licensed at no charge to
224 all third parties on terms identical to those here.
226 If you do have a fix to any problem, please send it to me, so that
227 other people can have the benefits.
229 While every effort has been taken to make this program as reliable as
230 possible, no responsibility can be taken for the correctness of the
231 output, nor suitability for any particular use.
233 This program is an offshoot of a project funded by public funds.
234 If you use this program for research or commercial use (i.e. more
235 than just for the fun of knowing about your compiler) mailing a short
236 note of acknowledgement may help keep enquire.c supported.
238 ACKNOWLEDGEMENTS
239 Many people have given time and ideas to making this program what it is.
240 To all of them thanks, and apologies for not mentioning them by name.
242 HISTORY
243 Originally started as a program to generate configuration constants
244 for a large piece of software we were writing, which later took on
245 a life of its own...
246 1.0 Length 6658!; end 1984?
247 Unix only. Only printed a dozen maximum int/double values.
248 2.0 Length 10535; Spring 1985
249 Prints values as #defines (about 20 of them)
250 More extensive floating point, using Cody and Waite
251 Handles signals better
252 Programs around optimisations
253 Handles Cybers
254 3.0 Length 12648; Aug 1987; prints about 42 values
255 Added PASS stuff, so treats float as well as double
256 4.0 Length 33891; Feb 1989; prints around 85 values
257 First GNU version (for gcc, where they call it hard-params.c)
258 Generates float.h and limits.h files
259 Handles long double
260 Generates warnings for dubious output
261 4.1 Length 47738; April 1989
262 Added VERIFY and TEST
263 4.2 Length 63442; Feb 1990
264 Added SEP
265 Fixed eps/epsneg
266 Added check for pseudo-unsigned chars
267 Added description for each #define output
268 Added check for absence of defines during verify
269 Added prototypes
270 Added NO_STDC and NO_FILE
271 Fixed alignments output
272 4.3 Length 75000; Oct 1990; around 114 lines of output
273 Function xmalloc defined, Richard Stallman, June 89.
274 Alignments computed from member offsets rather than structure sizes,
275 Richard Stallman, Oct 89.
276 Print whether char* and int* pointers have the same format;
277 also char * and function *.
278 Update to Draft C version Dec 7, 1988
279 - types of constants produced in limits.h
280 (whether to put a U after unsigned shorts and chars and
281 whether to output -1024 as (-1023-1))
282 - values of SCHAR_MIN/MAX
283 - values of *_EPSILON (not the smallest but the effective smallest)
284 Added FILENAME, since standard C doesn't allow #define __FILE__
285 Renamed from config.c to enquire.c
286 Added size_t and ptrdiff_t enquiries
287 Added promotion enquiries
288 Added type checks of #defines
289 Added NO_STDDEF
290 Changed endian to allow for cases where not all bits are used
291 Sanity check for max integrals
292 Fixed definition of setjmp for -DNO_SIG
293 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
294 Added NO_MEM
297 /* Set FILENAME to the name of this file */
298 #ifndef FILENAME
299 #ifdef NO_FILE
300 #define FILENAME "enquire.c"
301 #else
302 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
303 #define FILENAME __FILE__
304 #else
305 #define FILENAME "enquire.c"
306 #endif /* __FILE__ */
307 #endif /* NO_FILE */
308 #endif /* FILENAME */
310 /* If PASS isn't defined, then this is the first pass over this file. */
311 #ifndef PASS
312 #ifndef SEP
313 #define PASS 1
314 #define PASS0 1
315 #define PASS1 1
316 #endif /* SEP */
318 /* A description of the ANSI constants */
319 #define D_CHAR_BIT "Number of bits in a storage unit"
320 #define D_CHAR_MAX "Maximum char"
321 #define D_CHAR_MIN "Minimum char"
322 #define D_SCHAR_MAX "Maximum signed char"
323 #define D_SCHAR_MIN "Minimum signed char"
324 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
326 #define D_INT_MAX "Maximum %s"
327 #define D_INT_MIN "Minimum %s"
328 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
330 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
331 #define D_FLT_RADIX "Radix of exponent representation"
332 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
333 #define D_DIG "Number of decimal digits of precision in a %s"
334 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
335 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
336 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
337 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
338 #define D_MAX "Maximum %s"
339 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
340 #define D_MIN "Minimum normalised %s"
342 /* Procedure just marks the functions that don't return a result */
343 #ifdef NO_VOID
344 #define Procedure int
345 #else
346 #define Procedure void
347 #endif
349 /* Some bad compilers define __STDC__, when they don't support it.
350 Compile with -DNO_STDC to get round this.
352 #ifndef NO_STDC
353 #ifdef __STDC__
354 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
355 #define STDC
356 #endif
357 #endif
358 #endif
360 /* Stuff different for ANSI C, and old C:
361 ARGS and NOARGS are used for function prototypes.
362 Volatile is used to reduce the chance of optimisation,
363 and to prevent variables being put in registers (when setjmp/longjmp
364 wouldn't work as we want)
365 Long_double is the longest floating point type available.
366 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
367 U is output after unsigned constants.
369 #ifdef STDC
371 #define ARGS(x) x
372 #define NOARGS (void)
373 #define Volatile volatile
374 #define Long_double long double
375 #define stdc 1
376 #define U "U"
378 #else /* Old style C */
380 #define ARGS(x) ()
381 #define NOARGS ()
382 #define Volatile static
383 #define Long_double double
384 #define stdc 0
385 #define U ""
387 #endif /* STDC */
389 /* include files */
390 #include <stdio.h>
392 #ifdef STDC
393 #ifndef NO_STDDEF
394 #include <stddef.h> /* for size_t: if this fails, define NO_STDDEF */
395 #endif
396 #endif
398 #ifdef NO_SIG
399 #define jmp_buf int
400 #else
401 #include <sys/types.h>
402 #include <signal.h>
403 #include <setjmp.h>
404 #endif
406 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
407 #ifdef CHAR_BIT
408 #undef CHAR_BIT
409 #undef CHAR_MAX
410 #undef CHAR_MIN
411 #undef SCHAR_MAX
412 #undef SCHAR_MIN
413 #undef UCHAR_MAX
414 #undef UCHAR_MIN
415 #endif
417 #ifdef VERIFY
418 #include "limits.h"
419 #include "float.h"
420 #endif
422 #define Vprintf if (V) printf
423 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
424 #define fabs(x) (((x)<0.0)?(-x):(x))
426 #endif /* PASS */
428 #ifdef PASS0
430 /* Prototypes for what's to come: */
432 int false NOARGS;
434 #ifdef NO_STDDEF
435 char *malloc (); /* Old style prototype */
436 #else
437 char *malloc ARGS((size_t size));
438 #endif
440 Procedure exit ARGS((int status));
442 char *f_rep ARGS((int precision, Long_double val));
443 char *fake_f_rep ARGS((char *type, Long_double val));
445 int maximum_int NOARGS;
446 int cprop NOARGS;
447 int basic NOARGS;
448 Procedure sprop NOARGS;
449 Procedure iprop NOARGS;
450 Procedure lprop NOARGS;
451 Procedure usprop NOARGS;
452 Procedure uiprop NOARGS;
453 Procedure ulprop NOARGS;
454 int fprop ARGS((int bits_per_byte));
455 int dprop ARGS((int bits_per_byte));
456 int ldprop ARGS((int bits_per_byte));
457 Procedure efprop ARGS((int fprec, int dprec, int lprec));
458 Procedure edprop ARGS((int fprec, int dprec, int lprec));
459 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
461 int setmode ARGS((char *s));
462 Procedure farewell ARGS((int bugs));
463 Procedure describe ARGS((char *description, char *extra));
464 Procedure missing ARGS((char *s));
465 Procedure fmissing ARGS((char *s));
466 Procedure check_defines NOARGS;
467 Procedure bitpattern ARGS((char *p, unsigned int size));
468 int ceil_log ARGS((int base, Long_double x));
469 Procedure croak ARGS((int place));
470 Procedure eek_a_bug ARGS((char *problem));
471 Procedure endian ARGS((int bits_per_byte));
472 int exponent ARGS((Long_double x, double *fract, int *exp));
473 int floor_log ARGS((int base, Long_double x));
474 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
475 int prec, Long_double val, char *mark));
476 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
477 long val, long lim, long req, char *mark));
478 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
479 unsigned long val, unsigned long req, char *mark));
481 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
483 /* Dummy routines instead */
485 int setjmp ARGS((int lab));
487 int lab=1;
488 int setjmp(lab) int lab; { return(0); }
489 Procedure signal(i, p) int i, (*p)(); {}
491 #else
492 jmp_buf lab;
493 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
494 signal(sig, overflow);
495 longjmp(lab, 1);
498 #endif /*NO_SIG*/
500 int V= 0, /* verbose */
501 L= 0, /* produce limits.h */
502 F= 0, /* produce float.h */
503 bugs=0; /* The number of (possible) bugs in the output */
505 char co[4], oc[4]; /* Comment starter and ender symbols */
507 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
508 int flt_rounds; /* The calculated value of FLT_ROUNDS */
509 int flt_radix; /* The calculated value of FLT_RADIX */
511 #ifdef TEST
512 /* Set the fp modes on a SUN with 68881 chip, to check that different
513 rounding modes etc. get properly detected.
514 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
515 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
516 register to hex-number
519 /* Bits 0x30 = rounding mode */
520 #define ROUND_BITS 0x30
521 #define TO_NEAREST 0x00
522 #define TO_ZERO 0x10
523 #define TO_MINUS_INF 0x20
524 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
526 /* Bits 0xc0 = extended rounding */
527 #define EXT_BITS 0xc0
528 #define ROUND_EXTENDED 0x00
529 #define ROUND_SINGLE 0x40
530 #define ROUND_DOUBLE 0x80
532 /* Enabled traps */
533 #define EXE_INEX1 0x100
534 #define EXE_INEX2 0x200
535 #define EXE_DZ 0x400
536 #define EXE_UNFL 0x800
537 #define EXE_OVFL 0x1000
538 #define EXE_OPERR 0x2000
539 #define EXE_SNAN 0x4000
540 #define EXE_BSUN 0x8000
542 /* Only used for testing, on a Sun with 68881 chip */
543 /* Print the FP mode */
544 printmode(new) unsigned new; {
545 fpmode_(&new);
546 printf("New fp mode:\n");
547 printf(" Round toward ");
548 switch (new & ROUND_BITS) {
549 case TO_NEAREST: printf("nearest"); break;
550 case TO_ZERO: printf("zero"); break;
551 case TO_MINUS_INF: printf("minus infinity"); break;
552 case TO_PLUS_INF: printf("plus infinity"); break;
553 default: printf("???"); break;
556 printf("\n Extended rounding precision: ");
558 switch (new & EXT_BITS) {
559 case ROUND_EXTENDED: printf("extended"); break;
560 case ROUND_SINGLE: printf("single"); break;
561 case ROUND_DOUBLE: printf("double"); break;
562 default: printf("???"); break;
565 printf("\n Enabled exceptions:");
566 if (new & (unsigned) EXE_INEX1) printf(" inex1");
567 if (new & (unsigned) EXE_INEX2) printf(" inex2");
568 if (new & (unsigned) EXE_DZ) printf(" dz");
569 if (new & (unsigned) EXE_UNFL) printf(" unfl");
570 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
571 if (new & (unsigned) EXE_OPERR) printf(" operr");
572 if (new & (unsigned) EXE_SNAN) printf(" snan");
573 if (new & (unsigned) EXE_BSUN) printf(" bsun");
574 printf("\n");
577 /* Only used for testing, on a Sun with 68881 chip */
578 /* Set the FP mode */
579 int setmode(s) char *s; {
580 unsigned mode=0, dig;
581 char c;
583 while (*s) {
584 c= *s++;
585 if (c>='0' && c<='9') dig= c-'0';
586 else if (c>='a' && c<='f') dig= c-'a'+10;
587 else if (c>='A' && c<='F') dig= c-'A'+10;
588 else return 1;
589 mode= mode<<4 | dig;
591 printmode(mode);
592 return 0;
594 #else
595 /* ARGSUSED */
596 int setmode(s) char *s; {
597 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
598 return(1);
600 #endif
602 Procedure farewell(bugs) int bugs; {
603 if (bugs == 0) exit(0);
604 printf("\n%sFor hints on dealing with the ", co);
605 if (bugs == 1) printf("problem");
606 else printf("%d problems", bugs);
607 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
608 printf("%s%s\n", FILENAME, oc);
609 exit(bugs);
612 /* The program has received a signal where it wasn't expecting one */
613 Procedure croak(place) int place; {
614 printf("*** Unexpected signal at point %d\n", place);
615 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
618 /* This is here in case alloca.c is used, which calls this. */
619 char *xmalloc(size) unsigned size; {
620 char *value = (char *)malloc(size);
621 if (value == 0) {
622 fprintf(stderr, "Virtual memory exceeded\n");
623 exit(bugs+1);
625 return value;
628 int maxint;
630 int maximum_int() {
631 /* Find the maximum integer */
632 Volatile int newi, int_max, two=2;
634 /* Calculate maxint ***********************************/
635 /* Calculate 2**n-1 until overflow - then use the previous value */
637 newi=1; int_max=0;
639 if (setjmp(lab)==0) { /* Yields int_max */
640 while(newi>int_max) {
641 int_max=newi;
642 newi=newi*two+1;
645 Unexpected(0);
646 return int_max;
649 int main(argc, argv) int argc; char *argv[]; {
650 int dprec, fprec, lprec;
651 int i; char *s; int bad;
653 #ifdef SIGFPE
654 signal(SIGFPE, overflow);
655 #endif
656 #ifdef SIGOVER
657 signal(SIGOVER, overflow);
658 #endif
659 /* Add more calls as necessary */
661 Unexpected(1);
663 bad=0;
664 for (i=1; i < argc; i++) {
665 s= argv[i];
666 if (*s == '-') {
667 s++;
668 while (*s) {
669 switch (*(s++)) {
670 case 'v': V=1; break;
671 case 'l': L=1; break;
672 case 'f': F=1; break;
673 default: bad=1; break;
676 } else if (*s == '+') {
677 s++;
678 bad= setmode(s);
679 } else bad= 1;
681 if (bad) {
682 fprintf(stderr,
683 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
684 argv[0]);
685 exit(1);
687 if (L || F) {
688 co[0]= '/'; oc[0]= ' ';
689 co[1]= '*'; oc[1]= '*';
690 co[2]= ' '; oc[2]= '/';
691 co[3]= '\0'; oc[3]= '\0';
692 } else {
693 co[0]= '\0'; oc[0]= '\0';
694 V=1;
697 if (L) printf("%slimits.h%s\n", co, oc);
698 if (F) printf("%sfloat.h%s\n", co, oc);
699 if (F) {
700 printf ("#ifndef _FLOAT_H___\n");
701 printf ("#define _FLOAT_H___\n");
703 #ifdef ID
704 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
705 co, ID, VERSION, oc);
706 #else
707 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
708 co, VERSION, oc);
709 #endif
711 #ifdef VERIFY
712 printf("%sVerification phase%s\n", co, oc);
713 #endif
715 #ifdef NO_SIG
716 Vprintf("%sCompiled without signal(): %s%s\n",
718 "there's nothing that can be done if overflow occurs",
719 oc);
720 #endif
721 #ifdef NO_SC
722 Vprintf("%sCompiled without signed char%s\n", co, oc);
723 #endif
724 #ifdef NO_UC
725 Vprintf("%Compiled without unsigned char%s\n", co, oc);
726 #endif
727 #ifdef NO_UI
728 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
729 #endif
730 #ifdef __STDC__
731 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
732 co, __STDC__, oc);
733 #else
734 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
735 #endif
736 printf("\n");
737 check_defines();
739 maxint= maximum_int();
740 bits_per_byte= basic();
741 Vprintf("\n");
742 if (F||V) {
743 fprec= fprop(bits_per_byte);
744 dprec= dprop(bits_per_byte);
745 lprec= ldprop(bits_per_byte);
746 efprop(fprec, dprec, lprec);
747 edprop(fprec, dprec, lprec);
748 eldprop(fprec, dprec, lprec);
750 #ifndef NO_MEM
751 if (V) {
752 unsigned int size;
753 long total;
754 /* An extra goody: the approximate amount of data-space */
755 /* Allocate store until no more available */
756 /* Different implementations have a different argument type
757 to malloc. Here we assume that it's the same type as
758 that which sizeof() returns */
759 size=1<<((bits_per_byte*sizeof(int))-2);
760 total=0;
761 while (size!=0) {
762 while ( malloc((false()?sizeof(int):size)) !=
763 (char *)NULL
765 total+=(size/2);
767 size/=2;
770 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
771 co, (total+511)/512, oc);
773 #endif
774 if (F) {
775 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
777 farewell(bugs);
778 return bugs; /* To keep compilers and lint happy */
781 Procedure eek_a_bug(problem) char *problem; {
782 /* The program has discovered a problem */
783 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
784 bugs++;
787 Procedure describe(description, extra) char *description, *extra; {
788 /* Produce the description for a #define */
789 printf(" %s", co);
790 printf(description, extra);
791 printf("%s\n", oc);
794 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
795 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
796 /* Produce a #define for a signed int type */
797 describe(desc, extra);
798 printf("#undef %s%s\n", sort, name);
799 if (val >= 0) {
800 printf("#define %s%s %ld%s\n", sort, name, val, mark);
801 } else if (val + lim < 0) {
802 /* We may not produce a constant like -1024 if the max
803 allowable value is 1023. It has then to be output as
804 -1023-1. lim is the max allowable value. */
805 printf("#define %s%s (%ld%s%ld%s)\n",
806 sort, name, -lim, mark, val+lim, mark);
807 } else {
808 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
810 /* If VERIFY is not set, val and req are just the same value;
811 if it is set, val is the value as calculated, and req is
812 the #defined constant
814 if (val != req) {
815 printf("%s*** Verify failed for above #define!\n", co);
816 printf(" Compiler has %ld for value%s\n\n", req, oc);
817 bugs++;
819 Vprintf("\n");
822 Procedure u_define(desc, extra, sort, name, val, req, mark)
823 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
824 /* Produce a #define for an unsigned value */
825 describe(desc, extra);
826 printf("#undef %s%s\n", sort, name);
827 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
828 if (val != req) {
829 printf("%s*** Verify failed for above #define!\n", co);
830 printf(" Compiler has %lu for value%s\n\n", req, oc);
831 bugs++;
833 Vprintf("\n");
836 Procedure f_define(desc, extra, sort, name, precision, val, mark)
837 char *desc, *extra, *sort, *name; int precision;
838 Long_double val; char *mark; {
839 /* Produce a #define for a float/double/long double */
840 describe(desc, extra);
841 printf ("#undef %s%s\n", sort, name);
842 if (stdc) {
843 #ifdef NO_LONG_DOUBLE_IO
844 static int union_defined = 0;
845 if (sizeof(double) != sizeof(Long_double)
846 && !strcmp(sort, "LDBL")) {
847 if (!union_defined) {
848 printf("#ifndef __LDBL_UNION__\n");
849 printf("#define __LDBL_UNION__\n");
850 printf("union __convert_long_double {\n");
851 printf(" unsigned __convert_long_double_i[4];\n");
852 printf(" long double __convert_long_double_d;\n");
853 printf("};\n");
854 printf("#endif\n");
855 union_defined = 1;
857 printf("#define %s%s %s\n",
858 sort, name, fake_f_rep("long double", val));
859 } else {
860 printf("#define %s%s %s%s\n",
861 sort, name, f_rep(precision, val), mark);
863 #else
864 printf("#define %s%s %s%s\n",
865 sort, name, f_rep(precision, val), mark);
866 #endif
867 } else if (*mark == 'F') {
868 /* non-ANSI C has no float constants, so cast the constant */
869 printf("#define %s%s ((float)%s)\n",
870 sort, name, f_rep(precision, val));
871 } else {
872 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
874 Vprintf("\n");
877 int floor_log(base, x) int base; Long_double x; {
878 /* return floor(log base(x)) */
879 int r=0;
880 while (x>=base) { r++; x/=base; }
881 return r;
884 int ceil_log(base, x) int base; Long_double x; {
885 int r=0;
886 while (x>1.0) { r++; x/=base; }
887 return r;
890 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
891 /* Split x into a fraction and a power of ten;
892 returns 0 if x is unusable, 1 otherwise.
893 Only used for error messages about faulty output.
895 int r=0, neg=0;
896 Long_double old;
897 *fract=0.0; *exp=0;
898 if (x<0.0) {
899 x= -x;
900 neg= 1;
902 if (x==0.0) return 1;
903 if (x>=10.0) {
904 while (x>=10.0) {
905 old=x; r++; x/=10.0;
906 if (old==x) return 0;
908 } else {
909 while (x<1.0) {
910 old=x; r--; x*=10.0;
911 if (old==x) return 0;
914 if (neg) *fract= (double) -x;
915 else *fract=(double) x;
916 *exp=r;
917 return 1;
920 /* Print a value of type TYPE with value VAL,
921 assuming that sprintf can't handle this type properly (without truncation).
922 We create an expression that uses type casting to create the value from
923 a bit pattern. */
925 char *fake_f_rep(type, val) char *type; Long_double val; {
926 static char buf[1024];
927 union { unsigned int i[4]; Long_double ld;} u;
928 u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
929 u.ld = val;
930 sprintf(buf, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
931 u.i[0], u.i[1], u.i[2], u.i[3]);
932 return buf;
935 char *f_rep(precision, val) int precision; Long_double val; {
936 /* Return the floating representation of val */
937 static char buf[1024];
938 #ifdef NO_LONG_DOUBLE_IO
939 if (1)
940 #else
941 if (sizeof(double) == sizeof(Long_double))
942 #endif
944 double d = val;
945 /* Assume they're the same, and use non-stdc format */
946 /* This is for stdc compilers using non-stdc libraries */
947 sprintf(buf, "%.*e", precision, d);
948 } else {
949 /* It had better support Le then */
950 sprintf(buf, "%.*Le", precision, val);
952 return buf;
955 Procedure bitpattern(p, size) char *p; unsigned int size; {
956 /* Printf the bit-pattern of p */
957 char c;
958 int i, j;
960 for (i=1; i<=size; i++) {
961 c= *p;
962 p++;
963 for (j=bits_per_byte-1; j>=0; j--)
964 printf("%c", (c>>j)&1 ? '1' : '0');
965 if (i!=size) printf(" ");
969 #define Order(x, px, mode)\
970 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
971 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
972 putchar(c==0 ? '?' : (char)c); }\
973 printf("%s\n", oc);
975 Procedure endian(bits_per_byte) int bits_per_byte; {
976 /* Printf the byte-order used on this machine */
977 /*unsigned*/ short s=0;
978 /*unsigned*/ int j=0;
979 /*unsigned*/ long l=0;
981 char *ps= (char *) &s,
982 *pj= (char *) &j,
983 *pl= (char *) &l,
984 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
985 unsigned int mask, i, c;
987 mask=0;
988 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
990 if (V) {
991 printf("%sCHARACTER ORDER%s\n", co, oc);
992 Order(s, ps, "short:");
993 Order(j, pj, "int: ");
994 Order(l, pl, "long: ");
998 Procedure missing(s) char *s; {
999 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
1000 bugs++;
1003 Procedure fmissing(s) char *s; {
1004 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
1005 bugs++;
1008 /* To try and fool optimisers */
1009 int false() { return 0; }
1011 #define Promoted(x) (false()?(x):(-1))
1012 #define is_signed(x) (Promoted(x) < 0)
1013 #define sign_of(x) ((x)?"signed":"unsigned")
1014 #define Signed 1
1015 #define Unsigned 0
1016 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1018 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1020 char *type_of(x) int x; {
1021 if (x == sizeof(char)) {
1022 if (sizeof(char) == sizeof(int)) return "char/short/int";
1023 if (sizeof(char) == sizeof(short)) return "char/short";
1024 return "char";
1026 if (x == sizeof(short)) {
1027 if (sizeof(short) == sizeof(int)) return "short/int";
1028 return "short";
1030 if (x == sizeof(int)) {
1031 if (sizeof(int) == sizeof(long)) return "int/long";
1032 return "int";
1034 if (x == sizeof(long)) return "long";
1035 return "unknown-type";
1038 char *ftype_of(x) int x; {
1039 if (x == sizeof(float)) {
1040 return "float";
1042 if (x == sizeof(double)) {
1043 if (sizeof(double) == sizeof(Long_double))
1044 return "(long)double";
1045 return "double";
1047 if (x == sizeof(Long_double)) {
1048 return "long double";
1050 return "unknown-type";
1053 Procedure typerr(name, esign, esize, sign, size)
1054 char *name; int esign, esize, sign, size;
1056 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1057 name, sign_of(esign), type_of(esize),
1058 sign_of(sign), type_of(size));
1061 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
1062 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1063 name, ftype_of(esize), ftype_of(size));
1066 int promotions() {
1067 int si = 0; long sl = 0;
1068 unsigned int ui; unsigned long ul;
1069 short ss; unsigned short us;
1071 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1073 if (
1074 /* Possible warnings here; no problem */
1075 (sizeof(Promoted(si)) != sizeof(int)) ||
1076 (sizeof(Promoted(sl)) != sizeof(long)) ||
1077 (sizeof(Promoted(ss)) != sizeof(int)) ||
1078 (sizeof(Promoted(ui)) != sizeof(int)) ||
1079 (sizeof(Promoted(ul)) != sizeof(long)) ||
1080 (sizeof(Promoted(us)) != sizeof(int)) ||
1081 is_signed(ui) || is_signed(ul) ||
1082 !is_signed(si) || !is_signed(sl)
1085 eek_a_bug("promotions don't work properly in conditional expressions\n");
1088 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1089 showtype("long+unsigned gives", sl+ui);
1090 return 0;
1093 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1095 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1097 Procedure check_defines() {
1098 /* ensure that all #defines are present and have the correct type */
1099 #ifdef VERIFY
1100 int usign;
1102 #ifdef NO_UI
1103 usign= Signed;
1104 #else
1105 /* Implementations promote unsigned short differently */
1106 usign= is_signed((unsigned short)0);
1107 #endif
1109 if (L) {
1110 #ifdef CHAR_BIT
1111 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1112 #else
1113 missing("CHAR_BIT");
1114 #endif
1115 #ifdef CHAR_MAX
1116 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1117 #else
1118 missing("CHAR_MAX");
1119 #endif
1120 #ifdef CHAR_MIN
1121 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1122 #else
1123 missing("CHAR_MIN");
1124 #endif
1125 #ifdef SCHAR_MAX
1126 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1127 #else
1128 missing("SCHAR_MAX");
1129 #endif
1130 #ifdef SCHAR_MIN
1131 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1132 #else
1133 missing("SCHAR_MIN");
1134 #endif
1135 #ifdef UCHAR_MAX
1136 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1137 #else
1138 missing("UCHAR_MAX");
1139 #endif
1140 #ifdef SHRT_MAX
1141 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1142 #else
1143 missing("SHRT_MAX");
1144 #endif
1145 #ifdef SHRT_MIN
1146 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1147 #else
1148 missing("SHRT_MIN");
1149 #endif
1150 #ifdef INT_MAX
1151 checktype(INT_MAX, "INT_MAX", Signed, int);
1152 #else
1153 missing("INT_MAX");
1154 #endif
1155 #ifdef INT_MIN
1156 checktype(INT_MIN, "INT_MIN", Signed, int);
1157 #else
1158 missing("INT_MIN");
1159 #endif
1160 #ifdef LONG_MAX
1161 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1162 #else
1163 missing("LONG_MAX");
1164 #endif
1165 #ifdef LONG_MIN
1166 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1167 #else
1168 missing("LONG_MIN");
1169 #endif
1170 #ifdef USHRT_MAX
1171 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1172 #else
1173 missing("USHRT_MAX");
1174 #endif
1175 #ifdef UINT_MAX
1176 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1177 #else
1178 missing("UINT_MAX");
1179 #endif
1180 #ifdef ULONG_MAX
1181 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1182 #else
1183 missing("ULONG_MAX");
1184 #endif
1185 } /* if (L) */
1187 if (F) {
1188 #ifdef FLT_RADIX
1189 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1190 #else
1191 fmissing("FLT_RADIX");
1192 #endif
1193 #ifdef FLT_MANT_DIG
1194 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1195 #else
1196 fmissing("FLT_MANT_DIG");
1197 #endif
1198 #ifdef FLT_DIG
1199 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1200 #else
1201 fmissing("FLT_DIG");
1202 #endif
1203 #ifdef FLT_ROUNDS
1204 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1205 #else
1206 fmissing("FLT_ROUNDS");
1207 #endif
1208 #ifdef FLT_EPSILON
1209 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1210 #else
1211 fmissing("FLT_EPSILON");
1212 #endif
1213 #ifdef FLT_MIN_EXP
1214 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1215 #else
1216 fmissing("FLT_MIN_EXP");
1217 #endif
1218 #ifdef FLT_MIN
1219 fchecktype(FLT_MIN, "FLT_MIN", float);
1220 #else
1221 fmissing("FLT_MIN");
1222 #endif
1223 #ifdef FLT_MIN_10_EXP
1224 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1225 #else
1226 fmissing("FLT_MIN_10_EXP");
1227 #endif
1228 #ifdef FLT_MAX_EXP
1229 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1230 #else
1231 fmissing("FLT_MAX_EXP");
1232 #endif
1233 #ifdef FLT_MAX
1234 fchecktype(FLT_MAX, "FLT_MAX", float);
1235 #else
1236 fmissing("FLT_MAX");
1237 #endif
1238 #ifdef FLT_MAX_10_EXP
1239 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1240 #else
1241 fmissing("FLT_MAX_10_EXP");
1242 #endif
1243 #ifdef DBL_MANT_DIG
1244 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1245 #else
1246 fmissing("DBL_MANT_DIG");
1247 #endif
1248 #ifdef DBL_DIG
1249 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1250 #else
1251 fmissing("DBL_DIG");
1252 #endif
1253 #ifdef DBL_EPSILON
1254 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1255 #else
1256 fmissing("DBL_EPSILON");
1257 #endif
1258 #ifdef DBL_MIN_EXP
1259 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1260 #else
1261 fmissing("DBL_MIN_EXP");
1262 #endif
1263 #ifdef DBL_MIN
1264 fchecktype(DBL_MIN, "DBL_MIN", double);
1265 #else
1266 fmissing("DBL_MIN");
1267 #endif
1268 #ifdef DBL_MIN_10_EXP
1269 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1270 #else
1271 fmissing("DBL_MIN_10_EXP");
1272 #endif
1273 #ifdef DBL_MAX_EXP
1274 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1275 #else
1276 fmissing("DBL_MAX_EXP");
1277 #endif
1278 #ifdef DBL_MAX
1279 fchecktype(DBL_MAX, "DBL_MAX", double);
1280 #else
1281 fmissing("DBL_MAX");
1282 #endif
1283 #ifdef DBL_MAX_10_EXP
1284 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1285 #else
1286 fmissing("DBL_MAX_10_EXP");
1287 #endif
1288 #ifdef STDC
1289 #ifdef LDBL_MANT_DIG
1290 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1291 #else
1292 fmissing("LDBL_MANT_DIG");
1293 #endif
1294 #ifdef LDBL_DIG
1295 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1296 #else
1297 fmissing("LDBL_DIG");
1298 #endif
1299 #ifdef LDBL_EPSILON
1300 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1301 #else
1302 fmissing("LDBL_EPSILON");
1303 #endif
1304 #ifdef LDBL_MIN_EXP
1305 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1306 #else
1307 fmissing("LDBL_MIN_EXP");
1308 #endif
1309 #ifdef LDBL_MIN
1310 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1311 #else
1312 fmissing("LDBL_MIN");
1313 #endif
1314 #ifdef LDBL_MIN_10_EXP
1315 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1316 #else
1317 fmissing("LDBL_MIN_10_EXP");
1318 #endif
1319 #ifdef LDBL_MAX_EXP
1320 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1321 #else
1322 fmissing("LDBL_MAX_EXP");
1323 #endif
1324 #ifdef LDBL_MAX
1325 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1326 #else
1327 fmissing("LDBL_MAX");
1328 #endif
1329 #ifdef LDBL_MAX_10_EXP
1330 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1331 #else
1332 fmissing("LDBL_MAX_10_EXP");
1333 #endif
1334 #endif /* STDC */
1335 } /* if (F) */
1336 #endif /* VERIFY */
1339 #ifdef VERIFY
1340 #ifndef SCHAR_MAX
1341 #define SCHAR_MAX char_max
1342 #endif
1343 #ifndef SCHAR_MIN
1344 #define SCHAR_MIN char_min
1345 #endif
1346 #ifndef UCHAR_MAX
1347 #define UCHAR_MAX char_max
1348 #endif
1349 #endif /* VERIFY */
1351 #ifndef CHAR_BIT
1352 #define CHAR_BIT char_bit
1353 #endif
1354 #ifndef CHAR_MAX
1355 #define CHAR_MAX char_max
1356 #endif
1357 #ifndef CHAR_MIN
1358 #define CHAR_MIN char_min
1359 #endif
1360 #ifndef SCHAR_MAX
1361 #define SCHAR_MAX char_max
1362 #endif
1363 #ifndef SCHAR_MIN
1364 #define SCHAR_MIN char_min
1365 #endif
1366 #ifndef UCHAR_MAX
1367 #define UCHAR_MAX char_max
1368 #endif
1370 int cprop() {
1371 /* Properties of type char */
1372 Volatile char c, char_max, char_min;
1373 Volatile int bits_per_byte, c_signed;
1374 long char_bit;
1376 Unexpected(2);
1378 /* Calculate number of bits per character *************************/
1379 c=1; bits_per_byte=0;
1380 do { c=c<<1; bits_per_byte++; } while(c!=0);
1381 c= (char)(-1);
1382 if (((int)c)<0) c_signed=1;
1383 else c_signed=0;
1384 Vprintf("%schar = %d bits, %ssigned%s\n",
1385 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1386 char_bit=(long)(sizeof(c)*bits_per_byte);
1387 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1388 char_bit, 0L, (long) CHAR_BIT, "");
1390 c=0; char_max=0;
1391 c++;
1392 if (setjmp(lab)==0) { /* Yields char_max */
1393 while (c>char_max) {
1394 char_max=c;
1395 c++;
1397 } else {
1398 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1400 c=0; char_min=0;
1401 c--;
1402 if (setjmp(lab)==0) { /* Yields char_min */
1403 while (c<char_min) {
1404 char_min=c;
1405 c--;
1408 if (c_signed && char_min == 0) {
1409 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1410 Vprintf("%s %s%s%s\n",
1411 "They contain only nonnegative values, ",
1412 "but sign extend when used as integers.", co, oc);
1414 Unexpected(3);
1416 if (L) {
1417 /* Because of the integer promotions, you must use a U after
1418 the MAX_CHARS in the following cases */
1419 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1420 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1421 (long) char_max,
1422 (long) CHAR_MAX, "");
1423 } else {
1424 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1425 (long) char_max, 0L,
1426 (long) CHAR_MAX, "");
1428 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1429 (long) char_min, (long) maxint,
1430 (long) CHAR_MIN, "");
1431 if (c_signed) {
1432 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1433 (long) char_max, 0L,
1434 (long) SCHAR_MAX, "");
1435 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1436 (long) char_min, (long) maxint,
1437 (long) SCHAR_MIN, "");
1438 } else {
1439 if (sizeof(char) == sizeof(int)) {
1440 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1441 (long) char_max,
1442 (long) UCHAR_MAX, "");
1443 } else {
1444 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1445 (long) char_max, 0L,
1446 (long) UCHAR_MAX, "");
1450 if (c_signed) {
1451 #ifndef NO_UC
1452 Volatile unsigned char c, char_max;
1453 c=0; char_max=0;
1454 c++;
1455 if (setjmp(lab)==0) { /* Yields char_max */
1456 while (c>char_max) {
1457 char_max=c;
1458 c++;
1461 Unexpected(4);
1462 if (sizeof(char) == sizeof(int)) {
1463 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1464 (long) char_max,
1465 (long) UCHAR_MAX, "");
1466 } else {
1467 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1468 (long) char_max, 0L,
1469 (long) UCHAR_MAX, "");
1471 #endif
1472 } else {
1473 #ifndef NO_SC
1474 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1475 c=0; char_max=0;
1476 c++;
1477 if (setjmp(lab)==0) { /* Yields char_max */
1478 while (c>char_max) {
1479 char_max=c;
1480 c++;
1483 c=0; char_min=0;
1484 c--;
1485 if (setjmp(lab)==0) { /* Yields char_min */
1486 while (c<char_min) {
1487 char_min=c;
1488 c--;
1491 Unexpected(5);
1492 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1493 (long) char_min, (long) maxint,
1494 (long) SCHAR_MIN, "");
1495 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1496 (long) char_max, 0L,
1497 (long) SCHAR_MAX, "");
1498 #endif /* NO_SC */
1501 return bits_per_byte;
1504 int basic() {
1505 /* The properties of the basic types.
1506 Returns number of bits per sizeof unit */
1507 Volatile int bits_per_byte;
1508 typedef int function ();
1509 int variable;
1510 int *p, *q;
1512 Vprintf("%sSIZES%s\n", co, oc);
1513 bits_per_byte= cprop();
1515 /* Shorts, ints and longs *****************************************/
1516 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1518 (int) sizeof(short)*bits_per_byte,
1519 (int) sizeof(int)*bits_per_byte,
1520 (int) sizeof(long)*bits_per_byte,
1521 (int) sizeof(float)*bits_per_byte,
1522 (int) sizeof(double)*bits_per_byte, oc);
1523 if (stdc) {
1524 Vprintf("%slong double=%d bits%s\n",
1525 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1527 Vprintf("%schar*=%d bits%s%s\n",
1528 co, (int)sizeof(char *)*bits_per_byte,
1529 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1530 oc);
1531 Vprintf("%sint* =%d bits%s%s\n",
1532 co, (int)sizeof(int *)*bits_per_byte,
1533 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1534 oc);
1535 Vprintf("%sfunc*=%d bits%s%s\n",
1536 co, (int)sizeof(function *)*bits_per_byte,
1537 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1538 oc);
1539 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1540 ((((false()?( sizeof(int)):(-1)) < 0) )?
1541 "signed":"unsigned") ,
1542 type_of(sizeof(
1543 sizeof(int)+0
1546 oc);
1547 showtype("Type size_t is", sizeof(0));
1549 /* Alignment constants ********************************************/
1551 #define alignment(TYPE) \
1552 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1554 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1556 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1558 alignment(char), alignment(short),
1559 alignment(int), alignment(long),
1560 oc);
1562 Vprintf("%sfloat=%ld double=%ld%s\n",
1564 alignment(float), alignment(double),
1565 oc);
1567 if (stdc) {
1568 Vprintf("%slong double=%ld%s\n",
1570 alignment(Long_double),
1571 oc);
1573 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1575 alignment(char *), alignment(int *), alignment(function *),
1576 oc);
1578 Vprintf("\n");
1580 /* Ten little endians *********************************************/
1582 endian(bits_per_byte);
1584 /* Pointers *******************************************************/
1586 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1588 if ((long) (char *) &variable == (long) (int *) &variable)
1589 Vprintf("%sChar and int pointer formats seem identical%s\n",
1590 co, oc);
1591 else
1592 Vprintf("%sChar and int pointer formats are different%s\n",
1593 co, oc);
1594 if ((long) (char *) &variable == (long) (function *) &variable)
1595 Vprintf("%sChar and function pointer formats seem identical%s\n",
1596 co, oc);
1597 else
1598 Vprintf("%sChar and function pointer formats are different%s\n",
1599 co, oc);
1601 if (V) {
1602 if ("abcd"=="abcd")
1603 printf("%sStrings are shared%s\n", co, oc);
1604 else printf("%sStrings are not shared%s\n", co, oc);
1607 p=0; q=0;
1608 showtype("Type ptrdiff_t is", p-q);
1610 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1612 sprop();
1613 iprop();
1614 lprop();
1615 usprop();
1616 uiprop();
1617 ulprop();
1619 promotions();
1621 Unexpected(6);
1623 return bits_per_byte;
1626 #else /* not PASS0 */
1628 #ifdef SEP
1629 extern jmp_buf lab;
1630 extern int V, L, F, bugs, bits_per_byte;
1631 extern char co[], oc[];
1632 extern char *f_rep();
1633 #endif /* SEP */
1634 #endif /* ifdef PASS0 */
1636 /* As I said, I apologise for the contortions below. The functions are
1637 expanded by the preprocessor twice or three times (for float and double,
1638 and maybe for long double, and for short, int and long). That way,
1639 I never make a change to one that I forget to make to the other.
1640 You can look on it as C's fault for not supporting multi-line macro's.
1641 This whole file is read 3 times by the preprocessor, with PASSn set for
1642 n=1, 2 or 3, to decide which parts to reprocess.
1645 /* #undef on an already undefined thing is (wrongly) flagged as an error
1646 by some compilers, therefore the #ifdef that follows:
1648 #ifdef Number
1649 #undef Number
1650 #undef THING
1651 #undef Thing
1652 #undef thing
1653 #undef FPROP
1654 #undef Fname
1655 #undef Store
1656 #undef Sum
1657 #undef Diff
1658 #undef Mul
1659 #undef Div
1660 #undef ZERO
1661 #undef HALF
1662 #undef ONE
1663 #undef TWO
1664 #undef THREE
1665 #undef FOUR
1666 #undef Self
1667 #undef F_check
1668 #undef Validate
1669 #undef EPROP
1670 #undef MARK
1672 /* These are the float.h constants */
1673 #undef F_RADIX
1674 #undef F_MANT_DIG
1675 #undef F_DIG
1676 #undef F_ROUNDS
1677 #undef F_EPSILON
1678 #undef F_MIN_EXP
1679 #undef F_MIN
1680 #undef F_MIN_10_EXP
1681 #undef F_MAX_EXP
1682 #undef F_MAX
1683 #undef F_MAX_10_EXP
1684 #endif
1686 #ifdef Integer
1687 #undef Integer
1688 #undef INT
1689 #undef IPROP
1690 #undef Iname
1691 #undef UPROP
1692 #undef Uname
1693 #undef OK_UI
1694 #undef IMARK
1696 #undef I_MAX
1697 #undef I_MIN
1698 #undef U_MAX
1699 #endif
1701 #ifdef PASS1
1703 /* Define the things we're going to use this pass */
1705 #define Number float
1706 #define THING "FLOAT"
1707 #define Thing "Float"
1708 #define thing "float"
1709 #define Fname "FLT"
1710 #define FPROP fprop
1711 #define Store fStore
1712 #define Sum fSum
1713 #define Diff fDiff
1714 #define Mul fMul
1715 #define Div fDiv
1716 #define ZERO 0.0
1717 #define HALF 0.5
1718 #define ONE 1.0
1719 #define TWO 2.0
1720 #define THREE 3.0
1721 #define FOUR 4.0
1722 #define Self fSelf
1723 #define F_check fCheck
1724 #define MARK "F"
1725 #ifdef VERIFY
1726 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1727 #endif
1729 #define EPROP efprop
1731 #define Integer short
1732 #define INT "short"
1733 #define IPROP sprop
1734 #define Iname "SHRT"
1735 #ifndef NO_UI
1736 #define OK_UI 1
1737 #endif
1738 #define IMARK ""
1740 #define UPROP usprop
1741 #define Uname "USHRT"
1743 #ifdef VERIFY
1744 #ifdef SHRT_MAX
1745 #define I_MAX SHRT_MAX
1746 #endif
1747 #ifdef SHRT_MIN
1748 #define I_MIN SHRT_MIN
1749 #endif
1750 #ifdef USHRT_MAX
1751 #define U_MAX USHRT_MAX
1752 #endif
1754 #ifdef FLT_RADIX
1755 #define F_RADIX FLT_RADIX
1756 #endif
1757 #ifdef FLT_MANT_DIG
1758 #define F_MANT_DIG FLT_MANT_DIG
1759 #endif
1760 #ifdef FLT_DIG
1761 #define F_DIG FLT_DIG
1762 #endif
1763 #ifdef FLT_ROUNDS
1764 #define F_ROUNDS FLT_ROUNDS
1765 #endif
1766 #ifdef FLT_EPSILON
1767 #define F_EPSILON FLT_EPSILON
1768 #endif
1769 #ifdef FLT_MIN_EXP
1770 #define F_MIN_EXP FLT_MIN_EXP
1771 #endif
1772 #ifdef FLT_MIN
1773 #define F_MIN FLT_MIN
1774 #endif
1775 #ifdef FLT_MIN_10_EXP
1776 #define F_MIN_10_EXP FLT_MIN_10_EXP
1777 #endif
1778 #ifdef FLT_MAX_EXP
1779 #define F_MAX_EXP FLT_MAX_EXP
1780 #endif
1781 #ifdef FLT_MAX
1782 #define F_MAX FLT_MAX
1783 #endif
1784 #ifdef FLT_MAX_10_EXP
1785 #define F_MAX_10_EXP FLT_MAX_10_EXP
1786 #endif
1787 #endif /* VERIFY */
1789 #endif /* PASS1 */
1791 #ifdef PASS2
1793 #define Number double
1794 #define THING "DOUBLE"
1795 #define Thing "Double"
1796 #define thing "double"
1797 #define Fname "DBL"
1798 #define FPROP dprop
1799 #define Store dStore
1800 #define Sum dSum
1801 #define Diff dDiff
1802 #define Mul dMul
1803 #define Div dDiv
1804 #define ZERO 0.0
1805 #define HALF 0.5
1806 #define ONE 1.0
1807 #define TWO 2.0
1808 #define THREE 3.0
1809 #define FOUR 4.0
1810 #define Self dSelf
1811 #define F_check dCheck
1812 #define MARK ""
1813 #ifdef VERIFY
1814 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1815 #endif
1817 #define EPROP edprop
1819 #define Integer int
1820 #define INT "int"
1821 #define IPROP iprop
1822 #define Iname "INT"
1823 #define OK_UI 1 /* Unsigned int is always possible */
1824 #define IMARK ""
1826 #define UPROP uiprop
1827 #define Uname "UINT"
1829 #ifdef VERIFY
1830 #ifdef INT_MAX
1831 #define I_MAX INT_MAX
1832 #endif
1833 #ifdef INT_MIN
1834 #define I_MIN INT_MIN
1835 #endif
1836 #ifdef UINT_MAX
1837 #define U_MAX UINT_MAX
1838 #endif
1840 #ifdef DBL_MANT_DIG
1841 #define F_MANT_DIG DBL_MANT_DIG
1842 #endif
1843 #ifdef DBL_DIG
1844 #define F_DIG DBL_DIG
1845 #endif
1846 #ifdef DBL_EPSILON
1847 #define F_EPSILON DBL_EPSILON
1848 #endif
1849 #ifdef DBL_MIN_EXP
1850 #define F_MIN_EXP DBL_MIN_EXP
1851 #endif
1852 #ifdef DBL_MIN
1853 #define F_MIN DBL_MIN
1854 #endif
1855 #ifdef DBL_MIN_10_EXP
1856 #define F_MIN_10_EXP DBL_MIN_10_EXP
1857 #endif
1858 #ifdef DBL_MAX_EXP
1859 #define F_MAX_EXP DBL_MAX_EXP
1860 #endif
1861 #ifdef DBL_MAX
1862 #define F_MAX DBL_MAX
1863 #endif
1864 #ifdef DBL_MAX_10_EXP
1865 #define F_MAX_10_EXP DBL_MAX_10_EXP
1866 #endif
1867 #endif /* VERIFY */
1869 #endif /* PASS2 */
1871 #ifdef PASS3
1873 #ifdef STDC
1874 #define Number long double
1876 #define ZERO 0.0L
1877 #define HALF 0.5L
1878 #define ONE 1.0L
1879 #define TWO 2.0L
1880 #define THREE 3.0L
1881 #define FOUR 4.0L
1882 #endif
1884 #define THING "LONG DOUBLE"
1885 #define Thing "Long double"
1886 #define thing "long double"
1887 #define Fname "LDBL"
1888 #define FPROP ldprop
1889 #define Store ldStore
1890 #define Sum ldSum
1891 #define Diff ldDiff
1892 #define Mul ldMul
1893 #define Div ldDiv
1894 #define Self ldSelf
1895 #define F_check ldCheck
1896 #define MARK "L"
1897 #ifdef VERIFY
1898 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1899 #endif
1901 #define EPROP eldprop
1903 #define Integer long
1904 #define INT "long"
1905 #define IPROP lprop
1906 #define Iname "LONG"
1907 #ifndef NO_UI
1908 #define OK_UI 1
1909 #endif
1910 #define IMARK "L"
1912 #define UPROP ulprop
1913 #define Uname "ULONG"
1915 #ifdef VERIFY
1916 #ifdef LONG_MAX
1917 #define I_MAX LONG_MAX
1918 #endif
1919 #ifdef LONG_MIN
1920 #define I_MIN LONG_MIN
1921 #endif
1922 #ifdef ULONG_MAX
1923 #define U_MAX ULONG_MAX
1924 #endif
1926 #ifdef LDBL_MANT_DIG
1927 #define F_MANT_DIG LDBL_MANT_DIG
1928 #endif
1929 #ifdef LDBL_DIG
1930 #define F_DIG LDBL_DIG
1931 #endif
1932 #ifdef LDBL_EPSILON
1933 #define F_EPSILON LDBL_EPSILON
1934 #endif
1935 #ifdef LDBL_MIN_EXP
1936 #define F_MIN_EXP LDBL_MIN_EXP
1937 #endif
1938 #ifdef LDBL_MIN
1939 #define F_MIN LDBL_MIN
1940 #endif
1941 #ifdef LDBL_MIN_10_EXP
1942 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1943 #endif
1944 #ifdef LDBL_MAX_EXP
1945 #define F_MAX_EXP LDBL_MAX_EXP
1946 #endif
1947 #ifdef LDBL_MAX
1948 #define F_MAX LDBL_MAX
1949 #endif
1950 #ifdef LDBL_MAX_10_EXP
1951 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1952 #endif
1953 #endif /* VERIFY */
1955 #endif /* PASS3 */
1957 #ifndef I_MAX
1958 #define I_MAX int_max
1959 #endif
1960 #ifndef I_MIN
1961 #define I_MIN int_min
1962 #endif
1963 #ifndef U_MAX
1964 #define U_MAX u_max
1965 #endif
1967 #ifndef F_RADIX
1968 #define F_RADIX f_radix
1969 #endif
1970 #ifndef F_MANT_DIG
1971 #define F_MANT_DIG f_mant_dig
1972 #endif
1973 #ifndef F_DIG
1974 #define F_DIG f_dig
1975 #endif
1976 #ifndef F_ROUNDS
1977 #define F_ROUNDS f_rounds
1978 #endif
1979 #ifndef F_EPSILON
1980 #define F_EPSILON f_epsilon
1981 #endif
1982 #ifndef F_MIN_EXP
1983 #define F_MIN_EXP f_min_exp
1984 #endif
1985 #ifndef F_MIN
1986 #define F_MIN f_min
1987 #endif
1988 #ifndef F_MIN_10_EXP
1989 #define F_MIN_10_EXP f_min_10_exp
1990 #endif
1991 #ifndef F_MAX_EXP
1992 #define F_MAX_EXP f_max_exp
1993 #endif
1994 #ifndef F_MAX
1995 #define F_MAX f_max
1996 #endif
1997 #ifndef F_MAX_10_EXP
1998 #define F_MAX_10_EXP f_max_10_exp
1999 #endif
2001 #ifndef VERIFY
2002 #define Validate(prec, val, req, same) {;}
2003 #endif
2005 #ifdef Integer
2007 Procedure IPROP() {
2008 /* the properties of short, int, and long */
2009 Volatile Integer newi, int_max, maxeri, int_min, minneri;
2010 Volatile int ibits, ipower, two=2;
2012 /* Calculate max short/int/long ***********************************/
2013 /* Calculate 2**n-1 until overflow - then use the previous value */
2015 newi=1; int_max=0;
2017 if (setjmp(lab)==0) { /* Yields int_max */
2018 for(ipower=0; newi>int_max; ipower++) {
2019 int_max=newi;
2020 newi=newi*two+1;
2022 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2023 co, INT[0]=='i'?"n":"", INT, oc);
2024 } else {
2025 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2026 co, INT[0]=='i'?"n":"", INT, oc);
2028 Unexpected(7);
2030 /* Minimum value: assume either two's or one's complement *********/
2031 int_min= -int_max;
2032 if (setjmp(lab)==0) { /* Yields int_min */
2033 if (int_min-1 < int_min) int_min--;
2035 Unexpected(8);
2037 /* Now for those daft Cybers */
2039 maxeri=0; newi=int_max;
2041 if (setjmp(lab)==0) { /* Yields maxeri */
2042 for(ibits=ipower; newi>maxeri; ibits++) {
2043 maxeri=newi;
2044 newi=newi+newi+1;
2047 Unexpected(9);
2049 minneri= -maxeri;
2050 if (setjmp(lab)==0) { /* Yields minneri */
2051 if (minneri-1 < minneri) minneri--;
2053 Unexpected(10);
2055 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2056 co, INT, (long)int_max, ipower, oc);
2057 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
2059 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
2060 (long) int_max, 0L,
2061 (long) I_MAX, IMARK);
2062 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
2063 (long) int_min, (long) (PASS==1?maxint:int_max),
2064 (long) I_MIN, IMARK);
2066 if(int_max < 0) { /* It has happened */
2067 eek_a_bug("signed integral comparison faulty?");
2070 if (maxeri>int_max) {
2071 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2072 co, INT, (long)maxeri, ibits,
2073 "but only for addition, not multiplication",
2074 "(I smell a Cyber!)",
2075 oc);
2078 if (minneri<int_min) {
2079 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2080 co, INT, (long)minneri,
2081 "but only for addition, not multiplication",
2082 "(I smell a Cyber!)",
2083 oc);
2087 Procedure UPROP () {
2088 /* The properties of unsigned short/int/long */
2089 #ifdef OK_UI
2090 Volatile unsigned Integer u_max, newi, two;
2091 newi=1; u_max=0; two=2;
2093 if (setjmp(lab)==0) { /* Yields u_max */
2094 while(newi>u_max) {
2095 u_max=newi;
2096 newi=newi*two+1;
2099 Unexpected(11);
2100 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2101 co, INT, (unsigned long) u_max, oc);
2103 /* Oh woe: new standard C defines value preserving promotions */
2104 if (L) {
2105 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2106 /* Special only for short */
2107 i_define(D_UINT_MAX, INT, Uname, "_MAX",
2108 (unsigned long) u_max, 0L,
2109 (unsigned long) U_MAX, IMARK);
2110 } else {
2111 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2112 (unsigned long) u_max,
2113 (unsigned long) U_MAX, IMARK);
2116 #endif
2119 #endif /* Integer */
2121 #ifdef Number
2123 /* The following routines are intended to defeat any attempt at optimisation
2124 or use of extended precision, and to defeat faulty narrowing casts.
2125 The weird prototypes are because of widening incompatibilities.
2127 #ifdef STDC
2128 #define ARGS1(atype, a) (atype a)
2129 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2130 #else
2131 #define ARGS1(atype, a) (a) atype a;
2132 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2133 #endif
2135 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2136 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2137 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2138 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2139 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2140 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2142 Procedure F_check ARGS((int precision, Long_double val1));
2144 Procedure F_check(precision, val1) int precision; Long_double val1; {
2145 /* You don't think I'm going to go to all the trouble of writing
2146 a program that works out what all sorts of values are, only to
2147 have printf go and print the wrong values out, do you?
2148 No, you're right, so this function tries to see if printf
2149 has written the right value, by reading it back again.
2150 This introduces a new problem of course: suppose printf writes
2151 the correct value, and scanf reads it back wrong... oh well.
2152 But I'm adamant about this: the precision given is enough
2153 to uniquely identify the printed number, therefore I insist
2154 that sscanf read the number back identically. Harsh yes, but
2155 sometimes you've got to be cruel to be kind.
2157 Number val, new, diff;
2158 double rem;
2159 int e;
2160 char *rep;
2161 char *f2;
2163 #ifdef NO_LONG_DOUBLE_IO
2164 double new1;
2165 /* On the Sun 3, sscanf clobbers 4 words,
2166 which leads to a crash when this function tries to return. */
2167 f2= "%le"; /* Input */
2168 /* It is no use checking long doubles if we can't
2169 read and write them. */
2170 if (sizeof (Number) > sizeof(double))
2171 return;
2172 #else
2173 Long_double new1;
2174 if (sizeof(double) == sizeof(Long_double)) {
2175 /* Assume they're the same, and use non-stdc format */
2176 /* This is for stdc compilers using non-stdc libraries */
2177 f2= "%le"; /* Input */
2178 } else {
2179 /* It had better support Le then */
2180 f2= "%Le";
2182 #endif
2183 val= val1;
2184 rep= f_rep(precision, (Long_double) val);
2185 if (setjmp(lab)==0) {
2186 sscanf(rep, f2, &new1);
2187 } else {
2188 eek_a_bug("sscanf caused a trap");
2189 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2190 Unexpected(12);
2191 return;
2194 if (setjmp(lab)==0) { /* See if new is usable */
2195 new= new1;
2196 if (new != 0.0) {
2197 diff= val/new - 1.0;
2198 if (diff < 0.1) diff= 1.0;
2199 /* That should be enough to generate a trap */
2201 } else {
2202 eek_a_bug("sscanf returned an unusable number");
2203 printf("%s scanning: %s with format: %s%s\n\n",
2204 co, rep, f2, oc);
2205 Unexpected(13);
2206 return;
2209 Unexpected(14);
2210 if (new != val) {
2211 eek_a_bug("Possibly bad output from printf above");
2212 if (!exponent((Long_double)val, &rem, &e)) {
2213 printf("%s but value was an unusable number%s\n\n",
2214 co, oc);
2215 return;
2217 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2218 co, precision, rem, e);
2219 bitpattern((char *) &val, (unsigned)sizeof(val));
2220 printf ("%s\n", oc);
2221 printf("%s sscanf gave %s, bit pattern:\n ",
2222 co, f_rep(precision, (Long_double) new));
2223 bitpattern((char *) &new, (unsigned)sizeof(new));
2224 printf ("%s\n", oc);
2225 if (setjmp(lab) == 0) {
2226 diff= val-new;
2227 printf("%s difference= %s%s\n\n",
2228 co, f_rep(precision, (Long_double) diff), oc);
2229 } /* else forget it */
2230 Unexpected(15);
2234 #ifdef VERIFY
2235 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2236 /* Check that the compiler has read a #define value correctly */
2237 Unexpected(16);
2238 if (!same) {
2239 printf("%s*** Verify failed for above #define!\n", co);
2240 if (setjmp(lab) == 0) { /* for the case that req == nan */
2241 printf(" Compiler has %s for value%s\n",
2242 f_rep(prec, req), oc);
2243 } else {
2244 printf(" Compiler has %s for value%s\n",
2245 "an unusable number", oc);
2247 if (setjmp(lab) == 0) {
2248 F_check(prec, (Long_double) req);
2249 } /*else forget it*/
2250 if (setjmp(lab) == 0) {
2251 if (req > 0.0 && val > 0.0) {
2252 printf("%s difference= %s%s\n",
2253 co, f_rep(prec, val-req), oc);
2255 } /*else forget it*/
2256 Unexpected(17);
2257 printf("\n");
2258 bugs++;
2259 } else if (val != req) {
2260 if (stdc) eek_a_bug("constant has the wrong precision");
2261 else eek_a_bug("the cast didn't work");
2262 printf("\n");
2265 #endif /* VERIFY */
2267 int FPROP(bits_per_byte) int bits_per_byte; {
2268 /* Properties of floating types, using algorithms by Cody and Waite
2269 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2270 Further extended by S Pemberton.
2272 Returns the number of digits in the fraction.
2275 Volatile int
2276 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2277 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2278 mantbits, digs, f_dig, trap,
2279 hidden, normal, f_min_10_exp, f_max_10_exp;
2280 Volatile Number
2281 a, b, base, basein, basem1, f_epsilon, epsneg,
2282 eps, epsp1, etop, ebot,
2283 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2285 Unexpected(18);
2287 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2289 /* Base and size of significand **************************************/
2290 /* First repeatedly double until adding 1 has no effect. */
2291 /* For instance, if base is 10, with 3 significant digits */
2292 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2293 /* since 1024 is only representable as 1020. */
2294 a=1.0;
2295 if (setjmp(lab)==0) { /* inexact trap? */
2296 do { a=Sum(a, a); }
2297 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2298 } else {
2299 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2300 /* And supporting those is just TOO much trouble! */
2301 farewell(bugs+1);
2303 Unexpected(19);
2304 /* Now double until you find a number that can be added to the */
2305 /* above number. For 1020 this is 8 or 16, depending whether the */
2306 /* result is rounded or truncated. */
2307 /* In either case the result is 1030. 1030-1020= the base, 10. */
2308 b=1.0;
2309 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2310 f_radix=base;
2311 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2313 /* Sanity check; if base<2, I can't guarantee the rest will work */
2314 if (f_radix < 2) {
2315 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2316 printf("\n");
2317 return(0);
2320 if (PASS == 1) { /* only for FLT */
2321 flt_radix= f_radix;
2322 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2323 (long) f_radix, 0L, (long) F_RADIX, "");
2324 } else if (f_radix != flt_radix) {
2325 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2326 co, thing, "arithmetic has a different radix",
2327 f_radix, "from float", oc);
2328 bugs++;
2331 /* Now the number of digits precision */
2332 f_mant_dig=0; b=1.0;
2333 do { f_mant_dig++; b=Mul(b, base); }
2334 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2335 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2336 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2337 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2338 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2339 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2340 if (F) i_define(D_DIG, thing, Fname, "_DIG",
2341 (long) f_dig, 0L, (long) F_DIG, "");
2342 digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2344 /* Rounding *******************************************************/
2345 basem1=Diff(base, HALF);
2346 if (Diff(Sum(a, basem1), a) != ZERO) {
2347 if (f_radix == 2) basem1=0.375;
2348 else basem1=1.0;
2349 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2350 else irnd=1; /* to nearest */
2351 } else irnd=0; /* towards 0 */
2353 basem1=Diff(base, HALF);
2355 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2356 if (f_radix == 2) basem1=0.375;
2357 else basem1=1.0;
2358 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2359 else mrnd=1; /* to nearest */
2360 } else mrnd=0; /* towards 0 */
2362 f_rounds= -1; /* Unknown rounding */
2363 if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2364 if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2365 if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2366 if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2368 if (f_rounds != -1) {
2369 Vprintf("%sArithmetic rounds towards ", co);
2370 switch (f_rounds) {
2371 case 0: Vprintf("zero (i.e. it chops)"); break;
2372 case 1: Vprintf("nearest"); break;
2373 case 2: Vprintf("+infinity"); break;
2374 case 3: Vprintf("-infinity"); break;
2375 default: Vprintf("???"); break;
2377 Vprintf("%s\n", oc);
2378 } else { /* Hmm, try to give some help here */
2379 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2380 Vprintf("%s Negative numbers %s%s\n",
2381 co, mrnd==0 ? "towards zero" :
2382 mrnd==1 ? "to nearest" :
2383 "away from zero",
2384 oc);
2385 Vprintf("%s Positive numbers %s%s\n",
2386 co, irnd==0 ? "towards zero" :
2387 irnd==1 ? "to nearest" :
2388 "away from zero",
2389 oc);
2391 /* An extra goody */
2392 if (f_radix == 2 && f_rounds == 1) {
2393 if (Diff(Sum(a, ONE), a) != ZERO) {
2394 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
2395 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2396 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
2397 } else {
2398 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2401 if (PASS == 1) { /* only for FLT */
2402 flt_rounds= f_rounds;
2403 if (F)
2404 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2405 (long) f_rounds, 1L, (long) F_ROUNDS, "");
2406 } else if (f_rounds != flt_rounds) {
2407 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2408 co, thing, "arithmetic rounds differently",
2409 f_rounds, "from float", oc);
2410 bugs++;
2413 /* Various flavours of epsilon ************************************/
2414 negeps=f_mant_dig+f_mant_dig;
2415 basein=1.0/base;
2416 a=1.0;
2417 for(i=1; i<=negeps; i++) a*=basein;
2419 b=a;
2420 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2421 a*=base;
2422 negeps--;
2424 negeps= -negeps;
2425 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2426 co, negeps, oc);
2428 etop = ONE;
2429 ebot = ZERO;
2430 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2431 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2432 ebot and etop are the current bounds */
2433 while (eps != ebot && eps != etop) {
2434 epsp1 = Diff(ONE, eps);
2435 if (epsp1 < ONE) etop = eps;
2436 else ebot = eps;
2437 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2439 eps= etop;
2440 /* Sanity check */
2441 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2442 eek_a_bug("internal error calculating epsneg");
2444 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2445 co, f_rep(digs, (Long_double) eps), oc);
2446 if (V) F_check(digs, (Long_double) eps);
2448 epsneg=a;
2449 if ((f_radix!=2) && irnd) {
2450 /* a=(a*(1.0+a))/(1.0+1.0); => */
2451 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2452 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2453 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2455 /* epsneg is used later */
2456 Unexpected(20);
2458 machep= -f_mant_dig-f_mant_dig;
2459 a=b;
2460 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2461 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2462 co, machep, oc);
2464 etop = ONE;
2465 ebot = ZERO;
2466 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2467 /* find the smallest eps (1+eps != 1) by binary search.
2468 ebot and etop are the current bounds */
2469 while (eps != ebot && eps != etop) {
2470 epsp1 = Sum(ONE, eps);
2471 if (epsp1 > ONE) etop = eps;
2472 else ebot = eps;
2473 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2475 /* Sanity check */
2476 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2477 eek_a_bug("internal error calculating eps");
2479 f_epsilon=etop;
2481 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2482 co, f_rep(digs, (Long_double) f_epsilon), oc);
2484 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2485 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2486 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2488 /* Possible loss of precision warnings here from non-stdc compilers */
2489 if (F) f_define(D_EPSILON, thing,
2490 Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2491 if (V || F) F_check(digs, (Long_double) f_epsilon);
2492 Unexpected(21);
2493 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2494 f_epsilon == Self(F_EPSILON));
2495 Unexpected(22);
2497 /* Extra chop info *************************************************/
2498 if (f_rounds == 0) {
2499 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
2500 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2504 /* Size of and minimum normalised exponent ************************/
2505 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2507 /* Coarse search for the largest power of two */
2508 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2509 do {
2510 y=z; y1=z1;
2511 z=Mul(y,y); z1=Mul(z1, y);
2512 a=Mul(z,ONE);
2513 z2=Div(z1,y);
2514 if (z2 != y1) break;
2515 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2516 i++;
2517 k+=k;
2518 } while(1);
2519 } else {
2520 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2522 Unexpected(23);
2524 if (f_radix != 10) {
2525 iexp=i+1; /* for the sign */
2526 mx=k+k;
2527 } else {
2528 iexp=2;
2529 iz=f_radix;
2530 while (k >= iz) { iz*=f_radix; iexp++; }
2531 mx=iz+iz-1;
2534 /* Fine tune starting with y and y1 */
2535 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2536 do {
2537 f_min=y; z1=y1;
2538 y=Div(y,base); y1=Div(y1,base);
2539 a=Mul(y,ONE);
2540 z2=Mul(y1,base);
2541 if (z2 != z1) break;
2542 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2543 k++;
2544 } while (1);
2546 Unexpected(24);
2548 f_min_exp=(-k)+1;
2550 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2551 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2552 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2553 if (F)
2554 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2555 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2557 if (setjmp(lab)==0) {
2558 Vprintf("%sMinimum normalised positive number = %s%s\n",
2559 co, f_rep(digs, (Long_double) f_min), oc);
2560 } else {
2561 eek_a_bug("printf can't print the smallest normalised number");
2562 printf("\n");
2564 Unexpected(25);
2565 /* Possible loss of precision warnings here from non-stdc compilers */
2566 if (setjmp(lab) == 0) {
2567 if (F) f_define(D_MIN, thing,
2568 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2569 if (V || F) F_check(digs, (Long_double) f_min);
2570 } else {
2571 eek_a_bug("xxx_MIN caused a trap");
2572 printf("\n");
2575 if (setjmp(lab) == 0) {
2576 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2577 f_min == Self(F_MIN));
2578 } else {
2579 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2580 co, "Compiler has an unusable number for value", oc);
2581 bugs++;
2583 Unexpected(26);
2585 a=1.0; f_min_10_exp=0;
2586 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2587 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2588 (long) f_min_10_exp, (long) maxint,
2589 (long) F_MIN_10_EXP, "");
2591 /* Minimum exponent ************************************************/
2592 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2593 do {
2594 xminner=y;
2595 y=Div(y,base);
2596 a=Mul(y,ONE);
2597 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2598 } while (1);
2600 Unexpected(27);
2602 if (xminner != 0.0 && xminner != f_min) {
2603 normal= 0;
2604 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2605 co, oc);
2606 if (setjmp(lab)==0) {
2607 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2608 co, f_rep(digs, (Long_double) xminner), oc);
2609 if (V) F_check(digs, (Long_double) xminner);
2610 } else {
2611 eek_a_bug("printf can't print the smallest unnormalised number.");
2612 printf("\n");
2614 Unexpected(28);
2615 } else {
2616 normal= 1;
2617 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2620 /* Maximum exponent ************************************************/
2621 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2622 inf=0; trap=0;
2623 while (f_max<newxmax) {
2624 f_max=newxmax;
2625 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2626 newxmax=Mul(newxmax, base);
2627 } else {
2628 trap=1;
2629 break;
2631 if (Div(newxmax, base) != f_max) {
2632 inf=1; /* ieee infinity */
2633 break;
2635 f_max_exp++;
2637 Unexpected(29);
2638 if (trap) {
2639 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2642 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2643 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2644 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2645 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2647 /* Largest number ***************************************************/
2648 f_max=Diff(ONE, epsneg);
2649 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2650 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2652 if (setjmp(lab)==0) {
2653 Vprintf("%sMaximum number = %s%s\n",
2654 co, f_rep(digs, (Long_double) f_max), oc);
2655 } else {
2656 eek_a_bug("printf can't print the largest double.");
2657 printf("\n");
2659 if (setjmp(lab)==0) {
2660 /* Possible loss of precision warnings here from non-stdc compilers */
2661 if (F) f_define(D_MAX, thing,
2662 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2663 if (V || F) F_check(digs, (Long_double) f_max);
2664 } else {
2665 eek_a_bug("xxx_MAX caused a trap");
2666 printf("\n");
2668 if (setjmp(lab)==0) {
2669 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2670 f_max == Self(F_MAX));
2671 } else {
2672 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2673 co, "Compiler has an unusable number for value", oc);
2674 bugs++;
2676 Unexpected(30);
2678 a=1.0; f_max_10_exp=0;
2679 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2680 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2681 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2683 /* Hidden bit + sanity check ****************************************/
2684 if (f_radix != 10) {
2685 hidden=0;
2686 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2687 if (mantbits == 64
2688 && iexp == 15
2689 && f_max_exp+f_min_exp > 0 /* ??? f_min_exp may be wrong. */
2690 && mantbits+iexp+17 == (int)sizeof(Number)*bits_per_byte) {
2691 Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co, oc);
2692 Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co, oc);
2693 goto is_extended;
2695 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2696 hidden=1;
2697 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2698 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2699 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2700 co, oc);
2701 } else {
2702 printf("\n%s%s\n %s %s %s!%s\n\n",
2704 "*** Something fishy here!",
2705 "Exponent size + significand size doesn't match",
2706 "with the size of a", thing,
2707 oc);
2709 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2710 Vprintf("%sIt looks like %s length IEEE format%s\n",
2711 co, f_mant_dig==24 ? "single" :
2712 f_mant_dig==53 ? "double" :
2713 f_mant_dig >53 ? "extended" :
2714 "some", oc);
2715 is_extended:
2716 if (f_rounds != 1 || normal) {
2717 Vprintf("%s though ", co);
2718 if (f_rounds != 1) {
2719 Vprintf("the rounding is unusual");
2720 if (normal) Vprintf(" and ");
2722 if (normal) Vprintf("the normalisation is unusual");
2723 Vprintf("%s\n", oc);
2725 } else {
2726 Vprintf("%sIt doesn't look like IEEE format%s\n",
2727 co, oc);
2730 printf("\n"); /* regardless of verbosity */
2731 return f_mant_dig;
2734 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2735 /* See if expressions are evaluated in extended precision.
2736 Some compilers optimise even if you don't want it,
2737 and then this function fails to produce the right result.
2738 We try to diagnose this if it happens.
2740 Volatile int eprec;
2741 Volatile double a, b, base, old;
2742 Volatile Number d, oldd, dbase, one, zero;
2743 Volatile int bad=0;
2745 /* Size of significand **************************************/
2746 a=1.0;
2747 if (setjmp(lab) == 0) { /* Yields nothing */
2748 do { old=a; a=a+a; }
2749 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2750 } else bad=1;
2752 /* Avoid the comparison if bad is set,
2753 to avoid trouble on the convex. */
2754 if (!bad && (a <= old)) bad=1;
2756 if (!bad) {
2757 b=1.0;
2758 if (setjmp(lab) == 0) { /* Yields nothing */
2759 do { old=b; b=b+b; }
2760 while ((base=((a+b)-a)) == 0.0 && b>old);
2761 if (b <= old) bad=1;
2762 } else bad=1;
2765 if (!bad) {
2766 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2767 if (setjmp(lab) == 0) { /* Yields nothing */
2768 do { eprec++; oldd=d; d=d*dbase; }
2769 while ((((d+one)-d)-one) == zero && d>oldd);
2770 if (d <= oldd) bad=1;
2771 } else bad=1;
2774 Unexpected(31);
2776 if (bad) {
2777 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2778 co, thing, " check that you compiled without optimisation!",
2779 oc);
2780 } else if (eprec==dprec) {
2781 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2782 co, Thing, oc);
2783 } else if (eprec==fprec) {
2784 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2785 co, Thing, oc);
2786 } else if (eprec==lprec) {
2787 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2788 co, Thing, oc);
2789 } else {
2790 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2791 co, Thing, eprec>dprec ? "higher" : "lower",
2792 "precision than double,\n using",
2793 eprec, "base digits",
2794 oc);
2798 #else /* not Number */
2800 #ifdef FPROP /* Then create dummy routines for long double */
2801 /* ARGSUSED */
2802 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2803 #endif
2804 #ifdef EPROP
2805 /* ARGSUSED */
2806 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2807 #endif
2809 #endif /* ifdef Number */
2811 /* Increment the pass number */
2812 #undef PASS
2814 #ifdef PASS2
2815 #undef PASS2
2816 #define PASS 3
2817 #define PASS3 1
2818 #endif
2820 #ifdef PASS1
2821 #undef PASS1
2822 #define PASS 2
2823 #define PASS2 1
2824 #endif
2826 #ifdef PASS0
2827 #undef PASS0
2828 #endif
2830 #ifdef PASS /* then rescan this file */
2831 #ifdef NO_FILE
2832 #include "enquire.c"
2833 #else
2834 #include FILENAME /* if this line fails to compile, define NO_FILE */
2835 #endif
2836 #endif /* PASS */