00001
00002
00003
00004 #ifndef VERSION
00005 #define VERSION "4.3"
00006 #endif
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 #ifndef FILENAME
00302 #ifdef NO_FILE
00303 #define FILENAME "enquire.c"
00304 #else
00305 #ifdef __FILE__
00306 #define FILENAME __FILE__
00307 #else
00308 #define FILENAME "enquire.c"
00309 #endif
00310 #endif
00311 #endif
00312
00313
00314 #ifndef PASS
00315 #ifndef SEP
00316 #define PASS 1
00317 #define PASS0 1
00318 #define PASS1 1
00319 #endif
00320
00321
00322 #define D_CHAR_BIT "Number of bits in a storage unit"
00323 #define D_CHAR_MAX "Maximum char"
00324 #define D_CHAR_MIN "Minimum char"
00325 #define D_SCHAR_MAX "Maximum signed char"
00326 #define D_SCHAR_MIN "Minimum signed char"
00327 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
00328
00329 #define D_INT_MAX "Maximum %s"
00330 #define D_INT_MIN "Minimum %s"
00331 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
00332
00333 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
00334 #define D_FLT_RADIX "Radix of exponent representation"
00335 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
00336 #define D_DIG "Number of decimal digits of precision in a %s"
00337 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
00338 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
00339 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
00340 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
00341 #define D_MAX "Maximum %s"
00342 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
00343 #define D_MIN "Minimum normalised %s"
00344
00345
00346 #ifdef NO_VOID
00347 #define Procedure int
00348 #else
00349 #define Procedure void
00350 #endif
00351
00352
00353
00354
00355 #ifndef NO_STDC
00356 #ifdef __STDC__
00357 #if __STDC__
00358 #define STDC
00359 #endif
00360 #endif
00361 #endif
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 #ifdef STDC
00373
00374 #define ARGS(x) x
00375 #define NOARGS (void)
00376 #define Volatile volatile
00377 #define Long_double long double
00378 #define stdc 1
00379 #define U "U"
00380
00381 #else
00382
00383 #define ARGS(x) ()
00384 #define NOARGS ()
00385 #define Volatile static
00386 #define Long_double double
00387 #define stdc 0
00388 #define U ""
00389
00390 #endif
00391
00392
00393
00394
00395
00396
00397 #define __GCC_FLOAT_NOT_NEEDED
00398 #include <stdio.h>
00399
00400 #ifdef STDC
00401 #ifndef NO_STDDEF
00402 #include <stddef.h>
00403 #endif
00404 #endif
00405
00406 #ifdef NO_SIG
00407 #define jmp_buf int
00408 #else
00409 #include <sys/types.h>
00410 #include <signal.h>
00411 #include <setjmp.h>
00412 #endif
00413
00414
00415 #ifdef CHAR_BIT
00416 #undef CHAR_BIT
00417 #undef CHAR_MAX
00418 #undef CHAR_MIN
00419 #undef SCHAR_MAX
00420 #undef SCHAR_MIN
00421 #undef UCHAR_MAX
00422 #undef UCHAR_MIN
00423 #endif
00424
00425 #ifdef VERIFY
00426 #include "limits.h"
00427 #endif
00428
00429 #ifndef SYS_FLOAT_H_WRAP
00430 #define SYS_FLOAT_H_WRAP 0
00431 #endif
00432
00433 #if SYS_FLOAT_H_WRAP || defined VERIFY
00434 #include "float.h"
00435 #endif
00436
00437 #define Vprintf if (V) printf
00438 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
00439 #define fabs(x) (((x)<0.0)?(-x):(x))
00440
00441 #endif
00442
00443 #ifdef PASS0
00444
00445
00446
00447 int false NOARGS;
00448
00449 #ifdef NO_STDDEF
00450 char *malloc ();
00451 #else
00452 char *malloc ARGS((size_t size));
00453 #endif
00454
00455 Procedure exit ARGS((int status));
00456
00457 char *f_rep ARGS((int precision, Long_double val));
00458 char *fake_f_rep ARGS((char *type, Long_double val));
00459
00460 int maximum_int NOARGS;
00461 int cprop NOARGS;
00462 int basic NOARGS;
00463 Procedure sprop NOARGS;
00464 Procedure iprop NOARGS;
00465 Procedure lprop NOARGS;
00466 Procedure usprop NOARGS;
00467 Procedure uiprop NOARGS;
00468 Procedure ulprop NOARGS;
00469 int fprop ARGS((int bits_per_byte));
00470 int dprop ARGS((int bits_per_byte));
00471 int ldprop ARGS((int bits_per_byte));
00472 Procedure efprop ARGS((int fprec, int dprec, int lprec));
00473 Procedure edprop ARGS((int fprec, int dprec, int lprec));
00474 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
00475
00476 int setmode ARGS((char *s));
00477 Procedure farewell ARGS((int bugs));
00478 Procedure describe ARGS((char *description, char *extra));
00479 Procedure missing ARGS((char *s));
00480 Procedure fmissing ARGS((char *s));
00481 Procedure check_defines NOARGS;
00482 Procedure bitpattern ARGS((char *p, unsigned int size));
00483 int ceil_log ARGS((int base, Long_double x));
00484 Procedure croak ARGS((int place));
00485 Procedure eek_a_bug ARGS((char *problem));
00486 Procedure endian ARGS((int bits_per_byte));
00487 int exponent ARGS((Long_double x, double *fract, int *exp));
00488 int floor_log ARGS((int base, Long_double x));
00489 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
00490 int prec, Long_double val, Long_double req,
00491 char *mark));
00492 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
00493 long val, long lim, long req, char *mark));
00494 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
00495 unsigned long val, unsigned long req, char *mark));
00496
00497 #ifdef NO_SIG
00498
00499
00500
00501 int setjmp ARGS((int lab));
00502
00503 int lab=1;
00504 int setjmp(lab) int lab; { return(0); }
00505 Procedure signal(i, p) int i, (*p)(); {}
00506
00507 #else
00508 jmp_buf lab;
00509 Procedure overflow(sig) int sig; {
00510 signal(sig, overflow);
00511 longjmp(lab, 1);
00512 }
00513
00514 #endif
00515
00516 int V= 0,
00517 L= 0,
00518 F= 0,
00519 bugs=0;
00520
00521 char co[4], oc[4];
00522
00523 int bits_per_byte;
00524 int flt_rounds;
00525 int flt_radix;
00526
00527 #ifdef TEST
00528
00529
00530
00531
00532
00533
00534
00535
00536 #define ROUND_BITS 0x30
00537 #define TO_NEAREST 0x00
00538 #define TO_ZERO 0x10
00539 #define TO_MINUS_INF 0x20
00540 #define TO_PLUS_INF 0x30
00541
00542
00543 #define EXT_BITS 0xc0
00544 #define ROUND_EXTENDED 0x00
00545 #define ROUND_SINGLE 0x40
00546 #define ROUND_DOUBLE 0x80
00547
00548
00549 #define EXE_INEX1 0x100
00550 #define EXE_INEX2 0x200
00551 #define EXE_DZ 0x400
00552 #define EXE_UNFL 0x800
00553 #define EXE_OVFL 0x1000
00554 #define EXE_OPERR 0x2000
00555 #define EXE_SNAN 0x4000
00556 #define EXE_BSUN 0x8000
00557
00558
00559
00560 printmode(new) unsigned new; {
00561 fpmode_(&new);
00562 printf("New fp mode:\n");
00563 printf(" Round toward ");
00564 switch (new & ROUND_BITS) {
00565 case TO_NEAREST: printf("nearest"); break;
00566 case TO_ZERO: printf("zero"); break;
00567 case TO_MINUS_INF: printf("minus infinity"); break;
00568 case TO_PLUS_INF: printf("plus infinity"); break;
00569 default: printf("???"); break;
00570 }
00571
00572 printf("\n Extended rounding precision: ");
00573
00574 switch (new & EXT_BITS) {
00575 case ROUND_EXTENDED: printf("extended"); break;
00576 case ROUND_SINGLE: printf("single"); break;
00577 case ROUND_DOUBLE: printf("double"); break;
00578 default: printf("???"); break;
00579 }
00580
00581 printf("\n Enabled exceptions:");
00582 if (new & (unsigned) EXE_INEX1) printf(" inex1");
00583 if (new & (unsigned) EXE_INEX2) printf(" inex2");
00584 if (new & (unsigned) EXE_DZ) printf(" dz");
00585 if (new & (unsigned) EXE_UNFL) printf(" unfl");
00586 if (new & (unsigned) EXE_OVFL) printf(" ovfl");
00587 if (new & (unsigned) EXE_OPERR) printf(" operr");
00588 if (new & (unsigned) EXE_SNAN) printf(" snan");
00589 if (new & (unsigned) EXE_BSUN) printf(" bsun");
00590 printf("\n");
00591 }
00592
00593
00594
00595 int setmode(s) char *s; {
00596 unsigned mode=0, dig;
00597 char c;
00598
00599 while (*s) {
00600 c= *s++;
00601 if (c>='0' && c<='9') dig= c-'0';
00602 else if (c>='a' && c<='f') dig= c-'a'+10;
00603 else if (c>='A' && c<='F') dig= c-'A'+10;
00604 else return 1;
00605 mode= mode<<4 | dig;
00606 }
00607 printmode(mode);
00608 return 0;
00609 }
00610 #else
00611
00612 int setmode(s) char *s; {
00613 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
00614 return(1);
00615 }
00616 #endif
00617
00618 Procedure farewell(bugs) int bugs; {
00619 if (bugs == 0) exit(0);
00620 printf("\n%sFor hints on dealing with the ", co);
00621 if (bugs == 1) printf("problem");
00622 else printf("%d problems", bugs);
00623 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
00624 printf("%s%s\n", FILENAME, oc);
00625 exit(bugs);
00626 }
00627
00628
00629 Procedure croak(place) int place; {
00630 printf("*** Unexpected signal at point %d\n", place);
00631 farewell(bugs+1);
00632 }
00633
00634
00635 char *xmalloc(size) unsigned size; {
00636 char *value = (char *)malloc(size);
00637 if (value == 0) {
00638 fprintf(stderr, "Virtual memory exceeded\n");
00639 exit(bugs+1);
00640 }
00641 return value;
00642 }
00643
00644 int maxint;
00645
00646 int maximum_int() {
00647
00648 Volatile int newi, int_max, two=2;
00649
00650
00651
00652
00653 newi=1; int_max=0;
00654
00655 if (setjmp(lab)==0) {
00656 while(newi>int_max) {
00657 int_max=newi;
00658 newi=newi*two+1;
00659 }
00660 }
00661 Unexpected(0);
00662 return int_max;
00663 }
00664
00665 int main(argc, argv) int argc; char *argv[]; {
00666 int dprec, fprec, lprec;
00667 int i; char *s; int bad;
00668
00669 #ifdef SIGFPE
00670 signal(SIGFPE, overflow);
00671 #endif
00672 #ifdef SIGOVER
00673 signal(SIGOVER, overflow);
00674 #endif
00675
00676
00677 Unexpected(1);
00678
00679 bad=0;
00680 for (i=1; i < argc; i++) {
00681 s= argv[i];
00682 if (*s == '-') {
00683 s++;
00684 while (*s) {
00685 switch (*(s++)) {
00686 case 'v': V=1; break;
00687 case 'l': L=1; break;
00688 case 'f': F=1; break;
00689 default: bad=1; break;
00690 }
00691 }
00692 } else if (*s == '+') {
00693 s++;
00694 bad= setmode(s);
00695 } else bad= 1;
00696 }
00697 if (bad) {
00698 fprintf(stderr,
00699 "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
00700 argv[0]);
00701 exit(1);
00702 }
00703 if (L || F) {
00704 co[0]= '/'; oc[0]= ' ';
00705 co[1]= '*'; oc[1]= '*';
00706 co[2]= ' '; oc[2]= '/';
00707 co[3]= '\0'; oc[3]= '\0';
00708 } else {
00709 co[0]= '\0'; oc[0]= '\0';
00710 V=1;
00711 }
00712
00713 if (L) printf("%slimits.h%s\n", co, oc);
00714 if (F) printf("%sfloat.h%s\n", co, oc);
00715 if (F) {
00716 printf ("#ifndef _FLOAT_H___\n");
00717 printf ("#define _FLOAT_H___\n");
00718 if (SYS_FLOAT_H_WRAP)
00719 printf (" #include_next <float.h>\n");
00720 }
00721 #ifdef ID
00722 printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
00723 co, ID, VERSION, oc);
00724 #else
00725 printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
00726 co, VERSION, oc);
00727 #endif
00728
00729 #ifdef VERIFY
00730 printf("%sVerification phase%s\n", co, oc);
00731 #endif
00732
00733 #ifdef NO_SIG
00734 Vprintf("%sCompiled without signal(): %s%s\n",
00735 co,
00736 "there's nothing that can be done if overflow occurs",
00737 oc);
00738 #endif
00739 #ifdef NO_SC
00740 Vprintf("%sCompiled without signed char%s\n", co, oc);
00741 #endif
00742 #ifdef NO_UC
00743 Vprintf("%Compiled without unsigned char%s\n", co, oc);
00744 #endif
00745 #ifdef NO_UI
00746 Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
00747 #endif
00748 #ifdef __STDC__
00749 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
00750 co, __STDC__, oc);
00751 #else
00752 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
00753 #endif
00754 printf("\n");
00755 check_defines();
00756
00757 maxint= maximum_int();
00758 bits_per_byte= basic();
00759 Vprintf("\n");
00760 if (F||V) {
00761 fprec= fprop(bits_per_byte);
00762 dprec= dprop(bits_per_byte);
00763 lprec= ldprop(bits_per_byte);
00764 efprop(fprec, dprec, lprec);
00765 edprop(fprec, dprec, lprec);
00766 eldprop(fprec, dprec, lprec);
00767 }
00768 #ifndef NO_MEM
00769 if (V) {
00770 unsigned int size;
00771 long total;
00772
00773
00774
00775
00776
00777 size=1<<((bits_per_byte*sizeof(int))-2);
00778 total=0;
00779 while (size!=0) {
00780 while ( malloc((false()?sizeof(int):size)) !=
00781 (char *)NULL
00782 ) {
00783 total+=(size/2);
00784 }
00785 size/=2;
00786 }
00787
00788 Vprintf("%sMemory allocable ~= %ld Kbytes%s\n",
00789 co, (total+511)/512, oc);
00790 }
00791 #endif
00792 if (F) {
00793 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
00794 }
00795 farewell(bugs);
00796 return bugs;
00797 }
00798
00799 Procedure eek_a_bug(problem) char *problem; {
00800
00801 printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
00802 bugs++;
00803 }
00804
00805 Procedure describe(description, extra) char *description, *extra; {
00806
00807 printf(" %s", co);
00808 printf(description, extra);
00809 printf("%s\n", oc);
00810 }
00811
00812 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
00813 char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
00814 if (SYS_FLOAT_H_WRAP && F && val == req)
00815 return;
00816
00817 describe(desc, extra);
00818 printf("#undef %s%s\n", sort, name);
00819 if (val >= 0) {
00820 printf("#define %s%s %ld%s\n", sort, name, val, mark);
00821 } else if (val + lim < 0) {
00822
00823
00824
00825 printf("#define %s%s (%ld%s%ld%s)\n",
00826 sort, name, -lim, mark, val+lim, mark);
00827 } else {
00828 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
00829 }
00830 #ifdef VERIFY
00831 if (val != req) {
00832 printf("%s*** Verify failed for above #define!\n", co);
00833 printf(" Compiler has %ld for value%s\n\n", req, oc);
00834 bugs++;
00835 }
00836 #endif
00837 Vprintf("\n");
00838 }
00839
00840 Procedure u_define(desc, extra, sort, name, val, req, mark)
00841 char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
00842
00843 describe(desc, extra);
00844 printf("#undef %s%s\n", sort, name);
00845 printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
00846 #ifdef VERIFY
00847 if (val != req) {
00848 printf("%s*** Verify failed for above #define!\n", co);
00849 printf(" Compiler has %lu for value%s\n\n", req, oc);
00850 bugs++;
00851 }
00852 #endif
00853 Vprintf("\n");
00854 }
00855
00856 Procedure f_define(desc, extra, sort, name, precision, val, req, mark)
00857 char *desc, *extra, *sort, *name; int precision;
00858 Long_double val, req; char *mark; {
00859 if (SYS_FLOAT_H_WRAP && F && val == req)
00860 return;
00861
00862 describe(desc, extra);
00863 printf ("#undef %s%s\n", sort, name);
00864 if (stdc) {
00865 #ifdef NO_LONG_DOUBLE_IO
00866 static int union_defined = 0;
00867 if (sizeof(double) != sizeof(Long_double)
00868 && !strcmp(sort, "LDBL")) {
00869 if (!union_defined) {
00870 printf("#ifndef __LDBL_UNION__\n");
00871 printf("#define __LDBL_UNION__\n");
00872 printf("union __convert_long_double {\n");
00873 printf(" unsigned __convert_long_double_i[4];\n");
00874 printf(" long double __convert_long_double_d;\n");
00875 printf("};\n");
00876 printf("#endif\n");
00877 union_defined = 1;
00878 }
00879 printf("#define %s%s %s\n",
00880 sort, name, fake_f_rep("long double", val));
00881 } else {
00882 printf("#define %s%s %s%s\n",
00883 sort, name, f_rep(precision, val), mark);
00884 }
00885 #else
00886 printf("#define %s%s %s%s\n",
00887 sort, name, f_rep(precision, val), mark);
00888 #endif
00889 } else if (*mark == 'F') {
00890
00891 printf("#define %s%s ((float)%s)\n",
00892 sort, name, f_rep(precision, val));
00893 } else {
00894 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
00895 }
00896 Vprintf("\n");
00897 }
00898
00899 int floor_log(base, x) int base; Long_double x; {
00900
00901 int r=0;
00902 while (x>=base) { r++; x/=base; }
00903 return r;
00904 }
00905
00906 int ceil_log(base, x) int base; Long_double x; {
00907 int r=0;
00908 while (x>1.0) { r++; x/=base; }
00909 return r;
00910 }
00911
00912 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
00913
00914
00915
00916
00917 int r=0, neg=0;
00918 Long_double old;
00919 *fract=0.0; *exp=0;
00920 if (x<0.0) {
00921 x= -x;
00922 neg= 1;
00923 }
00924 if (x==0.0) return 1;
00925 if (x>=10.0) {
00926 while (x>=10.0) {
00927 old=x; r++; x/=10.0;
00928 if (old==x) return 0;
00929 }
00930 } else {
00931 while (x<1.0) {
00932 old=x; r--; x*=10.0;
00933 if (old==x) return 0;
00934 }
00935 }
00936 if (neg) *fract= (double) -x;
00937 else *fract=(double) x;
00938 *exp=r;
00939 return 1;
00940 }
00941
00942
00943
00944
00945
00946
00947 char *fake_f_rep(type, val) char *type; Long_double val; {
00948 static char buf[1024];
00949 union { unsigned int i[4]; Long_double ld;} u;
00950 u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
00951 u.ld = val;
00952 sprintf(buf, "(__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x%x, 0x%x, 0x%x, 0x%x}}).__convert_long_double_d)",
00953 u.i[0], u.i[1], u.i[2], u.i[3]);
00954 return buf;
00955 }
00956
00957 char *f_rep(precision, val) int precision; Long_double val; {
00958
00959 static char buf[1024];
00960 #ifdef NO_LONG_DOUBLE_IO
00961 if (1)
00962 #else
00963 if (sizeof(double) == sizeof(Long_double))
00964 #endif
00965 {
00966 double d = val;
00967
00968
00969 sprintf(buf, "%.*e", precision, d);
00970 } else {
00971
00972 sprintf(buf, "%.*Le", precision, val);
00973 }
00974 return buf;
00975 }
00976
00977 Procedure bitpattern(p, size) char *p; unsigned int size; {
00978
00979 char c;
00980 unsigned int i;
00981 int j;
00982
00983 for (i=1; i<=size; i++) {
00984 c= *p;
00985 p++;
00986 for (j=bits_per_byte-1; j>=0; j--)
00987 printf("%c", (c>>j)&1 ? '1' : '0');
00988 if (i!=size) printf(" ");
00989 }
00990 }
00991
00992 #define Order(x, px, mode)\
00993 printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
00994 for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
00995 putchar(c==0 ? '?' : (char)c); }\
00996 printf("%s\n", oc);
00997
00998 Procedure endian(bits_per_byte) int bits_per_byte; {
00999
01000 short s=0;
01001 int j=0;
01002 long l=0;
01003
01004 char *ps= (char *) &s,
01005 *pj= (char *) &j,
01006 *pl= (char *) &l,
01007 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
01008 unsigned int mask, i, c;
01009
01010 mask=0;
01011 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
01012
01013 if (V) {
01014 printf("%sCHARACTER ORDER%s\n", co, oc);
01015 Order(s, ps, "short:");
01016 Order(j, pj, "int: ");
01017 Order(l, pl, "long: ");
01018 }
01019 }
01020
01021 Procedure missing(s) char *s; {
01022 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
01023 bugs++;
01024 }
01025
01026 Procedure fmissing(s) char *s; {
01027 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
01028 bugs++;
01029 }
01030
01031
01032 int false() { return 0; }
01033
01034 #define Promoted(x) (false()?(x):(-1))
01035 #define is_signed(x) (Promoted(x) < 0)
01036 #define sign_of(x) ((x)?"signed":"unsigned")
01037 #define Signed 1
01038 #define Unsigned 0
01039 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
01040
01041 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
01042
01043 char *type_of(x) int x; {
01044 if (x == sizeof(char)) {
01045 if (sizeof(char) == sizeof(int)) return "char/short/int";
01046 if (sizeof(char) == sizeof(short)) return "char/short";
01047 return "char";
01048 }
01049 if (x == sizeof(short)) {
01050 if (sizeof(short) == sizeof(int)) return "short/int";
01051 return "short";
01052 }
01053 if (x == sizeof(int)) {
01054 if (sizeof(int) == sizeof(long)) return "int/long";
01055 return "int";
01056 }
01057 if (x == sizeof(long)) return "long";
01058 return "unknown-type";
01059 }
01060
01061 char *ftype_of(x) int x; {
01062 if (x == sizeof(float)) {
01063 return "float";
01064 }
01065 if (x == sizeof(double)) {
01066 if (sizeof(double) == sizeof(Long_double))
01067 return "(long)double";
01068 return "double";
01069 }
01070 if (x == sizeof(Long_double)) {
01071 return "long double";
01072 }
01073 return "unknown-type";
01074 }
01075
01076 Procedure typerr(name, esign, esize, sign, size)
01077 char *name; int esign, esize, sign, size;
01078 {
01079 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
01080 name, sign_of(esign), type_of(esize),
01081 sign_of(sign), type_of(size));
01082 }
01083
01084 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
01085 Vprintf("*** %s has wrong type: expected %s, found %s\n",
01086 name, ftype_of(esize), ftype_of(size));
01087 }
01088
01089 int promotions() {
01090 int si = 0; long sl = 0;
01091 unsigned int ui; unsigned long ul;
01092 short ss; unsigned short us;
01093
01094 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
01095
01096 if (
01097
01098 (sizeof(Promoted(si)) != sizeof(int)) ||
01099 (sizeof(Promoted(sl)) != sizeof(long)) ||
01100 (sizeof(Promoted(ss)) != sizeof(int)) ||
01101 (sizeof(Promoted(ui)) != sizeof(int)) ||
01102 (sizeof(Promoted(ul)) != sizeof(long)) ||
01103 (sizeof(Promoted(us)) != sizeof(int)) ||
01104 is_signed(ui) || is_signed(ul) ||
01105 !is_signed(si) || !is_signed(sl)
01106 )
01107 {
01108 eek_a_bug("promotions don't work properly in conditional expressions\n");
01109 }
01110
01111 showtype("unsigned short promotes to", Promoted((unsigned short) 0));
01112 showtype("long+unsigned gives", sl+ui);
01113 return 0;
01114 }
01115
01116 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
01117
01118 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
01119
01120 Procedure check_defines() {
01121
01122 #ifdef VERIFY
01123 int usign;
01124
01125 #ifdef NO_UI
01126 usign= Signed;
01127 #else
01128
01129 usign= is_signed((unsigned short) 0);
01130 #endif
01131
01132 if (L) {
01133 #ifdef CHAR_BIT
01134 checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
01135 #else
01136 missing("CHAR_BIT");
01137 #endif
01138 #ifdef CHAR_MAX
01139 checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
01140 #else
01141 missing("CHAR_MAX");
01142 #endif
01143 #ifdef CHAR_MIN
01144 checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
01145 #else
01146 missing("CHAR_MIN");
01147 #endif
01148 #ifdef SCHAR_MAX
01149 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
01150 #else
01151 missing("SCHAR_MAX");
01152 #endif
01153 #ifdef SCHAR_MIN
01154 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
01155 #else
01156 missing("SCHAR_MIN");
01157 #endif
01158 #ifdef UCHAR_MAX
01159 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
01160 #else
01161 missing("UCHAR_MAX");
01162 #endif
01163 #ifdef SHRT_MAX
01164 checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
01165 #else
01166 missing("SHRT_MAX");
01167 #endif
01168 #ifdef SHRT_MIN
01169 checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
01170 #else
01171 missing("SHRT_MIN");
01172 #endif
01173 #ifdef INT_MAX
01174 checktype(INT_MAX, "INT_MAX", Signed, int);
01175 #else
01176 missing("INT_MAX");
01177 #endif
01178 #ifdef INT_MIN
01179 checktype(INT_MIN, "INT_MIN", Signed, int);
01180 #else
01181 missing("INT_MIN");
01182 #endif
01183 #ifdef LONG_MAX
01184 checktype(LONG_MAX, "LONG_MAX", Signed, long);
01185 #else
01186 missing("LONG_MAX");
01187 #endif
01188 #ifdef LONG_MIN
01189 checktype(LONG_MIN, "LONG_MIN", Signed, long);
01190 #else
01191 missing("LONG_MIN");
01192 #endif
01193 #ifdef USHRT_MAX
01194 checktype(USHRT_MAX, "USHRT_MAX", usign, int);
01195 #else
01196 missing("USHRT_MAX");
01197 #endif
01198 #ifdef UINT_MAX
01199 checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
01200 #else
01201 missing("UINT_MAX");
01202 #endif
01203 #ifdef ULONG_MAX
01204 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
01205 #else
01206 missing("ULONG_MAX");
01207 #endif
01208 }
01209
01210 if (F) {
01211 #ifdef FLT_RADIX
01212 checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
01213 #else
01214 fmissing("FLT_RADIX");
01215 #endif
01216 #ifdef FLT_MANT_DIG
01217 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
01218 #else
01219 fmissing("FLT_MANT_DIG");
01220 #endif
01221 #ifdef FLT_DIG
01222 checktype(FLT_DIG, "FLT_DIG", Signed, int);
01223 #else
01224 fmissing("FLT_DIG");
01225 #endif
01226 #ifdef FLT_ROUNDS
01227 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
01228 #else
01229 fmissing("FLT_ROUNDS");
01230 #endif
01231 #ifdef FLT_EPSILON
01232 fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
01233 #else
01234 fmissing("FLT_EPSILON");
01235 #endif
01236 #ifdef FLT_MIN_EXP
01237 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
01238 #else
01239 fmissing("FLT_MIN_EXP");
01240 #endif
01241 #ifdef FLT_MIN
01242 fchecktype(FLT_MIN, "FLT_MIN", float);
01243 #else
01244 fmissing("FLT_MIN");
01245 #endif
01246 #ifdef FLT_MIN_10_EXP
01247 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
01248 #else
01249 fmissing("FLT_MIN_10_EXP");
01250 #endif
01251 #ifdef FLT_MAX_EXP
01252 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
01253 #else
01254 fmissing("FLT_MAX_EXP");
01255 #endif
01256 #ifdef FLT_MAX
01257 fchecktype(FLT_MAX, "FLT_MAX", float);
01258 #else
01259 fmissing("FLT_MAX");
01260 #endif
01261 #ifdef FLT_MAX_10_EXP
01262 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
01263 #else
01264 fmissing("FLT_MAX_10_EXP");
01265 #endif
01266 #ifdef DBL_MANT_DIG
01267 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
01268 #else
01269 fmissing("DBL_MANT_DIG");
01270 #endif
01271 #ifdef DBL_DIG
01272 checktype(DBL_DIG, "DBL_DIG", Signed, int);
01273 #else
01274 fmissing("DBL_DIG");
01275 #endif
01276 #ifdef DBL_EPSILON
01277 fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
01278 #else
01279 fmissing("DBL_EPSILON");
01280 #endif
01281 #ifdef DBL_MIN_EXP
01282 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
01283 #else
01284 fmissing("DBL_MIN_EXP");
01285 #endif
01286 #ifdef DBL_MIN
01287 fchecktype(DBL_MIN, "DBL_MIN", double);
01288 #else
01289 fmissing("DBL_MIN");
01290 #endif
01291 #ifdef DBL_MIN_10_EXP
01292 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
01293 #else
01294 fmissing("DBL_MIN_10_EXP");
01295 #endif
01296 #ifdef DBL_MAX_EXP
01297 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
01298 #else
01299 fmissing("DBL_MAX_EXP");
01300 #endif
01301 #ifdef DBL_MAX
01302 fchecktype(DBL_MAX, "DBL_MAX", double);
01303 #else
01304 fmissing("DBL_MAX");
01305 #endif
01306 #ifdef DBL_MAX_10_EXP
01307 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
01308 #else
01309 fmissing("DBL_MAX_10_EXP");
01310 #endif
01311 #ifdef STDC
01312 #ifdef LDBL_MANT_DIG
01313 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
01314 #else
01315 fmissing("LDBL_MANT_DIG");
01316 #endif
01317 #ifdef LDBL_DIG
01318 checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
01319 #else
01320 fmissing("LDBL_DIG");
01321 #endif
01322 #ifdef LDBL_EPSILON
01323 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
01324 #else
01325 fmissing("LDBL_EPSILON");
01326 #endif
01327 #ifdef LDBL_MIN_EXP
01328 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
01329 #else
01330 fmissing("LDBL_MIN_EXP");
01331 #endif
01332 #ifdef LDBL_MIN
01333 fchecktype(LDBL_MIN, "LDBL_MIN", long double);
01334 #else
01335 fmissing("LDBL_MIN");
01336 #endif
01337 #ifdef LDBL_MIN_10_EXP
01338 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
01339 #else
01340 fmissing("LDBL_MIN_10_EXP");
01341 #endif
01342 #ifdef LDBL_MAX_EXP
01343 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
01344 #else
01345 fmissing("LDBL_MAX_EXP");
01346 #endif
01347 #ifdef LDBL_MAX
01348 fchecktype(LDBL_MAX, "LDBL_MAX", long double);
01349 #else
01350 fmissing("LDBL_MAX");
01351 #endif
01352 #ifdef LDBL_MAX_10_EXP
01353 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
01354 #else
01355 fmissing("LDBL_MAX_10_EXP");
01356 #endif
01357 #endif
01358 }
01359 #endif
01360 }
01361
01362 #ifdef VERIFY
01363 #ifndef SCHAR_MAX
01364 #define SCHAR_MAX char_max
01365 #endif
01366 #ifndef SCHAR_MIN
01367 #define SCHAR_MIN char_min
01368 #endif
01369 #ifndef UCHAR_MAX
01370 #define UCHAR_MAX char_max
01371 #endif
01372 #endif
01373
01374 #ifndef CHAR_BIT
01375 #define CHAR_BIT char_bit
01376 #endif
01377 #ifndef CHAR_MAX
01378 #define CHAR_MAX char_max
01379 #endif
01380 #ifndef CHAR_MIN
01381 #define CHAR_MIN char_min
01382 #endif
01383 #ifndef SCHAR_MAX
01384 #define SCHAR_MAX char_max
01385 #endif
01386 #ifndef SCHAR_MIN
01387 #define SCHAR_MIN char_min
01388 #endif
01389 #ifndef UCHAR_MAX
01390 #define UCHAR_MAX char_max
01391 #endif
01392
01393 int cprop() {
01394
01395 Volatile char c, char_max, char_min;
01396 Volatile int bits_per_byte, c_signed;
01397 long char_bit;
01398
01399 Unexpected(2);
01400
01401
01402 c=1; bits_per_byte=0;
01403 do { c=c<<1; bits_per_byte++; } while(c!=0);
01404 c= (char)(-1);
01405 if (((int)c)<0) c_signed=1;
01406 else c_signed=0;
01407 Vprintf("%schar = %d bits, %ssigned%s\n",
01408 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
01409 char_bit=(long)(sizeof(c)*bits_per_byte);
01410 if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
01411 char_bit, 0L, (long) CHAR_BIT, "");
01412
01413 c=0; char_max=0;
01414 c++;
01415 if (bits_per_byte <= 16) {
01416 if (setjmp(lab)==0) {
01417 while (c>char_max) {
01418 char_max=c;
01419 c++;
01420 }
01421 } else {
01422 Vprintf("%sCharacter overflow generates a trap!%s\n",
01423 co, oc);
01424 }
01425 c=0; char_min=0;
01426 c--;
01427 if (setjmp(lab)==0) {
01428 while (c<char_min) {
01429 char_min=c;
01430 c--;
01431 }
01432 }
01433 } else {
01434
01435 c = (1 << (bits_per_byte - 1)) - 1;
01436 char_max = c;
01437 c++;
01438 if (c > char_max)
01439 char_max = ~0;
01440 c = 0;
01441 char_min = 0;
01442 c--;
01443 if (c < char_min) {
01444 c = (1 << (bits_per_byte - 1)) - 1;
01445 c = -c;
01446 char_min = c;
01447 c--;
01448 if (c < char_min)
01449 char_min = c;
01450 }
01451 }
01452 if (c_signed && char_min == 0) {
01453 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
01454 Vprintf("%s %s%s%s\n",
01455 "They contain only nonnegative values, ",
01456 "but sign extend when used as integers.", co, oc);
01457 }
01458 Unexpected(3);
01459
01460 if (L) {
01461
01462
01463 if ((sizeof(char) == sizeof(int)) && !c_signed) {
01464 u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
01465 (long) char_max,
01466 (long) CHAR_MAX, "");
01467 } else {
01468 i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
01469 (long) char_max, 0L,
01470 (long) CHAR_MAX, "");
01471 }
01472 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
01473 (long) char_min, (long) maxint,
01474 (long) CHAR_MIN, "");
01475 if (c_signed) {
01476 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
01477 (long) char_max, 0L,
01478 (long) SCHAR_MAX, "");
01479 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
01480 (long) char_min, (long) maxint,
01481 (long) SCHAR_MIN, "");
01482 } else {
01483 if (sizeof(char) == sizeof(int)) {
01484 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
01485 (long) char_max,
01486 (long) UCHAR_MAX, "");
01487 } else {
01488 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
01489 (long) char_max, 0L,
01490 (long) UCHAR_MAX, "");
01491 }
01492 }
01493
01494 if (c_signed) {
01495 #ifndef NO_UC
01496 Volatile unsigned char c, char_max;
01497 c=0; char_max=0;
01498 c++;
01499 if (setjmp(lab)==0) {
01500 while (c>char_max) {
01501 char_max=c;
01502 c++;
01503 }
01504 }
01505 Unexpected(4);
01506 if (sizeof(char) == sizeof(int)) {
01507 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
01508 (long) char_max,
01509 (long) UCHAR_MAX, "");
01510 } else {
01511 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
01512 (long) char_max, 0L,
01513 (long) UCHAR_MAX, "");
01514 }
01515 #endif
01516 } else {
01517 #ifndef NO_SC
01518 Volatile signed char c, char_max, char_min;
01519 c=0; char_max=0;
01520 c++;
01521 if (setjmp(lab)==0) {
01522 while (c>char_max) {
01523 char_max=c;
01524 c++;
01525 }
01526 }
01527 c=0; char_min=0;
01528 c--;
01529 if (setjmp(lab)==0) {
01530 while (c<char_min) {
01531 char_min=c;
01532 c--;
01533 }
01534 }
01535 Unexpected(5);
01536 i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
01537 (long) char_min, (long) maxint,
01538 (long) SCHAR_MIN, "");
01539 i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
01540 (long) char_max, 0L,
01541 (long) SCHAR_MAX, "");
01542 #endif
01543 }
01544 }
01545 return bits_per_byte;
01546 }
01547
01548 int basic() {
01549
01550
01551 Volatile int bits_per_byte;
01552 typedef int function ();
01553 int variable;
01554 int *p, *q;
01555
01556 Vprintf("%sSIZES%s\n", co, oc);
01557 bits_per_byte= cprop();
01558
01559
01560 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
01561 co,
01562 (int) sizeof(short)*bits_per_byte,
01563 (int) sizeof(int)*bits_per_byte,
01564 (int) sizeof(long)*bits_per_byte,
01565 (int) sizeof(float)*bits_per_byte,
01566 (int) sizeof(double)*bits_per_byte, oc);
01567 if (stdc) {
01568 Vprintf("%slong double=%d bits%s\n",
01569 co, (int) sizeof(Long_double)*bits_per_byte, oc);
01570 }
01571 Vprintf("%schar*=%d bits%s%s\n",
01572 co, (int)sizeof(char *)*bits_per_byte,
01573 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
01574 oc);
01575 Vprintf("%sint* =%d bits%s%s\n",
01576 co, (int)sizeof(int *)*bits_per_byte,
01577 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
01578 oc);
01579 Vprintf("%sfunc*=%d bits%s%s\n",
01580 co, (int)sizeof(function *)*bits_per_byte,
01581 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
01582 oc);
01583 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
01584 ((((false()?( sizeof(int)):(-1)) < 0) )?
01585 "signed":"unsigned") ,
01586 type_of(sizeof(
01587 sizeof(int)+0
01588 )
01589 ),
01590 oc);
01591 showtype("Type size_t is", sizeof(0));
01592
01593
01594
01595 #define alignment(TYPE) \
01596 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *) 0))
01597
01598 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
01599
01600 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
01601 co,
01602 alignment(char), alignment(short),
01603 alignment(int), alignment(long),
01604 oc);
01605
01606 Vprintf("%sfloat=%ld double=%ld%s\n",
01607 co,
01608 alignment(float), alignment(double),
01609 oc);
01610
01611 if (stdc) {
01612 Vprintf("%slong double=%ld%s\n",
01613 co,
01614 alignment(Long_double),
01615 oc);
01616 }
01617 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
01618 co,
01619 alignment(char *), alignment(int *), alignment(function *),
01620 oc);
01621
01622 Vprintf("\n");
01623
01624
01625
01626 endian(bits_per_byte);
01627
01628
01629
01630 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
01631
01632 if ((long) (char *) &variable == (long) (int *) &variable) {
01633 Vprintf("%sChar and int pointer formats seem identical%s\n",
01634 co, oc);
01635 } else {
01636 Vprintf("%sChar and int pointer formats are different%s\n",
01637 co, oc);
01638 }
01639 if ((long) (char *) &variable == (long) (function *) &variable) {
01640 Vprintf("%sChar and function pointer formats seem identical%s\n",
01641 co, oc);
01642 } else {
01643 Vprintf("%sChar and function pointer formats are different%s\n",
01644 co, oc);
01645 }
01646
01647 if (V) {
01648 if ("abcd"=="abcd")
01649 printf("%sStrings are shared%s\n", co, oc);
01650 else printf("%sStrings are not shared%s\n", co, oc);
01651 }
01652
01653 p=0; q=0;
01654 showtype("Type ptrdiff_t is", p-q);
01655
01656 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
01657
01658 sprop();
01659 iprop();
01660 lprop();
01661 usprop();
01662 uiprop();
01663 ulprop();
01664
01665 promotions();
01666
01667 Unexpected(6);
01668
01669 return bits_per_byte;
01670 }
01671
01672 #else
01673
01674 #ifdef SEP
01675 extern jmp_buf lab;
01676 extern int V, L, F, bugs, bits_per_byte;
01677 extern char co[], oc[];
01678 extern char *f_rep();
01679 #endif
01680 #endif
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694 #ifdef Number
01695 #undef Number
01696 #undef THING
01697 #undef Thing
01698 #undef thing
01699 #undef FPROP
01700 #undef Fname
01701 #undef Store
01702 #undef Sum
01703 #undef Diff
01704 #undef Mul
01705 #undef Div
01706 #undef ZERO
01707 #undef HALF
01708 #undef ONE
01709 #undef TWO
01710 #undef THREE
01711 #undef FOUR
01712 #undef Self
01713 #undef F_check
01714 #undef Validate
01715 #undef EPROP
01716 #undef MARK
01717
01718
01719 #undef F_RADIX
01720 #undef F_MANT_DIG
01721 #undef F_DIG
01722 #undef F_ROUNDS
01723 #undef F_EPSILON
01724 #undef F_MIN_EXP
01725 #undef F_MIN
01726 #undef F_MIN_10_EXP
01727 #undef F_MAX_EXP
01728 #undef F_MAX
01729 #undef F_MAX_10_EXP
01730 #endif
01731
01732 #ifdef Integer
01733 #undef Integer
01734 #undef INT
01735 #undef IPROP
01736 #undef Iname
01737 #undef UPROP
01738 #undef Uname
01739 #undef OK_UI
01740 #undef IMARK
01741
01742 #undef I_MAX
01743 #undef I_MIN
01744 #undef U_MAX
01745 #endif
01746
01747 #ifdef PASS1
01748
01749
01750
01751 #define Number float
01752 #define THING "FLOAT"
01753 #define Thing "Float"
01754 #define thing "float"
01755 #define Fname "FLT"
01756 #define FPROP fprop
01757 #define Store fStore
01758 #define Sum fSum
01759 #define Diff fDiff
01760 #define Mul fMul
01761 #define Div fDiv
01762 #define ZERO 0.0
01763 #define HALF 0.5
01764 #define ONE 1.0
01765 #define TWO 2.0
01766 #define THREE 3.0
01767 #define FOUR 4.0
01768 #define Self fSelf
01769 #define F_check fCheck
01770 #define MARK "F"
01771 #ifdef VERIFY
01772 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
01773 #endif
01774
01775 #define EPROP efprop
01776
01777 #define Integer short
01778 #define INT "short"
01779 #define IPROP sprop
01780 #define Iname "SHRT"
01781 #ifndef NO_UI
01782 #define OK_UI 1
01783 #endif
01784 #define IMARK ""
01785
01786 #define UPROP usprop
01787 #define Uname "USHRT"
01788
01789 #ifdef SHRT_MAX
01790 #define I_MAX SHRT_MAX
01791 #endif
01792 #ifdef SHRT_MIN
01793 #define I_MIN SHRT_MIN
01794 #endif
01795 #ifdef USHRT_MAX
01796 #define U_MAX USHRT_MAX
01797 #endif
01798
01799 #ifdef FLT_RADIX
01800 #define F_RADIX FLT_RADIX
01801 #endif
01802 #ifdef FLT_MANT_DIG
01803 #define F_MANT_DIG FLT_MANT_DIG
01804 #endif
01805 #ifdef FLT_DIG
01806 #define F_DIG FLT_DIG
01807 #endif
01808 #ifdef FLT_ROUNDS
01809 #define F_ROUNDS FLT_ROUNDS
01810 #endif
01811 #ifdef FLT_EPSILON
01812 #define F_EPSILON FLT_EPSILON
01813 #endif
01814 #ifdef FLT_MIN_EXP
01815 #define F_MIN_EXP FLT_MIN_EXP
01816 #endif
01817 #ifdef FLT_MIN
01818 #define F_MIN FLT_MIN
01819 #endif
01820 #ifdef FLT_MIN_10_EXP
01821 #define F_MIN_10_EXP FLT_MIN_10_EXP
01822 #endif
01823 #ifdef FLT_MAX_EXP
01824 #define F_MAX_EXP FLT_MAX_EXP
01825 #endif
01826 #ifdef FLT_MAX
01827 #define F_MAX FLT_MAX
01828 #endif
01829 #ifdef FLT_MAX_10_EXP
01830 #define F_MAX_10_EXP FLT_MAX_10_EXP
01831 #endif
01832
01833 #endif
01834
01835 #ifdef PASS2
01836
01837 #define Number double
01838 #define THING "DOUBLE"
01839 #define Thing "Double"
01840 #define thing "double"
01841 #define Fname "DBL"
01842 #define FPROP dprop
01843 #define Store dStore
01844 #define Sum dSum
01845 #define Diff dDiff
01846 #define Mul dMul
01847 #define Div dDiv
01848 #define ZERO 0.0
01849 #define HALF 0.5
01850 #define ONE 1.0
01851 #define TWO 2.0
01852 #define THREE 3.0
01853 #define FOUR 4.0
01854 #define Self dSelf
01855 #define F_check dCheck
01856 #define MARK ""
01857 #ifdef VERIFY
01858 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
01859 #endif
01860
01861 #define EPROP edprop
01862
01863 #define Integer int
01864 #define INT "int"
01865 #define IPROP iprop
01866 #define Iname "INT"
01867 #define OK_UI 1
01868 #define IMARK ""
01869
01870 #define UPROP uiprop
01871 #define Uname "UINT"
01872
01873 #ifdef INT_MAX
01874 #define I_MAX INT_MAX
01875 #endif
01876 #ifdef INT_MIN
01877 #define I_MIN INT_MIN
01878 #endif
01879 #ifdef UINT_MAX
01880 #define U_MAX UINT_MAX
01881 #endif
01882
01883 #ifdef DBL_MANT_DIG
01884 #define F_MANT_DIG DBL_MANT_DIG
01885 #endif
01886 #ifdef DBL_DIG
01887 #define F_DIG DBL_DIG
01888 #endif
01889 #ifdef DBL_EPSILON
01890 #define F_EPSILON DBL_EPSILON
01891 #endif
01892 #ifdef DBL_MIN_EXP
01893 #define F_MIN_EXP DBL_MIN_EXP
01894 #endif
01895 #ifdef DBL_MIN
01896 #define F_MIN DBL_MIN
01897 #endif
01898 #ifdef DBL_MIN_10_EXP
01899 #define F_MIN_10_EXP DBL_MIN_10_EXP
01900 #endif
01901 #ifdef DBL_MAX_EXP
01902 #define F_MAX_EXP DBL_MAX_EXP
01903 #endif
01904 #ifdef DBL_MAX
01905 #define F_MAX DBL_MAX
01906 #endif
01907 #ifdef DBL_MAX_10_EXP
01908 #define F_MAX_10_EXP DBL_MAX_10_EXP
01909 #endif
01910
01911 #endif
01912
01913 #ifdef PASS3
01914
01915 #ifdef STDC
01916 #define Number long double
01917
01918 #define ZERO 0.0L
01919 #define HALF 0.5L
01920 #define ONE 1.0L
01921 #define TWO 2.0L
01922 #define THREE 3.0L
01923 #define FOUR 4.0L
01924 #endif
01925
01926 #define THING "LONG DOUBLE"
01927 #define Thing "Long double"
01928 #define thing "long double"
01929 #define Fname "LDBL"
01930 #define FPROP ldprop
01931 #define Store ldStore
01932 #define Sum ldSum
01933 #define Diff ldDiff
01934 #define Mul ldMul
01935 #define Div ldDiv
01936 #define Self ldSelf
01937 #define F_check ldCheck
01938 #define MARK "L"
01939 #ifdef VERIFY
01940 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
01941 #endif
01942
01943 #define EPROP eldprop
01944
01945 #define Integer long
01946 #define INT "long"
01947 #define IPROP lprop
01948 #define Iname "LONG"
01949 #ifndef NO_UI
01950 #define OK_UI 1
01951 #endif
01952 #define IMARK "L"
01953
01954 #define UPROP ulprop
01955 #define Uname "ULONG"
01956
01957 #ifdef LONG_MAX
01958 #define I_MAX LONG_MAX
01959 #endif
01960 #ifdef LONG_MIN
01961 #define I_MIN LONG_MIN
01962 #endif
01963 #ifdef ULONG_MAX
01964 #define U_MAX ULONG_MAX
01965 #endif
01966
01967 #ifdef LDBL_MANT_DIG
01968 #define F_MANT_DIG LDBL_MANT_DIG
01969 #endif
01970 #ifdef LDBL_DIG
01971 #define F_DIG LDBL_DIG
01972 #endif
01973 #ifdef LDBL_EPSILON
01974 #define F_EPSILON LDBL_EPSILON
01975 #endif
01976 #ifdef LDBL_MIN_EXP
01977 #define F_MIN_EXP LDBL_MIN_EXP
01978 #endif
01979 #ifdef LDBL_MIN
01980 #define F_MIN LDBL_MIN
01981 #endif
01982 #ifdef LDBL_MIN_10_EXP
01983 #define F_MIN_10_EXP LDBL_MIN_10_EXP
01984 #endif
01985 #ifdef LDBL_MAX_EXP
01986 #define F_MAX_EXP LDBL_MAX_EXP
01987 #endif
01988 #ifdef LDBL_MAX
01989 #define F_MAX LDBL_MAX
01990 #endif
01991 #ifdef LDBL_MAX_10_EXP
01992 #define F_MAX_10_EXP LDBL_MAX_10_EXP
01993 #endif
01994
01995 #endif
01996
01997 #define UNDEFINED (-2)
01998
01999 #ifndef I_MAX
02000 #define I_MAX ((unsigned long) UNDEFINED)
02001 #endif
02002 #ifndef I_MIN
02003 #define I_MIN ((unsigned long) UNDEFINED)
02004 #endif
02005 #ifndef U_MAX
02006 #define U_MAX ((unsigned long) UNDEFINED)
02007 #endif
02008
02009 #ifndef F_RADIX
02010 #define F_RADIX UNDEFINED
02011 #endif
02012 #ifndef F_MANT_DIG
02013 #define F_MANT_DIG UNDEFINED
02014 #endif
02015 #ifndef F_DIG
02016 #define F_DIG UNDEFINED
02017 #endif
02018 #ifndef F_ROUNDS
02019 #define F_ROUNDS UNDEFINED
02020 #endif
02021 #ifndef F_EPSILON
02022 #define F_EPSILON ((Number) UNDEFINED)
02023 #endif
02024 #ifndef F_MIN_EXP
02025 #define F_MIN_EXP UNDEFINED
02026 #endif
02027 #ifndef F_MIN
02028 #define F_MIN ((Number) UNDEFINED)
02029 #endif
02030 #ifndef F_MIN_10_EXP
02031 #define F_MIN_10_EXP UNDEFINED
02032 #endif
02033 #ifndef F_MAX_EXP
02034 #define F_MAX_EXP UNDEFINED
02035 #endif
02036 #ifndef F_MAX
02037 #define F_MAX ((Number) UNDEFINED)
02038 #endif
02039 #ifndef F_MAX_10_EXP
02040 #define F_MAX_10_EXP UNDEFINED
02041 #endif
02042
02043 #ifndef VERIFY
02044 #define Validate(prec, val, req, same) {;}
02045 #endif
02046
02047 #ifdef Integer
02048
02049 Procedure IPROP() {
02050
02051 Volatile Integer newi, int_max, maxeri, int_min, minneri;
02052 Volatile int ibits, ipower, two=2;
02053
02054
02055
02056
02057 newi=1; int_max=0;
02058
02059 if (setjmp(lab)==0) {
02060 for(ipower=0; newi>int_max; ipower++) {
02061 int_max=newi;
02062 newi=newi*two+1;
02063 }
02064 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
02065 co, INT[0]=='i'?"n":"", INT, oc);
02066 } else {
02067 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
02068 co, INT[0]=='i'?"n":"", INT, oc);
02069 }
02070 Unexpected(7);
02071
02072
02073 int_min= -int_max;
02074 if (setjmp(lab)==0) {
02075 if (int_min-1 < int_min) int_min--;
02076 }
02077 Unexpected(8);
02078
02079
02080
02081 maxeri=0; newi=int_max;
02082
02083 if (setjmp(lab)==0) {
02084 for(ibits=ipower; newi>maxeri; ibits++) {
02085 maxeri=newi;
02086 newi=newi+newi+1;
02087 }
02088 }
02089 Unexpected(9);
02090
02091 minneri= -maxeri;
02092 if (setjmp(lab)==0) {
02093 if (minneri-1 < minneri) minneri--;
02094 }
02095 Unexpected(10);
02096
02097 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
02098 co, INT, (long)int_max, ipower, oc);
02099 Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
02100
02101 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
02102 (long) int_max, 0L,
02103 (long) I_MAX, IMARK);
02104 if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
02105 (long) int_min, (long) (PASS==1?maxint:int_max),
02106 (long) I_MIN, IMARK);
02107
02108 if(int_max < 0) {
02109 eek_a_bug("signed integral comparison faulty?");
02110 }
02111
02112 if (maxeri>int_max) {
02113 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
02114 co, INT, (long)maxeri, ibits,
02115 "but only for addition, not multiplication",
02116 "(I smell a Cyber!)",
02117 oc);
02118 }
02119
02120 if (minneri<int_min) {
02121 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
02122 co, INT, (long)minneri,
02123 "but only for addition, not multiplication",
02124 "(I smell a Cyber!)",
02125 oc);
02126 }
02127 }
02128
02129 Procedure UPROP () {
02130
02131 #ifdef OK_UI
02132 Volatile unsigned Integer u_max, newi, two;
02133 newi=1; u_max=0; two=2;
02134
02135 if (setjmp(lab)==0) {
02136 while(newi>u_max) {
02137 u_max=newi;
02138 newi=newi*two+1;
02139 }
02140 }
02141 Unexpected(11);
02142 Vprintf("%sMaximum unsigned %s = %lu%s\n",
02143 co, INT, (unsigned long) u_max, oc);
02144
02145
02146 if (L) {
02147 if (PASS == 1 && sizeof(short) < sizeof(int)) {
02148
02149 i_define(D_UINT_MAX, INT, Uname, "_MAX",
02150 (unsigned long) u_max, 0L,
02151 (unsigned long) U_MAX, IMARK);
02152 } else {
02153 u_define(D_UINT_MAX, INT, Uname, "_MAX",
02154 (unsigned long) u_max,
02155 (unsigned long) U_MAX, IMARK);
02156 }
02157 }
02158 #endif
02159 }
02160
02161 #endif
02162
02163 #ifdef Number
02164
02165
02166
02167
02168
02169 #ifdef STDC
02170 #define ARGS1(atype, a) (atype a)
02171 #define ARGS2(atype, a, btype, b) (atype a, btype b)
02172 #else
02173 #define ARGS1(atype, a) (a) atype a;
02174 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
02175 #endif
02176
02177 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
02178 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
02179 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
02180 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
02181 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
02182 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
02183
02184 Procedure F_check ARGS((int precision, Long_double val1));
02185
02186 Procedure F_check(precision, val1) int precision; Long_double val1; {
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199 Number val, new, diff;
02200 double rem;
02201 int e;
02202 char *rep;
02203 char *f2;
02204
02205 #ifdef NO_LONG_DOUBLE_IO
02206 double new1;
02207
02208
02209 f2= "%le";
02210
02211
02212 if (sizeof (Number) > sizeof(double))
02213 return;
02214 #else
02215 Long_double new1;
02216 if (sizeof(double) == sizeof(Long_double)) {
02217
02218
02219 f2= "%le";
02220 } else {
02221
02222 f2= "%Le";
02223 }
02224 #endif
02225 val= val1;
02226 rep= f_rep(precision, (Long_double) val);
02227 if (setjmp(lab)==0) {
02228 sscanf(rep, f2, &new1);
02229 } else {
02230 eek_a_bug("sscanf caused a trap");
02231 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc);
02232 Unexpected(12);
02233 return;
02234 }
02235
02236 if (setjmp(lab)==0) {
02237 new= new1;
02238 if (new != 0.0) {
02239 diff= val/new - 1.0;
02240 if (diff < 0.1) diff= 1.0;
02241
02242 }
02243 } else {
02244 eek_a_bug("sscanf returned an unusable number");
02245 printf("%s scanning: %s with format: %s%s\n\n",
02246 co, rep, f2, oc);
02247 Unexpected(13);
02248 return;
02249 }
02250
02251 Unexpected(14);
02252 if (new != val) {
02253 eek_a_bug("Possibly bad output from printf above");
02254 if (!exponent((Long_double)val, &rem, &e)) {
02255 printf("%s but value was an unusable number%s\n\n",
02256 co, oc);
02257 return;
02258 }
02259 printf("%s expected value around %.*fe%d, bit pattern:\n ",
02260 co, precision, rem, e);
02261 bitpattern((char *) &val, (unsigned)sizeof(val));
02262 printf ("%s\n", oc);
02263 printf("%s sscanf gave %s, bit pattern:\n ",
02264 co, f_rep(precision, (Long_double) new));
02265 bitpattern((char *) &new, (unsigned)sizeof(new));
02266 printf ("%s\n", oc);
02267 if (setjmp(lab) == 0) {
02268 diff= val-new;
02269 printf("%s difference= %s%s\n\n",
02270 co, f_rep(precision, (Long_double) diff), oc);
02271 }
02272 Unexpected(15);
02273 }
02274 }
02275
02276 #ifdef VERIFY
02277 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
02278
02279 Unexpected(16);
02280 if (!same) {
02281 printf("%s*** Verify failed for above #define!\n", co);
02282 if (setjmp(lab) == 0) {
02283 printf(" Compiler has %s for value%s\n",
02284 f_rep(prec, req), oc);
02285 } else {
02286 printf(" Compiler has %s for value%s\n",
02287 "an unusable number", oc);
02288 }
02289 if (setjmp(lab) == 0) {
02290 F_check(prec, (Long_double) req);
02291 }
02292 if (setjmp(lab) == 0) {
02293 if (req > 0.0 && val > 0.0) {
02294 printf("%s difference= %s%s\n",
02295 co, f_rep(prec, val-req), oc);
02296 }
02297 }
02298 Unexpected(17);
02299 printf("\n");
02300 bugs++;
02301 } else if (val != req) {
02302 if (stdc) eek_a_bug("constant has the wrong precision");
02303 else eek_a_bug("the cast didn't work");
02304 printf("\n");
02305 }
02306 }
02307 #endif
02308
02309 int FPROP(bits_per_byte) int bits_per_byte; {
02310
02311
02312
02313
02314
02315
02316
02317 Volatile int
02318 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
02319 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
02320 mantbits, digs, f_dig, trap,
02321 hidden, normal, f_min_10_exp, f_max_10_exp;
02322 Volatile Number
02323 a, b, base, basein, basem1, f_epsilon, epsneg,
02324 eps, epsp1, etop, ebot,
02325 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
02326
02327 Unexpected(18);
02328
02329 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
02330
02331
02332
02333
02334
02335
02336 a=1.0;
02337 if (setjmp(lab)==0) {
02338 do { a=Sum(a, a); }
02339 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
02340 } else {
02341 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
02342
02343 farewell(bugs+1);
02344 }
02345 Unexpected(19);
02346
02347
02348
02349
02350 b=1.0;
02351 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
02352 f_radix=base;
02353 Vprintf("%sBase = %d%s\n", co, f_radix, oc);
02354
02355
02356 if (f_radix < 2) {
02357 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
02358 printf("\n");
02359 return(0);
02360 }
02361
02362 if (PASS == 1) {
02363 flt_radix= f_radix;
02364 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
02365 (long) f_radix, 0L, (long) F_RADIX, "");
02366 } else if (f_radix != flt_radix) {
02367 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
02368 co, thing, "arithmetic has a different radix",
02369 f_radix, "from float", oc);
02370 bugs++;
02371 }
02372
02373
02374 f_mant_dig=0; b=1.0;
02375 do { f_mant_dig++; b=Mul(b, base); }
02376 while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
02377 f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
02378 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
02379 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
02380 if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
02381 (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
02382 if (F) i_define(D_DIG, thing, Fname, "_DIG",
02383 (long) f_dig, 0L, (long) F_DIG, "");
02384 digs= ceil_log(10, (Long_double)b);
02385
02386
02387 basem1=Diff(base, HALF);
02388 if (Diff(Sum(a, basem1), a) != ZERO) {
02389 if (f_radix == 2) basem1=0.375;
02390 else basem1=1.0;
02391 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2;
02392 else irnd=1;
02393 } else irnd=0;
02394
02395 basem1=Diff(base, HALF);
02396
02397 if (Diff(Diff(-a, basem1), -a) != ZERO) {
02398 if (f_radix == 2) basem1=0.375;
02399 else basem1=1.0;
02400 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2;
02401 else mrnd=1;
02402 } else mrnd=0;
02403
02404 f_rounds= -1;
02405 if (irnd==0 && mrnd==0) f_rounds=0;
02406 if (irnd==1 && mrnd==1) f_rounds=1;
02407 if (irnd==2 && mrnd==0) f_rounds=2;
02408 if (irnd==0 && mrnd==2) f_rounds=3;
02409
02410 if (f_rounds != -1) {
02411 Vprintf("%sArithmetic rounds towards ", co);
02412 switch (f_rounds) {
02413 case 0: Vprintf("zero (i.e. it chops)"); break;
02414 case 1: Vprintf("nearest"); break;
02415 case 2: Vprintf("+infinity"); break;
02416 case 3: Vprintf("-infinity"); break;
02417 default: Vprintf("???"); break;
02418 }
02419 Vprintf("%s\n", oc);
02420 } else {
02421 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
02422 Vprintf("%s Negative numbers %s%s\n",
02423 co, mrnd==0 ? "towards zero" :
02424 mrnd==1 ? "to nearest" :
02425 "away from zero",
02426 oc);
02427 Vprintf("%s Positive numbers %s%s\n",
02428 co, irnd==0 ? "towards zero" :
02429 irnd==1 ? "to nearest" :
02430 "away from zero",
02431 oc);
02432 }
02433
02434 if (f_radix == 2 && f_rounds == 1) {
02435 if (Diff(Sum(a, ONE), a) != ZERO) {
02436 Vprintf("%s Tie breaking rounds up%s\n", co, oc);
02437 } else if (Diff(Sum(a, THREE), a) == FOUR) {
02438 Vprintf("%s Tie breaking rounds to even%s\n", co, oc);
02439 } else {
02440 Vprintf("%s Tie breaking rounds down%s\n", co, oc);
02441 }
02442 }
02443 if (PASS == 1) {
02444 flt_rounds= f_rounds;
02445
02446
02447 if (F && (!SYS_FLOAT_H_WRAP || F_ROUNDS == UNDEFINED))
02448 i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
02449 (long) f_rounds, 1L, (long) F_ROUNDS, "");
02450 } else if (f_rounds != flt_rounds) {
02451 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
02452 co, thing, "arithmetic rounds differently",
02453 f_rounds, "from float", oc);
02454 bugs++;
02455 }
02456
02457
02458 negeps=f_mant_dig+f_mant_dig;
02459 basein=1.0/base;
02460 a=1.0;
02461 for(i=1; i<=negeps; i++) a*=basein;
02462
02463 b=a;
02464 while (Diff(Diff(ONE, a), ONE) == ZERO) {
02465 a*=base;
02466 negeps--;
02467 }
02468 negeps= -negeps;
02469 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
02470 co, negeps, oc);
02471
02472 etop = ONE;
02473 ebot = ZERO;
02474 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
02475
02476
02477 while (eps != ebot && eps != etop) {
02478 epsp1 = Diff(ONE, eps);
02479 if (epsp1 < ONE) etop = eps;
02480 else ebot = eps;
02481 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
02482 }
02483 eps= etop;
02484
02485 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
02486 eek_a_bug("internal error calculating epsneg");
02487 }
02488 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
02489 co, f_rep(digs, (Long_double) eps), oc);
02490 if (V) F_check(digs, (Long_double) eps);
02491
02492 epsneg=a;
02493 if ((f_radix!=2) && irnd) {
02494
02495 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
02496
02497 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
02498 }
02499
02500 Unexpected(20);
02501
02502 machep= -f_mant_dig-f_mant_dig;
02503 a=b;
02504 while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
02505 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
02506 co, machep, oc);
02507
02508 etop = ONE;
02509 ebot = ZERO;
02510 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
02511
02512
02513 while (eps != ebot && eps != etop) {
02514 epsp1 = Sum(ONE, eps);
02515 if (epsp1 > ONE) etop = eps;
02516 else ebot = eps;
02517 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
02518 }
02519
02520 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
02521 eek_a_bug("internal error calculating eps");
02522 }
02523 f_epsilon=etop;
02524
02525 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
02526 co, f_rep(digs, (Long_double) f_epsilon), oc);
02527
02528 f_epsilon= Diff(Sum(ONE, f_epsilon), ONE);
02529 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
02530 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
02531
02532
02533 if (F) f_define(D_EPSILON, thing,
02534 Fname, "_EPSILON", digs,
02535 (Long_double) f_epsilon,
02536 (Long_double) F_EPSILON, MARK);
02537 if (V || F) F_check(digs, (Long_double) f_epsilon);
02538 Unexpected(21);
02539 if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
02540 f_epsilon == Self(F_EPSILON));
02541 Unexpected(22);
02542
02543
02544 if (f_rounds == 0) {
02545 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) != ZERO) {
02546 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
02547 }
02548 }
02549
02550
02551 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
02552
02553
02554 if (setjmp(lab)==0) {
02555 do {
02556 y=z; y1=z1;
02557 z=Mul(y,y); z1=Mul(z1, y);
02558 a=Mul(z,ONE);
02559 z2=Div(z1,y);
02560 if (z2 != y1) break;
02561 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
02562 i++;
02563 k+=k;
02564 } while(1);
02565 } else {
02566 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
02567 }
02568 Unexpected(23);
02569
02570 if (f_radix != 10) {
02571 iexp=i+1;
02572 mx=k+k;
02573 } else {
02574 iexp=2;
02575 iz=f_radix;
02576 while (k >= iz) { iz*=f_radix; iexp++; }
02577 mx=iz+iz-1;
02578 }
02579
02580
02581 if (setjmp(lab)==0) {
02582 do {
02583 f_min=y; z1=y1;
02584 y=Div(y,base); y1=Div(y1,base);
02585 a=Mul(y,ONE);
02586 z2=Mul(y1,base);
02587 if (z2 != z1) break;
02588 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
02589 k++;
02590 } while (1);
02591 }
02592 Unexpected(24);
02593
02594 f_min_exp=(-k)+1;
02595
02596 if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
02597 Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
02598 Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
02599 if (F)
02600 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
02601 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
02602
02603 if (setjmp(lab)==0) {
02604 Vprintf("%sMinimum normalised positive number = %s%s\n",
02605 co, f_rep(digs, (Long_double) f_min), oc);
02606 } else {
02607 eek_a_bug("printf can't print the smallest normalised number");
02608 printf("\n");
02609 }
02610 Unexpected(25);
02611
02612 if (setjmp(lab) == 0) {
02613 if (F) f_define(D_MIN, thing,
02614 Fname, "_MIN", digs,
02615 (Long_double) f_min,
02616 (Long_double) F_MIN, MARK);
02617 if (V || F) F_check(digs, (Long_double) f_min);
02618 } else {
02619 eek_a_bug("xxx_MIN caused a trap");
02620 printf("\n");
02621 }
02622
02623 if (setjmp(lab) == 0) {
02624 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
02625 f_min == Self(F_MIN));
02626 } else {
02627 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
02628 co, "Compiler has an unusable number for value", oc);
02629 bugs++;
02630 }
02631 Unexpected(26);
02632
02633 a=1.0; f_min_10_exp=0;
02634 while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
02635 if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
02636 (long) f_min_10_exp, (long) maxint,
02637 (long) F_MIN_10_EXP, "");
02638
02639
02640 if (setjmp(lab)==0) {
02641 do {
02642 xminner=y;
02643 y=Div(y,base);
02644 a=Mul(y,ONE);
02645 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
02646 } while (1);
02647 }
02648 Unexpected(27);
02649
02650 if (xminner != 0.0 && xminner != f_min) {
02651 normal= 0;
02652 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
02653 co, oc);
02654 if (setjmp(lab)==0) {
02655 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
02656 co, f_rep(digs, (Long_double) xminner), oc);
02657 if (V) F_check(digs, (Long_double) xminner);
02658 } else {
02659 eek_a_bug("printf can't print the smallest unnormalised number.");
02660 printf("\n");
02661 }
02662 Unexpected(28);
02663 } else {
02664 normal= 1;
02665 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
02666 }
02667
02668
02669 f_max_exp=2; f_max=1.0; newxmax=base+1.0;
02670 inf=0; trap=0;
02671 while (f_max<newxmax) {
02672 f_max=newxmax;
02673 if (setjmp(lab) == 0) {
02674 newxmax=Mul(newxmax, base);
02675 } else {
02676 trap=1;
02677 break;
02678 }
02679 if (Div(newxmax, base) != f_max) {
02680 inf=1;
02681 break;
02682 }
02683 f_max_exp++;
02684 }
02685 Unexpected(29);
02686 if (trap) {
02687 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
02688 }
02689
02690 if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
02691 Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
02692 if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
02693 (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
02694
02695
02696 f_max=Diff(ONE, epsneg);
02697 if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
02698 for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
02699
02700 if (setjmp(lab)==0) {
02701 Vprintf("%sMaximum number = %s%s\n",
02702 co, f_rep(digs, (Long_double) f_max), oc);
02703 } else {
02704 eek_a_bug("printf can't print the largest double.");
02705 printf("\n");
02706 }
02707 if (setjmp(lab)==0) {
02708
02709 if (F) f_define(D_MAX, thing,
02710 Fname, "_MAX", digs,
02711 (Long_double) f_max,
02712 (Long_double) F_MAX, MARK);
02713 if (V || F) F_check(digs, (Long_double) f_max);
02714 } else {
02715 eek_a_bug("xxx_MAX caused a trap");
02716 printf("\n");
02717 }
02718 if (setjmp(lab)==0) {
02719 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
02720 f_max == Self(F_MAX));
02721 } else {
02722 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
02723 co, "Compiler has an unusable number for value", oc);
02724 bugs++;
02725 }
02726 Unexpected(30);
02727
02728 a=1.0; f_max_10_exp=0;
02729 while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
02730 if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
02731 (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
02732
02733
02734 if (f_radix != 10) {
02735 hidden=0;
02736 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
02737 if (mantbits == 64
02738 && iexp == 15
02739 && f_max_exp+f_min_exp > 0
02740 && mantbits+iexp+17 == (int)sizeof(Number)*bits_per_byte) {
02741 Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co, oc);
02742 Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co, oc);
02743 goto is_extended;
02744 }
02745 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
02746 hidden=1;
02747 Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
02748 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
02749 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
02750 co, oc);
02751 } else {
02752 printf("\n%s%s\n %s %s %s!%s\n\n",
02753 co,
02754 "*** Something fishy here!",
02755 "Exponent size + significand size doesn't match",
02756 "with the size of a", thing,
02757 oc);
02758 }
02759 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
02760 Vprintf("%sIt looks like %s length IEEE format%s\n",
02761 co, f_mant_dig==24 ? "single" :
02762 f_mant_dig==53 ? "double" :
02763 f_mant_dig >53 ? "extended" :
02764 "some", oc);
02765 is_extended:
02766 if (f_rounds != 1 || normal) {
02767 Vprintf("%s though ", co);
02768 if (f_rounds != 1) {
02769 Vprintf("the rounding is unusual");
02770 if (normal) Vprintf(" and ");
02771 }
02772 if (normal) Vprintf("the normalisation is unusual");
02773 Vprintf("%s\n", oc);
02774 }
02775 } else {
02776 Vprintf("%sIt doesn't look like IEEE format%s\n",
02777 co, oc);
02778 }
02779 }
02780 printf("\n");
02781 return f_mant_dig;
02782 }
02783
02784 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
02785
02786
02787
02788
02789
02790 Volatile int eprec;
02791 Volatile double a, b, base, old;
02792 Volatile Number d, oldd, dbase, one, zero;
02793 Volatile int bad=0;
02794
02795
02796 a=1.0;
02797 if (setjmp(lab) == 0) {
02798 do { old=a; a=a+a; }
02799 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
02800 } else bad=1;
02801
02802
02803
02804 if (!bad && (a <= old)) bad=1;
02805
02806 if (!bad) {
02807 b=1.0;
02808 if (setjmp(lab) == 0) {
02809 do { old=b; b=b+b; }
02810 while ((base=((a+b)-a)) == 0.0 && b>old);
02811 if (b <= old) bad=1;
02812 } else bad=1;
02813 }
02814
02815 if (!bad) {
02816 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
02817 if (setjmp(lab) == 0) {
02818 do { eprec++; oldd=d; d=d*dbase; }
02819 while ((((d+one)-d)-one) == zero && d>oldd);
02820 if (d <= oldd) bad=1;
02821 } else bad=1;
02822 }
02823
02824 Unexpected(31);
02825
02826 if (bad) {
02827 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
02828 co, thing, " check that you compiled without optimisation!",
02829 oc);
02830 } else if (eprec==dprec) {
02831 Vprintf("%s%s expressions are evaluated in double precision%s\n",
02832 co, Thing, oc);
02833 } else if (eprec==fprec) {
02834 Vprintf("%s%s expressions are evaluated in float precision%s\n",
02835 co, Thing, oc);
02836 } else if (eprec==lprec) {
02837 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
02838 co, Thing, oc);
02839 } else {
02840 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
02841 co, Thing, eprec>dprec ? "higher" : "lower",
02842 "precision than double,\n using",
02843 eprec, "base digits",
02844 oc);
02845 }
02846 }
02847
02848 #else
02849
02850 #ifdef FPROP
02851
02852 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
02853 #endif
02854 #ifdef EPROP
02855
02856 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
02857 #endif
02858
02859 #endif
02860
02861
02862 #undef PASS
02863
02864 #ifdef PASS2
02865 #undef PASS2
02866 #define PASS 3
02867 #define PASS3 1
02868 #endif
02869
02870 #ifdef PASS1
02871 #undef PASS1
02872 #define PASS 2
02873 #define PASS2 1
02874 #endif
02875
02876 #ifdef PASS0
02877 #undef PASS0
02878 #endif
02879
02880 #ifdef PASS
02881 #ifdef NO_FILE
02882 #include "enquire.c"
02883 #else
02884 #include FILENAME
02885 #endif
02886 #endif
02887