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