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