1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9 Bugfixes and upgrades gratefully received.
11 Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
14 Changes by Richard Stallman:
15 Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
16 In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
17 Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
18 Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
19 Include sys/types.h before signal.h, Apr 92.
20 Support NO_LONG_DOUBLE_IO in f_define and f_rep; new fn fake_f_rep, Apr 92.
21 Enclose -f output in #ifndef _FLOAT_H___, Richard Stallman, May 92.
23 Add #undef before every #define, Jim Wilson, Dec 92.
25 Changes by Paul Eggert, installed Feb 93:
26 (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
27 (f_define): Use ordinary constants for long double
28 if it's same width as double. Make __convert_long_double_i unsigned.
31 With luck and a following wind, just the following will work:
32 cc enquire.c -o enquire
33 You may get some messages about unreachable code, which you can ignore.
35 If your compiler doesn't support: add flag:
36 signed char (eg pcc) -DNO_SC
38 unsigned short and long -DNO_UI
40 signal(), or setjmp/longjmp() -DNO_SIG
41 %Lf in printf -DNO_LONG_DOUBLE_IO
43 Try to compile first with no flags, and see if you get any errors -
44 you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
45 Some compilers need a -f flag for floating point.
47 Don't use any optimisation flags: the program may not work if you do.
48 Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
49 optimiser, to a floating-point unit there's a world of difference.
51 Some compilers offer various flags for different floating point
52 modes; it's worth trying all possible combinations of these.
54 Add -DID=\"name\" if you want the machine/flags identified in the output.
57 Because of bugs and/or inadequacies, some compilers need the following
60 If your C preprocessor doesn't have the predefined __FILE__ macro, and
61 you don't want to call this file enquire.c but, say, tell.c, add the
62 flag -DFILENAME=\"tell.c\" .
64 Some compilers won't accept the line "#include FILENAME".
65 Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
67 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
68 or -DNO_FILE as above.
70 Some naughty compilers define __STDC__, but don't really support it.
71 Some define it as 0, in which case we treat it as undefined.
72 But if your compiler defines it, and isn't really ANSI C,
73 add flag -DNO_STDC. (To those compiler writers: for shame).
75 Some naughty compilers define __STDC__, but don't have the stddef.h
76 include file. Add flag -DNO_STDDEF.
78 Summary of naughty-compiler flags:
79 If your compiler doesn't support: add flag:
80 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
81 #ifdef __FILE__ -DNO_FILE or -DFILENAME=...
82 #include FILENAME -DNO_FILE
83 __STDC__ (properly) -DNO_STDC
86 Some systems crash when you try to malloc all store. To save users of
87 such defective systems too much grief, they may compile with -DNO_MEM,
88 which ignores that bit of the code.
90 While it is not our policy to support defective compilers, pity has been
91 taken on people with compilers that can't produce object files bigger than
92 32k (especially since it was an easy addition). Compile the program
93 into separate parts like this:
94 cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
95 cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
96 cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
97 cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
98 cc -o enquire p0.o p1.o p2.o p3.o
101 You may possibly need to add some calls to signal() for other sorts of
102 exception on your machine than SIGFPE, and SIGOVER. See lines beginning
103 #ifdef SIGxxx in main() (and communicate the differences to me!).
106 Run without argument to get the information as English text. If run
107 with argument -l (e.g. enquire -l), output is a series of #define's for
108 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
109 with argument -f, output is a series of #define's for the ANSI standard
110 float.h include file (according to ANSI C Draft of Dec 7, 1988).
111 Flag -v gives verbose output: output includes the English text above
112 as C comments. The program exit(0)'s if everything went ok, otherwise
113 it exits with a positive number, telling how many problems there were.
115 VERIFYING THE COMPILER
116 If, having produced the float.h and limits.h header files, you want to
117 verify that the compiler reads them back correctly (there are a lot of
118 boundary cases, of course, like minimum and maximum numbers), you can
119 recompile enquire.c with -DVERIFY set (plus the other flags that you used
120 when compiling the version that produced the header files). This then
121 recompiles the program so that it #includes "limits.h" and "float.h",
122 and checks that the constants it finds there are the same as the
123 constants it produces. Run the resulting program with enquire -fl.
124 Very few compilers have passed without error.
125 NB: You *must* recompile with the same compiler and flags, otherwise
126 you may get odd results.
128 You can also use this option if your compiler already has both files,
129 and you want to confirm that this program produces the right results.
132 This program is now quite trustworthy, and suspicious and wrong output
133 may well be caused by bugs in the compiler, not in the program (however
134 of course, this is not guaranteed, and no responsibility can be
137 The program only works if overflows are ignored by the C system or
138 are catchable with signal().
140 If the program fails to run to completion (often with the error message
141 "Unexpected signal at point x"), this often turns out to be a bug in the
142 C compiler's run-time system. Check what was about to be printed, and
143 try to narrow the problem down.
145 Another possible problem is that you have compiled the program to produce
146 loss-of-precision arithmetic traps. The program cannot cope with these,
147 and you should re-compile without them. (They should never be the default).
149 Make sure you compiled with optimisation turned off.
151 Output preceded by *** WARNING: identifies behaviour of the C system
152 deemed incorrect by the program. Likely problems are that printf or
153 scanf don't cope properly with certain boundary numbers: this program
154 goes to a lot of trouble to calculate its values, and these values
155 are mostly boundary numbers. Experience has shown that often printf
156 cannot cope with these values, and so in an attempt to increase
157 confidence in the output, for each float and double that is printed,
158 the printed value is checked by using sscanf to read it back.
159 Care is taken that numbers are printed with enough digits to uniquely
160 identify them, and therefore that they can be read back identically.
161 If the number read back is different, then there is probably a bug in
162 printf or sscanf, and the program prints the warning message.
163 If the two numbers in the warning look identical, then printf is more
164 than likely rounding the last digit(s) incorrectly. To put you at ease
165 that the two really are different, the bit patterns of the two numbers
166 are also printed. The difference is very likely in the last bit.
167 Many scanf's read the minimum double back as 0.0, and similarly cause
168 overflow when reading the maximum double. This program quite ruthlessly
169 declares all these behaviours faulty. The point is that if you get
170 one of these warnings, the output may be wrong, so you should check
171 the result carefully if you intend to use the results. Of course, printf
172 and sscanf may both be wrong, and cancel each other out, so you should
173 check the output carefully anyway.
175 The warning that "a cast didn't work" refers to cases like this:
178 #define C 1.234567890123456789
180 if (f != (float) C) printf ("Wrong!");
182 A faulty compiler will widen f to double and ignore the cast to float,
183 and because there is more accuracy in a double than a float, fail to
184 recognise that they are the same. In the actual case in point, f and C
185 are passed as parameters to a function that discovers they are not equal,
186 so it's just possible that the error was in the parameter passing,
187 not in the cast (see function Validate()).
188 For ANSI C, which has float constants, the error message is "constant has
192 If the program doesn't work for you for any reason that can't be
193 narrowed down to a problem in the C compiler, or it has to be changed in
194 order to get it to compile, or it produces suspicious output (like a very
195 low maximum float, for instance), please mail the problem and an example
196 of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
197 improvements can be worked into future versions; cwi.nl is the European
198 backbone, and is connected to uunet and other fine hosts.
200 The program tries to catch and diagnose bugs in the compiler/run-time
201 system. I would be especially pleased to have reports of failures so
202 that I can improve this service.
204 I apologise unreservedly for the contorted use of the preprocessor...
207 You may copy and distribute verbatim copies of this source file.
209 You may modify this source file, and copy and distribute such
210 modified versions, provided that you leave the copyright notice
211 at the top of the file and also cause the modified file to carry
212 prominent notices stating that you changed the files and the date
213 of any change; and cause the whole of any work that you distribute
214 or publish, that in whole or in part contains or is a derivative of
215 this program or any part thereof, to be licensed at no charge to
216 all third parties on terms identical to those here.
218 If you do have a fix to any problem, please send it to me, so that
219 other people can have the benefits.
221 While every effort has been taken to make this program as reliable as
222 possible, no responsibility can be taken for the correctness of the
223 output, nor suitability for any particular use.
225 This program is an offshoot of a project funded by public funds.
226 If you use this program for research or commercial use (i.e. more
227 than just for the fun of knowing about your compiler) mailing a short
228 note of acknowledgement may help keep enquire.c supported.
231 Many people have given time and ideas to making this program what it is.
232 To all of them thanks, and apologies for not mentioning them by name.
235 Originally started as a program to generate configuration constants
236 for a large piece of software we were writing, which later took on
238 1.0 Length 6658!; end 1984?
239 Unix only. Only printed a dozen maximum int/double values.
240 2.0 Length 10535; Spring 1985
241 Prints values as #defines (about 20 of them)
242 More extensive floating point, using Cody and Waite
243 Handles signals better
244 Programs around optimisations
246 3.0 Length 12648; Aug 1987; prints about 42 values
247 Added PASS stuff, so treats float as well as double
248 4.0 Length 33891; Feb 1989; prints around 85 values
249 First GNU version (for gcc, where they call it hard-params.c)
250 Generates float.h and limits.h files
252 Generates warnings for dubious output
253 4.1 Length 47738; April 1989
254 Added VERIFY and TEST
255 4.2 Length 63442; Feb 1990
258 Added check for pseudo-unsigned chars
259 Added description for each #define output
260 Added check for absence of defines during verify
262 Added NO_STDC and NO_FILE
263 Fixed alignments output
264 4.3 Length 75000; Oct 1990; around 114 lines of output
265 Function xmalloc defined, Richard Stallman, June 89.
266 Alignments computed from member offsets rather than structure sizes,
267 Richard Stallman, Oct 89.
268 Print whether char* and int* pointers have the same format;
269 also char * and function *.
270 Update to Draft C version Dec 7, 1988
271 - types of constants produced in limits.h
272 (whether to put a U after unsigned shorts and chars and
273 whether to output -1024 as (-1023-1))
274 - values of SCHAR_MIN/MAX
275 - values of *_EPSILON (not the smallest but the effective smallest)
276 Added FILENAME, since standard C doesn't allow #define __FILE__
277 Renamed from config.c to enquire.c
278 Added size_t and ptrdiff_t enquiries
279 Added promotion enquiries
280 Added type checks of #defines
282 Changed endian to allow for cases where not all bits are used
283 Sanity check for max integrals
284 Fixed definition of setjmp for -DNO_SIG
285 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
289 /* Set FILENAME to the name of this file */
292 #define FILENAME "enquire.c"
294 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
295 #define FILENAME __FILE__
297 #define FILENAME "enquire.c"
298 #endif /* __FILE__ */
300 #endif /* FILENAME */
302 /* If PASS isn't defined, then this is the first pass over this file. */
310 /* A description of the ANSI constants */
311 #define D_CHAR_BIT "Number of bits in a storage unit"
312 #define D_CHAR_MAX "Maximum char"
313 #define D_CHAR_MIN "Minimum char"
314 #define D_SCHAR_MAX "Maximum signed char"
315 #define D_SCHAR_MIN "Minimum signed char"
316 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
318 #define D_INT_MAX "Maximum %s"
319 #define D_INT_MIN "Minimum %s"
320 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
322 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
323 #define D_FLT_RADIX "Radix of exponent representation"
324 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
325 #define D_DIG "Number of decimal digits of precision in a %s"
326 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
327 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
328 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
329 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
330 #define D_MAX "Maximum %s"
331 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
332 #define D_MIN "Minimum normalised %s"
334 /* Procedure just marks the functions that don't return a result */
336 #define Procedure int
338 #define Procedure void
341 /* Some bad compilers define __STDC__, when they don't support it.
342 Compile with -DNO_STDC to get round this.
346 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
352 /* Stuff different for ANSI C, and old C:
353 ARGS and NOARGS are used for function prototypes.
354 Volatile is used to reduce the chance of optimisation,
355 and to prevent variables being put in registers (when setjmp/longjmp
356 wouldn't work as we want)
357 Long_double is the longest floating point type available.
358 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
359 U is output after unsigned constants.
364 #define NOARGS (void)
365 #define Volatile volatile
366 #define Long_double long double
370 #else /* Old style C */
374 #define Volatile static
375 #define Long_double double
386 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
393 #include <sys/types.h>
398 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
414 #define Vprintf if (V) printf
415 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
416 #define fabs(x) (((x)<0.0)?(-x):(x))
422 /* Prototypes for what's to come: */
427 char *malloc (); /* Old style prototype */
429 char *malloc
ARGS((size_t size
));
432 Procedure exit
ARGS((int status
));
434 char *f_rep
ARGS((int precision
, Long_double val
));
435 char *fake_f_rep
ARGS((char *type
, Long_double val
));
437 int maximum_int NOARGS
;
440 Procedure sprop NOARGS
;
441 Procedure iprop NOARGS
;
442 Procedure lprop NOARGS
;
443 Procedure usprop NOARGS
;
444 Procedure uiprop NOARGS
;
445 Procedure ulprop NOARGS
;
446 int fprop
ARGS((int bits_per_byte
));
447 int dprop
ARGS((int bits_per_byte
));
448 int ldprop
ARGS((int bits_per_byte
));
449 Procedure efprop
ARGS((int fprec
, int dprec
, int lprec
));
450 Procedure edprop
ARGS((int fprec
, int dprec
, int lprec
));
451 Procedure eldprop
ARGS((int fprec
, int dprec
, int lprec
));
453 int setmode
ARGS((char *s
));
454 Procedure farewell
ARGS((int bugs
));
455 Procedure describe
ARGS((char *description
, char *extra
));
456 Procedure missing
ARGS((char *s
));
457 Procedure fmissing
ARGS((char *s
));
458 Procedure check_defines NOARGS
;
459 Procedure bitpattern
ARGS((char *p
, unsigned int size
));
460 int ceil_log
ARGS((int base
, Long_double x
));
461 Procedure croak
ARGS((int place
));
462 Procedure eek_a_bug
ARGS((char *problem
));
463 Procedure endian
ARGS((int bits_per_byte
));
464 int exponent
ARGS((Long_double x
, double *fract
, int *exp
));
465 int floor_log
ARGS((int base
, Long_double x
));
466 Procedure f_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
467 int prec
, Long_double val
, char *mark
));
468 Procedure i_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
469 long val
, long lim
, long req
, char *mark
));
470 Procedure u_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
471 unsigned long val
, unsigned long req
, char *mark
));
473 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
475 /* Dummy routines instead */
477 int setjmp
ARGS((int lab
));
480 int setjmp(lab
) int lab
; { return(0); }
481 Procedure
signal(i
, p
) int i
, (*p
)(); {}
485 Procedure
overflow(sig
) int sig
; { /* what to do on over/underflow */
486 signal(sig
, overflow
);
492 int V
= 0, /* verbose */
493 L
= 0, /* produce limits.h */
494 F
= 0, /* produce float.h */
495 bugs
=0; /* The number of (possible) bugs in the output */
497 char co
[4], oc
[4]; /* Comment starter and ender symbols */
499 int bits_per_byte
; /* the number of bits per unit returned by sizeof() */
500 int flt_rounds
; /* The calculated value of FLT_ROUNDS */
501 int flt_radix
; /* The calculated value of FLT_RADIX */
504 /* Set the fp modes on a SUN with 68881 chip, to check that different
505 rounding modes etc. get properly detected.
506 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
507 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
508 register to hex-number
511 /* Bits 0x30 = rounding mode */
512 #define ROUND_BITS 0x30
513 #define TO_NEAREST 0x00
515 #define TO_MINUS_INF 0x20
516 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
518 /* Bits 0xc0 = extended rounding */
519 #define EXT_BITS 0xc0
520 #define ROUND_EXTENDED 0x00
521 #define ROUND_SINGLE 0x40
522 #define ROUND_DOUBLE 0x80
525 #define EXE_INEX1 0x100
526 #define EXE_INEX2 0x200
528 #define EXE_UNFL 0x800
529 #define EXE_OVFL 0x1000
530 #define EXE_OPERR 0x2000
531 #define EXE_SNAN 0x4000
532 #define EXE_BSUN 0x8000
534 /* Only used for testing, on a Sun with 68881 chip */
535 /* Print the FP mode */
536 printmode(new) unsigned new; {
538 printf("New fp mode:\n");
539 printf(" Round toward ");
540 switch (new & ROUND_BITS
) {
541 case TO_NEAREST
: printf("nearest"); break;
542 case TO_ZERO
: printf("zero"); break;
543 case TO_MINUS_INF
: printf("minus infinity"); break;
544 case TO_PLUS_INF
: printf("plus infinity"); break;
545 default: printf("???"); break;
548 printf("\n Extended rounding precision: ");
550 switch (new & EXT_BITS
) {
551 case ROUND_EXTENDED
: printf("extended"); break;
552 case ROUND_SINGLE
: printf("single"); break;
553 case ROUND_DOUBLE
: printf("double"); break;
554 default: printf("???"); break;
557 printf("\n Enabled exceptions:");
558 if (new & (unsigned) EXE_INEX1
) printf(" inex1");
559 if (new & (unsigned) EXE_INEX2
) printf(" inex2");
560 if (new & (unsigned) EXE_DZ
) printf(" dz");
561 if (new & (unsigned) EXE_UNFL
) printf(" unfl");
562 if (new & (unsigned) EXE_OVFL
) printf(" ovfl");
563 if (new & (unsigned) EXE_OPERR
) printf(" operr");
564 if (new & (unsigned) EXE_SNAN
) printf(" snan");
565 if (new & (unsigned) EXE_BSUN
) printf(" bsun");
569 /* Only used for testing, on a Sun with 68881 chip */
570 /* Set the FP mode */
571 int setmode(s
) char *s
; {
572 unsigned mode
=0, dig
;
577 if (c
>='0' && c
<='9') dig
= c
-'0';
578 else if (c
>='a' && c
<='f') dig
= c
-'a'+10;
579 else if (c
>='A' && c
<='F') dig
= c
-'A'+10;
588 int setmode(s
) char *s
; {
589 fprintf(stderr
, "Can't set mode: not compiled with TEST\n");
594 Procedure
farewell(bugs
) int bugs
; {
595 if (bugs
== 0) exit(0);
596 printf("\n%sFor hints on dealing with the ", co
);
597 if (bugs
== 1) printf("problem");
598 else printf("%d problems", bugs
);
599 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
600 printf("%s%s\n", FILENAME
, oc
);
604 /* The program has received a signal where it wasn't expecting one */
605 Procedure
croak(place
) int place
; {
606 printf("*** Unexpected signal at point %d\n", place
);
607 farewell(bugs
+1); /* An exit isn't essential here, but avoids loops */
610 /* This is here in case alloca.c is used, which calls this. */
611 char *xmalloc(size
) unsigned size
; {
612 char *value
= (char *)malloc(size
);
614 fprintf(stderr
, "Virtual memory exceeded\n");
623 /* Find the maximum integer */
624 Volatile
int newi
, int_max
, two
=2;
626 /* Calculate maxint ***********************************/
627 /* Calculate 2**n-1 until overflow - then use the previous value */
631 if (setjmp(lab
)==0) { /* Yields int_max */
632 while(newi
>int_max
) {
641 int main(argc
, argv
) int argc
; char *argv
[]; {
642 int dprec
, fprec
, lprec
;
645 int i
; char *s
; int bad
;
648 signal(SIGFPE
, overflow
);
651 signal(SIGOVER
, overflow
);
653 /* Add more calls as necessary */
658 for (i
=1; i
< argc
; i
++) {
664 case 'v': V
=1; break;
665 case 'l': L
=1; break;
666 case 'f': F
=1; break;
667 default: bad
=1; break;
670 } else if (*s
== '+') {
677 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
682 co
[0]= '/'; oc
[0]= ' ';
683 co
[1]= '*'; oc
[1]= '*';
684 co
[2]= ' '; oc
[2]= '/';
685 co
[3]= '\0'; oc
[3]= '\0';
687 co
[0]= '\0'; oc
[0]= '\0';
691 if (L
) printf("%slimits.h%s\n", co
, oc
);
692 if (F
) printf("%sfloat.h%s\n", co
, oc
);
694 printf ("#ifndef _FLOAT_H___\n");
695 printf ("#define _FLOAT_H___\n");
698 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
699 co
, ID
, VERSION
, oc
);
701 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
706 printf("%sVerification phase%s\n", co
, oc
);
710 Vprintf("%sCompiled without signal(): %s%s\n",
712 "there's nothing that can be done if overflow occurs",
716 Vprintf("%sCompiled without signed char%s\n", co
, oc
);
719 Vprintf("%Compiled without unsigned char%s\n", co
, oc
);
722 Vprintf("%Compiled without unsigned short or long%s\n", co
, oc
);
725 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
728 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co
, oc
);
733 maxint
= maximum_int();
734 bits_per_byte
= basic();
737 fprec
= fprop(bits_per_byte
);
738 dprec
= dprop(bits_per_byte
);
739 lprec
= ldprop(bits_per_byte
);
740 efprop(fprec
, dprec
, lprec
);
741 edprop(fprec
, dprec
, lprec
);
742 eldprop(fprec
, dprec
, lprec
);
746 /* An extra goody: the approximate amount of data-space */
747 /* Allocate store until no more available */
748 /* Different implementations have a different argument type
749 to malloc. Here we assume that it's the same type as
750 that which sizeof() returns */
751 size
=1<<((bits_per_byte
*sizeof(int))-2);
754 while ( malloc((false()?sizeof(int):size
)) !=
762 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
763 co
, (total
+511)/512, oc
);
767 printf ("#endif %s _FLOAT_H___%s\n", co
, oc
);
770 return bugs
; /* To keep compilers and lint happy */
773 Procedure
eek_a_bug(problem
) char *problem
; {
774 /* The program has discovered a problem */
775 printf("\n%s*** WARNING: %s%s\n", co
, problem
, oc
);
779 Procedure
describe(description
, extra
) char *description
, *extra
; {
780 /* Produce the description for a #define */
782 printf(description
, extra
);
786 Procedure
i_define(desc
, extra
, sort
, name
, val
, lim
, req
, mark
)
787 char *desc
, *extra
, *sort
, *name
; long val
, lim
, req
; char *mark
; {
788 /* Produce a #define for a signed int type */
789 describe(desc
, extra
);
790 printf("#undef %s%s\n", sort
, name
);
792 printf("#define %s%s %ld%s\n", sort
, name
, val
, mark
);
793 } else if (val
+ lim
< 0) {
794 /* We may not produce a constant like -1024 if the max
795 allowable value is 1023. It has then to be output as
796 -1023-1. lim is the max allowable value. */
797 printf("#define %s%s (%ld%s%ld%s)\n",
798 sort
, name
, -lim
, mark
, val
+lim
, mark
);
800 printf("#define %s%s (%ld%s)\n", sort
, name
, val
, mark
);
802 /* If VERIFY is not set, val and req are just the same value;
803 if it is set, val is the value as calculated, and req is
804 the #defined constant
807 printf("%s*** Verify failed for above #define!\n", co
);
808 printf(" Compiler has %ld for value%s\n\n", req
, oc
);
814 Procedure
u_define(desc
, extra
, sort
, name
, val
, req
, mark
)
815 char *desc
, *extra
, *sort
, *name
; unsigned long val
, req
; char *mark
; {
816 /* Produce a #define for an unsigned value */
817 describe(desc
, extra
);
818 printf("#undef %s%s\n", sort
, name
);
819 printf("#define %s%s %lu%s%s\n", sort
, name
, val
, U
, mark
);
821 printf("%s*** Verify failed for above #define!\n", co
);
822 printf(" Compiler has %lu for value%s\n\n", req
, oc
);
828 Procedure
f_define(desc
, extra
, sort
, name
, precision
, val
, mark
)
829 char *desc
, *extra
, *sort
, *name
; int precision
;
830 Long_double val
; char *mark
; {
831 /* Produce a #define for a float/double/long double */
832 describe(desc
, extra
);
833 printf ("#undef %s%s\n", sort
, name
);
835 #ifdef NO_LONG_DOUBLE_IO
836 static int union_defined
= 0;
837 if (sizeof(double) != sizeof(Long_double
)
838 && !strcmp(sort
, "LDBL")) {
839 if (!union_defined
) {
840 printf("#ifndef __LDBL_UNION__\n");
841 printf("#define __LDBL_UNION__\n");
842 printf("union __convert_long_double {\n");
843 printf(" unsigned __convert_long_double_i[4];\n");
844 printf(" long double __convert_long_double_d;\n");
849 printf("#define %s%s %s\n",
850 sort
, name
, fake_f_rep("long double", val
));
852 printf("#define %s%s %s%s\n",
853 sort
, name
, f_rep(precision
, val
), mark
);
856 printf("#define %s%s %s%s\n",
857 sort
, name
, f_rep(precision
, val
), mark
);
859 } else if (*mark
== 'F') {
860 /* non-ANSI C has no float constants, so cast the constant */
861 printf("#define %s%s ((float)%s)\n",
862 sort
, name
, f_rep(precision
, val
));
864 printf("#define %s%s %s\n", sort
, name
, f_rep(precision
, val
));
869 int floor_log(base
, x
) int base
; Long_double x
; {
870 /* return floor(log base(x)) */
872 while (x
>=base
) { r
++; x
/=base
; }
876 int ceil_log(base
, x
) int base
; Long_double x
; {
878 while (x
>1.0) { r
++; x
/=base
; }
882 int exponent(x
, fract
, exp
) Long_double x
; double *fract
; int *exp
; {
883 /* Split x into a fraction and a power of ten;
884 returns 0 if x is unusable, 1 otherwise.
885 Only used for error messages about faulty output.
894 if (x
==0.0) return 1;
898 if (old
==x
) return 0;
903 if (old
==x
) return 0;
906 if (neg
) *fract
= (double) -x
;
907 else *fract
=(double) x
;
912 /* Print a value of type TYPE with value VAL,
913 assuming that sprintf can't handle this type properly (without truncation).
914 We create an expression that uses type casting to create the value from
917 char *fake_f_rep(type
, val
) char *type
; Long_double val
; {
918 static char buf
[1024];
919 union { unsigned int i
[4]; Long_double ld
;} u
;
920 u
.i
[0] = u
.i
[1] = u
.i
[2] = u
.i
[3] = 0;
922 sprintf(buf
, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
923 u
.i
[0], u
.i
[1], u
.i
[2], u
.i
[3]);
927 char *f_rep(precision
, val
) int precision
; Long_double val
; {
928 /* Return the floating representation of val */
929 static char buf
[1024];
931 #ifdef NO_LONG_DOUBLE_IO
934 if (sizeof(double) == sizeof(Long_double
))
938 /* Assume they're the same, and use non-stdc format */
939 /* This is for stdc compilers using non-stdc libraries */
940 sprintf(buf
, "%.*e", precision
, d
);
942 /* It had better support Le then */
943 sprintf(buf
, "%.*Le", precision
, val
);
948 Procedure
bitpattern(p
, size
) char *p
; unsigned int size
; {
949 /* Printf the bit-pattern of p */
953 for (i
=1; i
<=size
; i
++) {
956 for (j
=bits_per_byte
-1; j
>=0; j
--)
957 printf("%c", (c
>>j
)&1 ? '1' : '0');
958 if (i
!=size
) printf(" ");
962 #define Order(x, px, mode)\
963 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
964 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
965 putchar(c==0 ? '?' : (char)c); }\
968 Procedure
endian(bits_per_byte
) int bits_per_byte
; {
969 /* Printf the byte-order used on this machine */
970 /*unsigned*/ short s
=0;
971 /*unsigned*/ int j
=0;
972 /*unsigned*/ long l
=0;
974 char *ps
= (char *) &s
,
977 *ab
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
978 unsigned int mask
, i
, c
;
981 for (i
=1; i
<=(unsigned)bits_per_byte
; i
++) mask
= (mask
<<1)|1;
984 printf("%sCHARACTER ORDER%s\n", co
, oc
);
985 Order(s
, ps
, "short:");
986 Order(j
, pj
, "int: ");
987 Order(l
, pl
, "long: ");
991 Procedure
missing(s
) char *s
; {
992 printf("%s*** #define %s missing from limits.h%s\n", co
, s
, oc
);
996 Procedure
fmissing(s
) char *s
; {
997 printf("%s*** #define %s missing from float.h%s\n", co
, s
, oc
);
1001 /* To try and fool optimisers */
1002 int false() { return 0; }
1004 #define Promoted(x) (false()?(x):(-1))
1005 #define is_signed(x) (Promoted(x) < 0)
1006 #define sign_of(x) ((x)?"signed":"unsigned")
1009 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1011 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1013 char *type_of(x
) int x
; {
1014 if (x
== sizeof(char)) {
1015 if (sizeof(char) == sizeof(int)) return "char/short/int";
1016 if (sizeof(char) == sizeof(short)) return "char/short";
1019 if (x
== sizeof(short)) {
1020 if (sizeof(short) == sizeof(int)) return "short/int";
1023 if (x
== sizeof(int)) {
1024 if (sizeof(int) == sizeof(long)) return "int/long";
1027 if (x
== sizeof(long)) return "long";
1028 return "unknown-type";
1031 char *ftype_of(x
) int x
; {
1032 if (x
== sizeof(float)) {
1035 if (x
== sizeof(double)) {
1036 if (sizeof(double) == sizeof(Long_double
))
1037 return "(long)double";
1040 if (x
== sizeof(Long_double
)) {
1041 return "long double";
1043 return "unknown-type";
1046 Procedure
typerr(name
, esign
, esize
, sign
, size
)
1047 char *name
; int esign
, esize
, sign
, size
;
1049 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1050 name
, sign_of(esign
), type_of(esize
),
1051 sign_of(sign
), type_of(size
));
1054 Procedure
ftyperr(name
, esize
, size
) char *name
; int esize
, size
; {
1055 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1056 name
, ftype_of(esize
), ftype_of(size
));
1061 unsigned int ui
; unsigned long ul
;
1062 short ss
; unsigned short us
;
1064 Vprintf("\n%sPROMOTIONS%s\n", co
, oc
);
1067 /* Possible warnings here; no problem */
1068 (sizeof(Promoted(si
)) != sizeof(int)) ||
1069 (sizeof(Promoted(sl
)) != sizeof(long)) ||
1070 (sizeof(Promoted(ss
)) != sizeof(int)) ||
1071 (sizeof(Promoted(ui
)) != sizeof(int)) ||
1072 (sizeof(Promoted(ul
)) != sizeof(long)) ||
1073 (sizeof(Promoted(us
)) != sizeof(int)) ||
1074 is_signed(ui
) || is_signed(ul
) ||
1075 !is_signed(si
) || !is_signed(sl
)
1078 eek_a_bug("promotions don't work properly in conditional expressions\n");
1081 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1082 showtype("long+unsigned gives", sl
+ui
);
1085 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1087 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1089 Procedure
check_defines() {
1090 /* ensure that all #defines are present and have the correct type */
1097 /* Implementations promote unsigned short differently */
1098 usign
= is_signed((unsigned short)0);
1103 checktype(CHAR_BIT
, "CHAR_BIT", Signed
, int);
1105 missing("CHAR_BIT");
1108 checktype(CHAR_MAX
, "CHAR_MAX", Signed
, int);
1110 missing("CHAR_MAX");
1113 checktype(CHAR_MIN
, "CHAR_MIN", Signed
, int);
1115 missing("CHAR_MIN");
1118 checktype(SCHAR_MAX
, "SCHAR_MAX", Signed
, int);
1120 missing("SCHAR_MAX");
1123 checktype(SCHAR_MIN
, "SCHAR_MIN", Signed
, int);
1125 missing("SCHAR_MIN");
1128 checktype(UCHAR_MAX
, "UCHAR_MAX", Signed
, int);
1130 missing("UCHAR_MAX");
1133 checktype(SHRT_MAX
, "SHRT_MAX", Signed
, int);
1135 missing("SHRT_MAX");
1138 checktype(SHRT_MIN
, "SHRT_MIN", Signed
, int);
1140 missing("SHRT_MIN");
1143 checktype(INT_MAX
, "INT_MAX", Signed
, int);
1148 checktype(INT_MIN
, "INT_MIN", Signed
, int);
1153 checktype(LONG_MAX
, "LONG_MAX", Signed
, long);
1155 missing("LONG_MAX");
1158 checktype(LONG_MIN
, "LONG_MIN", Signed
, long);
1160 missing("LONG_MIN");
1163 checktype(USHRT_MAX
, "USHRT_MAX", usign
, int);
1165 missing("USHRT_MAX");
1168 checktype(UINT_MAX
, "UINT_MAX", Unsigned
, int);
1170 missing("UINT_MAX");
1173 checktype(ULONG_MAX
, "ULONG_MAX", Unsigned
, long);
1175 missing("ULONG_MAX");
1181 checktype(FLT_RADIX
, "FLT_RADIX", Signed
, int);
1183 fmissing("FLT_RADIX");
1186 checktype(FLT_MANT_DIG
, "FLT_MANT_DIG", Signed
, int);
1188 fmissing("FLT_MANT_DIG");
1191 checktype(FLT_DIG
, "FLT_DIG", Signed
, int);
1193 fmissing("FLT_DIG");
1196 checktype(FLT_ROUNDS
, "FLT_ROUNDS", Signed
, int);
1198 fmissing("FLT_ROUNDS");
1201 fchecktype(FLT_EPSILON
, "FLT_EPSILON", float);
1203 fmissing("FLT_EPSILON");
1206 checktype(FLT_MIN_EXP
, "FLT_MIN_EXP", Signed
, int);
1208 fmissing("FLT_MIN_EXP");
1211 fchecktype(FLT_MIN
, "FLT_MIN", float);
1213 fmissing("FLT_MIN");
1215 #ifdef FLT_MIN_10_EXP
1216 checktype(FLT_MIN_10_EXP
, "FLT_MIN_10_EXP", Signed
, int);
1218 fmissing("FLT_MIN_10_EXP");
1221 checktype(FLT_MAX_EXP
, "FLT_MAX_EXP", Signed
, int);
1223 fmissing("FLT_MAX_EXP");
1226 fchecktype(FLT_MAX
, "FLT_MAX", float);
1228 fmissing("FLT_MAX");
1230 #ifdef FLT_MAX_10_EXP
1231 checktype(FLT_MAX_10_EXP
, "FLT_MAX_10_EXP", Signed
, int);
1233 fmissing("FLT_MAX_10_EXP");
1236 checktype(DBL_MANT_DIG
, "DBL_MANT_DIG", Signed
, int);
1238 fmissing("DBL_MANT_DIG");
1241 checktype(DBL_DIG
, "DBL_DIG", Signed
, int);
1243 fmissing("DBL_DIG");
1246 fchecktype(DBL_EPSILON
, "DBL_EPSILON", double);
1248 fmissing("DBL_EPSILON");
1251 checktype(DBL_MIN_EXP
, "DBL_MIN_EXP", Signed
, int);
1253 fmissing("DBL_MIN_EXP");
1256 fchecktype(DBL_MIN
, "DBL_MIN", double);
1258 fmissing("DBL_MIN");
1260 #ifdef DBL_MIN_10_EXP
1261 checktype(DBL_MIN_10_EXP
, "DBL_MIN_10_EXP", Signed
, int);
1263 fmissing("DBL_MIN_10_EXP");
1266 checktype(DBL_MAX_EXP
, "DBL_MAX_EXP", Signed
, int);
1268 fmissing("DBL_MAX_EXP");
1271 fchecktype(DBL_MAX
, "DBL_MAX", double);
1273 fmissing("DBL_MAX");
1275 #ifdef DBL_MAX_10_EXP
1276 checktype(DBL_MAX_10_EXP
, "DBL_MAX_10_EXP", Signed
, int);
1278 fmissing("DBL_MAX_10_EXP");
1281 #ifdef LDBL_MANT_DIG
1282 checktype(LDBL_MANT_DIG
, "LDBL_MANT_DIG", Signed
, int);
1284 fmissing("LDBL_MANT_DIG");
1287 checktype(LDBL_DIG
, "LDBL_DIG", Signed
, int);
1289 fmissing("LDBL_DIG");
1292 fchecktype(LDBL_EPSILON
, "LDBL_EPSILON", long double);
1294 fmissing("LDBL_EPSILON");
1297 checktype(LDBL_MIN_EXP
, "LDBL_MIN_EXP", Signed
, int);
1299 fmissing("LDBL_MIN_EXP");
1302 fchecktype(LDBL_MIN
, "LDBL_MIN", long double);
1304 fmissing("LDBL_MIN");
1306 #ifdef LDBL_MIN_10_EXP
1307 checktype(LDBL_MIN_10_EXP
, "LDBL_MIN_10_EXP", Signed
, int);
1309 fmissing("LDBL_MIN_10_EXP");
1312 checktype(LDBL_MAX_EXP
, "LDBL_MAX_EXP", Signed
, int);
1314 fmissing("LDBL_MAX_EXP");
1317 fchecktype(LDBL_MAX
, "LDBL_MAX", long double);
1319 fmissing("LDBL_MAX");
1321 #ifdef LDBL_MAX_10_EXP
1322 checktype(LDBL_MAX_10_EXP
, "LDBL_MAX_10_EXP", Signed
, int);
1324 fmissing("LDBL_MAX_10_EXP");
1333 #define SCHAR_MAX char_max
1336 #define SCHAR_MIN char_min
1339 #define UCHAR_MAX char_max
1344 #define CHAR_BIT char_bit
1347 #define CHAR_MAX char_max
1350 #define CHAR_MIN char_min
1353 #define SCHAR_MAX char_max
1356 #define SCHAR_MIN char_min
1359 #define UCHAR_MAX char_max
1363 /* Properties of type char */
1364 Volatile
char c
, char_max
, char_min
;
1365 Volatile
int bits_per_byte
, c_signed
;
1370 /* Calculate number of bits per character *************************/
1371 c
=1; bits_per_byte
=0;
1372 do { c
=c
<<1; bits_per_byte
++; } while(c
!=0);
1374 if (((int)c
)<0) c_signed
=1;
1376 Vprintf("%schar = %d bits, %ssigned%s\n",
1377 co
, (int)sizeof(c
)*bits_per_byte
, (c_signed
?"":"un"), oc
);
1378 char_bit
=(long)(sizeof(c
)*bits_per_byte
);
1379 if (L
) i_define(D_CHAR_BIT
, "", "CHAR", "_BIT",
1380 char_bit
, 0L, (long) CHAR_BIT
, "");
1384 if (setjmp(lab
)==0) { /* Yields char_max */
1385 while (c
>char_max
) {
1390 Vprintf("%sCharacter overflow generates a trap!%s\n", co
, oc
);
1394 if (setjmp(lab
)==0) { /* Yields char_min */
1395 while (c
<char_min
) {
1400 if (c_signed
&& char_min
== 0) {
1401 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co
, oc
);
1402 Vprintf("%s %s%s%s\n",
1403 "They contain only nonnegative values, ",
1404 "but sign extend when used as integers.", co
, oc
);
1409 /* Because of the integer promotions, you must use a U after
1410 the MAX_CHARS in the following cases */
1411 if ((sizeof(char) == sizeof(int)) && !c_signed
) {
1412 u_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1414 (long) CHAR_MAX
, "");
1416 i_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1417 (long) char_max
, 0L,
1418 (long) CHAR_MAX
, "");
1420 i_define(D_CHAR_MIN
, "", "CHAR", "_MIN",
1421 (long) char_min
, (long) maxint
,
1422 (long) CHAR_MIN
, "");
1424 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1425 (long) char_max
, 0L,
1426 (long) SCHAR_MAX
, "");
1427 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1428 (long) char_min
, (long) maxint
,
1429 (long) SCHAR_MIN
, "");
1431 if (sizeof(char) == sizeof(int)) {
1432 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1434 (long) UCHAR_MAX
, "");
1436 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1437 (long) char_max
, 0L,
1438 (long) UCHAR_MAX
, "");
1444 Volatile
unsigned char c
, char_max
;
1447 if (setjmp(lab
)==0) { /* Yields char_max */
1448 while (c
>char_max
) {
1454 if (sizeof(char) == sizeof(int)) {
1455 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1457 (long) UCHAR_MAX
, "");
1459 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1460 (long) char_max
, 0L,
1461 (long) UCHAR_MAX
, "");
1466 /* Define NO_SC if this gives a syntax error */ Volatile
signed char c
, char_max
, char_min
;
1469 if (setjmp(lab
)==0) { /* Yields char_max */
1470 while (c
>char_max
) {
1477 if (setjmp(lab
)==0) { /* Yields char_min */
1478 while (c
<char_min
) {
1484 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1485 (long) char_min
, (long) maxint
,
1486 (long) SCHAR_MIN
, "");
1487 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1488 (long) char_max
, 0L,
1489 (long) SCHAR_MAX
, "");
1493 return bits_per_byte
;
1497 /* The properties of the basic types.
1498 Returns number of bits per sizeof unit */
1499 Volatile
int bits_per_byte
;
1500 typedef int function ();
1504 Vprintf("%sSIZES%s\n", co
, oc
);
1505 bits_per_byte
= cprop();
1507 /* Shorts, ints and longs *****************************************/
1508 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1510 (int) sizeof(short)*bits_per_byte
,
1511 (int) sizeof(int)*bits_per_byte
,
1512 (int) sizeof(long)*bits_per_byte
,
1513 (int) sizeof(float)*bits_per_byte
,
1514 (int) sizeof(double)*bits_per_byte
, oc
);
1516 Vprintf("%slong double=%d bits%s\n",
1517 co
, (int) sizeof(Long_double
)*bits_per_byte
, oc
);
1519 Vprintf("%schar*=%d bits%s%s\n",
1520 co
, (int)sizeof(char *)*bits_per_byte
,
1521 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1523 Vprintf("%sint* =%d bits%s%s\n",
1524 co
, (int)sizeof(int *)*bits_per_byte
,
1525 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1527 Vprintf("%sfunc*=%d bits%s%s\n",
1528 co
, (int)sizeof(function
*)*bits_per_byte
,
1529 sizeof(function
*)>sizeof(int)?" BEWARE! larger than int!":"",
1531 if (V
) printf ("%s%s %s %s%s\n", co
, "Type size_t is",
1532 ((((false()?( sizeof(int)):(-1)) < 0) )?
1533 "signed":"unsigned") ,
1539 showtype("Type size_t is", sizeof(0));
1541 /* Alignment constants ********************************************/
1543 #define alignment(TYPE) \
1544 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1546 Vprintf("\n%sALIGNMENTS%s\n", co
, oc
);
1548 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1550 alignment(char), alignment(short),
1551 alignment(int), alignment(long),
1554 Vprintf("%sfloat=%ld double=%ld%s\n",
1556 alignment(float), alignment(double),
1560 Vprintf("%slong double=%ld%s\n",
1562 alignment(Long_double
),
1565 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1567 alignment(char *), alignment(int *), alignment(function
*),
1572 /* Ten little endians *********************************************/
1574 endian(bits_per_byte
);
1576 /* Pointers *******************************************************/
1578 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co
, oc
);
1580 if ((long) (char *) &variable
== (long) (int *) &variable
)
1581 Vprintf("%sChar and int pointer formats seem identical%s\n",
1584 Vprintf("%sChar and int pointer formats are different%s\n",
1586 if ((long) (char *) &variable
== (long) (function
*) &variable
)
1587 Vprintf("%sChar and function pointer formats seem identical%s\n",
1590 Vprintf("%sChar and function pointer formats are different%s\n",
1595 printf("%sStrings are shared%s\n", co
, oc
);
1596 else printf("%sStrings are not shared%s\n", co
, oc
);
1600 showtype("Type ptrdiff_t is", p
-q
);
1602 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co
, oc
);
1615 return bits_per_byte
;
1618 #else /* not PASS0 */
1622 extern int V
, L
, F
, bugs
, bits_per_byte
;
1623 extern char co
[], oc
[];
1624 extern char *f_rep();
1626 #endif /* ifdef PASS0 */
1628 /* As I said, I apologise for the contortions below. The functions are
1629 expanded by the preprocessor twice or three times (for float and double,
1630 and maybe for long double, and for short, int and long). That way,
1631 I never make a change to one that I forget to make to the other.
1632 You can look on it as C's fault for not supporting multi-line macro's.
1633 This whole file is read 3 times by the preprocessor, with PASSn set for
1634 n=1, 2 or 3, to decide which parts to reprocess.
1637 /* #undef on an already undefined thing is (wrongly) flagged as an error
1638 by some compilers, therefore the #ifdef that follows:
1664 /* These are the float.h constants */
1695 /* Define the things we're going to use this pass */
1697 #define Number float
1698 #define THING "FLOAT"
1699 #define Thing "Float"
1700 #define thing "float"
1703 #define Store fStore
1715 #define F_check fCheck
1718 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1721 #define EPROP efprop
1723 #define Integer short
1726 #define Iname "SHRT"
1732 #define UPROP usprop
1733 #define Uname "USHRT"
1737 #define I_MAX SHRT_MAX
1740 #define I_MIN SHRT_MIN
1743 #define U_MAX USHRT_MAX
1747 #define F_RADIX FLT_RADIX
1750 #define F_MANT_DIG FLT_MANT_DIG
1753 #define F_DIG FLT_DIG
1756 #define F_ROUNDS FLT_ROUNDS
1759 #define F_EPSILON FLT_EPSILON
1762 #define F_MIN_EXP FLT_MIN_EXP
1765 #define F_MIN FLT_MIN
1767 #ifdef FLT_MIN_10_EXP
1768 #define F_MIN_10_EXP FLT_MIN_10_EXP
1771 #define F_MAX_EXP FLT_MAX_EXP
1774 #define F_MAX FLT_MAX
1776 #ifdef FLT_MAX_10_EXP
1777 #define F_MAX_10_EXP FLT_MAX_10_EXP
1785 #define Number double
1786 #define THING "DOUBLE"
1787 #define Thing "Double"
1788 #define thing "double"
1791 #define Store dStore
1803 #define F_check dCheck
1806 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1809 #define EPROP edprop
1815 #define OK_UI 1 /* Unsigned int is always possible */
1818 #define UPROP uiprop
1819 #define Uname "UINT"
1823 #define I_MAX INT_MAX
1826 #define I_MIN INT_MIN
1829 #define U_MAX UINT_MAX
1833 #define F_MANT_DIG DBL_MANT_DIG
1836 #define F_DIG DBL_DIG
1839 #define F_EPSILON DBL_EPSILON
1842 #define F_MIN_EXP DBL_MIN_EXP
1845 #define F_MIN DBL_MIN
1847 #ifdef DBL_MIN_10_EXP
1848 #define F_MIN_10_EXP DBL_MIN_10_EXP
1851 #define F_MAX_EXP DBL_MAX_EXP
1854 #define F_MAX DBL_MAX
1856 #ifdef DBL_MAX_10_EXP
1857 #define F_MAX_10_EXP DBL_MAX_10_EXP
1866 #define Number long double
1876 #define THING "LONG DOUBLE"
1877 #define Thing "Long double"
1878 #define thing "long double"
1879 #define Fname "LDBL"
1880 #define FPROP ldprop
1881 #define Store ldStore
1887 #define F_check ldCheck
1890 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1893 #define EPROP eldprop
1895 #define Integer long
1898 #define Iname "LONG"
1904 #define UPROP ulprop
1905 #define Uname "ULONG"
1909 #define I_MAX LONG_MAX
1912 #define I_MIN LONG_MIN
1915 #define U_MAX ULONG_MAX
1918 #ifdef LDBL_MANT_DIG
1919 #define F_MANT_DIG LDBL_MANT_DIG
1922 #define F_DIG LDBL_DIG
1925 #define F_EPSILON LDBL_EPSILON
1928 #define F_MIN_EXP LDBL_MIN_EXP
1931 #define F_MIN LDBL_MIN
1933 #ifdef LDBL_MIN_10_EXP
1934 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1937 #define F_MAX_EXP LDBL_MAX_EXP
1940 #define F_MAX LDBL_MAX
1942 #ifdef LDBL_MAX_10_EXP
1943 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1950 #define I_MAX int_max
1953 #define I_MIN int_min
1960 #define F_RADIX f_radix
1963 #define F_MANT_DIG f_mant_dig
1969 #define F_ROUNDS f_rounds
1972 #define F_EPSILON f_epsilon
1975 #define F_MIN_EXP f_min_exp
1980 #ifndef F_MIN_10_EXP
1981 #define F_MIN_10_EXP f_min_10_exp
1984 #define F_MAX_EXP f_max_exp
1989 #ifndef F_MAX_10_EXP
1990 #define F_MAX_10_EXP f_max_10_exp
1994 #define Validate(prec, val, req, same) {;}
2000 /* the properties of short, int, and long */
2001 Volatile Integer newi
, int_max
, maxeri
, int_min
, minneri
;
2002 Volatile
int ibits
, ipower
, two
=2;
2004 /* Calculate max short/int/long ***********************************/
2005 /* Calculate 2**n-1 until overflow - then use the previous value */
2009 if (setjmp(lab
)==0) { /* Yields int_max */
2010 for(ipower
=0; newi
>int_max
; ipower
++) {
2014 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2015 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2017 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2018 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2022 /* Minimum value: assume either two's or one's complement *********/
2024 if (setjmp(lab
)==0) { /* Yields int_min */
2025 if (int_min
-1 < int_min
) int_min
--;
2029 /* Now for those daft Cybers */
2031 maxeri
=0; newi
=int_max
;
2033 if (setjmp(lab
)==0) { /* Yields maxeri */
2034 for(ibits
=ipower
; newi
>maxeri
; ibits
++) {
2042 if (setjmp(lab
)==0) { /* Yields minneri */
2043 if (minneri
-1 < minneri
) minneri
--;
2047 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2048 co
, INT
, (long)int_max
, ipower
, oc
);
2049 Vprintf("%sMinimum %s = %ld%s\n", co
, INT
, (long)int_min
, oc
);
2051 if (L
) i_define(D_INT_MAX
, INT
, Iname
, "_MAX",
2053 (long) I_MAX
, IMARK
);
2054 if (L
) i_define(D_INT_MIN
, INT
, Iname
, "_MIN",
2055 (long) int_min
, (long) (PASS
==1?maxint
:int_max
),
2056 (long) I_MIN
, IMARK
);
2058 if(int_max
< 0) { /* It has happened */
2059 eek_a_bug("signed integral comparison faulty?");
2062 if (maxeri
>int_max
) {
2063 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2064 co
, INT
, (long)maxeri
, ibits
,
2065 "but only for addition, not multiplication",
2066 "(I smell a Cyber!)",
2070 if (minneri
<int_min
) {
2071 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2072 co
, INT
, (long)minneri
,
2073 "but only for addition, not multiplication",
2074 "(I smell a Cyber!)",
2079 Procedure
UPROP () {
2080 /* The properties of unsigned short/int/long */
2082 Volatile
unsigned Integer u_max
, newi
, two
;
2083 newi
=1; u_max
=0; two
=2;
2085 if (setjmp(lab
)==0) { /* Yields u_max */
2092 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2093 co
, INT
, (unsigned long) u_max
, oc
);
2095 /* Oh woe: new standard C defines value preserving promotions */
2097 if (PASS
== 1 && sizeof(short) < sizeof(int)) {
2098 /* Special only for short */
2099 i_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2100 (unsigned long) u_max
, 0L,
2101 (unsigned long) U_MAX
, IMARK
);
2103 u_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2104 (unsigned long) u_max
,
2105 (unsigned long) U_MAX
, IMARK
);
2111 #endif /* Integer */
2115 /* The following routines are intended to defeat any attempt at optimisation
2116 or use of extended precision, and to defeat faulty narrowing casts.
2117 The weird prototypes are because of widening incompatibilities.
2120 #define ARGS1(atype, a) (atype a)
2121 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2123 #define ARGS1(atype, a) (a) atype a;
2124 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2127 Procedure Store
ARGS2(Number
, a
, Number
*, b
) { *b
=a
; }
2128 Number Sum
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
+b
, &r
); return (r
); }
2129 Number Diff
ARGS2(Number
, a
, Number
, b
){Number r
; Store(a
-b
, &r
); return (r
); }
2130 Number Mul
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
*b
, &r
); return (r
); }
2131 Number Div
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
/b
, &r
); return (r
); }
2132 Number Self
ARGS1(Number
, a
) {Number r
; Store(a
, &r
); return (r
); }
2134 Procedure F_check
ARGS((int precision
, Long_double val1
));
2136 Procedure
F_check(precision
, val1
) int precision
; Long_double val1
; {
2137 /* You don't think I'm going to go to all the trouble of writing
2138 a program that works out what all sorts of values are, only to
2139 have printf go and print the wrong values out, do you?
2140 No, you're right, so this function tries to see if printf
2141 has written the right value, by reading it back again.
2142 This introduces a new problem of course: suppose printf writes
2143 the correct value, and scanf reads it back wrong... oh well.
2144 But I'm adamant about this: the precision given is enough
2145 to uniquely identify the printed number, therefore I insist
2146 that sscanf read the number back identically. Harsh yes, but
2147 sometimes you've got to be cruel to be kind.
2150 Number val
, new, diff
;
2156 if (sizeof(double) == sizeof(Long_double
)) {
2157 /* Assume they're the same, and use non-stdc format */
2158 /* This is for stdc compilers using non-stdc libraries */
2159 f2
= "%le"; /* Input */
2161 /* It had better support Le then */
2165 rep
= f_rep(precision
, (Long_double
) val
);
2166 if (setjmp(lab
)==0) {
2167 sscanf(rep
, f2
, &new1
);
2169 eek_a_bug("sscanf caused a trap");
2170 printf("%s scanning: %s format: %s%s\n\n", co
, rep
, f2
, oc
);
2175 if (setjmp(lab
)==0) { /* See if new is usable */
2178 diff
= val
/new - 1.0;
2179 if (diff
< 0.1) diff
= 1.0;
2180 /* That should be enough to generate a trap */
2183 eek_a_bug("sscanf returned an unusable number");
2184 printf("%s scanning: %s with format: %s%s\n\n",
2192 eek_a_bug("Possibly bad output from printf above");
2193 if (!exponent((Long_double
)val
, &rem
, &e
)) {
2194 printf("%s but value was an unusable number%s\n\n",
2198 printf("%s expected value around %.*fe%d, bit pattern:\n ",
2199 co
, precision
, rem
, e
);
2200 bitpattern((char *) &val
, (unsigned)sizeof(val
));
2201 printf ("%s\n", oc
);
2202 printf("%s sscanf gave %s, bit pattern:\n ",
2203 co
, f_rep(precision
, (Long_double
) new));
2204 bitpattern((char *) &new, (unsigned)sizeof(new));
2205 printf ("%s\n", oc
);
2206 if (setjmp(lab
) == 0) {
2208 printf("%s difference= %s%s\n\n",
2209 co
, f_rep(precision
, (Long_double
) diff
), oc
);
2210 } /* else forget it */
2216 Procedure
Validate(prec
, val
, req
, same
) int prec
, same
; Long_double val
, req
; {
2217 /* Check that the compiler has read a #define value correctly */
2220 printf("%s*** Verify failed for above #define!\n", co
);
2221 if (setjmp(lab
) == 0) { /* for the case that req == nan */
2222 printf(" Compiler has %s for value%s\n",
2223 f_rep(prec
, req
), oc
);
2225 printf(" Compiler has %s for value%s\n",
2226 "an unusable number", oc
);
2228 if (setjmp(lab
) == 0) {
2229 F_check(prec
, (Long_double
) req
);
2230 } /*else forget it*/
2231 if (setjmp(lab
) == 0) {
2232 if (req
> 0.0 && val
> 0.0) {
2233 printf("%s difference= %s%s\n",
2234 co
, f_rep(prec
, val
-req
), oc
);
2236 } /*else forget it*/
2240 } else if (val
!= req
) {
2241 if (stdc
) eek_a_bug("constant has the wrong precision");
2242 else eek_a_bug("the cast didn't work");
2248 int FPROP(bits_per_byte
) int bits_per_byte
; {
2249 /* Properties of floating types, using algorithms by Cody and Waite
2250 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2251 Further extended by S Pemberton.
2253 Returns the number of digits in the fraction.
2257 i
, f_radix
, iexp
, irnd
, mrnd
, f_rounds
, f_mant_dig
,
2258 iz
, k
, inf
, machep
, f_max_exp
, f_min_exp
, mx
, negeps
,
2259 mantbits
, digs
, f_dig
, trap
,
2260 hidden
, normal
, f_min_10_exp
, f_max_10_exp
;
2262 a
, b
, base
, basein
, basem1
, f_epsilon
, epsneg
,
2263 eps
, epsp1
, etop
, ebot
,
2264 f_max
, newxmax
, f_min
, xminner
, y
, y1
, z
, z1
, z2
;
2268 Vprintf("%sPROPERTIES OF %s%s\n", co
, THING
, oc
);
2270 /* Base and size of significand **************************************/
2271 /* First repeatedly double until adding 1 has no effect. */
2272 /* For instance, if base is 10, with 3 significant digits */
2273 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2274 /* since 1024 is only representable as 1020. */
2276 if (setjmp(lab
)==0) { /* inexact trap? */
2278 while (Diff(Diff(Sum(a
, ONE
), a
), ONE
) == ZERO
);
2280 fprintf(stderr
, "*** Program got loss-of-precision trap!\n");
2281 /* And supporting those is just TOO much trouble! */
2285 /* Now double until you find a number that can be added to the */
2286 /* above number. For 1020 this is 8 or 16, depending whether the */
2287 /* result is rounded or truncated. */
2288 /* In either case the result is 1030. 1030-1020= the base, 10. */
2290 do { b
=Sum(b
, b
); } while ((base
=Diff(Sum(a
, b
), a
)) == ZERO
);
2292 Vprintf("%sBase = %d%s\n", co
, f_radix
, oc
);
2294 /* Sanity check; if base<2, I can't guarantee the rest will work */
2296 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2301 if (PASS
== 1) { /* only for FLT */
2303 if (F
) i_define(D_FLT_RADIX
, "", "FLT", "_RADIX",
2304 (long) f_radix
, 0L, (long) F_RADIX
, "");
2305 } else if (f_radix
!= flt_radix
) {
2306 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2307 co
, thing
, "arithmetic has a different radix",
2308 f_radix
, "from float", oc
);
2312 /* Now the number of digits precision */
2313 f_mant_dig
=0; b
=1.0;
2314 do { f_mant_dig
++; b
=Mul(b
, base
); }
2315 while (Diff(Diff(Sum(b
, ONE
), b
), ONE
) == ZERO
);
2316 f_dig
=floor_log(10, (Long_double
)(b
/base
)) + (base
==10?1:0);
2317 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2318 co
, f_mant_dig
, "(= at least", f_dig
, "decimal digits)", oc
);
2319 if (F
) i_define(D_MANT_DIG
, thing
, Fname
, "_MANT_DIG",
2320 (long) f_mant_dig
, 0L, (long) F_MANT_DIG
, "");
2321 if (F
) i_define(D_DIG
, thing
, Fname
, "_DIG",
2322 (long) f_dig
, 0L, (long) F_DIG
, "");
2323 digs
= ceil_log(10, (Long_double
)b
); /* the number of digits to printf */
2325 /* Rounding *******************************************************/
2326 basem1
=Diff(base
, HALF
);
2327 if (Diff(Sum(a
, basem1
), a
) != ZERO
) {
2328 if (f_radix
== 2) basem1
=0.375;
2330 if (Diff(Sum(a
, basem1
), a
) != ZERO
) irnd
=2; /* away from 0 */
2331 else irnd
=1; /* to nearest */
2332 } else irnd
=0; /* towards 0 */
2334 basem1
=Diff(base
, HALF
);
2336 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) {
2337 if (f_radix
== 2) basem1
=0.375;
2339 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) mrnd
=2; /* away from 0*/
2340 else mrnd
=1; /* to nearest */
2341 } else mrnd
=0; /* towards 0 */
2343 f_rounds
= -1; /* Unknown rounding */
2344 if (irnd
==0 && mrnd
==0) f_rounds
=0; /* zero = chops */
2345 if (irnd
==1 && mrnd
==1) f_rounds
=1; /* nearest */
2346 if (irnd
==2 && mrnd
==0) f_rounds
=2; /* +inf */
2347 if (irnd
==0 && mrnd
==2) f_rounds
=3; /* -inf */
2349 if (f_rounds
!= -1) {
2350 Vprintf("%sArithmetic rounds towards ", co
);
2352 case 0: Vprintf("zero (i.e. it chops)"); break;
2353 case 1: Vprintf("nearest"); break;
2354 case 2: Vprintf("+infinity"); break;
2355 case 3: Vprintf("-infinity"); break;
2356 default: Vprintf("???"); break;
2358 Vprintf("%s\n", oc
);
2359 } else { /* Hmm, try to give some help here */
2360 Vprintf("%sArithmetic rounds oddly: %s\n", co
, oc
);
2361 Vprintf("%s Negative numbers %s%s\n",
2362 co
, mrnd
==0 ? "towards zero" :
2363 mrnd
==1 ? "to nearest" :
2366 Vprintf("%s Positive numbers %s%s\n",
2367 co
, irnd
==0 ? "towards zero" :
2368 irnd
==1 ? "to nearest" :
2372 /* An extra goody */
2373 if (f_radix
== 2 && f_rounds
== 1) {
2374 if (Diff(Sum(a
, ONE
), a
) != ZERO
) {
2375 Vprintf("%s Tie breaking rounds up%s\n", co
, oc
);
2376 } else if (Diff(Sum(a
, THREE
), a
) == FOUR
) {
2377 Vprintf("%s Tie breaking rounds to even%s\n", co
, oc
);
2379 Vprintf("%s Tie breaking rounds down%s\n", co
, oc
);
2382 if (PASS
== 1) { /* only for FLT */
2383 flt_rounds
= f_rounds
;
2385 i_define(D_FLT_ROUNDS
, "", "FLT", "_ROUNDS",
2386 (long) f_rounds
, 1L, (long) F_ROUNDS
, "");
2387 } else if (f_rounds
!= flt_rounds
) {
2388 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2389 co
, thing
, "arithmetic rounds differently",
2390 f_rounds
, "from float", oc
);
2394 /* Various flavours of epsilon ************************************/
2395 negeps
=f_mant_dig
+f_mant_dig
;
2398 for(i
=1; i
<=negeps
; i
++) a
*=basein
;
2401 while (Diff(Diff(ONE
, a
), ONE
) == ZERO
) {
2406 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2411 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2412 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2413 ebot and etop are the current bounds */
2414 while (eps
!= ebot
&& eps
!= etop
) {
2415 epsp1
= Diff(ONE
, eps
);
2416 if (epsp1
< ONE
) etop
= eps
;
2418 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2422 if (Diff(ONE
, etop
) >= ONE
|| Diff(ONE
, ebot
) != ONE
) {
2423 eek_a_bug("internal error calculating epsneg");
2425 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2426 co
, f_rep(digs
, (Long_double
) eps
), oc
);
2427 if (V
) F_check(digs
, (Long_double
) eps
);
2430 if ((f_radix
!=2) && irnd
) {
2431 /* a=(a*(1.0+a))/(1.0+1.0); => */
2432 a
=Div(Mul(a
, Sum(ONE
, a
)), Sum(ONE
, ONE
));
2433 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2434 if (Diff(Diff(ONE
, a
), ONE
) != ZERO
) epsneg
=a
;
2436 /* epsneg is used later */
2439 machep
= -f_mant_dig
-f_mant_dig
;
2441 while (Diff(Sum(ONE
, a
), ONE
) == ZERO
) { a
*=base
; machep
++; }
2442 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2447 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2448 /* find the smallest eps (1+eps != 1) by binary search.
2449 ebot and etop are the current bounds */
2450 while (eps
!= ebot
&& eps
!= etop
) {
2451 epsp1
= Sum(ONE
, eps
);
2452 if (epsp1
> ONE
) etop
= eps
;
2454 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2457 if (Sum(ONE
, etop
) <= ONE
|| Sum(ONE
, ebot
) != ONE
) {
2458 eek_a_bug("internal error calculating eps");
2462 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2463 co
, f_rep(digs
, (Long_double
) f_epsilon
), oc
);
2465 f_epsilon
= Diff(Sum(ONE
, f_epsilon
), ONE
); /* New C standard defn */
2466 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2467 co
, f_rep(digs
, (Long_double
) (f_epsilon
)), oc
);
2469 /* Possible loss of precision warnings here from non-stdc compilers */
2470 if (F
) f_define(D_EPSILON
, thing
,
2471 Fname
, "_EPSILON", digs
, (Long_double
) f_epsilon
, MARK
);
2472 if (V
|| F
) F_check(digs
, (Long_double
) f_epsilon
);
2474 if (F
) Validate(digs
, (Long_double
) f_epsilon
, (Long_double
) F_EPSILON
,
2475 f_epsilon
== Self(F_EPSILON
));
2478 /* Extra chop info *************************************************/
2479 if (f_rounds
== 0) {
2480 if (Diff(Mul(Sum(ONE
,f_epsilon
),ONE
),ONE
) != ZERO
) {
2481 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co
, oc
);
2485 /* Size of and minimum normalised exponent ************************/
2486 y
=0; i
=0; k
=1; z
=basein
; z1
=(1.0+f_epsilon
)/base
;
2488 /* Coarse search for the largest power of two */
2489 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2492 z
=Mul(y
,y
); z1
=Mul(z1
, y
);
2495 if (z2
!= y1
) break;
2496 if ((Sum(a
,a
) == ZERO
) || (fabs(z
) >= y
)) break;
2501 Vprintf("%s%s underflow generates a trap%s\n", co
, Thing
, oc
);
2505 if (f_radix
!= 10) {
2506 iexp
=i
+1; /* for the sign */
2511 while (k
>= iz
) { iz
*=f_radix
; iexp
++; }
2515 /* Fine tune starting with y and y1 */
2516 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields k, f_min */
2519 y
=Div(y
,base
); y1
=Div(y1
,base
);
2522 if (z2
!= z1
) break;
2523 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= f_min
)) break;
2531 if ((mx
<= k
+k
-3) && (f_radix
!= 10)) { mx
+=mx
; iexp
+=1; }
2532 Vprintf("%sNumber of bits used for exponent = %d%s\n", co
, iexp
, oc
);
2533 Vprintf("%sMinimum normalised exponent = %d%s\n", co
, f_min_exp
-1, oc
);
2535 i_define(D_MIN_EXP
, thing
, Fname
, "_MIN_EXP",
2536 (long) f_min_exp
, (long) maxint
, (long) F_MIN_EXP
, "");
2538 if (setjmp(lab
)==0) {
2539 Vprintf("%sMinimum normalised positive number = %s%s\n",
2540 co
, f_rep(digs
, (Long_double
) f_min
), oc
);
2542 eek_a_bug("printf can't print the smallest normalised number");
2546 /* Possible loss of precision warnings here from non-stdc compilers */
2547 if (setjmp(lab
) == 0) {
2548 if (F
) f_define(D_MIN
, thing
,
2549 Fname
, "_MIN", digs
, (Long_double
) f_min
, MARK
);
2550 if (V
|| F
) F_check(digs
, (Long_double
) f_min
);
2552 eek_a_bug("xxx_MIN caused a trap");
2556 if (setjmp(lab
) == 0) {
2557 if (F
) Validate(digs
, (Long_double
) f_min
, (Long_double
) F_MIN
,
2558 f_min
== Self(F_MIN
));
2560 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2561 co
, "Compiler has an unusable number for value", oc
);
2566 a
=1.0; f_min_10_exp
=0;
2567 while (a
> f_min
*10.0) { a
/=10.0; f_min_10_exp
--; }
2568 if (F
) i_define(D_MIN_10_EXP
, thing
, Fname
, "_MIN_10_EXP",
2569 (long) f_min_10_exp
, (long) maxint
,
2570 (long) F_MIN_10_EXP
, "");
2572 /* Minimum exponent ************************************************/
2573 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields xminner */
2578 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= xminner
)) break;
2583 if (xminner
!= 0.0 && xminner
!= f_min
) {
2585 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2587 if (setjmp(lab
)==0) {
2588 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2589 co
, f_rep(digs
, (Long_double
) xminner
), oc
);
2590 if (V
) F_check(digs
, (Long_double
) xminner
);
2592 eek_a_bug("printf can't print the smallest unnormalised number.");
2598 Vprintf("%sThe smallest numbers are normalised%s\n", co
, oc
);
2601 /* Maximum exponent ************************************************/
2602 f_max_exp
=2; f_max
=1.0; newxmax
=base
+1.0;
2604 while (f_max
<newxmax
) {
2606 if (setjmp(lab
) == 0) { /* Yields inf, f_max_exp */
2607 newxmax
=Mul(newxmax
, base
);
2612 if (Div(newxmax
, base
) != f_max
) {
2613 inf
=1; /* ieee infinity */
2620 Vprintf("%s%s overflow generates a trap%s\n", co
, Thing
, oc
);
2623 if (inf
) Vprintf("%sThere is an 'infinite' value%s\n", co
, oc
);
2624 Vprintf("%sMaximum exponent = %d%s\n", co
, f_max_exp
, oc
);
2625 if (F
) i_define(D_MAX_EXP
, thing
, Fname
, "_MAX_EXP",
2626 (long) f_max_exp
, 0L, (long) F_MAX_EXP
, "");
2628 /* Largest number ***************************************************/
2629 f_max
=Diff(ONE
, epsneg
);
2630 if (Mul(f_max
,ONE
) != f_max
) f_max
=Diff(ONE
, Mul(base
,epsneg
));
2631 for (i
=1; i
<=f_max_exp
; i
++) f_max
=Mul(f_max
, base
);
2633 if (setjmp(lab
)==0) {
2634 Vprintf("%sMaximum number = %s%s\n",
2635 co
, f_rep(digs
, (Long_double
) f_max
), oc
);
2637 eek_a_bug("printf can't print the largest double.");
2640 if (setjmp(lab
)==0) {
2641 /* Possible loss of precision warnings here from non-stdc compilers */
2642 if (F
) f_define(D_MAX
, thing
,
2643 Fname
, "_MAX", digs
, (Long_double
) f_max
, MARK
);
2644 if (V
|| F
) F_check(digs
, (Long_double
) f_max
);
2646 eek_a_bug("xxx_MAX caused a trap");
2649 if (setjmp(lab
)==0) {
2650 if (F
) Validate(digs
, (Long_double
) f_max
, (Long_double
) F_MAX
,
2651 f_max
== Self(F_MAX
));
2653 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2654 co
, "Compiler has an unusable number for value", oc
);
2659 a
=1.0; f_max_10_exp
=0;
2660 while (a
< f_max
/10.0) { a
*=10.0; f_max_10_exp
++; }
2661 if (F
) i_define(D_MAX_10_EXP
, thing
, Fname
, "_MAX_10_EXP",
2662 (long) f_max_10_exp
, 0L, (long) F_MAX_10_EXP
, "");
2664 /* Hidden bit + sanity check ****************************************/
2665 if (f_radix
!= 10) {
2667 mantbits
=floor_log(2, (Long_double
)f_radix
)*f_mant_dig
;
2668 if (mantbits
+iexp
== (int)sizeof(Number
)*bits_per_byte
) {
2670 Vprintf("%sArithmetic uses a hidden bit%s\n", co
, oc
);
2671 } else if (mantbits
+iexp
+1 == (int)sizeof(Number
)*bits_per_byte
) {
2672 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2675 printf("\n%s%s\n %s %s %s!%s\n\n",
2677 "*** Something fishy here!",
2678 "Exponent size + significand size doesn't match",
2679 "with the size of a", thing
,
2682 if (hidden
&& f_radix
== 2 && f_max_exp
+f_min_exp
==3) {
2683 Vprintf("%sIt looks like %s length IEEE format%s\n",
2684 co
, f_mant_dig
==24 ? "single" :
2685 f_mant_dig
==53 ? "double" :
2686 f_mant_dig
>53 ? "extended" :
2688 if (f_rounds
!= 1 || normal
) {
2689 Vprintf("%s though ", co
);
2690 if (f_rounds
!= 1) {
2691 Vprintf("the rounding is unusual");
2692 if (normal
) Vprintf(" and ");
2694 if (normal
) Vprintf("the normalisation is unusual");
2695 Vprintf("%s\n", oc
);
2698 Vprintf("%sIt doesn't look like IEEE format%s\n",
2702 printf("\n"); /* regardless of verbosity */
2706 Procedure
EPROP(fprec
, dprec
, lprec
) int fprec
, dprec
, lprec
; {
2707 /* See if expressions are evaluated in extended precision.
2708 Some compilers optimise even if you don't want it,
2709 and then this function fails to produce the right result.
2710 We try to diagnose this if it happens.
2713 Volatile
double a
, b
, base
, old
;
2714 Volatile Number d
, oldd
, dbase
, one
, zero
;
2717 /* Size of significand **************************************/
2719 if (setjmp(lab
) == 0) { /* Yields nothing */
2720 do { old
=a
; a
=a
+a
; }
2721 while ((((a
+1.0)-a
)-1.0) == 0.0 && a
>old
);
2724 /* Avoid the comparison if bad is set,
2725 to avoid trouble on the convex. */
2726 if (!bad
&& (a
<= old
)) bad
=1;
2730 if (setjmp(lab
) == 0) { /* Yields nothing */
2731 do { old
=b
; b
=b
+b
; }
2732 while ((base
=((a
+b
)-a
)) == 0.0 && b
>old
);
2733 if (b
<= old
) bad
=1;
2738 eprec
=0; d
=1.0; dbase
=base
; one
=1.0; zero
=0.0;
2739 if (setjmp(lab
) == 0) { /* Yields nothing */
2740 do { eprec
++; oldd
=d
; d
=d
*dbase
; }
2741 while ((((d
+one
)-d
)-one
) == zero
&& d
>oldd
);
2742 if (d
<= oldd
) bad
=1;
2749 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2750 co
, thing
, " check that you compiled without optimisation!",
2752 } else if (eprec
==dprec
) {
2753 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2755 } else if (eprec
==fprec
) {
2756 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2758 } else if (eprec
==lprec
) {
2759 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2762 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2763 co
, Thing
, eprec
>dprec
? "higher" : "lower",
2764 "precision than double,\n using",
2765 eprec
, "base digits",
2770 #else /* not Number */
2772 #ifdef FPROP /* Then create dummy routines for long double */
2774 int FPROP(bits_per_byte
) int bits_per_byte
; { return 0; }
2778 Procedure
EPROP(fprec
, dprec
, lprec
) int fprec
, dprec
, lprec
; {}
2781 #endif /* ifdef Number */
2783 /* Increment the pass number */
2802 #ifdef PASS /* then rescan this file */
2804 #include "enquire.c"
2806 #include FILENAME /* if this line fails to compile, define NO_FILE */