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