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