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