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