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