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.
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.
37 Change by Manfred Hollstein, installed Mar 98:
38 (bitpattern): Change type of variable i to unsigned int.
42 With luck and a following wind, just the following will work:
43 cc enquire.c -o enquire
44 You may get some messages about unreachable code, which you can ignore.
46 If your compiler doesn't support: add flag:
47 signed char (eg pcc) -DNO_SC
49 unsigned short and long -DNO_UI
51 signal(), or setjmp/longjmp() -DNO_SIG
52 %Lf in printf -DNO_LONG_DOUBLE_IO
54 Try to compile first with no flags, and see if you get any errors -
55 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
56 Some compilers need a -f flag for floating point.
58 Don't use any optimisation flags: the program may not work if you do.
59 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
60 optimiser, to a floating-point unit there's a world of difference.
62 Some compilers offer various flags for different floating point
63 modes; it's worth trying all possible combinations of these.
65 Add -DID=\"name\" if you want the machine/flags identified in the output.
68 Because of bugs and/or inadequacies, some compilers need the following
71 If your C preprocessor doesn't have the predefined __FILE__ macro, and
72 you don't want to call this file enquire.c but, say, tell.c, add the
73 flag -DFILENAME=\"tell.c\" .
75 Some compilers won't accept the line "#include FILENAME".
76 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
78 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
79 or -DNO_FILE as above.
81 Some naughty compilers define __STDC__, but don't really support it.
82 Some define it as 0, in which case we treat it as undefined.
83 But if your compiler defines it, and isn't really ANSI C,
84 add flag -DNO_STDC. (To those compiler writers: for shame).
86 Some naughty compilers define __STDC__, but don't have the stddef.h
87 include file. Add flag -DNO_STDDEF.
89 Summary of naughty-compiler flags:
90 If your compiler doesn't support: add flag:
91 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
92 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
93 #include FILENAME -DNO_FILE
94 __STDC__ (properly) -DNO_STDC
97 Some systems crash when you try to malloc all store. To save users of
98 such defective systems too much grief, they may compile with -DNO_MEM,
99 which ignores that bit of the code.
101 While it is not our policy to support defective compilers, pity has been
102 taken on people with compilers that can't produce object files bigger than
103 32k (especially since it was an easy addition). Compile the program
104 into separate parts like this:
105 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
106 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
107 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
108 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
109 cc -o enquire p0.o p1.o p2.o p3.o
112 You may possibly need to add some calls to signal() for other sorts of
113 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
114 #ifdef SIGxxx in main() (and communicate the differences to me!).
117 Run without argument to get the information as English text. If run
118 with argument -l (e.g. enquire -l), output is a series of #define's for
119 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
120 with argument -f, output is a series of #define's for the ANSI standard
121 float.h include file (according to ANSI C Draft of Dec 7, 1988).
122 Flag -v gives verbose output: output includes the English text above
123 as C comments. The program exit(0)'s if everything went ok, otherwise
124 it exits with a positive number, telling how many problems there were.
126 VERIFYING THE COMPILER
127 If, having produced the float.h and limits.h header files, you want to
128 verify that the compiler reads them back correctly (there are a lot of
129 boundary cases, of course, like minimum and maximum numbers), you can
130 recompile enquire.c with -DVERIFY set (plus the other flags that you used
131 when compiling the version that produced the header files). This then
132 recompiles the program so that it #includes "limits.h" and "float.h",
133 and checks that the constants it finds there are the same as the
134 constants it produces. Run the resulting program with enquire -fl.
135 Very few compilers have passed without error.
136 NB: You *must* recompile with the same compiler and flags, otherwise
137 you may get odd results.
139 You can also use this option if your compiler already has both files,
140 and you want to confirm that this program produces the right results.
143 This program is now quite trustworthy, and suspicious and wrong output
144 may well be caused by bugs in the compiler, not in the program (however
145 of course, this is not guaranteed, and no responsibility can be
148 The program only works if overflows are ignored by the C system or
149 are catchable with signal().
151 If the program fails to run to completion (often with the error message
152 "Unexpected signal at point x"), this often turns out to be a bug in the
153 C compiler's run-time system. Check what was about to be printed, and
154 try to narrow the problem down.
156 Another possible problem is that you have compiled the program to produce
157 loss-of-precision arithmetic traps. The program cannot cope with these,
158 and you should re-compile without them. (They should never be the default).
160 Make sure you compiled with optimisation turned off.
162 Output preceded by *** WARNING: identifies behaviour of the C system
163 deemed incorrect by the program. Likely problems are that printf or
164 scanf don't cope properly with certain boundary numbers: this program
165 goes to a lot of trouble to calculate its values, and these values
166 are mostly boundary numbers. Experience has shown that often printf
167 cannot cope with these values, and so in an attempt to increase
168 confidence in the output, for each float and double that is printed,
169 the printed value is checked by using sscanf to read it back.
170 Care is taken that numbers are printed with enough digits to uniquely
171 identify them, and therefore that they can be read back identically.
172 If the number read back is different, then there is probably a bug in
173 printf or sscanf, and the program prints the warning message.
174 If the two numbers in the warning look identical, then printf is more
175 than likely rounding the last digit(s) incorrectly. To put you at ease
176 that the two really are different, the bit patterns of the two numbers
177 are also printed. The difference is very likely in the last bit.
178 Many scanf's read the minimum double back as 0.0, and similarly cause
179 overflow when reading the maximum double. This program quite ruthlessly
180 declares all these behaviours faulty. The point is that if you get
181 one of these warnings, the output may be wrong, so you should check
182 the result carefully if you intend to use the results. Of course, printf
183 and sscanf may both be wrong, and cancel each other out, so you should
184 check the output carefully anyway.
186 The warning that "a cast didn't work" refers to cases like this:
189 #define C 1.234567890123456789
191 if (f != (float) C) printf ("Wrong!");
193 A faulty compiler will widen f to double and ignore the cast to float,
194 and because there is more accuracy in a double than a float, fail to
195 recognise that they are the same. In the actual case in point, f and C
196 are passed as parameters to a function that discovers they are not equal,
197 so it's just possible that the error was in the parameter passing,
198 not in the cast (see function Validate()).
199 For ANSI C, which has float constants, the error message is "constant has
203 If the program doesn't work for you for any reason that can't be
204 narrowed down to a problem in the C compiler, or it has to be changed in
205 order to get it to compile, or it produces suspicious output (like a very
206 low maximum float, for instance), please mail the problem and an example
207 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
208 improvements can be worked into future versions; cwi.nl is the European
209 backbone, and is connected to uunet and other fine hosts.
211 The program tries to catch and diagnose bugs in the compiler/run-time
212 system. I would be especially pleased to have reports of failures so
213 that I can improve this service.
215 I apologise unreservedly for the contorted use of the preprocessor...
218 You may copy and distribute verbatim copies of this source file.
220 You may modify this source file, and copy and distribute such
221 modified versions, provided that you leave the copyright notice
222 at the top of the file and also cause the modified file to carry
223 prominent notices stating that you changed the files and the date
224 of any change; and cause the whole of any work that you distribute
225 or publish, that in whole or in part contains or is a derivative of
226 this program or any part thereof, to be licensed at no charge to
227 all third parties on terms identical to those here.
229 If you do have a fix to any problem, please send it to me, so that
230 other people can have the benefits.
232 While every effort has been taken to make this program as reliable as
233 possible, no responsibility can be taken for the correctness of the
234 output, nor suitability for any particular use.
236 This program is an offshoot of a project funded by public funds.
237 If you use this program for research or commercial use (i.e. more
238 than just for the fun of knowing about your compiler) mailing a short
239 note of acknowledgement may help keep enquire.c supported.
242 Many people have given time and ideas to making this program what it is.
243 To all of them thanks, and apologies for not mentioning them by name.
246 Originally started as a program to generate configuration constants
247 for a large piece of software we were writing, which later took on
249 1.0 Length 6658!; end 1984?
250 Unix only. Only printed a dozen maximum int/double values.
251 2.0 Length 10535; Spring 1985
252 Prints values as #defines (about 20 of them)
253 More extensive floating point, using Cody and Waite
254 Handles signals better
255 Programs around optimisations
257 3.0 Length 12648; Aug 1987; prints about 42 values
258 Added PASS stuff, so treats float as well as double
259 4.0 Length 33891; Feb 1989; prints around 85 values
260 First GNU version (for gcc, where they call it hard-params.c)
261 Generates float.h and limits.h files
263 Generates warnings for dubious output
264 4.1 Length 47738; April 1989
265 Added VERIFY and TEST
266 4.2 Length 63442; Feb 1990
269 Added check for pseudo-unsigned chars
270 Added description for each #define output
271 Added check for absence of defines during verify
273 Added NO_STDC and NO_FILE
274 Fixed alignments output
275 4.3 Length 75000; Oct 1990; around 114 lines of output
276 Function xmalloc defined, Richard Stallman, June 89.
277 Alignments computed from member offsets rather than structure sizes,
278 Richard Stallman, Oct 89.
279 Print whether char* and int* pointers have the same format;
280 also char * and function *.
281 Update to Draft C version Dec 7, 1988
282 - types of constants produced in limits.h
283 (whether to put a U after unsigned shorts and chars and
284 whether to output -1024 as (-1023-1))
285 - values of SCHAR_MIN/MAX
286 - values of *_EPSILON (not the smallest but the effective smallest)
287 Added FILENAME, since standard C doesn't allow #define __FILE__
288 Renamed from config.c to enquire.c
289 Added size_t and ptrdiff_t enquiries
290 Added promotion enquiries
291 Added type checks of #defines
293 Changed endian to allow for cases where not all bits are used
294 Sanity check for max integrals
295 Fixed definition of setjmp for -DNO_SIG
296 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
300 /* Set FILENAME to the name of this file */
303 #define FILENAME "enquire.c"
305 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
306 #define FILENAME __FILE__
308 #define FILENAME "enquire.c"
309 #endif /* __FILE__ */
311 #endif /* FILENAME */
313 /* If PASS isn't defined, then this is the first pass over this file. */
321 /* A description of the ANSI constants */
322 #define D_CHAR_BIT "Number of bits in a storage unit"
323 #define D_CHAR_MAX "Maximum char"
324 #define D_CHAR_MIN "Minimum char"
325 #define D_SCHAR_MAX "Maximum signed char"
326 #define D_SCHAR_MIN "Minimum signed char"
327 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
329 #define D_INT_MAX "Maximum %s"
330 #define D_INT_MIN "Minimum %s"
331 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
333 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
334 #define D_FLT_RADIX "Radix of exponent representation"
335 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
336 #define D_DIG "Number of decimal digits of precision in a %s"
337 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
338 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
339 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
340 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
341 #define D_MAX "Maximum %s"
342 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
343 #define D_MIN "Minimum normalised %s"
345 /* Procedure just marks the functions that don't return a result */
347 #define Procedure int
349 #define Procedure void
352 /* Some bad compilers define __STDC__, when they don't support it.
353 Compile with -DNO_STDC to get round this.
357 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
363 /* Stuff different for ANSI C, and old C:
364 ARGS and NOARGS are used for function prototypes.
365 Volatile is used to reduce the chance of optimisation,
366 and to prevent variables being put in registers (when setjmp/longjmp
367 wouldn't work as we want)
368 Long_double is the longest floating point type available.
369 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
370 U is output after unsigned constants.
375 #define NOARGS (void)
376 #define Volatile volatile
377 #define Long_double long double
381 #else /* Old style C */
385 #define Volatile static
386 #define Long_double double
393 /* Stdio.h might include limits.h, and limits.h might include float.h, and
394 float.h is probably the float.h put together by the gcc makefile to
395 cause errors. We use our special define to assure float.h that we don't
397 #define __GCC_FLOAT_NOT_NEEDED
402 #include <stddef.h> /* for size_t: if this fails, define NO_STDDEF */
409 #include <sys/types.h>
414 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
429 #ifndef SYS_FLOAT_H_WRAP
430 #define SYS_FLOAT_H_WRAP 0
433 #if SYS_FLOAT_H_WRAP || defined VERIFY
437 #define Vprintf if (V) printf
438 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
439 #define fabs(x) (((x)<0.0)?(-x):(x))
445 /* Prototypes for what's to come: */
450 char *malloc (); /* Old style prototype */
452 char *malloc
ARGS((size_t size
));
455 Procedure exit
ARGS((int status
));
457 char *f_rep
ARGS((int precision
, Long_double val
));
458 char *fake_f_rep
ARGS((char *type
, Long_double val
));
460 int maximum_int NOARGS
;
463 Procedure sprop NOARGS
;
464 Procedure iprop NOARGS
;
465 Procedure lprop NOARGS
;
466 Procedure usprop NOARGS
;
467 Procedure uiprop NOARGS
;
468 Procedure ulprop NOARGS
;
469 int fprop
ARGS((int bits_per_byte
));
470 int dprop
ARGS((int bits_per_byte
));
471 int ldprop
ARGS((int bits_per_byte
));
472 Procedure efprop
ARGS((int fprec
, int dprec
, int lprec
));
473 Procedure edprop
ARGS((int fprec
, int dprec
, int lprec
));
474 Procedure eldprop
ARGS((int fprec
, int dprec
, int lprec
));
476 int setmode
ARGS((char *s
));
477 Procedure farewell
ARGS((int bugs
));
478 Procedure describe
ARGS((char *description
, char *extra
));
479 Procedure missing
ARGS((char *s
));
480 Procedure fmissing
ARGS((char *s
));
481 Procedure check_defines NOARGS
;
482 Procedure bitpattern
ARGS((char *p
, unsigned int size
));
483 int ceil_log
ARGS((int base
, Long_double x
));
484 Procedure croak
ARGS((int place
));
485 Procedure eek_a_bug
ARGS((char *problem
));
486 Procedure endian
ARGS((int bits_per_byte
));
487 int exponent
ARGS((Long_double x
, double *fract
, int *exp
));
488 int floor_log
ARGS((int base
, Long_double x
));
489 Procedure f_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
490 int prec
, Long_double val
, Long_double req
,
492 Procedure i_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
493 long val
, long lim
, long req
, char *mark
));
494 Procedure u_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
495 unsigned long val
, unsigned long req
, char *mark
));
497 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
499 /* Dummy routines instead */
501 int setjmp
ARGS((int lab
));
504 int setjmp(lab
) int lab
; { return(0); }
505 Procedure
signal(i
, p
) int i
, (*p
)(); {}
509 Procedure
overflow(sig
) int sig
; { /* what to do on over/underflow */
510 signal(sig
, overflow
);
516 int V
= 0, /* verbose */
517 L
= 0, /* produce limits.h */
518 F
= 0, /* produce float.h */
519 bugs
=0; /* The number of (possible) bugs in the output */
521 char co
[4], oc
[4]; /* Comment starter and ender symbols */
523 int bits_per_byte
; /* the number of bits per unit returned by sizeof() */
524 int flt_rounds
; /* The calculated value of FLT_ROUNDS */
525 int flt_radix
; /* The calculated value of FLT_RADIX */
528 /* Set the fp modes on a SUN with 68881 chip, to check that different
529 rounding modes etc. get properly detected.
530 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
531 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
532 register to hex-number
535 /* Bits 0x30 = rounding mode */
536 #define ROUND_BITS 0x30
537 #define TO_NEAREST 0x00
539 #define TO_MINUS_INF 0x20
540 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
542 /* Bits 0xc0 = extended rounding */
543 #define EXT_BITS 0xc0
544 #define ROUND_EXTENDED 0x00
545 #define ROUND_SINGLE 0x40
546 #define ROUND_DOUBLE 0x80
549 #define EXE_INEX1 0x100
550 #define EXE_INEX2 0x200
552 #define EXE_UNFL 0x800
553 #define EXE_OVFL 0x1000
554 #define EXE_OPERR 0x2000
555 #define EXE_SNAN 0x4000
556 #define EXE_BSUN 0x8000
558 /* Only used for testing, on a Sun with 68881 chip */
559 /* Print the FP mode */
560 printmode(new) unsigned new; {
562 printf("New fp mode:\n");
563 printf(" Round toward ");
564 switch (new & ROUND_BITS
) {
565 case TO_NEAREST
: printf("nearest"); break;
566 case TO_ZERO
: printf("zero"); break;
567 case TO_MINUS_INF
: printf("minus infinity"); break;
568 case TO_PLUS_INF
: printf("plus infinity"); break;
569 default: printf("???"); break;
572 printf("\n Extended rounding precision: ");
574 switch (new & EXT_BITS
) {
575 case ROUND_EXTENDED
: printf("extended"); break;
576 case ROUND_SINGLE
: printf("single"); break;
577 case ROUND_DOUBLE
: printf("double"); break;
578 default: printf("???"); break;
581 printf("\n Enabled exceptions:");
582 if (new & (unsigned) EXE_INEX1
) printf(" inex1");
583 if (new & (unsigned) EXE_INEX2
) printf(" inex2");
584 if (new & (unsigned) EXE_DZ
) printf(" dz");
585 if (new & (unsigned) EXE_UNFL
) printf(" unfl");
586 if (new & (unsigned) EXE_OVFL
) printf(" ovfl");
587 if (new & (unsigned) EXE_OPERR
) printf(" operr");
588 if (new & (unsigned) EXE_SNAN
) printf(" snan");
589 if (new & (unsigned) EXE_BSUN
) printf(" bsun");
593 /* Only used for testing, on a Sun with 68881 chip */
594 /* Set the FP mode */
595 int setmode(s
) char *s
; {
596 unsigned mode
=0, dig
;
601 if (c
>='0' && c
<='9') dig
= c
-'0';
602 else if (c
>='a' && c
<='f') dig
= c
-'a'+10;
603 else if (c
>='A' && c
<='F') dig
= c
-'A'+10;
612 int setmode(s
) char *s
; {
613 fprintf(stderr
, "Can't set mode: not compiled with TEST\n");
618 Procedure
farewell(bugs
) int bugs
; {
619 if (bugs
== 0) exit(0);
620 printf("\n%sFor hints on dealing with the ", co
);
621 if (bugs
== 1) printf("problem");
622 else printf("%d problems", bugs
);
623 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
624 printf("%s%s\n", FILENAME
, oc
);
628 /* The program has received a signal where it wasn't expecting one */
629 Procedure
croak(place
) int place
; {
630 printf("*** Unexpected signal at point %d\n", place
);
631 farewell(bugs
+1); /* An exit isn't essential here, but avoids loops */
634 /* This is here in case alloca.c is used, which calls this. */
635 char *xmalloc(size
) unsigned size
; {
636 char *value
= (char *)malloc(size
);
638 fprintf(stderr
, "Virtual memory exceeded\n");
647 /* Find the maximum integer */
648 Volatile
int newi
, int_max
, two
=2;
650 /* Calculate maxint ***********************************/
651 /* Calculate 2**n-1 until overflow - then use the previous value */
655 if (setjmp(lab
)==0) { /* Yields int_max */
656 while(newi
>int_max
) {
665 int main(argc
, argv
) int argc
; char *argv
[]; {
666 int dprec
, fprec
, lprec
;
667 int i
; char *s
; int bad
;
670 signal(SIGFPE
, overflow
);
673 signal(SIGOVER
, overflow
);
675 /* Add more calls as necessary */
680 for (i
=1; i
< argc
; i
++) {
686 case 'v': V
=1; break;
687 case 'l': L
=1; break;
688 case 'f': F
=1; break;
689 default: bad
=1; break;
692 } else if (*s
== '+') {
699 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
704 co
[0]= '/'; oc
[0]= ' ';
705 co
[1]= '*'; oc
[1]= '*';
706 co
[2]= ' '; oc
[2]= '/';
707 co
[3]= '\0'; oc
[3]= '\0';
709 co
[0]= '\0'; oc
[0]= '\0';
713 if (L
) printf("%slimits.h%s\n", co
, oc
);
714 if (F
) printf("%sfloat.h%s\n", co
, oc
);
716 printf ("#ifndef _FLOAT_H___\n");
717 printf ("#define _FLOAT_H___\n");
718 if (SYS_FLOAT_H_WRAP
)
719 printf ("#include_next <float.h>\n");
722 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
723 co
, ID
, VERSION
, oc
);
725 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
730 printf("%sVerification phase%s\n", co
, oc
);
734 Vprintf("%sCompiled without signal(): %s%s\n",
736 "there's nothing that can be done if overflow occurs",
740 Vprintf("%sCompiled without signed char%s\n", co
, oc
);
743 Vprintf("%Compiled without unsigned char%s\n", co
, oc
);
746 Vprintf("%Compiled without unsigned short or long%s\n", co
, oc
);
749 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
752 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co
, oc
);
757 maxint
= maximum_int();
758 bits_per_byte
= basic();
761 fprec
= fprop(bits_per_byte
);
762 dprec
= dprop(bits_per_byte
);
763 lprec
= ldprop(bits_per_byte
);
764 efprop(fprec
, dprec
, lprec
);
765 edprop(fprec
, dprec
, lprec
);
766 eldprop(fprec
, dprec
, lprec
);
772 /* An extra goody: the approximate amount of data-space */
773 /* Allocate store until no more available */
774 /* Different implementations have a different argument type
775 to malloc. Here we assume that it's the same type as
776 that which sizeof() returns */
777 size
=1<<((bits_per_byte
*sizeof(int))-2);
780 while ( malloc((false()?sizeof(int):size
)) !=
788 Vprintf("%sMemory allocable ~= %ld Kbytes%s\n",
789 co
, (total
+511)/512, oc
);
793 printf ("#endif %s _FLOAT_H___%s\n", co
, oc
);
796 return bugs
; /* To keep compilers and lint happy */
799 Procedure
eek_a_bug(problem
) char *problem
; {
800 /* The program has discovered a problem */
801 printf("\n%s*** WARNING: %s%s\n", co
, problem
, oc
);
805 Procedure
describe(description
, extra
) char *description
, *extra
; {
806 /* Produce the description for a #define */
808 printf(description
, extra
);
812 Procedure
i_define(desc
, extra
, sort
, name
, val
, lim
, req
, mark
)
813 char *desc
, *extra
, *sort
, *name
; long val
, lim
, req
; char *mark
; {
814 if (SYS_FLOAT_H_WRAP
&& F
&& val
== req
)
816 /* Produce a #define for a signed int type */
817 describe(desc
, extra
);
818 printf("#undef %s%s\n", sort
, name
);
820 printf("#define %s%s %ld%s\n", sort
, name
, val
, mark
);
821 } else if (val
+ lim
< 0) {
822 /* We may not produce a constant like -1024 if the max
823 allowable value is 1023. It has then to be output as
824 -1023-1. lim is the max allowable value. */
825 printf("#define %s%s (%ld%s%ld%s)\n",
826 sort
, name
, -lim
, mark
, val
+lim
, mark
);
828 printf("#define %s%s (%ld%s)\n", sort
, name
, val
, mark
);
832 printf("%s*** Verify failed for above #define!\n", co
);
833 printf(" Compiler has %ld for value%s\n\n", req
, oc
);
840 Procedure
u_define(desc
, extra
, sort
, name
, val
, req
, mark
)
841 char *desc
, *extra
, *sort
, *name
; unsigned long val
, req
; char *mark
; {
842 /* Produce a #define for an unsigned value */
843 describe(desc
, extra
);
844 printf("#undef %s%s\n", sort
, name
);
845 printf("#define %s%s %lu%s%s\n", sort
, name
, val
, U
, mark
);
848 printf("%s*** Verify failed for above #define!\n", co
);
849 printf(" Compiler has %lu for value%s\n\n", req
, oc
);
856 Procedure
f_define(desc
, extra
, sort
, name
, precision
, val
, req
, mark
)
857 char *desc
, *extra
, *sort
, *name
; int precision
;
858 Long_double val
, req
; char *mark
; {
859 if (SYS_FLOAT_H_WRAP
&& F
&& val
== req
)
861 /* Produce a #define for a float/double/long double */
862 describe(desc
, extra
);
863 printf ("#undef %s%s\n", sort
, name
);
865 #ifdef NO_LONG_DOUBLE_IO
866 static int union_defined
= 0;
867 if (sizeof(double) != sizeof(Long_double
)
868 && !strcmp(sort
, "LDBL")) {
869 if (!union_defined
) {
870 printf("#ifndef __LDBL_UNION__\n");
871 printf("#define __LDBL_UNION__\n");
872 printf("union __convert_long_double {\n");
873 printf(" unsigned __convert_long_double_i[4];\n");
874 printf(" long double __convert_long_double_d;\n");
879 printf("#define %s%s %s\n",
880 sort
, name
, fake_f_rep("long double", val
));
882 printf("#define %s%s %s%s\n",
883 sort
, name
, f_rep(precision
, val
), mark
);
886 printf("#define %s%s %s%s\n",
887 sort
, name
, f_rep(precision
, val
), mark
);
889 } else if (*mark
== 'F') {
890 /* non-ANSI C has no float constants, so cast the constant */
891 printf("#define %s%s ((float)%s)\n",
892 sort
, name
, f_rep(precision
, val
));
894 printf("#define %s%s %s\n", sort
, name
, f_rep(precision
, val
));
899 int floor_log(base
, x
) int base
; Long_double x
; {
900 /* return floor(log base(x)) */
902 while (x
>=base
) { r
++; x
/=base
; }
906 int ceil_log(base
, x
) int base
; Long_double x
; {
908 while (x
>1.0) { r
++; x
/=base
; }
912 int exponent(x
, fract
, exp
) Long_double x
; double *fract
; int *exp
; {
913 /* Split x into a fraction and a power of ten;
914 returns 0 if x is unusable, 1 otherwise.
915 Only used for error messages about faulty output.
924 if (x
==0.0) return 1;
928 if (old
==x
) return 0;
933 if (old
==x
) return 0;
936 if (neg
) *fract
= (double) -x
;
937 else *fract
=(double) x
;
942 /* Print a value of type TYPE with value VAL,
943 assuming that sprintf can't handle this type properly (without truncation).
944 We create an expression that uses type casting to create the value from
947 char *fake_f_rep(type
, val
) char *type
; Long_double val
; {
948 static char buf
[1024];
949 union { unsigned int i
[4]; Long_double ld
;} u
;
950 u
.i
[0] = u
.i
[1] = u
.i
[2] = u
.i
[3] = 0;
952 sprintf(buf
, "(__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x%x, 0x%x, 0x%x, 0x%x}}).__convert_long_double_d)",
953 u
.i
[0], u
.i
[1], u
.i
[2], u
.i
[3]);
957 char *f_rep(precision
, val
) int precision
; Long_double val
; {
958 /* Return the floating representation of val */
959 static char buf
[1024];
960 #ifdef NO_LONG_DOUBLE_IO
963 if (sizeof(double) == sizeof(Long_double
))
967 /* Assume they're the same, and use non-stdc format */
968 /* This is for stdc compilers using non-stdc libraries */
969 sprintf(buf
, "%.*e", precision
, d
);
971 /* It had better support Le then */
972 sprintf(buf
, "%.*Le", precision
, val
);
977 Procedure
bitpattern(p
, size
) char *p
; unsigned int size
; {
978 /* Printf the bit-pattern of p */
983 for (i
=1; i
<=size
; i
++) {
986 for (j
=bits_per_byte
-1; j
>=0; j
--)
987 printf("%c", (c
>>j
)&1 ? '1' : '0');
988 if (i
!=size
) printf(" ");
992 #define Order(x, px, mode)\
993 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
994 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
995 putchar(c==0 ? '?' : (char)c); }\
998 Procedure
endian(bits_per_byte
) int bits_per_byte
; {
999 /* Printf the byte-order used on this machine */
1000 /*unsigned*/ short s
=0;
1001 /*unsigned*/ int j
=0;
1002 /*unsigned*/ long l
=0;
1004 char *ps
= (char *) &s
,
1007 *ab
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1008 unsigned int mask
, i
, c
;
1011 for (i
=1; i
<=(unsigned)bits_per_byte
; i
++) mask
= (mask
<<1)|1;
1014 printf("%sCHARACTER ORDER%s\n", co
, oc
);
1015 Order(s
, ps
, "short:");
1016 Order(j
, pj
, "int: ");
1017 Order(l
, pl
, "long: ");
1021 Procedure
missing(s
) char *s
; {
1022 printf("%s*** #define %s missing from limits.h%s\n", co
, s
, oc
);
1026 Procedure
fmissing(s
) char *s
; {
1027 printf("%s*** #define %s missing from float.h%s\n", co
, s
, oc
);
1031 /* To try and fool optimisers */
1032 int false() { return 0; }
1034 #define Promoted(x) (false()?(x):(-1))
1035 #define is_signed(x) (Promoted(x) < 0)
1036 #define sign_of(x) ((x)?"signed":"unsigned")
1039 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1041 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1043 char *type_of(x
) int x
; {
1044 if (x
== sizeof(char)) {
1045 if (sizeof(char) == sizeof(int)) return "char/short/int";
1046 if (sizeof(char) == sizeof(short)) return "char/short";
1049 if (x
== sizeof(short)) {
1050 if (sizeof(short) == sizeof(int)) return "short/int";
1053 if (x
== sizeof(int)) {
1054 if (sizeof(int) == sizeof(long)) return "int/long";
1057 if (x
== sizeof(long)) return "long";
1058 return "unknown-type";
1061 char *ftype_of(x
) int x
; {
1062 if (x
== sizeof(float)) {
1065 if (x
== sizeof(double)) {
1066 if (sizeof(double) == sizeof(Long_double
))
1067 return "(long)double";
1070 if (x
== sizeof(Long_double
)) {
1071 return "long double";
1073 return "unknown-type";
1076 Procedure
typerr(name
, esign
, esize
, sign
, size
)
1077 char *name
; int esign
, esize
, sign
, size
;
1079 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1080 name
, sign_of(esign
), type_of(esize
),
1081 sign_of(sign
), type_of(size
));
1084 Procedure
ftyperr(name
, esize
, size
) char *name
; int esize
, size
; {
1085 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1086 name
, ftype_of(esize
), ftype_of(size
));
1090 int si
= 0; long sl
= 0;
1091 unsigned int ui
; unsigned long ul
;
1092 short ss
; unsigned short us
;
1094 Vprintf("\n%sPROMOTIONS%s\n", co
, oc
);
1097 /* Possible warnings here; no problem */
1098 (sizeof(Promoted(si
)) != sizeof(int)) ||
1099 (sizeof(Promoted(sl
)) != sizeof(long)) ||
1100 (sizeof(Promoted(ss
)) != sizeof(int)) ||
1101 (sizeof(Promoted(ui
)) != sizeof(int)) ||
1102 (sizeof(Promoted(ul
)) != sizeof(long)) ||
1103 (sizeof(Promoted(us
)) != sizeof(int)) ||
1104 is_signed(ui
) || is_signed(ul
) ||
1105 !is_signed(si
) || !is_signed(sl
)
1108 eek_a_bug("promotions don't work properly in conditional expressions\n");
1111 showtype("unsigned short promotes to", Promoted((unsigned short) 0));
1112 showtype("long+unsigned gives", sl
+ui
);
1116 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1118 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1120 Procedure
check_defines() {
1121 /* ensure that all #defines are present and have the correct type */
1128 /* Implementations promote unsigned short differently */
1129 usign
= is_signed((unsigned short) 0);
1134 checktype(CHAR_BIT
, "CHAR_BIT", Signed
, int);
1136 missing("CHAR_BIT");
1139 checktype(CHAR_MAX
, "CHAR_MAX", Signed
, int);
1141 missing("CHAR_MAX");
1144 checktype(CHAR_MIN
, "CHAR_MIN", Signed
, int);
1146 missing("CHAR_MIN");
1149 checktype(SCHAR_MAX
, "SCHAR_MAX", Signed
, int);
1151 missing("SCHAR_MAX");
1154 checktype(SCHAR_MIN
, "SCHAR_MIN", Signed
, int);
1156 missing("SCHAR_MIN");
1159 checktype(UCHAR_MAX
, "UCHAR_MAX", Signed
, int);
1161 missing("UCHAR_MAX");
1164 checktype(SHRT_MAX
, "SHRT_MAX", Signed
, int);
1166 missing("SHRT_MAX");
1169 checktype(SHRT_MIN
, "SHRT_MIN", Signed
, int);
1171 missing("SHRT_MIN");
1174 checktype(INT_MAX
, "INT_MAX", Signed
, int);
1179 checktype(INT_MIN
, "INT_MIN", Signed
, int);
1184 checktype(LONG_MAX
, "LONG_MAX", Signed
, long);
1186 missing("LONG_MAX");
1189 checktype(LONG_MIN
, "LONG_MIN", Signed
, long);
1191 missing("LONG_MIN");
1194 checktype(USHRT_MAX
, "USHRT_MAX", usign
, int);
1196 missing("USHRT_MAX");
1199 checktype(UINT_MAX
, "UINT_MAX", Unsigned
, int);
1201 missing("UINT_MAX");
1204 checktype(ULONG_MAX
, "ULONG_MAX", Unsigned
, long);
1206 missing("ULONG_MAX");
1212 checktype(FLT_RADIX
, "FLT_RADIX", Signed
, int);
1214 fmissing("FLT_RADIX");
1217 checktype(FLT_MANT_DIG
, "FLT_MANT_DIG", Signed
, int);
1219 fmissing("FLT_MANT_DIG");
1222 checktype(FLT_DIG
, "FLT_DIG", Signed
, int);
1224 fmissing("FLT_DIG");
1227 checktype(FLT_ROUNDS
, "FLT_ROUNDS", Signed
, int);
1229 fmissing("FLT_ROUNDS");
1232 fchecktype(FLT_EPSILON
, "FLT_EPSILON", float);
1234 fmissing("FLT_EPSILON");
1237 checktype(FLT_MIN_EXP
, "FLT_MIN_EXP", Signed
, int);
1239 fmissing("FLT_MIN_EXP");
1242 fchecktype(FLT_MIN
, "FLT_MIN", float);
1244 fmissing("FLT_MIN");
1246 #ifdef FLT_MIN_10_EXP
1247 checktype(FLT_MIN_10_EXP
, "FLT_MIN_10_EXP", Signed
, int);
1249 fmissing("FLT_MIN_10_EXP");
1252 checktype(FLT_MAX_EXP
, "FLT_MAX_EXP", Signed
, int);
1254 fmissing("FLT_MAX_EXP");
1257 fchecktype(FLT_MAX
, "FLT_MAX", float);
1259 fmissing("FLT_MAX");
1261 #ifdef FLT_MAX_10_EXP
1262 checktype(FLT_MAX_10_EXP
, "FLT_MAX_10_EXP", Signed
, int);
1264 fmissing("FLT_MAX_10_EXP");
1267 checktype(DBL_MANT_DIG
, "DBL_MANT_DIG", Signed
, int);
1269 fmissing("DBL_MANT_DIG");
1272 checktype(DBL_DIG
, "DBL_DIG", Signed
, int);
1274 fmissing("DBL_DIG");
1277 fchecktype(DBL_EPSILON
, "DBL_EPSILON", double);
1279 fmissing("DBL_EPSILON");
1282 checktype(DBL_MIN_EXP
, "DBL_MIN_EXP", Signed
, int);
1284 fmissing("DBL_MIN_EXP");
1287 fchecktype(DBL_MIN
, "DBL_MIN", double);
1289 fmissing("DBL_MIN");
1291 #ifdef DBL_MIN_10_EXP
1292 checktype(DBL_MIN_10_EXP
, "DBL_MIN_10_EXP", Signed
, int);
1294 fmissing("DBL_MIN_10_EXP");
1297 checktype(DBL_MAX_EXP
, "DBL_MAX_EXP", Signed
, int);
1299 fmissing("DBL_MAX_EXP");
1302 fchecktype(DBL_MAX
, "DBL_MAX", double);
1304 fmissing("DBL_MAX");
1306 #ifdef DBL_MAX_10_EXP
1307 checktype(DBL_MAX_10_EXP
, "DBL_MAX_10_EXP", Signed
, int);
1309 fmissing("DBL_MAX_10_EXP");
1312 #ifdef LDBL_MANT_DIG
1313 checktype(LDBL_MANT_DIG
, "LDBL_MANT_DIG", Signed
, int);
1315 fmissing("LDBL_MANT_DIG");
1318 checktype(LDBL_DIG
, "LDBL_DIG", Signed
, int);
1320 fmissing("LDBL_DIG");
1323 fchecktype(LDBL_EPSILON
, "LDBL_EPSILON", long double);
1325 fmissing("LDBL_EPSILON");
1328 checktype(LDBL_MIN_EXP
, "LDBL_MIN_EXP", Signed
, int);
1330 fmissing("LDBL_MIN_EXP");
1333 fchecktype(LDBL_MIN
, "LDBL_MIN", long double);
1335 fmissing("LDBL_MIN");
1337 #ifdef LDBL_MIN_10_EXP
1338 checktype(LDBL_MIN_10_EXP
, "LDBL_MIN_10_EXP", Signed
, int);
1340 fmissing("LDBL_MIN_10_EXP");
1343 checktype(LDBL_MAX_EXP
, "LDBL_MAX_EXP", Signed
, int);
1345 fmissing("LDBL_MAX_EXP");
1348 fchecktype(LDBL_MAX
, "LDBL_MAX", long double);
1350 fmissing("LDBL_MAX");
1352 #ifdef LDBL_MAX_10_EXP
1353 checktype(LDBL_MAX_10_EXP
, "LDBL_MAX_10_EXP", Signed
, int);
1355 fmissing("LDBL_MAX_10_EXP");
1364 #define SCHAR_MAX char_max
1367 #define SCHAR_MIN char_min
1370 #define UCHAR_MAX char_max
1375 #define CHAR_BIT char_bit
1378 #define CHAR_MAX char_max
1381 #define CHAR_MIN char_min
1384 #define SCHAR_MAX char_max
1387 #define SCHAR_MIN char_min
1390 #define UCHAR_MAX char_max
1394 /* Properties of type char */
1395 Volatile
char c
, char_max
, char_min
;
1396 Volatile
int bits_per_byte
, c_signed
;
1401 /* Calculate number of bits per character *************************/
1402 c
=1; bits_per_byte
=0;
1403 do { c
=c
<<1; bits_per_byte
++; } while(c
!=0);
1405 if (((int)c
)<0) c_signed
=1;
1407 Vprintf("%schar = %d bits, %ssigned%s\n",
1408 co
, (int)sizeof(c
)*bits_per_byte
, (c_signed
?"":"un"), oc
);
1409 char_bit
=(long)(sizeof(c
)*bits_per_byte
);
1410 if (L
) i_define(D_CHAR_BIT
, "", "CHAR", "_BIT",
1411 char_bit
, 0L, (long) CHAR_BIT
, "");
1415 if (setjmp(lab
)==0) { /* Yields char_max */
1416 while (c
>char_max
) {
1421 Vprintf("%sCharacter overflow generates a trap!%s\n", co
, oc
);
1425 if (setjmp(lab
)==0) { /* Yields char_min */
1426 while (c
<char_min
) {
1431 if (c_signed
&& char_min
== 0) {
1432 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co
, oc
);
1433 Vprintf("%s %s%s%s\n",
1434 "They contain only nonnegative values, ",
1435 "but sign extend when used as integers.", co
, oc
);
1440 /* Because of the integer promotions, you must use a U after
1441 the MAX_CHARS in the following cases */
1442 if ((sizeof(char) == sizeof(int)) && !c_signed
) {
1443 u_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1445 (long) CHAR_MAX
, "");
1447 i_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1448 (long) char_max
, 0L,
1449 (long) CHAR_MAX
, "");
1451 i_define(D_CHAR_MIN
, "", "CHAR", "_MIN",
1452 (long) char_min
, (long) maxint
,
1453 (long) CHAR_MIN
, "");
1455 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1456 (long) char_max
, 0L,
1457 (long) SCHAR_MAX
, "");
1458 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1459 (long) char_min
, (long) maxint
,
1460 (long) SCHAR_MIN
, "");
1462 if (sizeof(char) == sizeof(int)) {
1463 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1465 (long) UCHAR_MAX
, "");
1467 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1468 (long) char_max
, 0L,
1469 (long) UCHAR_MAX
, "");
1475 Volatile
unsigned char c
, char_max
;
1478 if (setjmp(lab
)==0) { /* Yields char_max */
1479 while (c
>char_max
) {
1485 if (sizeof(char) == sizeof(int)) {
1486 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1488 (long) UCHAR_MAX
, "");
1490 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1491 (long) char_max
, 0L,
1492 (long) UCHAR_MAX
, "");
1497 /* Define NO_SC if this gives a syntax error */ Volatile
signed char c
, char_max
, char_min
;
1500 if (setjmp(lab
)==0) { /* Yields char_max */
1501 while (c
>char_max
) {
1508 if (setjmp(lab
)==0) { /* Yields char_min */
1509 while (c
<char_min
) {
1515 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1516 (long) char_min
, (long) maxint
,
1517 (long) SCHAR_MIN
, "");
1518 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1519 (long) char_max
, 0L,
1520 (long) SCHAR_MAX
, "");
1524 return bits_per_byte
;
1528 /* The properties of the basic types.
1529 Returns number of bits per sizeof unit */
1530 Volatile
int bits_per_byte
;
1531 typedef int function ();
1535 Vprintf("%sSIZES%s\n", co
, oc
);
1536 bits_per_byte
= cprop();
1538 /* Shorts, ints and longs *****************************************/
1539 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1541 (int) sizeof(short)*bits_per_byte
,
1542 (int) sizeof(int)*bits_per_byte
,
1543 (int) sizeof(long)*bits_per_byte
,
1544 (int) sizeof(float)*bits_per_byte
,
1545 (int) sizeof(double)*bits_per_byte
, oc
);
1547 Vprintf("%slong double=%d bits%s\n",
1548 co
, (int) sizeof(Long_double
)*bits_per_byte
, oc
);
1550 Vprintf("%schar*=%d bits%s%s\n",
1551 co
, (int)sizeof(char *)*bits_per_byte
,
1552 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1554 Vprintf("%sint* =%d bits%s%s\n",
1555 co
, (int)sizeof(int *)*bits_per_byte
,
1556 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1558 Vprintf("%sfunc*=%d bits%s%s\n",
1559 co
, (int)sizeof(function
*)*bits_per_byte
,
1560 sizeof(function
*)>sizeof(int)?" BEWARE! larger than int!":"",
1562 if (V
) printf ("%s%s %s %s%s\n", co
, "Type size_t is",
1563 ((((false()?( sizeof(int)):(-1)) < 0) )?
1564 "signed":"unsigned") ,
1570 showtype("Type size_t is", sizeof(0));
1572 /* Alignment constants ********************************************/
1574 #define alignment(TYPE) \
1575 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *) 0))
1577 Vprintf("\n%sALIGNMENTS%s\n", co
, oc
);
1579 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1581 alignment(char), alignment(short),
1582 alignment(int), alignment(long),
1585 Vprintf("%sfloat=%ld double=%ld%s\n",
1587 alignment(float), alignment(double),
1591 Vprintf("%slong double=%ld%s\n",
1593 alignment(Long_double
),
1596 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1598 alignment(char *), alignment(int *), alignment(function
*),
1603 /* Ten little endians *********************************************/
1605 endian(bits_per_byte
);
1607 /* Pointers *******************************************************/
1609 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co
, oc
);
1611 if ((long) (char *) &variable
== (long) (int *) &variable
) {
1612 Vprintf("%sChar and int pointer formats seem identical%s\n",
1615 Vprintf("%sChar and int pointer formats are different%s\n",
1618 if ((long) (char *) &variable
== (long) (function
*) &variable
) {
1619 Vprintf("%sChar and function pointer formats seem identical%s\n",
1622 Vprintf("%sChar and function pointer formats are different%s\n",
1628 printf("%sStrings are shared%s\n", co
, oc
);
1629 else printf("%sStrings are not shared%s\n", co
, oc
);
1633 showtype("Type ptrdiff_t is", p
-q
);
1635 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co
, oc
);
1648 return bits_per_byte
;
1651 #else /* not PASS0 */
1655 extern int V
, L
, F
, bugs
, bits_per_byte
;
1656 extern char co
[], oc
[];
1657 extern char *f_rep();
1659 #endif /* ifdef PASS0 */
1661 /* As I said, I apologise for the contortions below. The functions are
1662 expanded by the preprocessor twice or three times (for float and double,
1663 and maybe for long double, and for short, int and long). That way,
1664 I never make a change to one that I forget to make to the other.
1665 You can look on it as C's fault for not supporting multi-line macro's.
1666 This whole file is read 3 times by the preprocessor, with PASSn set for
1667 n=1, 2 or 3, to decide which parts to reprocess.
1670 /* #undef on an already undefined thing is (wrongly) flagged as an error
1671 by some compilers, therefore the #ifdef that follows:
1697 /* These are the float.h constants */
1728 /* Define the things we're going to use this pass */
1730 #define Number float
1731 #define THING "FLOAT"
1732 #define Thing "Float"
1733 #define thing "float"
1736 #define Store fStore
1748 #define F_check fCheck
1751 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1754 #define EPROP efprop
1756 #define Integer short
1759 #define Iname "SHRT"
1765 #define UPROP usprop
1766 #define Uname "USHRT"
1769 #define I_MAX SHRT_MAX
1772 #define I_MIN SHRT_MIN
1775 #define U_MAX USHRT_MAX
1779 #define F_RADIX FLT_RADIX
1782 #define F_MANT_DIG FLT_MANT_DIG
1785 #define F_DIG FLT_DIG
1788 #define F_ROUNDS FLT_ROUNDS
1791 #define F_EPSILON FLT_EPSILON
1794 #define F_MIN_EXP FLT_MIN_EXP
1797 #define F_MIN FLT_MIN
1799 #ifdef FLT_MIN_10_EXP
1800 #define F_MIN_10_EXP FLT_MIN_10_EXP
1803 #define F_MAX_EXP FLT_MAX_EXP
1806 #define F_MAX FLT_MAX
1808 #ifdef FLT_MAX_10_EXP
1809 #define F_MAX_10_EXP FLT_MAX_10_EXP
1816 #define Number double
1817 #define THING "DOUBLE"
1818 #define Thing "Double"
1819 #define thing "double"
1822 #define Store dStore
1834 #define F_check dCheck
1837 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1840 #define EPROP edprop
1846 #define OK_UI 1 /* Unsigned int is always possible */
1849 #define UPROP uiprop
1850 #define Uname "UINT"
1853 #define I_MAX INT_MAX
1856 #define I_MIN INT_MIN
1859 #define U_MAX UINT_MAX
1863 #define F_MANT_DIG DBL_MANT_DIG
1866 #define F_DIG DBL_DIG
1869 #define F_EPSILON DBL_EPSILON
1872 #define F_MIN_EXP DBL_MIN_EXP
1875 #define F_MIN DBL_MIN
1877 #ifdef DBL_MIN_10_EXP
1878 #define F_MIN_10_EXP DBL_MIN_10_EXP
1881 #define F_MAX_EXP DBL_MAX_EXP
1884 #define F_MAX DBL_MAX
1886 #ifdef DBL_MAX_10_EXP
1887 #define F_MAX_10_EXP DBL_MAX_10_EXP
1895 #define Number long double
1905 #define THING "LONG DOUBLE"
1906 #define Thing "Long double"
1907 #define thing "long double"
1908 #define Fname "LDBL"
1909 #define FPROP ldprop
1910 #define Store ldStore
1916 #define F_check ldCheck
1919 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1922 #define EPROP eldprop
1924 #define Integer long
1927 #define Iname "LONG"
1933 #define UPROP ulprop
1934 #define Uname "ULONG"
1937 #define I_MAX LONG_MAX
1940 #define I_MIN LONG_MIN
1943 #define U_MAX ULONG_MAX
1946 #ifdef LDBL_MANT_DIG
1947 #define F_MANT_DIG LDBL_MANT_DIG
1950 #define F_DIG LDBL_DIG
1953 #define F_EPSILON LDBL_EPSILON
1956 #define F_MIN_EXP LDBL_MIN_EXP
1959 #define F_MIN LDBL_MIN
1961 #ifdef LDBL_MIN_10_EXP
1962 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1965 #define F_MAX_EXP LDBL_MAX_EXP
1968 #define F_MAX LDBL_MAX
1970 #ifdef LDBL_MAX_10_EXP
1971 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1976 #define UNDEFINED (-2)
1979 #define I_MAX ((unsigned long) UNDEFINED)
1982 #define I_MIN ((unsigned long) UNDEFINED)
1985 #define U_MAX ((unsigned long) UNDEFINED)
1989 #define F_RADIX UNDEFINED
1992 #define F_MANT_DIG UNDEFINED
1995 #define F_DIG UNDEFINED
1998 #define F_ROUNDS UNDEFINED
2001 #define F_EPSILON ((Number) UNDEFINED)
2004 #define F_MIN_EXP UNDEFINED
2007 #define F_MIN ((Number) UNDEFINED)
2009 #ifndef F_MIN_10_EXP
2010 #define F_MIN_10_EXP UNDEFINED
2013 #define F_MAX_EXP UNDEFINED
2016 #define F_MAX ((Number) UNDEFINED)
2018 #ifndef F_MAX_10_EXP
2019 #define F_MAX_10_EXP UNDEFINED
2023 #define Validate(prec, val, req, same) {;}
2029 /* the properties of short, int, and long */
2030 Volatile Integer newi
, int_max
, maxeri
, int_min
, minneri
;
2031 Volatile
int ibits
, ipower
, two
=2;
2033 /* Calculate max short/int/long ***********************************/
2034 /* Calculate 2**n-1 until overflow - then use the previous value */
2038 if (setjmp(lab
)==0) { /* Yields int_max */
2039 for(ipower
=0; newi
>int_max
; ipower
++) {
2043 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2044 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2046 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2047 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2051 /* Minimum value: assume either two's or one's complement *********/
2053 if (setjmp(lab
)==0) { /* Yields int_min */
2054 if (int_min
-1 < int_min
) int_min
--;
2058 /* Now for those daft Cybers */
2060 maxeri
=0; newi
=int_max
;
2062 if (setjmp(lab
)==0) { /* Yields maxeri */
2063 for(ibits
=ipower
; newi
>maxeri
; ibits
++) {
2071 if (setjmp(lab
)==0) { /* Yields minneri */
2072 if (minneri
-1 < minneri
) minneri
--;
2076 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2077 co
, INT
, (long)int_max
, ipower
, oc
);
2078 Vprintf("%sMinimum %s = %ld%s\n", co
, INT
, (long)int_min
, oc
);
2080 if (L
) i_define(D_INT_MAX
, INT
, Iname
, "_MAX",
2082 (long) I_MAX
, IMARK
);
2083 if (L
) i_define(D_INT_MIN
, INT
, Iname
, "_MIN",
2084 (long) int_min
, (long) (PASS
==1?maxint
:int_max
),
2085 (long) I_MIN
, IMARK
);
2087 if(int_max
< 0) { /* It has happened */
2088 eek_a_bug("signed integral comparison faulty?");
2091 if (maxeri
>int_max
) {
2092 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2093 co
, INT
, (long)maxeri
, ibits
,
2094 "but only for addition, not multiplication",
2095 "(I smell a Cyber!)",
2099 if (minneri
<int_min
) {
2100 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2101 co
, INT
, (long)minneri
,
2102 "but only for addition, not multiplication",
2103 "(I smell a Cyber!)",
2108 Procedure
UPROP () {
2109 /* The properties of unsigned short/int/long */
2111 Volatile
unsigned Integer u_max
, newi
, two
;
2112 newi
=1; u_max
=0; two
=2;
2114 if (setjmp(lab
)==0) { /* Yields u_max */
2121 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2122 co
, INT
, (unsigned long) u_max
, oc
);
2124 /* Oh woe: new standard C defines value preserving promotions */
2126 if (PASS
== 1 && sizeof(short) < sizeof(int)) {
2127 /* Special only for short */
2128 i_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2129 (unsigned long) u_max
, 0L,
2130 (unsigned long) U_MAX
, IMARK
);
2132 u_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2133 (unsigned long) u_max
,
2134 (unsigned long) U_MAX
, IMARK
);
2140 #endif /* Integer */
2144 /* The following routines are intended to defeat any attempt at optimisation
2145 or use of extended precision, and to defeat faulty narrowing casts.
2146 The weird prototypes are because of widening incompatibilities.
2149 #define ARGS1(atype, a) (atype a)
2150 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2152 #define ARGS1(atype, a) (a) atype a;
2153 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2156 Procedure Store
ARGS2(Number
, a
, Number
*, b
) { *b
=a
; }
2157 Number Sum
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
+b
, &r
); return (r
); }
2158 Number Diff
ARGS2(Number
, a
, Number
, b
){Number r
; Store(a
-b
, &r
); return (r
); }
2159 Number Mul
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
*b
, &r
); return (r
); }
2160 Number Div
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
/b
, &r
); return (r
); }
2161 Number Self
ARGS1(Number
, a
) {Number r
; Store(a
, &r
); return (r
); }
2163 Procedure F_check
ARGS((int precision
, Long_double val1
));
2165 Procedure
F_check(precision
, val1
) int precision
; Long_double val1
; {
2166 /* You don't think I'm going to go to all the trouble of writing
2167 a program that works out what all sorts of values are, only to
2168 have printf go and print the wrong values out, do you?
2169 No, you're right, so this function tries to see if printf
2170 has written the right value, by reading it back again.
2171 This introduces a new problem of course: suppose printf writes
2172 the correct value, and scanf reads it back wrong... oh well.
2173 But I'm adamant about this: the precision given is enough
2174 to uniquely identify the printed number, therefore I insist
2175 that sscanf read the number back identically. Harsh yes, but
2176 sometimes you've got to be cruel to be kind.
2178 Number val
, new, diff
;
2184 #ifdef NO_LONG_DOUBLE_IO
2186 /* On the Sun 3, sscanf clobbers 4 words,
2187 which leads to a crash when this function tries to return. */
2188 f2
= "%le"; /* Input */
2189 /* It is no use checking long doubles if we can't
2190 read and write them. */
2191 if (sizeof (Number
) > sizeof(double))
2195 if (sizeof(double) == sizeof(Long_double
)) {
2196 /* Assume they're the same, and use non-stdc format */
2197 /* This is for stdc compilers using non-stdc libraries */
2198 f2
= "%le"; /* Input */
2200 /* It had better support Le then */
2205 rep
= f_rep(precision
, (Long_double
) val
);
2206 if (setjmp(lab
)==0) {
2207 sscanf(rep
, f2
, &new1
);
2209 eek_a_bug("sscanf caused a trap");
2210 printf("%s scanning: %s format: %s%s\n\n", co
, rep
, f2
, oc
);
2215 if (setjmp(lab
)==0) { /* See if new is usable */
2218 diff
= val
/new - 1.0;
2219 if (diff
< 0.1) diff
= 1.0;
2220 /* That should be enough to generate a trap */
2223 eek_a_bug("sscanf returned an unusable number");
2224 printf("%s scanning: %s with format: %s%s\n\n",
2232 eek_a_bug("Possibly bad output from printf above");
2233 if (!exponent((Long_double
)val
, &rem
, &e
)) {
2234 printf("%s but value was an unusable number%s\n\n",
2238 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2239 co
, precision
, rem
, e
);
2240 bitpattern((char *) &val
, (unsigned)sizeof(val
));
2241 printf ("%s\n", oc
);
2242 printf("%s sscanf gave %s, bit pattern:\n ",
2243 co
, f_rep(precision
, (Long_double
) new));
2244 bitpattern((char *) &new, (unsigned)sizeof(new));
2245 printf ("%s\n", oc
);
2246 if (setjmp(lab
) == 0) {
2248 printf("%s difference= %s%s\n\n",
2249 co
, f_rep(precision
, (Long_double
) diff
), oc
);
2250 } /* else forget it */
2256 Procedure
Validate(prec
, val
, req
, same
) int prec
, same
; Long_double val
, req
; {
2257 /* Check that the compiler has read a #define value correctly */
2260 printf("%s*** Verify failed for above #define!\n", co
);
2261 if (setjmp(lab
) == 0) { /* for the case that req == nan */
2262 printf(" Compiler has %s for value%s\n",
2263 f_rep(prec
, req
), oc
);
2265 printf(" Compiler has %s for value%s\n",
2266 "an unusable number", oc
);
2268 if (setjmp(lab
) == 0) {
2269 F_check(prec
, (Long_double
) req
);
2270 } /*else forget it*/
2271 if (setjmp(lab
) == 0) {
2272 if (req
> 0.0 && val
> 0.0) {
2273 printf("%s difference= %s%s\n",
2274 co
, f_rep(prec
, val
-req
), oc
);
2276 } /*else forget it*/
2280 } else if (val
!= req
) {
2281 if (stdc
) eek_a_bug("constant has the wrong precision");
2282 else eek_a_bug("the cast didn't work");
2288 int FPROP(bits_per_byte
) int bits_per_byte
; {
2289 /* Properties of floating types, using algorithms by Cody and Waite
2290 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2291 Further extended by S Pemberton.
2293 Returns the number of digits in the fraction.
2297 i
, f_radix
, iexp
, irnd
, mrnd
, f_rounds
, f_mant_dig
,
2298 iz
, k
, inf
, machep
, f_max_exp
, f_min_exp
, mx
, negeps
,
2299 mantbits
, digs
, f_dig
, trap
,
2300 hidden
, normal
, f_min_10_exp
, f_max_10_exp
;
2302 a
, b
, base
, basein
, basem1
, f_epsilon
, epsneg
,
2303 eps
, epsp1
, etop
, ebot
,
2304 f_max
, newxmax
, f_min
, xminner
, y
, y1
, z
, z1
, z2
;
2308 Vprintf("%sPROPERTIES OF %s%s\n", co
, THING
, oc
);
2310 /* Base and size of significand **************************************/
2311 /* First repeatedly double until adding 1 has no effect. */
2312 /* For instance, if base is 10, with 3 significant digits */
2313 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2314 /* since 1024 is only representable as 1020. */
2316 if (setjmp(lab
)==0) { /* inexact trap? */
2318 while (Diff(Diff(Sum(a
, ONE
), a
), ONE
) == ZERO
);
2320 fprintf(stderr
, "*** Program got loss-of-precision trap!\n");
2321 /* And supporting those is just TOO much trouble! */
2325 /* Now double until you find a number that can be added to the */
2326 /* above number. For 1020 this is 8 or 16, depending whether the */
2327 /* result is rounded or truncated. */
2328 /* In either case the result is 1030. 1030-1020= the base, 10. */
2330 do { b
=Sum(b
, b
); } while ((base
=Diff(Sum(a
, b
), a
)) == ZERO
);
2332 Vprintf("%sBase = %d%s\n", co
, f_radix
, oc
);
2334 /* Sanity check; if base<2, I can't guarantee the rest will work */
2336 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2341 if (PASS
== 1) { /* only for FLT */
2343 if (F
) i_define(D_FLT_RADIX
, "", "FLT", "_RADIX",
2344 (long) f_radix
, 0L, (long) F_RADIX
, "");
2345 } else if (f_radix
!= flt_radix
) {
2346 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2347 co
, thing
, "arithmetic has a different radix",
2348 f_radix
, "from float", oc
);
2352 /* Now the number of digits precision */
2353 f_mant_dig
=0; b
=1.0;
2354 do { f_mant_dig
++; b
=Mul(b
, base
); }
2355 while (Diff(Diff(Sum(b
, ONE
), b
), ONE
) == ZERO
);
2356 f_dig
=floor_log(10, (Long_double
)(b
/base
)) + (base
==10?1:0);
2357 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2358 co
, f_mant_dig
, "(= at least", f_dig
, "decimal digits)", oc
);
2359 if (F
) i_define(D_MANT_DIG
, thing
, Fname
, "_MANT_DIG",
2360 (long) f_mant_dig
, 0L, (long) F_MANT_DIG
, "");
2361 if (F
) i_define(D_DIG
, thing
, Fname
, "_DIG",
2362 (long) f_dig
, 0L, (long) F_DIG
, "");
2363 digs
= ceil_log(10, (Long_double
)b
); /* the number of digits to printf */
2365 /* Rounding *******************************************************/
2366 basem1
=Diff(base
, HALF
);
2367 if (Diff(Sum(a
, basem1
), a
) != ZERO
) {
2368 if (f_radix
== 2) basem1
=0.375;
2370 if (Diff(Sum(a
, basem1
), a
) != ZERO
) irnd
=2; /* away from 0 */
2371 else irnd
=1; /* to nearest */
2372 } else irnd
=0; /* towards 0 */
2374 basem1
=Diff(base
, HALF
);
2376 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) {
2377 if (f_radix
== 2) basem1
=0.375;
2379 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) mrnd
=2; /* away from 0*/
2380 else mrnd
=1; /* to nearest */
2381 } else mrnd
=0; /* towards 0 */
2383 f_rounds
= -1; /* Unknown rounding */
2384 if (irnd
==0 && mrnd
==0) f_rounds
=0; /* zero = chops */
2385 if (irnd
==1 && mrnd
==1) f_rounds
=1; /* nearest */
2386 if (irnd
==2 && mrnd
==0) f_rounds
=2; /* +inf */
2387 if (irnd
==0 && mrnd
==2) f_rounds
=3; /* -inf */
2389 if (f_rounds
!= -1) {
2390 Vprintf("%sArithmetic rounds towards ", co
);
2392 case 0: Vprintf("zero (i.e. it chops)"); break;
2393 case 1: Vprintf("nearest"); break;
2394 case 2: Vprintf("+infinity"); break;
2395 case 3: Vprintf("-infinity"); break;
2396 default: Vprintf("???"); break;
2398 Vprintf("%s\n", oc
);
2399 } else { /* Hmm, try to give some help here */
2400 Vprintf("%sArithmetic rounds oddly: %s\n", co
, oc
);
2401 Vprintf("%s Negative numbers %s%s\n",
2402 co
, mrnd
==0 ? "towards zero" :
2403 mrnd
==1 ? "to nearest" :
2406 Vprintf("%s Positive numbers %s%s\n",
2407 co
, irnd
==0 ? "towards zero" :
2408 irnd
==1 ? "to nearest" :
2412 /* An extra goody */
2413 if (f_radix
== 2 && f_rounds
== 1) {
2414 if (Diff(Sum(a
, ONE
), a
) != ZERO
) {
2415 Vprintf("%s Tie breaking rounds up%s\n", co
, oc
);
2416 } else if (Diff(Sum(a
, THREE
), a
) == FOUR
) {
2417 Vprintf("%s Tie breaking rounds to even%s\n", co
, oc
);
2419 Vprintf("%s Tie breaking rounds down%s\n", co
, oc
);
2422 if (PASS
== 1) { /* only for FLT */
2423 flt_rounds
= f_rounds
;
2424 /* Prefer system float.h definition of F_ROUNDS,
2425 since it's more likely to be right than our "1". */
2426 if (F
&& (!SYS_FLOAT_H_WRAP
|| F_ROUNDS
== UNDEFINED
))
2427 i_define(D_FLT_ROUNDS
, "", "FLT", "_ROUNDS",
2428 (long) f_rounds
, 1L, (long) F_ROUNDS
, "");
2429 } else if (f_rounds
!= flt_rounds
) {
2430 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2431 co
, thing
, "arithmetic rounds differently",
2432 f_rounds
, "from float", oc
);
2436 /* Various flavours of epsilon ************************************/
2437 negeps
=f_mant_dig
+f_mant_dig
;
2440 for(i
=1; i
<=negeps
; i
++) a
*=basein
;
2443 while (Diff(Diff(ONE
, a
), ONE
) == ZERO
) {
2448 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2453 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2454 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2455 ebot and etop are the current bounds */
2456 while (eps
!= ebot
&& eps
!= etop
) {
2457 epsp1
= Diff(ONE
, eps
);
2458 if (epsp1
< ONE
) etop
= eps
;
2460 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2464 if (Diff(ONE
, etop
) >= ONE
|| Diff(ONE
, ebot
) != ONE
) {
2465 eek_a_bug("internal error calculating epsneg");
2467 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2468 co
, f_rep(digs
, (Long_double
) eps
), oc
);
2469 if (V
) F_check(digs
, (Long_double
) eps
);
2472 if ((f_radix
!=2) && irnd
) {
2473 /* a=(a*(1.0+a))/(1.0+1.0); => */
2474 a
=Div(Mul(a
, Sum(ONE
, a
)), Sum(ONE
, ONE
));
2475 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2476 if (Diff(Diff(ONE
, a
), ONE
) != ZERO
) epsneg
=a
;
2478 /* epsneg is used later */
2481 machep
= -f_mant_dig
-f_mant_dig
;
2483 while (Diff(Sum(ONE
, a
), ONE
) == ZERO
) { a
*=base
; machep
++; }
2484 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2489 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2490 /* find the smallest eps (1+eps != 1) by binary search.
2491 ebot and etop are the current bounds */
2492 while (eps
!= ebot
&& eps
!= etop
) {
2493 epsp1
= Sum(ONE
, eps
);
2494 if (epsp1
> ONE
) etop
= eps
;
2496 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2499 if (Sum(ONE
, etop
) <= ONE
|| Sum(ONE
, ebot
) != ONE
) {
2500 eek_a_bug("internal error calculating eps");
2504 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2505 co
, f_rep(digs
, (Long_double
) f_epsilon
), oc
);
2507 f_epsilon
= Diff(Sum(ONE
, f_epsilon
), ONE
); /* New C standard defn */
2508 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2509 co
, f_rep(digs
, (Long_double
) (f_epsilon
)), oc
);
2511 /* Possible loss of precision warnings here from non-stdc compilers */
2512 if (F
) f_define(D_EPSILON
, thing
,
2513 Fname
, "_EPSILON", digs
,
2514 (Long_double
) f_epsilon
,
2515 (Long_double
) F_EPSILON
, MARK
);
2516 if (V
|| F
) F_check(digs
, (Long_double
) f_epsilon
);
2518 if (F
) Validate(digs
, (Long_double
) f_epsilon
, (Long_double
) F_EPSILON
,
2519 f_epsilon
== Self(F_EPSILON
));
2522 /* Extra chop info *************************************************/
2523 if (f_rounds
== 0) {
2524 if (Diff(Mul(Sum(ONE
,f_epsilon
),ONE
),ONE
) != ZERO
) {
2525 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co
, oc
);
2529 /* Size of and minimum normalised exponent ************************/
2530 y
=0; i
=0; k
=1; z
=basein
; z1
=(1.0+f_epsilon
)/base
;
2532 /* Coarse search for the largest power of two */
2533 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2536 z
=Mul(y
,y
); z1
=Mul(z1
, y
);
2539 if (z2
!= y1
) break;
2540 if ((Sum(a
,a
) == ZERO
) || (fabs(z
) >= y
)) break;
2545 Vprintf("%s%s underflow generates a trap%s\n", co
, Thing
, oc
);
2549 if (f_radix
!= 10) {
2550 iexp
=i
+1; /* for the sign */
2555 while (k
>= iz
) { iz
*=f_radix
; iexp
++; }
2559 /* Fine tune starting with y and y1 */
2560 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields k, f_min */
2563 y
=Div(y
,base
); y1
=Div(y1
,base
);
2566 if (z2
!= z1
) break;
2567 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= f_min
)) break;
2575 if ((mx
<= k
+k
-3) && (f_radix
!= 10)) { mx
+=mx
; iexp
+=1; }
2576 Vprintf("%sNumber of bits used for exponent = %d%s\n", co
, iexp
, oc
);
2577 Vprintf("%sMinimum normalised exponent = %d%s\n", co
, f_min_exp
-1, oc
);
2579 i_define(D_MIN_EXP
, thing
, Fname
, "_MIN_EXP",
2580 (long) f_min_exp
, (long) maxint
, (long) F_MIN_EXP
, "");
2582 if (setjmp(lab
)==0) {
2583 Vprintf("%sMinimum normalised positive number = %s%s\n",
2584 co
, f_rep(digs
, (Long_double
) f_min
), oc
);
2586 eek_a_bug("printf can't print the smallest normalised number");
2590 /* Possible loss of precision warnings here from non-stdc compilers */
2591 if (setjmp(lab
) == 0) {
2592 if (F
) f_define(D_MIN
, thing
,
2593 Fname
, "_MIN", digs
,
2594 (Long_double
) f_min
,
2595 (Long_double
) F_MIN
, MARK
);
2596 if (V
|| F
) F_check(digs
, (Long_double
) f_min
);
2598 eek_a_bug("xxx_MIN caused a trap");
2602 if (setjmp(lab
) == 0) {
2603 if (F
) Validate(digs
, (Long_double
) f_min
, (Long_double
) F_MIN
,
2604 f_min
== Self(F_MIN
));
2606 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2607 co
, "Compiler has an unusable number for value", oc
);
2612 a
=1.0; f_min_10_exp
=0;
2613 while (a
> f_min
*10.0) { a
/=10.0; f_min_10_exp
--; }
2614 if (F
) i_define(D_MIN_10_EXP
, thing
, Fname
, "_MIN_10_EXP",
2615 (long) f_min_10_exp
, (long) maxint
,
2616 (long) F_MIN_10_EXP
, "");
2618 /* Minimum exponent ************************************************/
2619 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields xminner */
2624 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= xminner
)) break;
2629 if (xminner
!= 0.0 && xminner
!= f_min
) {
2631 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2633 if (setjmp(lab
)==0) {
2634 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2635 co
, f_rep(digs
, (Long_double
) xminner
), oc
);
2636 if (V
) F_check(digs
, (Long_double
) xminner
);
2638 eek_a_bug("printf can't print the smallest unnormalised number.");
2644 Vprintf("%sThe smallest numbers are normalised%s\n", co
, oc
);
2647 /* Maximum exponent ************************************************/
2648 f_max_exp
=2; f_max
=1.0; newxmax
=base
+1.0;
2650 while (f_max
<newxmax
) {
2652 if (setjmp(lab
) == 0) { /* Yields inf, f_max_exp */
2653 newxmax
=Mul(newxmax
, base
);
2658 if (Div(newxmax
, base
) != f_max
) {
2659 inf
=1; /* ieee infinity */
2666 Vprintf("%s%s overflow generates a trap%s\n", co
, Thing
, oc
);
2669 if (inf
) Vprintf("%sThere is an 'infinite' value%s\n", co
, oc
);
2670 Vprintf("%sMaximum exponent = %d%s\n", co
, f_max_exp
, oc
);
2671 if (F
) i_define(D_MAX_EXP
, thing
, Fname
, "_MAX_EXP",
2672 (long) f_max_exp
, 0L, (long) F_MAX_EXP
, "");
2674 /* Largest number ***************************************************/
2675 f_max
=Diff(ONE
, epsneg
);
2676 if (Mul(f_max
,ONE
) != f_max
) f_max
=Diff(ONE
, Mul(base
,epsneg
));
2677 for (i
=1; i
<=f_max_exp
; i
++) f_max
=Mul(f_max
, base
);
2679 if (setjmp(lab
)==0) {
2680 Vprintf("%sMaximum number = %s%s\n",
2681 co
, f_rep(digs
, (Long_double
) f_max
), oc
);
2683 eek_a_bug("printf can't print the largest double.");
2686 if (setjmp(lab
)==0) {
2687 /* Possible loss of precision warnings here from non-stdc compilers */
2688 if (F
) f_define(D_MAX
, thing
,
2689 Fname
, "_MAX", digs
,
2690 (Long_double
) f_max
,
2691 (Long_double
) F_MAX
, MARK
);
2692 if (V
|| F
) F_check(digs
, (Long_double
) f_max
);
2694 eek_a_bug("xxx_MAX caused a trap");
2697 if (setjmp(lab
)==0) {
2698 if (F
) Validate(digs
, (Long_double
) f_max
, (Long_double
) F_MAX
,
2699 f_max
== Self(F_MAX
));
2701 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2702 co
, "Compiler has an unusable number for value", oc
);
2707 a
=1.0; f_max_10_exp
=0;
2708 while (a
< f_max
/10.0) { a
*=10.0; f_max_10_exp
++; }
2709 if (F
) i_define(D_MAX_10_EXP
, thing
, Fname
, "_MAX_10_EXP",
2710 (long) f_max_10_exp
, 0L, (long) F_MAX_10_EXP
, "");
2712 /* Hidden bit + sanity check ****************************************/
2713 if (f_radix
!= 10) {
2715 mantbits
=floor_log(2, (Long_double
)f_radix
)*f_mant_dig
;
2718 && f_max_exp
+f_min_exp
> 0 /* ??? f_min_exp may be wrong. */
2719 && mantbits
+iexp
+17 == (int)sizeof(Number
)*bits_per_byte
) {
2720 Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co
, oc
);
2721 Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co
, oc
);
2724 if (mantbits
+iexp
== (int)sizeof(Number
)*bits_per_byte
) {
2726 Vprintf("%sArithmetic uses a hidden bit%s\n", co
, oc
);
2727 } else if (mantbits
+iexp
+1 == (int)sizeof(Number
)*bits_per_byte
) {
2728 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2731 printf("\n%s%s\n %s %s %s!%s\n\n",
2733 "*** Something fishy here!",
2734 "Exponent size + significand size doesn't match",
2735 "with the size of a", thing
,
2738 if (hidden
&& f_radix
== 2 && f_max_exp
+f_min_exp
==3) {
2739 Vprintf("%sIt looks like %s length IEEE format%s\n",
2740 co
, f_mant_dig
==24 ? "single" :
2741 f_mant_dig
==53 ? "double" :
2742 f_mant_dig
>53 ? "extended" :
2745 if (f_rounds
!= 1 || normal
) {
2746 Vprintf("%s though ", co
);
2747 if (f_rounds
!= 1) {
2748 Vprintf("the rounding is unusual");
2749 if (normal
) Vprintf(" and ");
2751 if (normal
) Vprintf("the normalisation is unusual");
2752 Vprintf("%s\n", oc
);
2755 Vprintf("%sIt doesn't look like IEEE format%s\n",
2759 printf("\n"); /* regardless of verbosity */
2763 Procedure
EPROP(fprec
, dprec
, lprec
) int fprec
, dprec
, lprec
; {
2764 /* See if expressions are evaluated in extended precision.
2765 Some compilers optimise even if you don't want it,
2766 and then this function fails to produce the right result.
2767 We try to diagnose this if it happens.
2770 Volatile
double a
, b
, base
, old
;
2771 Volatile Number d
, oldd
, dbase
, one
, zero
;
2774 /* Size of significand **************************************/
2776 if (setjmp(lab
) == 0) { /* Yields nothing */
2777 do { old
=a
; a
=a
+a
; }
2778 while ((((a
+1.0)-a
)-1.0) == 0.0 && a
>old
);
2781 /* Avoid the comparison if bad is set,
2782 to avoid trouble on the convex. */
2783 if (!bad
&& (a
<= old
)) bad
=1;
2787 if (setjmp(lab
) == 0) { /* Yields nothing */
2788 do { old
=b
; b
=b
+b
; }
2789 while ((base
=((a
+b
)-a
)) == 0.0 && b
>old
);
2790 if (b
<= old
) bad
=1;
2795 eprec
=0; d
=1.0; dbase
=base
; one
=1.0; zero
=0.0;
2796 if (setjmp(lab
) == 0) { /* Yields nothing */
2797 do { eprec
++; oldd
=d
; d
=d
*dbase
; }
2798 while ((((d
+one
)-d
)-one
) == zero
&& d
>oldd
);
2799 if (d
<= oldd
) bad
=1;
2806 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2807 co
, thing
, " check that you compiled without optimisation!",
2809 } else if (eprec
==dprec
) {
2810 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2812 } else if (eprec
==fprec
) {
2813 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2815 } else if (eprec
==lprec
) {
2816 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2819 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2820 co
, Thing
, eprec
>dprec
? "higher" : "lower",
2821 "precision than double,\n using",
2822 eprec
, "base digits",
2827 #else /* not Number */
2829 #ifdef FPROP /* Then create dummy routines for long double */
2831 int FPROP(bits_per_byte
) int bits_per_byte
; { return 0; }
2835 Procedure
EPROP(fprec
, dprec
, lprec
) int fprec
, dprec
, lprec
; {}
2838 #endif /* ifdef Number */
2840 /* Increment the pass number */
2859 #ifdef PASS /* then rescan this file */
2861 #include "enquire.c"
2863 #include FILENAME /* if this line fails to compile, define NO_FILE */