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