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