📄 enquire.c
字号:
#define IPROP lprop#define Iname "LONG"#ifndef NO_UI#define OK_UI 1#endif#define IMARK "L"#define UPROP ulprop#define Uname "ULONG"#ifdef VERIFY#ifdef LONG_MAX#define I_MAX LONG_MAX#endif#ifdef LONG_MIN#define I_MIN LONG_MIN#endif#ifdef ULONG_MAX#define U_MAX ULONG_MAX#endif#ifdef LDBL_MANT_DIG#define F_MANT_DIG LDBL_MANT_DIG#endif#ifdef LDBL_DIG#define F_DIG LDBL_DIG#endif#ifdef LDBL_EPSILON#define F_EPSILON LDBL_EPSILON#endif#ifdef LDBL_MIN_EXP#define F_MIN_EXP LDBL_MIN_EXP#endif#ifdef LDBL_MIN#define F_MIN LDBL_MIN#endif#ifdef LDBL_MIN_10_EXP#define F_MIN_10_EXP LDBL_MIN_10_EXP#endif#ifdef LDBL_MAX_EXP#define F_MAX_EXP LDBL_MAX_EXP#endif#ifdef LDBL_MAX#define F_MAX LDBL_MAX#endif#ifdef LDBL_MAX_10_EXP#define F_MAX_10_EXP LDBL_MAX_10_EXP#endif#endif /* VERIFY */#endif /* PASS3 */#ifndef I_MAX#define I_MAX int_max#endif#ifndef I_MIN#define I_MIN int_min#endif#ifndef U_MAX#define U_MAX u_max#endif#ifndef F_RADIX#define F_RADIX f_radix#endif#ifndef F_MANT_DIG#define F_MANT_DIG f_mant_dig#endif#ifndef F_DIG#define F_DIG f_dig#endif#ifndef F_ROUNDS#define F_ROUNDS f_rounds#endif#ifndef F_EPSILON#define F_EPSILON f_epsilon#endif#ifndef F_MIN_EXP#define F_MIN_EXP f_min_exp#endif#ifndef F_MIN#define F_MIN f_min#endif#ifndef F_MIN_10_EXP#define F_MIN_10_EXP f_min_10_exp#endif#ifndef F_MAX_EXP#define F_MAX_EXP f_max_exp#endif#ifndef F_MAX#define F_MAX f_max#endif#ifndef F_MAX_10_EXP#define F_MAX_10_EXP f_max_10_exp#endif#ifndef VERIFY#define Validate(prec, val, req, same) {;}#endif#ifdef IntegerProcedure IPROP() { /* the properties of short, int, and long */ Volatile Integer newi, int_max, maxeri, int_min, minneri; Volatile int ibits, ipower, two=2; /* Calculate max short/int/long ***********************************/ /* Calculate 2**n-1 until overflow - then use the previous value */ newi=1; int_max=0; if (setjmp(lab)==0) { /* Yields int_max */ for(ipower=0; newi>int_max; ipower++) { int_max=newi; newi=newi*two+1; } Vprintf("%sOverflow of a%s %s does not generate a trap%s\n", co, INT[0]=='i'?"n":"", INT, oc); } else { Vprintf("%sOverflow of a%s %s generates a trap%s\n", co, INT[0]=='i'?"n":"", INT, oc); } Unexpected(7); /* Minimum value: assume either two's or one's complement *********/ int_min= -int_max; if (setjmp(lab)==0) { /* Yields int_min */ if (int_min-1 < int_min) int_min--; } Unexpected(8); /* Now for those daft Cybers */ maxeri=0; newi=int_max; if (setjmp(lab)==0) { /* Yields maxeri */ for(ibits=ipower; newi>maxeri; ibits++) { maxeri=newi; newi=newi+newi+1; } } Unexpected(9); minneri= -maxeri; if (setjmp(lab)==0) { /* Yields minneri */ if (minneri-1 < minneri) minneri--; } Unexpected(10); Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n", co, INT, (long)int_max, ipower, oc); Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc); if (L) i_define(D_INT_MAX, INT, Iname, "_MAX", (long) int_max, 0L, (long) I_MAX, IMARK); if (L) i_define(D_INT_MIN, INT, Iname, "_MIN", (long) int_min, (long) (PASS==1?maxint:int_max), (long) I_MIN, IMARK); if(int_max < 0) { /* It has happened */ eek_a_bug("signed integral comparison faulty?"); } if (maxeri>int_max) { Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n", co, INT, (long)maxeri, ibits, "but only for addition, not multiplication", "(I smell a Cyber!)", oc); } if (minneri<int_min) { Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n", co, INT, (long)minneri, "but only for addition, not multiplication", "(I smell a Cyber!)", oc); }}Procedure UPROP () { /* The properties of unsigned short/int/long */#ifdef OK_UI Volatile unsigned Integer u_max, newi, two; newi=1; u_max=0; two=2; if (setjmp(lab)==0) { /* Yields u_max */ while(newi>u_max) { u_max=newi; newi=newi*two+1; } } Unexpected(11); Vprintf("%sMaximum unsigned %s = %lu%s\n", co, INT, (unsigned long) u_max, oc); /* Oh woe: new standard C defines value preserving promotions */ if (L) { if (PASS == 1 && sizeof(short) < sizeof(int)) { /* Special only for short */ i_define(D_UINT_MAX, INT, Uname, "_MAX", (unsigned long) u_max, 0L, (unsigned long) U_MAX, IMARK); } else { u_define(D_UINT_MAX, INT, Uname, "_MAX", (unsigned long) u_max, (unsigned long) U_MAX, IMARK); } }#endif}#endif /* Integer */#ifdef Number/* The following routines are intended to defeat any attempt at optimisation or use of extended precision, and to defeat faulty narrowing casts. The weird prototypes are because of widening incompatibilities.*/#ifdef STDC#define ARGS1(atype, a) (atype a)#define ARGS2(atype, a, btype, b) (atype a, btype b)#else#define ARGS1(atype, a) (a) atype a;#define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;#endifProcedure Store ARGS2(Number, a, Number *, b) { *b=a; }Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }Procedure F_check ARGS((int precision, Long_double val1));Procedure F_check(precision, val1) int precision; Long_double val1; { /* You don't think I'm going to go to all the trouble of writing a program that works out what all sorts of values are, only to have printf go and print the wrong values out, do you? No, you're right, so this function tries to see if printf has written the right value, by reading it back again. This introduces a new problem of course: suppose printf writes the correct value, and scanf reads it back wrong... oh well. But I'm adamant about this: the precision given is enough to uniquely identify the printed number, therefore I insist that sscanf read the number back identically. Harsh yes, but sometimes you've got to be cruel to be kind. */ Number val, new, diff; double rem; int e; char *rep; char *f2;#ifdef NO_LONG_DOUBLE_IO double new1; /* On the Sun 3, sscanf clobbers 4 words, which leads to a crash when this function tries to return. */ f2= "%le"; /* Input */ /* It is no use checking long doubles if we can't read and write them. */ if (sizeof (Number) > sizeof(double)) return;#else Long_double new1; if (sizeof(double) == sizeof(Long_double)) { /* Assume they're the same, and use non-stdc format */ /* This is for stdc compilers using non-stdc libraries */ f2= "%le"; /* Input */ } else { /* It had better support Le then */ f2= "%Le"; }#endif val= val1; rep= f_rep(precision, (Long_double) val); if (setjmp(lab)==0) { sscanf(rep, f2, &new1); } else { eek_a_bug("sscanf caused a trap"); printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc); Unexpected(12); return; } if (setjmp(lab)==0) { /* See if new is usable */ new= new1; if (new != 0.0) { diff= val/new - 1.0; if (diff < 0.1) diff= 1.0; /* That should be enough to generate a trap */ } } else { eek_a_bug("sscanf returned an unusable number"); printf("%s scanning: %s with format: %s%s\n\n", co, rep, f2, oc); Unexpected(13); return; } Unexpected(14); if (new != val) { eek_a_bug("Possibly bad output from printf above"); if (!exponent((Long_double)val, &rem, &e)) { printf("%s but value was an unusable number%s\n\n", co, oc); return; } printf("%s expected value around %.*fe%d, bit pattern:\n ", co, precision, rem, e); bitpattern((char *) &val, (unsigned)sizeof(val)); printf ("%s\n", oc); printf("%s sscanf gave %s, bit pattern:\n ", co, f_rep(precision, (Long_double) new)); bitpattern((char *) &new, (unsigned)sizeof(new)); printf ("%s\n", oc); if (setjmp(lab) == 0) { diff= val-new; printf("%s difference= %s%s\n\n", co, f_rep(precision, (Long_double) diff), oc); } /* else forget it */ Unexpected(15); }}#ifdef VERIFYProcedure Validate(prec, val, req, same) int prec, same; Long_double val, req; { /* Check that the compiler has read a #define value correctly */ Unexpected(16); if (!same) { printf("%s*** Verify failed for above #define!\n", co); if (setjmp(lab) == 0) { /* for the case that req == nan */ printf(" Compiler has %s for value%s\n", f_rep(prec, req), oc); } else { printf(" Compiler has %s for value%s\n", "an unusable number", oc); } if (setjmp(lab) == 0) { F_check(prec, (Long_double) req); } /*else forget it*/ if (setjmp(lab) == 0) { if (req > 0.0 && val > 0.0) { printf("%s difference= %s%s\n", co, f_rep(prec, val-req), oc); } } /*else forget it*/ Unexpected(17); printf("\n"); bugs++; } else if (val != req) { if (stdc) eek_a_bug("constant has the wrong precision"); else eek_a_bug("the cast didn't work"); printf("\n"); }}#endif /* VERIFY */int FPROP(bits_per_byte) int bits_per_byte; { /* Properties of floating types, using algorithms by Cody and Waite from MA Malcolm, as modified by WM Gentleman and SB Marovich. Further extended by S Pemberton. Returns the number of digits in the fraction. */ Volatile int i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig, iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps, mantbits, digs, f_dig, trap, hidden, normal, f_min_10_exp, f_max_10_exp; Volatile Number a, b, base, basein, basem1, f_epsilon, epsneg, eps, epsp1, etop, ebot, f_max, newxmax, f_min, xminner, y, y1, z, z1, z2; Unexpected(18); Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc); /* Base and size of significand **************************************/ /* First repeatedly double until adding 1 has no effect. */ /* For instance, if base is 10, with 3 significant digits */ /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */ /* since 1024 is only representable as 1020. */ a=1.0; if (setjmp(lab)==0) { /* inexact trap? */ do { a=Sum(a, a); } while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO); } else { fprintf(stderr, "*** Program got loss-of-precision trap!\n"); /* And supporting those is just TOO much trouble! */ farewell(bugs+1); } Unexpected(19); /* Now double until you find a number that can be added to the */ /* above number. For 1020 this is 8 or 16, depending whether the */ /* result is rounded or truncated. */ /* In either case the result is 1030. 1030-1020= the base, 10. */ b=1.0; do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO); f_radix=base; Vprintf("%sBase = %d%s\n", co, f_radix, oc); /* Sanity check; if base<2, I can't guarantee the rest will work */ if (f_radix < 2) { eek_a_bug("Function return or parameter passing faulty? (This is a guess.)"); printf("\n"); return(0); } if (PASS == 1) { /* only for FLT */ flt_radix= f_radix; if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX", (long) f_radix, 0L, (long) F_RADIX, ""); } else if (f_radix != flt_radix) { printf("\n%s*** WARNING: %s %s (%d) %s%s\n", co, thing, "arithmetic has a different radix", f_radix, "from float", oc); bugs++; } /* Now the number of digits precision */ f_mant_dig=0; b=1.0; do { f_mant_dig++; b=Mul(b, base); } while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO); f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0); Vprintf("%sSignificant base digits = %d %s %d %s%s\n", co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc); if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG", (long) f_mant_dig, 0L, (long) F_MANT_DIG, ""); if (F) i_define(D_DIG, thing, Fname, "_DIG", (long) f_dig, 0L, (long) F_DIG, ""); digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */ /* Rounding *******************************************************/ basem1=Diff(base, HALF); if (Diff(Sum(a, basem1), a) != ZERO) { if (f_radix == 2) basem1=0.375; else basem1=1.0; if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */ else irnd=1; /* to nearest */ } else irnd=0; /* towards 0 */ basem1=Diff(base, HALF); if (Diff(Diff(-a, basem1), -a) != ZERO) { if (f_radix == 2) basem1=0.375; else basem1=1.0; if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/ else mrnd=1; /* to nearest */ } else mrnd=0; /* towards 0 */ f_rounds= -1; /* Unknown rounding */ if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */ if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */ if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */ if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */ if (f_rounds != -1) { Vprintf("%sArithmetic rounds towards ", co); switch (f_rounds) { case 0: Vprintf("zero (i.e. it chops)"); break; case 1: Vprintf("nearest"); break; case 2: Vprintf("+infinity"); break; case 3: Vprintf("-infinity"); break; default: Vprintf("???"); break; } Vprintf("%s\n", oc); } else { /* Hmm, try to give some help her
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -