]> gcc.gnu.org Git - gcc.git/blob - gcc/enquire.c
037dc1e47f471743f74dbda91d29acdce6757326
[gcc.git] / gcc / enquire.c
1 /* Everything you wanted to know about your machine and C compiler,
2 but didn't know who to ask. */
3
4 #ifndef VERSION
5 #define VERSION "4.3"
6 #endif
7
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9 Bugfixes and upgrades gratefully received.
10
11 Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
12 All rights reserved.
13
14 Changes by Richard Stallman:
15 Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
16 In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
17 Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
18 Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
19 Include sys/types.h before signal.h, Apr 92.
20 Support NO_LONG_DOUBLE_IO in f_define and f_rep; new fn fake_f_rep, Apr 92.
21 Enclose -f output in #ifndef _FLOAT_H___, Richard Stallman, May 92.
22
23 Add #undef before every #define, Jim Wilson, Dec 92.
24
25 Changes by Paul Eggert, installed Feb 93:
26 (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
27 (f_define): Use ordinary constants for long double
28 if it's same width as double. Make __convert_long_double_i unsigned.
29
30 COMPILING
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.
34
35 If your compiler doesn't support: add flag:
36 signed char (eg pcc) -DNO_SC
37 unsigned char -DNO_UC
38 unsigned short and long -DNO_UI
39 void -DNO_VOID
40 signal(), or setjmp/longjmp() -DNO_SIG
41 %Lf in printf -DNO_LONG_DOUBLE_IO
42
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.
46
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.
50
51 Some compilers offer various flags for different floating point
52 modes; it's worth trying all possible combinations of these.
53
54 Add -DID=\"name\" if you want the machine/flags identified in the output.
55
56 FAULTY COMPILERS
57 Because of bugs and/or inadequacies, some compilers need the following
58 defines:
59
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\" .
63
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.
66
67 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
68 or -DNO_FILE as above.
69
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).
74
75 Some naughty compilers define __STDC__, but don't have the stddef.h
76 include file. Add flag -DNO_STDDEF.
77
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
84 stddef.h -DNO_STDDEF
85
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.
89
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
99
100 SYSTEM DEPENDENCIES
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!).
104
105 OUTPUT
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.
114
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.
127
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.
130
131 TROUBLESHOOTING.
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
135 accepted, etc.)
136
137 The program only works if overflows are ignored by the C system or
138 are catchable with signal().
139
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.
144
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).
148
149 Make sure you compiled with optimisation turned off.
150
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.
174
175 The warning that "a cast didn't work" refers to cases like this:
176
177 float f;
178 #define C 1.234567890123456789
179 f= C;
180 if (f != (float) C) printf ("Wrong!");
181
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
189 wrong precision".
190
191 REPORTING PROBLEMS
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.
199
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.
203
204 I apologise unreservedly for the contorted use of the preprocessor...
205
206 THE SMALL PRINT
207 You may copy and distribute verbatim copies of this source file.
208
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.
217
218 If you do have a fix to any problem, please send it to me, so that
219 other people can have the benefits.
220
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.
224
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.
229
230 ACKNOWLEDGEMENTS
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.
233
234 HISTORY
235 Originally started as a program to generate configuration constants
236 for a large piece of software we were writing, which later took on
237 a life of its own...
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
245 Handles Cybers
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
251 Handles long double
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
256 Added SEP
257 Fixed eps/epsneg
258 Added check for pseudo-unsigned chars
259 Added description for each #define output
260 Added check for absence of defines during verify
261 Added prototypes
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
281 Added NO_STDDEF
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
286 Added NO_MEM
287 */
288
289 /* Set FILENAME to the name of this file */
290 #ifndef FILENAME
291 #ifdef NO_FILE
292 #define FILENAME "enquire.c"
293 #else
294 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
295 #define FILENAME __FILE__
296 #else
297 #define FILENAME "enquire.c"
298 #endif /* __FILE__ */
299 #endif /* NO_FILE */
300 #endif /* FILENAME */
301
302 /* If PASS isn't defined, then this is the first pass over this file. */
303 #ifndef PASS
304 #ifndef SEP
305 #define PASS 1
306 #define PASS0 1
307 #define PASS1 1
308 #endif /* SEP */
309
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)"
317
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)"
321
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"
333
334 /* Procedure just marks the functions that don't return a result */
335 #ifdef NO_VOID
336 #define Procedure int
337 #else
338 #define Procedure void
339 #endif
340
341 /* Some bad compilers define __STDC__, when they don't support it.
342 Compile with -DNO_STDC to get round this.
343 */
344 #ifndef NO_STDC
345 #ifdef __STDC__
346 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
347 #define STDC
348 #endif
349 #endif
350 #endif
351
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.
360 */
361 #ifdef STDC
362
363 #define ARGS(x) x
364 #define NOARGS (void)
365 #define Volatile volatile
366 #define Long_double long double
367 #define stdc 1
368 #define U "U"
369
370 #else /* Old style C */
371
372 #define ARGS(x) ()
373 #define NOARGS ()
374 #define Volatile static
375 #define Long_double double
376 #define stdc 0
377 #define U ""
378
379 #endif /* STDC */
380
381 /* include files */
382 #include <stdio.h>
383
384 #ifdef STDC
385 #ifndef NO_STDDEF
386 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
387 #endif
388 #endif
389
390 #ifdef NO_SIG
391 #define jmp_buf int
392 #else
393 #include <sys/types.h>
394 #include <signal.h>
395 #include <setjmp.h>
396 #endif
397
398 /* Kludge around the possibility that <stdio.h> includes <limits.h> */
399 #ifdef CHAR_BIT
400 #undef CHAR_BIT
401 #undef CHAR_MAX
402 #undef CHAR_MIN
403 #undef SCHAR_MAX
404 #undef SCHAR_MIN
405 #undef UCHAR_MAX
406 #undef UCHAR_MIN
407 #endif
408
409 #ifdef VERIFY
410 #include "limits.h"
411 #include "float.h"
412 #endif
413
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))
417
418 #endif /* PASS */
419
420 #ifdef PASS0
421
422 /* Prototypes for what's to come: */
423
424 int false NOARGS;
425
426 #ifdef NO_STDDEF
427 char *malloc (); /* Old style prototype */
428 #else
429 char *malloc ARGS((size_t size));
430 #endif
431
432 Procedure exit ARGS((int status));
433
434 char *f_rep ARGS((int precision, Long_double val));
435 char *fake_f_rep ARGS((char *type, Long_double val));
436
437 int maximum_int NOARGS;
438 int cprop NOARGS;
439 int basic 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));
452
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));
472
473 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
474
475 /* Dummy routines instead */
476
477 int setjmp ARGS((int lab));
478
479 int lab=1;
480 int setjmp(lab) int lab; { return(0); }
481 Procedure signal(i, p) int i, (*p)(); {}
482
483 #else
484 jmp_buf lab;
485 Procedure overflow(sig) int sig; { /* what to do on over/underflow */
486 signal(sig, overflow);
487 longjmp(lab, 1);
488 }
489
490 #endif /*NO_SIG*/
491
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 */
496
497 char co[4], oc[4]; /* Comment starter and ender symbols */
498
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 */
502
503 #ifdef TEST
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
509 */
510
511 /* Bits 0x30 = rounding mode */
512 #define ROUND_BITS 0x30
513 #define TO_NEAREST 0x00
514 #define TO_ZERO 0x10
515 #define TO_MINUS_INF 0x20
516 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
517
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
523
524 /* Enabled traps */
525 #define EXE_INEX1 0x100
526 #define EXE_INEX2 0x200
527 #define EXE_DZ 0x400
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
533
534 /* Only used for testing, on a Sun with 68881 chip */
535 /* Print the FP mode */
536 printmode(new) unsigned new; {
537 fpmode_(&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;
546 }
547
548 printf("\n Extended rounding precision: ");
549
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;
555 }
556
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");
566 printf("\n");
567 }
568
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;
573 char c;
574
575 while (*s) {
576 c= *s++;
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;
580 else return 1;
581 mode= mode<<4 | dig;
582 }
583 printmode(mode);
584 return 0;
585 }
586 #else
587 /* ARGSUSED */
588 int setmode(s) char *s; {
589 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
590 return(1);
591 }
592 #endif
593
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);
601 exit(bugs);
602 }
603
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 */
608 }
609
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);
613 if (value == 0) {
614 fprintf(stderr, "Virtual memory exceeded\n");
615 exit(bugs+1);
616 }
617 return value;
618 }
619
620 int maxint;
621
622 int maximum_int() {
623 /* Find the maximum integer */
624 Volatile int newi, int_max, two=2;
625
626 /* Calculate maxint ***********************************/
627 /* Calculate 2**n-1 until overflow - then use the previous value */
628
629 newi=1; int_max=0;
630
631 if (setjmp(lab)==0) { /* Yields int_max */
632 while(newi>int_max) {
633 int_max=newi;
634 newi=newi*two+1;
635 }
636 }
637 Unexpected(0);
638 return int_max;
639 }
640
641 int main(argc, argv) int argc; char *argv[]; {
642 int dprec, fprec, lprec;
643 unsigned int size;
644 long total;
645 int i; char *s; int bad;
646
647 #ifdef SIGFPE
648 signal(SIGFPE, overflow);
649 #endif
650 #ifdef SIGOVER
651 signal(SIGOVER, overflow);
652 #endif
653 /* Add more calls as necessary */
654
655 Unexpected(1);
656
657 bad=0;
658 for (i=1; i < argc; i++) {
659 s= argv[i];
660 if (*s == '-') {
661 s++;
662 while (*s) {
663 switch (*(s++)) {
664 case 'v': V=1; break;
665 case 'l': L=1; break;
666 case 'f': F=1; break;
667 default: bad=1; break;
668 }
669 }
670 } else if (*s == '+') {
671 s++;
672 bad= setmode(s);
673 } else bad= 1;
674 }
675 if (bad) {
676 fprintf(stderr,
677 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
678 argv[0]);
679 exit(1);
680 }
681 if (L || F) {
682 co[0]= '/'; oc[0]= ' ';
683 co[1]= '*'; oc[1]= '*';
684 co[2]= ' '; oc[2]= '/';
685 co[3]= '\0'; oc[3]= '\0';
686 } else {
687 co[0]= '\0'; oc[0]= '\0';
688 V=1;
689 }
690
691 if (L) printf("%slimits.h%s\n", co, oc);
692 if (F) printf("%sfloat.h%s\n", co, oc);
693 if (F) {
694 printf ("#ifndef _FLOAT_H___\n");
695 printf ("#define _FLOAT_H___\n");
696 }
697 #ifdef ID
698 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
699 co, ID, VERSION, oc);
700 #else
701 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
702 co, VERSION, oc);
703 #endif
704
705 #ifdef VERIFY
706 printf("%sVerification phase%s\n", co, oc);
707 #endif
708
709 #ifdef NO_SIG
710 Vprintf("%sCompiled without signal(): %s%s\n",
711 co,
712 "there's nothing that can be done if overflow occurs",
713 oc);
714 #endif
715 #ifdef NO_SC
716 Vprintf("%sCompiled without signed char%s\n", co, oc);
717 #endif
718 #ifdef NO_UC
719 Vprintf("%Compiled without unsigned char%s\n", co, oc);
720 #endif
721 #ifdef NO_UI
722 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
723 #endif
724 #ifdef __STDC__
725 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
726 co, __STDC__, oc);
727 #else
728 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
729 #endif
730 printf("\n");
731 check_defines();
732
733 maxint= maximum_int();
734 bits_per_byte= basic();
735 Vprintf("\n");
736 if (F||V) {
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);
743 }
744 #ifndef NO_MEM
745 if (V) {
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);
752 total=0;
753 while (size!=0) {
754 while ( malloc((false()?sizeof(int):size)) !=
755 (char *)NULL
756 ) {
757 total+=(size/2);
758 }
759 size/=2;
760 }
761
762 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
763 co, (total+511)/512, oc);
764 }
765 #endif
766 if (F) {
767 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
768 }
769 farewell(bugs);
770 return bugs; /* To keep compilers and lint happy */
771 }
772
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);
776 bugs++;
777 }
778
779 Procedure describe(description, extra) char *description, *extra; {
780 /* Produce the description for a #define */
781 printf(" %s", co);
782 printf(description, extra);
783 printf("%s\n", oc);
784 }
785
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);
791 if (val >= 0) {
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);
799 } else {
800 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
801 }
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
805 */
806 if (val != req) {
807 printf("%s*** Verify failed for above #define!\n", co);
808 printf(" Compiler has %ld for value%s\n\n", req, oc);
809 bugs++;
810 }
811 Vprintf("\n");
812 }
813
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);
820 if (val != req) {
821 printf("%s*** Verify failed for above #define!\n", co);
822 printf(" Compiler has %lu for value%s\n\n", req, oc);
823 bugs++;
824 }
825 Vprintf("\n");
826 }
827
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);
834 if (stdc) {
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");
845 printf("};\n");
846 printf("#endif\n");
847 union_defined = 1;
848 }
849 printf("#define %s%s %s\n",
850 sort, name, fake_f_rep("long double", val));
851 } else {
852 printf("#define %s%s %s%s\n",
853 sort, name, f_rep(precision, val), mark);
854 }
855 #else
856 printf("#define %s%s %s%s\n",
857 sort, name, f_rep(precision, val), mark);
858 #endif
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));
863 } else {
864 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
865 }
866 Vprintf("\n");
867 }
868
869 int floor_log(base, x) int base; Long_double x; {
870 /* return floor(log base(x)) */
871 int r=0;
872 while (x>=base) { r++; x/=base; }
873 return r;
874 }
875
876 int ceil_log(base, x) int base; Long_double x; {
877 int r=0;
878 while (x>1.0) { r++; x/=base; }
879 return r;
880 }
881
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.
886 */
887 int r=0, neg=0;
888 Long_double old;
889 *fract=0.0; *exp=0;
890 if (x<0.0) {
891 x= -x;
892 neg= 1;
893 }
894 if (x==0.0) return 1;
895 if (x>=10.0) {
896 while (x>=10.0) {
897 old=x; r++; x/=10.0;
898 if (old==x) return 0;
899 }
900 } else {
901 while (x<1.0) {
902 old=x; r--; x*=10.0;
903 if (old==x) return 0;
904 }
905 }
906 if (neg) *fract= (double) -x;
907 else *fract=(double) x;
908 *exp=r;
909 return 1;
910 }
911
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
915 a bit pattern. */
916
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;
921 u.ld = val;
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]);
924 return buf;
925 }
926
927 char *f_rep(precision, val) int precision; Long_double val; {
928 /* Return the floating representation of val */
929 static char buf[1024];
930 char *f1;
931 #ifdef NO_LONG_DOUBLE_IO
932 if (1)
933 #else
934 if (sizeof(double) == sizeof(Long_double))
935 #endif
936 {
937 double d = val;
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);
941 } else {
942 /* It had better support Le then */
943 sprintf(buf, "%.*Le", precision, val);
944 }
945 return buf;
946 }
947
948 Procedure bitpattern(p, size) char *p; unsigned int size; {
949 /* Printf the bit-pattern of p */
950 char c;
951 int i, j;
952
953 for (i=1; i<=size; i++) {
954 c= *p;
955 p++;
956 for (j=bits_per_byte-1; j>=0; j--)
957 printf("%c", (c>>j)&1 ? '1' : '0');
958 if (i!=size) printf(" ");
959 }
960 }
961
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); }\
966 printf("%s\n", oc);
967
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;
973
974 char *ps= (char *) &s,
975 *pj= (char *) &j,
976 *pl= (char *) &l,
977 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
978 unsigned int mask, i, c;
979
980 mask=0;
981 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
982
983 if (V) {
984 printf("%sCHARACTER ORDER%s\n", co, oc);
985 Order(s, ps, "short:");
986 Order(j, pj, "int: ");
987 Order(l, pl, "long: ");
988 }
989 }
990
991 Procedure missing(s) char *s; {
992 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
993 bugs++;
994 }
995
996 Procedure fmissing(s) char *s; {
997 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
998 bugs++;
999 }
1000
1001 /* To try and fool optimisers */
1002 int false() { return 0; }
1003
1004 #define Promoted(x) (false()?(x):(-1))
1005 #define is_signed(x) (Promoted(x) < 0)
1006 #define sign_of(x) ((x)?"signed":"unsigned")
1007 #define Signed 1
1008 #define Unsigned 0
1009 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1010
1011 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1012
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";
1017 return "char";
1018 }
1019 if (x == sizeof(short)) {
1020 if (sizeof(short) == sizeof(int)) return "short/int";
1021 return "short";
1022 }
1023 if (x == sizeof(int)) {
1024 if (sizeof(int) == sizeof(long)) return "int/long";
1025 return "int";
1026 }
1027 if (x == sizeof(long)) return "long";
1028 return "unknown-type";
1029 }
1030
1031 char *ftype_of(x) int x; {
1032 if (x == sizeof(float)) {
1033 return "float";
1034 }
1035 if (x == sizeof(double)) {
1036 if (sizeof(double) == sizeof(Long_double))
1037 return "(long)double";
1038 return "double";
1039 }
1040 if (x == sizeof(Long_double)) {
1041 return "long double";
1042 }
1043 return "unknown-type";
1044 }
1045
1046 Procedure typerr(name, esign, esize, sign, size)
1047 char *name; int esign, esize, sign, size;
1048 {
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));
1052 }
1053
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));
1057 }
1058
1059 promotions() {
1060 int si; long sl;
1061 unsigned int ui; unsigned long ul;
1062 short ss; unsigned short us;
1063
1064 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1065
1066 if (
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)
1076 )
1077 {
1078 eek_a_bug("promotions don't work properly in conditional expressions\n");
1079 }
1080
1081 showtype("unsigned short promotes to", Promoted((unsigned short)0));
1082 showtype("long+unsigned gives", sl+ui);
1083 }
1084
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));
1086
1087 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1088
1089 Procedure check_defines() {
1090 /* ensure that all #defines are present and have the correct type */
1091 #ifdef VERIFY
1092 int usign;
1093
1094 #ifdef NO_UI
1095 usign= Signed;
1096 #else
1097 /* Implementations promote unsigned short differently */
1098 usign= is_signed((unsigned short)0);
1099 #endif
1100
1101 if (L) {
1102 #ifdef CHAR_BIT
1103 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1104 #else
1105 missing("CHAR_BIT");
1106 #endif
1107 #ifdef CHAR_MAX
1108 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1109 #else
1110 missing("CHAR_MAX");
1111 #endif
1112 #ifdef CHAR_MIN
1113 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1114 #else
1115 missing("CHAR_MIN");
1116 #endif
1117 #ifdef SCHAR_MAX
1118 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1119 #else
1120 missing("SCHAR_MAX");
1121 #endif
1122 #ifdef SCHAR_MIN
1123 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1124 #else
1125 missing("SCHAR_MIN");
1126 #endif
1127 #ifdef UCHAR_MAX
1128 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1129 #else
1130 missing("UCHAR_MAX");
1131 #endif
1132 #ifdef SHRT_MAX
1133 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1134 #else
1135 missing("SHRT_MAX");
1136 #endif
1137 #ifdef SHRT_MIN
1138 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1139 #else
1140 missing("SHRT_MIN");
1141 #endif
1142 #ifdef INT_MAX
1143 checktype(INT_MAX, "INT_MAX", Signed, int);
1144 #else
1145 missing("INT_MAX");
1146 #endif
1147 #ifdef INT_MIN
1148 checktype(INT_MIN, "INT_MIN", Signed, int);
1149 #else
1150 missing("INT_MIN");
1151 #endif
1152 #ifdef LONG_MAX
1153 checktype(LONG_MAX, "LONG_MAX", Signed, long);
1154 #else
1155 missing("LONG_MAX");
1156 #endif
1157 #ifdef LONG_MIN
1158 checktype(LONG_MIN, "LONG_MIN", Signed, long);
1159 #else
1160 missing("LONG_MIN");
1161 #endif
1162 #ifdef USHRT_MAX
1163 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1164 #else
1165 missing("USHRT_MAX");
1166 #endif
1167 #ifdef UINT_MAX
1168 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1169 #else
1170 missing("UINT_MAX");
1171 #endif
1172 #ifdef ULONG_MAX
1173 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1174 #else
1175 missing("ULONG_MAX");
1176 #endif
1177 } /* if (L) */
1178
1179 if (F) {
1180 #ifdef FLT_RADIX
1181 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1182 #else
1183 fmissing("FLT_RADIX");
1184 #endif
1185 #ifdef FLT_MANT_DIG
1186 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1187 #else
1188 fmissing("FLT_MANT_DIG");
1189 #endif
1190 #ifdef FLT_DIG
1191 checktype(FLT_DIG, "FLT_DIG", Signed, int);
1192 #else
1193 fmissing("FLT_DIG");
1194 #endif
1195 #ifdef FLT_ROUNDS
1196 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1197 #else
1198 fmissing("FLT_ROUNDS");
1199 #endif
1200 #ifdef FLT_EPSILON
1201 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1202 #else
1203 fmissing("FLT_EPSILON");
1204 #endif
1205 #ifdef FLT_MIN_EXP
1206 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1207 #else
1208 fmissing("FLT_MIN_EXP");
1209 #endif
1210 #ifdef FLT_MIN
1211 fchecktype(FLT_MIN, "FLT_MIN", float);
1212 #else
1213 fmissing("FLT_MIN");
1214 #endif
1215 #ifdef FLT_MIN_10_EXP
1216 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1217 #else
1218 fmissing("FLT_MIN_10_EXP");
1219 #endif
1220 #ifdef FLT_MAX_EXP
1221 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1222 #else
1223 fmissing("FLT_MAX_EXP");
1224 #endif
1225 #ifdef FLT_MAX
1226 fchecktype(FLT_MAX, "FLT_MAX", float);
1227 #else
1228 fmissing("FLT_MAX");
1229 #endif
1230 #ifdef FLT_MAX_10_EXP
1231 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1232 #else
1233 fmissing("FLT_MAX_10_EXP");
1234 #endif
1235 #ifdef DBL_MANT_DIG
1236 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1237 #else
1238 fmissing("DBL_MANT_DIG");
1239 #endif
1240 #ifdef DBL_DIG
1241 checktype(DBL_DIG, "DBL_DIG", Signed, int);
1242 #else
1243 fmissing("DBL_DIG");
1244 #endif
1245 #ifdef DBL_EPSILON
1246 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1247 #else
1248 fmissing("DBL_EPSILON");
1249 #endif
1250 #ifdef DBL_MIN_EXP
1251 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1252 #else
1253 fmissing("DBL_MIN_EXP");
1254 #endif
1255 #ifdef DBL_MIN
1256 fchecktype(DBL_MIN, "DBL_MIN", double);
1257 #else
1258 fmissing("DBL_MIN");
1259 #endif
1260 #ifdef DBL_MIN_10_EXP
1261 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1262 #else
1263 fmissing("DBL_MIN_10_EXP");
1264 #endif
1265 #ifdef DBL_MAX_EXP
1266 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1267 #else
1268 fmissing("DBL_MAX_EXP");
1269 #endif
1270 #ifdef DBL_MAX
1271 fchecktype(DBL_MAX, "DBL_MAX", double);
1272 #else
1273 fmissing("DBL_MAX");
1274 #endif
1275 #ifdef DBL_MAX_10_EXP
1276 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1277 #else
1278 fmissing("DBL_MAX_10_EXP");
1279 #endif
1280 #ifdef STDC
1281 #ifdef LDBL_MANT_DIG
1282 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1283 #else
1284 fmissing("LDBL_MANT_DIG");
1285 #endif
1286 #ifdef LDBL_DIG
1287 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1288 #else
1289 fmissing("LDBL_DIG");
1290 #endif
1291 #ifdef LDBL_EPSILON
1292 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1293 #else
1294 fmissing("LDBL_EPSILON");
1295 #endif
1296 #ifdef LDBL_MIN_EXP
1297 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1298 #else
1299 fmissing("LDBL_MIN_EXP");
1300 #endif
1301 #ifdef LDBL_MIN
1302 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1303 #else
1304 fmissing("LDBL_MIN");
1305 #endif
1306 #ifdef LDBL_MIN_10_EXP
1307 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1308 #else
1309 fmissing("LDBL_MIN_10_EXP");
1310 #endif
1311 #ifdef LDBL_MAX_EXP
1312 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1313 #else
1314 fmissing("LDBL_MAX_EXP");
1315 #endif
1316 #ifdef LDBL_MAX
1317 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1318 #else
1319 fmissing("LDBL_MAX");
1320 #endif
1321 #ifdef LDBL_MAX_10_EXP
1322 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1323 #else
1324 fmissing("LDBL_MAX_10_EXP");
1325 #endif
1326 #endif /* STDC */
1327 } /* if (F) */
1328 #endif /* VERIFY */
1329 }
1330
1331 #ifdef VERIFY
1332 #ifndef SCHAR_MAX
1333 #define SCHAR_MAX char_max
1334 #endif
1335 #ifndef SCHAR_MIN
1336 #define SCHAR_MIN char_min
1337 #endif
1338 #ifndef UCHAR_MAX
1339 #define UCHAR_MAX char_max
1340 #endif
1341 #endif /* VERIFY */
1342
1343 #ifndef CHAR_BIT
1344 #define CHAR_BIT char_bit
1345 #endif
1346 #ifndef CHAR_MAX
1347 #define CHAR_MAX char_max
1348 #endif
1349 #ifndef CHAR_MIN
1350 #define CHAR_MIN char_min
1351 #endif
1352 #ifndef SCHAR_MAX
1353 #define SCHAR_MAX char_max
1354 #endif
1355 #ifndef SCHAR_MIN
1356 #define SCHAR_MIN char_min
1357 #endif
1358 #ifndef UCHAR_MAX
1359 #define UCHAR_MAX char_max
1360 #endif
1361
1362 int cprop() {
1363 /* Properties of type char */
1364 Volatile char c, char_max, char_min;
1365 Volatile int bits_per_byte, c_signed;
1366 long char_bit;
1367
1368 Unexpected(2);
1369
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);
1373 c= (char)(-1);
1374 if (((int)c)<0) c_signed=1;
1375 else c_signed=0;
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, "");
1381
1382 c=0; char_max=0;
1383 c++;
1384 if (setjmp(lab)==0) { /* Yields char_max */
1385 while (c>char_max) {
1386 char_max=c;
1387 c++;
1388 }
1389 } else {
1390 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1391 }
1392 c=0; char_min=0;
1393 c--;
1394 if (setjmp(lab)==0) { /* Yields char_min */
1395 while (c<char_min) {
1396 char_min=c;
1397 c--;
1398 }
1399 }
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);
1405 }
1406 Unexpected(3);
1407
1408 if (L) {
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",
1413 (long) char_max,
1414 (long) CHAR_MAX, "");
1415 } else {
1416 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1417 (long) char_max, 0L,
1418 (long) CHAR_MAX, "");
1419 }
1420 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1421 (long) char_min, (long) maxint,
1422 (long) CHAR_MIN, "");
1423 if (c_signed) {
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, "");
1430 } else {
1431 if (sizeof(char) == sizeof(int)) {
1432 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1433 (long) char_max,
1434 (long) UCHAR_MAX, "");
1435 } else {
1436 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1437 (long) char_max, 0L,
1438 (long) UCHAR_MAX, "");
1439 }
1440 }
1441
1442 if (c_signed) {
1443 #ifndef NO_UC
1444 Volatile unsigned char c, char_max;
1445 c=0; char_max=0;
1446 c++;
1447 if (setjmp(lab)==0) { /* Yields char_max */
1448 while (c>char_max) {
1449 char_max=c;
1450 c++;
1451 }
1452 }
1453 Unexpected(4);
1454 if (sizeof(char) == sizeof(int)) {
1455 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1456 (long) char_max,
1457 (long) UCHAR_MAX, "");
1458 } else {
1459 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1460 (long) char_max, 0L,
1461 (long) UCHAR_MAX, "");
1462 }
1463 #endif
1464 } else {
1465 #ifndef NO_SC
1466 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1467 c=0; char_max=0;
1468 c++;
1469 if (setjmp(lab)==0) { /* Yields char_max */
1470 while (c>char_max) {
1471 char_max=c;
1472 c++;
1473 }
1474 }
1475 c=0; char_min=0;
1476 c--;
1477 if (setjmp(lab)==0) { /* Yields char_min */
1478 while (c<char_min) {
1479 char_min=c;
1480 c--;
1481 }
1482 }
1483 Unexpected(5);
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, "");
1490 #endif /* NO_SC */
1491 }
1492 }
1493 return bits_per_byte;
1494 }
1495
1496 int basic() {
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 ();
1501 int variable;
1502 int *p, *q;
1503
1504 Vprintf("%sSIZES%s\n", co, oc);
1505 bits_per_byte= cprop();
1506
1507 /* Shorts, ints and longs *****************************************/
1508 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1509 co,
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);
1515 if (stdc) {
1516 Vprintf("%slong double=%d bits%s\n",
1517 co, (int) sizeof(Long_double)*bits_per_byte, oc);
1518 }
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!":"",
1522 oc);
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!":"",
1526 oc);
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!":"",
1530 oc);
1531 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1532 ((((false()?( sizeof(int)):(-1)) < 0) )?
1533 "signed":"unsigned") ,
1534 type_of(sizeof(
1535 sizeof(int)+0
1536 )
1537 ),
1538 oc);
1539 showtype("Type size_t is", sizeof(0));
1540
1541 /* Alignment constants ********************************************/
1542
1543 #define alignment(TYPE) \
1544 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1545
1546 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1547
1548 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1549 co,
1550 alignment(char), alignment(short),
1551 alignment(int), alignment(long),
1552 oc);
1553
1554 Vprintf("%sfloat=%ld double=%ld%s\n",
1555 co,
1556 alignment(float), alignment(double),
1557 oc);
1558
1559 if (stdc) {
1560 Vprintf("%slong double=%ld%s\n",
1561 co,
1562 alignment(Long_double),
1563 oc);
1564 }
1565 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1566 co,
1567 alignment(char *), alignment(int *), alignment(function *),
1568 oc);
1569
1570 Vprintf("\n");
1571
1572 /* Ten little endians *********************************************/
1573
1574 endian(bits_per_byte);
1575
1576 /* Pointers *******************************************************/
1577
1578 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1579
1580 if ((long) (char *) &variable == (long) (int *) &variable)
1581 Vprintf("%sChar and int pointer formats seem identical%s\n",
1582 co, oc);
1583 else
1584 Vprintf("%sChar and int pointer formats are different%s\n",
1585 co, oc);
1586 if ((long) (char *) &variable == (long) (function *) &variable)
1587 Vprintf("%sChar and function pointer formats seem identical%s\n",
1588 co, oc);
1589 else
1590 Vprintf("%sChar and function pointer formats are different%s\n",
1591 co, oc);
1592
1593 if (V) {
1594 if ("abcd"=="abcd")
1595 printf("%sStrings are shared%s\n", co, oc);
1596 else printf("%sStrings are not shared%s\n", co, oc);
1597 }
1598
1599 p=0; q=0;
1600 showtype("Type ptrdiff_t is", p-q);
1601
1602 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1603
1604 sprop();
1605 iprop();
1606 lprop();
1607 usprop();
1608 uiprop();
1609 ulprop();
1610
1611 promotions();
1612
1613 Unexpected(6);
1614
1615 return bits_per_byte;
1616 }
1617
1618 #else /* not PASS0 */
1619
1620 #ifdef SEP
1621 extern jmp_buf lab;
1622 extern int V, L, F, bugs, bits_per_byte;
1623 extern char co[], oc[];
1624 extern char *f_rep();
1625 #endif /* SEP */
1626 #endif /* ifdef PASS0 */
1627
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.
1635 */
1636
1637 /* #undef on an already undefined thing is (wrongly) flagged as an error
1638 by some compilers, therefore the #ifdef that follows:
1639 */
1640 #ifdef Number
1641 #undef Number
1642 #undef THING
1643 #undef Thing
1644 #undef thing
1645 #undef FPROP
1646 #undef Fname
1647 #undef Store
1648 #undef Sum
1649 #undef Diff
1650 #undef Mul
1651 #undef Div
1652 #undef ZERO
1653 #undef HALF
1654 #undef ONE
1655 #undef TWO
1656 #undef THREE
1657 #undef FOUR
1658 #undef Self
1659 #undef F_check
1660 #undef Validate
1661 #undef EPROP
1662 #undef MARK
1663
1664 /* These are the float.h constants */
1665 #undef F_RADIX
1666 #undef F_MANT_DIG
1667 #undef F_DIG
1668 #undef F_ROUNDS
1669 #undef F_EPSILON
1670 #undef F_MIN_EXP
1671 #undef F_MIN
1672 #undef F_MIN_10_EXP
1673 #undef F_MAX_EXP
1674 #undef F_MAX
1675 #undef F_MAX_10_EXP
1676 #endif
1677
1678 #ifdef Integer
1679 #undef Integer
1680 #undef INT
1681 #undef IPROP
1682 #undef Iname
1683 #undef UPROP
1684 #undef Uname
1685 #undef OK_UI
1686 #undef IMARK
1687
1688 #undef I_MAX
1689 #undef I_MIN
1690 #undef U_MAX
1691 #endif
1692
1693 #ifdef PASS1
1694
1695 /* Define the things we're going to use this pass */
1696
1697 #define Number float
1698 #define THING "FLOAT"
1699 #define Thing "Float"
1700 #define thing "float"
1701 #define Fname "FLT"
1702 #define FPROP fprop
1703 #define Store fStore
1704 #define Sum fSum
1705 #define Diff fDiff
1706 #define Mul fMul
1707 #define Div fDiv
1708 #define ZERO 0.0
1709 #define HALF 0.5
1710 #define ONE 1.0
1711 #define TWO 2.0
1712 #define THREE 3.0
1713 #define FOUR 4.0
1714 #define Self fSelf
1715 #define F_check fCheck
1716 #define MARK "F"
1717 #ifdef VERIFY
1718 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1719 #endif
1720
1721 #define EPROP efprop
1722
1723 #define Integer short
1724 #define INT "short"
1725 #define IPROP sprop
1726 #define Iname "SHRT"
1727 #ifndef NO_UI
1728 #define OK_UI 1
1729 #endif
1730 #define IMARK ""
1731
1732 #define UPROP usprop
1733 #define Uname "USHRT"
1734
1735 #ifdef VERIFY
1736 #ifdef SHRT_MAX
1737 #define I_MAX SHRT_MAX
1738 #endif
1739 #ifdef SHRT_MIN
1740 #define I_MIN SHRT_MIN
1741 #endif
1742 #ifdef USHRT_MAX
1743 #define U_MAX USHRT_MAX
1744 #endif
1745
1746 #ifdef FLT_RADIX
1747 #define F_RADIX FLT_RADIX
1748 #endif
1749 #ifdef FLT_MANT_DIG
1750 #define F_MANT_DIG FLT_MANT_DIG
1751 #endif
1752 #ifdef FLT_DIG
1753 #define F_DIG FLT_DIG
1754 #endif
1755 #ifdef FLT_ROUNDS
1756 #define F_ROUNDS FLT_ROUNDS
1757 #endif
1758 #ifdef FLT_EPSILON
1759 #define F_EPSILON FLT_EPSILON
1760 #endif
1761 #ifdef FLT_MIN_EXP
1762 #define F_MIN_EXP FLT_MIN_EXP
1763 #endif
1764 #ifdef FLT_MIN
1765 #define F_MIN FLT_MIN
1766 #endif
1767 #ifdef FLT_MIN_10_EXP
1768 #define F_MIN_10_EXP FLT_MIN_10_EXP
1769 #endif
1770 #ifdef FLT_MAX_EXP
1771 #define F_MAX_EXP FLT_MAX_EXP
1772 #endif
1773 #ifdef FLT_MAX
1774 #define F_MAX FLT_MAX
1775 #endif
1776 #ifdef FLT_MAX_10_EXP
1777 #define F_MAX_10_EXP FLT_MAX_10_EXP
1778 #endif
1779 #endif /* VERIFY */
1780
1781 #endif /* PASS1 */
1782
1783 #ifdef PASS2
1784
1785 #define Number double
1786 #define THING "DOUBLE"
1787 #define Thing "Double"
1788 #define thing "double"
1789 #define Fname "DBL"
1790 #define FPROP dprop
1791 #define Store dStore
1792 #define Sum dSum
1793 #define Diff dDiff
1794 #define Mul dMul
1795 #define Div dDiv
1796 #define ZERO 0.0
1797 #define HALF 0.5
1798 #define ONE 1.0
1799 #define TWO 2.0
1800 #define THREE 3.0
1801 #define FOUR 4.0
1802 #define Self dSelf
1803 #define F_check dCheck
1804 #define MARK ""
1805 #ifdef VERIFY
1806 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1807 #endif
1808
1809 #define EPROP edprop
1810
1811 #define Integer int
1812 #define INT "int"
1813 #define IPROP iprop
1814 #define Iname "INT"
1815 #define OK_UI 1 /* Unsigned int is always possible */
1816 #define IMARK ""
1817
1818 #define UPROP uiprop
1819 #define Uname "UINT"
1820
1821 #ifdef VERIFY
1822 #ifdef INT_MAX
1823 #define I_MAX INT_MAX
1824 #endif
1825 #ifdef INT_MIN
1826 #define I_MIN INT_MIN
1827 #endif
1828 #ifdef UINT_MAX
1829 #define U_MAX UINT_MAX
1830 #endif
1831
1832 #ifdef DBL_MANT_DIG
1833 #define F_MANT_DIG DBL_MANT_DIG
1834 #endif
1835 #ifdef DBL_DIG
1836 #define F_DIG DBL_DIG
1837 #endif
1838 #ifdef DBL_EPSILON
1839 #define F_EPSILON DBL_EPSILON
1840 #endif
1841 #ifdef DBL_MIN_EXP
1842 #define F_MIN_EXP DBL_MIN_EXP
1843 #endif
1844 #ifdef DBL_MIN
1845 #define F_MIN DBL_MIN
1846 #endif
1847 #ifdef DBL_MIN_10_EXP
1848 #define F_MIN_10_EXP DBL_MIN_10_EXP
1849 #endif
1850 #ifdef DBL_MAX_EXP
1851 #define F_MAX_EXP DBL_MAX_EXP
1852 #endif
1853 #ifdef DBL_MAX
1854 #define F_MAX DBL_MAX
1855 #endif
1856 #ifdef DBL_MAX_10_EXP
1857 #define F_MAX_10_EXP DBL_MAX_10_EXP
1858 #endif
1859 #endif /* VERIFY */
1860
1861 #endif /* PASS2 */
1862
1863 #ifdef PASS3
1864
1865 #ifdef STDC
1866 #define Number long double
1867
1868 #define ZERO 0.0L
1869 #define HALF 0.5L
1870 #define ONE 1.0L
1871 #define TWO 2.0L
1872 #define THREE 3.0L
1873 #define FOUR 4.0L
1874 #endif
1875
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
1882 #define Sum ldSum
1883 #define Diff ldDiff
1884 #define Mul ldMul
1885 #define Div ldDiv
1886 #define Self ldSelf
1887 #define F_check ldCheck
1888 #define MARK "L"
1889 #ifdef VERIFY
1890 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1891 #endif
1892
1893 #define EPROP eldprop
1894
1895 #define Integer long
1896 #define INT "long"
1897 #define IPROP lprop
1898 #define Iname "LONG"
1899 #ifndef NO_UI
1900 #define OK_UI 1
1901 #endif
1902 #define IMARK "L"
1903
1904 #define UPROP ulprop
1905 #define Uname "ULONG"
1906
1907 #ifdef VERIFY
1908 #ifdef LONG_MAX
1909 #define I_MAX LONG_MAX
1910 #endif
1911 #ifdef LONG_MIN
1912 #define I_MIN LONG_MIN
1913 #endif
1914 #ifdef ULONG_MAX
1915 #define U_MAX ULONG_MAX
1916 #endif
1917
1918 #ifdef LDBL_MANT_DIG
1919 #define F_MANT_DIG LDBL_MANT_DIG
1920 #endif
1921 #ifdef LDBL_DIG
1922 #define F_DIG LDBL_DIG
1923 #endif
1924 #ifdef LDBL_EPSILON
1925 #define F_EPSILON LDBL_EPSILON
1926 #endif
1927 #ifdef LDBL_MIN_EXP
1928 #define F_MIN_EXP LDBL_MIN_EXP
1929 #endif
1930 #ifdef LDBL_MIN
1931 #define F_MIN LDBL_MIN
1932 #endif
1933 #ifdef LDBL_MIN_10_EXP
1934 #define F_MIN_10_EXP LDBL_MIN_10_EXP
1935 #endif
1936 #ifdef LDBL_MAX_EXP
1937 #define F_MAX_EXP LDBL_MAX_EXP
1938 #endif
1939 #ifdef LDBL_MAX
1940 #define F_MAX LDBL_MAX
1941 #endif
1942 #ifdef LDBL_MAX_10_EXP
1943 #define F_MAX_10_EXP LDBL_MAX_10_EXP
1944 #endif
1945 #endif /* VERIFY */
1946
1947 #endif /* PASS3 */
1948
1949 #ifndef I_MAX
1950 #define I_MAX int_max
1951 #endif
1952 #ifndef I_MIN
1953 #define I_MIN int_min
1954 #endif
1955 #ifndef U_MAX
1956 #define U_MAX u_max
1957 #endif
1958
1959 #ifndef F_RADIX
1960 #define F_RADIX f_radix
1961 #endif
1962 #ifndef F_MANT_DIG
1963 #define F_MANT_DIG f_mant_dig
1964 #endif
1965 #ifndef F_DIG
1966 #define F_DIG f_dig
1967 #endif
1968 #ifndef F_ROUNDS
1969 #define F_ROUNDS f_rounds
1970 #endif
1971 #ifndef F_EPSILON
1972 #define F_EPSILON f_epsilon
1973 #endif
1974 #ifndef F_MIN_EXP
1975 #define F_MIN_EXP f_min_exp
1976 #endif
1977 #ifndef F_MIN
1978 #define F_MIN f_min
1979 #endif
1980 #ifndef F_MIN_10_EXP
1981 #define F_MIN_10_EXP f_min_10_exp
1982 #endif
1983 #ifndef F_MAX_EXP
1984 #define F_MAX_EXP f_max_exp
1985 #endif
1986 #ifndef F_MAX
1987 #define F_MAX f_max
1988 #endif
1989 #ifndef F_MAX_10_EXP
1990 #define F_MAX_10_EXP f_max_10_exp
1991 #endif
1992
1993 #ifndef VERIFY
1994 #define Validate(prec, val, req, same) {;}
1995 #endif
1996
1997 #ifdef Integer
1998
1999 Procedure IPROP() {
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;
2003
2004 /* Calculate max short/int/long ***********************************/
2005 /* Calculate 2**n-1 until overflow - then use the previous value */
2006
2007 newi=1; int_max=0;
2008
2009 if (setjmp(lab)==0) { /* Yields int_max */
2010 for(ipower=0; newi>int_max; ipower++) {
2011 int_max=newi;
2012 newi=newi*two+1;
2013 }
2014 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2015 co, INT[0]=='i'?"n":"", INT, oc);
2016 } else {
2017 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2018 co, INT[0]=='i'?"n":"", INT, oc);
2019 }
2020 Unexpected(7);
2021
2022 /* Minimum value: assume either two's or one's complement *********/
2023 int_min= -int_max;
2024 if (setjmp(lab)==0) { /* Yields int_min */
2025 if (int_min-1 < int_min) int_min--;
2026 }
2027 Unexpected(8);
2028
2029 /* Now for those daft Cybers */
2030
2031 maxeri=0; newi=int_max;
2032
2033 if (setjmp(lab)==0) { /* Yields maxeri */
2034 for(ibits=ipower; newi>maxeri; ibits++) {
2035 maxeri=newi;
2036 newi=newi+newi+1;
2037 }
2038 }
2039 Unexpected(9);
2040
2041 minneri= -maxeri;
2042 if (setjmp(lab)==0) { /* Yields minneri */
2043 if (minneri-1 < minneri) minneri--;
2044 }
2045 Unexpected(10);
2046
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);
2050
2051 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
2052 (long) int_max, 0L,
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);
2057
2058 if(int_max < 0) { /* It has happened */
2059 eek_a_bug("signed integral comparison faulty?");
2060 }
2061
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!)",
2067 oc);
2068 }
2069
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!)",
2075 oc);
2076 }
2077 }
2078
2079 Procedure UPROP () {
2080 /* The properties of unsigned short/int/long */
2081 #ifdef OK_UI
2082 Volatile unsigned Integer u_max, newi, two;
2083 newi=1; u_max=0; two=2;
2084
2085 if (setjmp(lab)==0) { /* Yields u_max */
2086 while(newi>u_max) {
2087 u_max=newi;
2088 newi=newi*two+1;
2089 }
2090 }
2091 Unexpected(11);
2092 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2093 co, INT, (unsigned long) u_max, oc);
2094
2095 /* Oh woe: new standard C defines value preserving promotions */
2096 if (L) {
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);
2102 } else {
2103 u_define(D_UINT_MAX, INT, Uname, "_MAX",
2104 (unsigned long) u_max,
2105 (unsigned long) U_MAX, IMARK);
2106 }
2107 }
2108 #endif
2109 }
2110
2111 #endif /* Integer */
2112
2113 #ifdef Number
2114
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.
2118 */
2119 #ifdef STDC
2120 #define ARGS1(atype, a) (atype a)
2121 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2122 #else
2123 #define ARGS1(atype, a) (a) atype a;
2124 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2125 #endif
2126
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); }
2133
2134 Procedure F_check ARGS((int precision, Long_double val1));
2135
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.
2148 */
2149 Long_double new1;
2150 Number val, new, diff;
2151 double rem;
2152 int e;
2153 char *rep;
2154 char *f2;
2155
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 */
2160 } else {
2161 /* It had better support Le then */
2162 f2= "%Le";
2163 }
2164 val= val1;
2165 rep= f_rep(precision, (Long_double) val);
2166 if (setjmp(lab)==0) {
2167 sscanf(rep, f2, &new1);
2168 } else {
2169 eek_a_bug("sscanf caused a trap");
2170 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2171 Unexpected(12);
2172 return;
2173 }
2174
2175 if (setjmp(lab)==0) { /* See if new is usable */
2176 new= new1;
2177 if (new != 0.0) {
2178 diff= val/new - 1.0;
2179 if (diff < 0.1) diff= 1.0;
2180 /* That should be enough to generate a trap */
2181 }
2182 } else {
2183 eek_a_bug("sscanf returned an unusable number");
2184 printf("%s scanning: %s with format: %s%s\n\n",
2185 co, rep, f2, oc);
2186 Unexpected(13);
2187 return;
2188 }
2189
2190 Unexpected(14);
2191 if (new != val) {
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",
2195 co, oc);
2196 return;
2197 }
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) {
2207 diff= val-new;
2208 printf("%s difference= %s%s\n\n",
2209 co, f_rep(precision, (Long_double) diff), oc);
2210 } /* else forget it */
2211 Unexpected(15);
2212 }
2213 }
2214
2215 #ifdef VERIFY
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 */
2218 Unexpected(16);
2219 if (!same) {
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);
2224 } else {
2225 printf(" Compiler has %s for value%s\n",
2226 "an unusable number", oc);
2227 }
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);
2235 }
2236 } /*else forget it*/
2237 Unexpected(17);
2238 printf("\n");
2239 bugs++;
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");
2243 printf("\n");
2244 }
2245 }
2246 #endif /* VERIFY */
2247
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.
2252
2253 Returns the number of digits in the fraction.
2254 */
2255
2256 Volatile int
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;
2261 Volatile Number
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;
2265
2266 Unexpected(18);
2267
2268 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2269
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. */
2275 a=1.0;
2276 if (setjmp(lab)==0) { /* inexact trap? */
2277 do { a=Sum(a, a); }
2278 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2279 } else {
2280 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2281 /* And supporting those is just TOO much trouble! */
2282 farewell(bugs+1);
2283 }
2284 Unexpected(19);
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. */
2289 b=1.0;
2290 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2291 f_radix=base;
2292 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2293
2294 /* Sanity check; if base<2, I can't guarantee the rest will work */
2295 if (f_radix < 2) {
2296 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2297 printf("\n");
2298 return(0);
2299 }
2300
2301 if (PASS == 1) { /* only for FLT */
2302 flt_radix= f_radix;
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);
2309 bugs++;
2310 }
2311
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 */
2324
2325 /* Rounding *******************************************************/
2326 basem1=Diff(base, HALF);
2327 if (Diff(Sum(a, basem1), a) != ZERO) {
2328 if (f_radix == 2) basem1=0.375;
2329 else basem1=1.0;
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 */
2333
2334 basem1=Diff(base, HALF);
2335
2336 if (Diff(Diff(-a, basem1), -a) != ZERO) {
2337 if (f_radix == 2) basem1=0.375;
2338 else basem1=1.0;
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 */
2342
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 */
2348
2349 if (f_rounds != -1) {
2350 Vprintf("%sArithmetic rounds towards ", co);
2351 switch (f_rounds) {
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;
2357 }
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" :
2364 "away from zero",
2365 oc);
2366 Vprintf("%s Positive numbers %s%s\n",
2367 co, irnd==0 ? "towards zero" :
2368 irnd==1 ? "to nearest" :
2369 "away from zero",
2370 oc);
2371 }
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);
2378 } else {
2379 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
2380 }
2381 }
2382 if (PASS == 1) { /* only for FLT */
2383 flt_rounds= f_rounds;
2384 if (F)
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);
2391 bugs++;
2392 }
2393
2394 /* Various flavours of epsilon ************************************/
2395 negeps=f_mant_dig+f_mant_dig;
2396 basein=1.0/base;
2397 a=1.0;
2398 for(i=1; i<=negeps; i++) a*=basein;
2399
2400 b=a;
2401 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2402 a*=base;
2403 negeps--;
2404 }
2405 negeps= -negeps;
2406 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2407 co, negeps, oc);
2408
2409 etop = ONE;
2410 ebot = ZERO;
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;
2417 else ebot = eps;
2418 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2419 }
2420 eps= etop;
2421 /* Sanity check */
2422 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2423 eek_a_bug("internal error calculating epsneg");
2424 }
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);
2428
2429 epsneg=a;
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;
2435 }
2436 /* epsneg is used later */
2437 Unexpected(20);
2438
2439 machep= -f_mant_dig-f_mant_dig;
2440 a=b;
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",
2443 co, machep, oc);
2444
2445 etop = ONE;
2446 ebot = ZERO;
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;
2453 else ebot = eps;
2454 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2455 }
2456 /* Sanity check */
2457 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2458 eek_a_bug("internal error calculating eps");
2459 }
2460 f_epsilon=etop;
2461
2462 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2463 co, f_rep(digs, (Long_double) f_epsilon), oc);
2464
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);
2468
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);
2473 Unexpected(21);
2474 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2475 f_epsilon == Self(F_EPSILON));
2476 Unexpected(22);
2477
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);
2482 }
2483 }
2484
2485 /* Size of and minimum normalised exponent ************************/
2486 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2487
2488 /* Coarse search for the largest power of two */
2489 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2490 do {
2491 y=z; y1=z1;
2492 z=Mul(y,y); z1=Mul(z1, y);
2493 a=Mul(z,ONE);
2494 z2=Div(z1,y);
2495 if (z2 != y1) break;
2496 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2497 i++;
2498 k+=k;
2499 } while(1);
2500 } else {
2501 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2502 }
2503 Unexpected(23);
2504
2505 if (f_radix != 10) {
2506 iexp=i+1; /* for the sign */
2507 mx=k+k;
2508 } else {
2509 iexp=2;
2510 iz=f_radix;
2511 while (k >= iz) { iz*=f_radix; iexp++; }
2512 mx=iz+iz-1;
2513 }
2514
2515 /* Fine tune starting with y and y1 */
2516 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2517 do {
2518 f_min=y; z1=y1;
2519 y=Div(y,base); y1=Div(y1,base);
2520 a=Mul(y,ONE);
2521 z2=Mul(y1,base);
2522 if (z2 != z1) break;
2523 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2524 k++;
2525 } while (1);
2526 }
2527 Unexpected(24);
2528
2529 f_min_exp=(-k)+1;
2530
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);
2534 if (F)
2535 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2536 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2537
2538 if (setjmp(lab)==0) {
2539 Vprintf("%sMinimum normalised positive number = %s%s\n",
2540 co, f_rep(digs, (Long_double) f_min), oc);
2541 } else {
2542 eek_a_bug("printf can't print the smallest normalised number");
2543 printf("\n");
2544 }
2545 Unexpected(25);
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);
2551 } else {
2552 eek_a_bug("xxx_MIN caused a trap");
2553 printf("\n");
2554 }
2555
2556 if (setjmp(lab) == 0) {
2557 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2558 f_min == Self(F_MIN));
2559 } else {
2560 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2561 co, "Compiler has an unusable number for value", oc);
2562 bugs++;
2563 }
2564 Unexpected(26);
2565
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, "");
2571
2572 /* Minimum exponent ************************************************/
2573 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2574 do {
2575 xminner=y;
2576 y=Div(y,base);
2577 a=Mul(y,ONE);
2578 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2579 } while (1);
2580 }
2581 Unexpected(27);
2582
2583 if (xminner != 0.0 && xminner != f_min) {
2584 normal= 0;
2585 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2586 co, oc);
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);
2591 } else {
2592 eek_a_bug("printf can't print the smallest unnormalised number.");
2593 printf("\n");
2594 }
2595 Unexpected(28);
2596 } else {
2597 normal= 1;
2598 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2599 }
2600
2601 /* Maximum exponent ************************************************/
2602 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2603 inf=0; trap=0;
2604 while (f_max<newxmax) {
2605 f_max=newxmax;
2606 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2607 newxmax=Mul(newxmax, base);
2608 } else {
2609 trap=1;
2610 break;
2611 }
2612 if (Div(newxmax, base) != f_max) {
2613 inf=1; /* ieee infinity */
2614 break;
2615 }
2616 f_max_exp++;
2617 }
2618 Unexpected(29);
2619 if (trap) {
2620 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2621 }
2622
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, "");
2627
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);
2632
2633 if (setjmp(lab)==0) {
2634 Vprintf("%sMaximum number = %s%s\n",
2635 co, f_rep(digs, (Long_double) f_max), oc);
2636 } else {
2637 eek_a_bug("printf can't print the largest double.");
2638 printf("\n");
2639 }
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);
2645 } else {
2646 eek_a_bug("xxx_MAX caused a trap");
2647 printf("\n");
2648 }
2649 if (setjmp(lab)==0) {
2650 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2651 f_max == Self(F_MAX));
2652 } else {
2653 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
2654 co, "Compiler has an unusable number for value", oc);
2655 bugs++;
2656 }
2657 Unexpected(30);
2658
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, "");
2663
2664 /* Hidden bit + sanity check ****************************************/
2665 if (f_radix != 10) {
2666 hidden=0;
2667 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2668 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2669 hidden=1;
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",
2673 co, oc);
2674 } else {
2675 printf("\n%s%s\n %s %s %s!%s\n\n",
2676 co,
2677 "*** Something fishy here!",
2678 "Exponent size + significand size doesn't match",
2679 "with the size of a", thing,
2680 oc);
2681 }
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" :
2687 "some", oc);
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 ");
2693 }
2694 if (normal) Vprintf("the normalisation is unusual");
2695 Vprintf("%s\n", oc);
2696 }
2697 } else {
2698 Vprintf("%sIt doesn't look like IEEE format%s\n",
2699 co, oc);
2700 }
2701 }
2702 printf("\n"); /* regardless of verbosity */
2703 return f_mant_dig;
2704 }
2705
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.
2711 */
2712 Volatile int eprec;
2713 Volatile double a, b, base, old;
2714 Volatile Number d, oldd, dbase, one, zero;
2715 Volatile int bad=0;
2716
2717 /* Size of significand **************************************/
2718 a=1.0;
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);
2722 } else bad=1;
2723
2724 /* Avoid the comparison if bad is set,
2725 to avoid trouble on the convex. */
2726 if (!bad && (a <= old)) bad=1;
2727
2728 if (!bad) {
2729 b=1.0;
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;
2734 } else bad=1;
2735 }
2736
2737 if (!bad) {
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;
2743 } else bad=1;
2744 }
2745
2746 Unexpected(31);
2747
2748 if (bad) {
2749 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2750 co, thing, " check that you compiled without optimisation!",
2751 oc);
2752 } else if (eprec==dprec) {
2753 Vprintf("%s%s expressions are evaluated in double precision%s\n",
2754 co, Thing, oc);
2755 } else if (eprec==fprec) {
2756 Vprintf("%s%s expressions are evaluated in float precision%s\n",
2757 co, Thing, oc);
2758 } else if (eprec==lprec) {
2759 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2760 co, Thing, oc);
2761 } else {
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",
2766 oc);
2767 }
2768 }
2769
2770 #else /* not Number */
2771
2772 #ifdef FPROP /* Then create dummy routines for long double */
2773 /* ARGSUSED */
2774 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2775 #endif
2776 #ifdef EPROP
2777 /* ARGSUSED */
2778 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2779 #endif
2780
2781 #endif /* ifdef Number */
2782
2783 /* Increment the pass number */
2784 #undef PASS
2785
2786 #ifdef PASS2
2787 #undef PASS2
2788 #define PASS 3
2789 #define PASS3 1
2790 #endif
2791
2792 #ifdef PASS1
2793 #undef PASS1
2794 #define PASS 2
2795 #define PASS2 1
2796 #endif
2797
2798 #ifdef PASS0
2799 #undef PASS0
2800 #endif
2801
2802 #ifdef PASS /* then rescan this file */
2803 #ifdef NO_FILE
2804 #include "enquire.c"
2805 #else
2806 #include FILENAME /* if this line fails to compile, define NO_FILE */
2807 #endif
2808 #endif /* PASS */
2809
This page took 0.157635 seconds and 4 git commands to generate.