1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2: 3: /* 4: $Header: mkconfig.c,v 1.4 85/08/26 10:41:39 timo Exp $ 5: */ 6: 7: /* Generate constants for configuration file */ 8: 9: /* If your C system is not unix but does have signal/setjmp, */ 10: /* add a #define unix */ 11: /* You may also need to add some calls to signal(). */ 12: 13: #ifdef unix 14: 15: #define SIGNAL 16: 17: #include <signal.h> 18: #include <setjmp.h> 19: 20: jmp_buf lab; 21: overflow(sig) int sig; { /* what to do on overflow/underflow */ 22: signal(sig, overflow); 23: longjmp(lab, 1); 24: } 25: 26: #else 27: /* Dummy routines instead */ 28: int lab=1; 29: int setjmp(lab) int lab; { return(0); } 30: 31: #endif 32: 33: #define fabs(x) (((x)<0.0)?(-x):(x)) 34: #define min(x,y) (((x)<(y))?(x):(y)) 35: 36: /* These routines are intended to defeat any attempt at optimisation */ 37: Dstore(a, b) double a, *b; { *b=a; } 38: double Dsum(a, b) double a, b; { double r; Dstore(a+b, &r); return (r); } 39: double Ddiff(a, b) double a, b; { double r; Dstore(a-b, &r); return (r); } 40: double Dmul(a, b) double a, b; { double r; Dstore(a*b, &r); return (r); } 41: double Ddiv(a, b) double a, b; { double r; Dstore(a/b, &r); return (r); } 42: 43: double power(x, n) int x, n; { 44: double r=1.0; 45: for (;n>0; n--) r*=x; 46: return r; 47: } 48: 49: int log(base, x) int base; double x; { 50: int r=0; 51: while (x>=base) { r++; x/=base; } 52: return r; 53: } 54: 55: main(argc, argv) int argc; char *argv[]; { 56: char c; 57: short newshort, maxshort, maxershort; 58: int newint, maxint, shortbits, bits, mantbits, 59: *p, shortpower, intpower, longpower; 60: long newlong, maxlong, count; 61: 62: int i, ibase, iexp, irnd, imant, iz, k, machep, maxexp, minexp, 63: mx, negeps, ngrd, normalised; 64: double a, b, base, basein, basem1, eps, epsneg, xmax, newxmax, 65: xmin, xminner, y, y1, z, z1, z2; 66: 67: double BIG, Maxreal; 68: int BASE, MAXNUMDIG, ipower, tenlogBASE, Maxexpo, Minexpo, Dblbits; 69: 70: #ifdef SIGNAL 71: signal(SIGFPE, overflow); 72: if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); } 73: #endif 74: 75: /****** Calculate max short *********************************************/ 76: /* Calculate 2**n-1 until overflow - then use the previous value */ 77: 78: newshort=1; maxshort=0; 79: 80: if (setjmp(lab)==0) 81: for(shortpower=0; newshort>maxshort; shortpower++) { 82: maxshort=newshort; 83: newshort=newshort*2+1; 84: } 85: 86: /* Now for those daft Cybers: */ 87: 88: maxershort=0; newshort=maxshort; 89: 90: if (setjmp(lab)==0) 91: for(shortbits=shortpower; newshort>maxershort; shortbits++) { 92: maxershort=newshort; 93: newshort=newshort+newshort+1; 94: } 95: 96: bits= (shortbits+1)/sizeof(short); 97: c= (char)(-1); 98: printf("/\* char=%d bits, %ssigned *\/\n", sizeof(c)*bits, 99: ((int)c)<0?"":"un"); 100: printf("/\* maxshort=%d (=2**%d-1) *\/\n", maxshort, shortpower); 101: 102: if (maxershort>maxshort) { 103: printf("/\* There is a larger maxshort, %d (=2**%d-1), %s *\/\n", 104: maxershort, shortbits, 105: "but only for addition, not multiplication"); 106: } 107: 108: /****** Calculate max int by the same method ***************************/ 109: 110: newint=1; maxint=0; 111: 112: if (setjmp(lab)==0) 113: for(intpower=0; newint>maxint; intpower++) { 114: maxint=newint; 115: newint=newint*2+1; 116: } 117: 118: printf("/\* maxint=%d (=2**%d-1) *\/\n", maxint, intpower); 119: 120: /****** Calculate max long by the same method ***************************/ 121: 122: newlong=1; maxlong=0; 123: 124: if (setjmp(lab)==0) 125: for(longpower=0; newlong>maxlong; longpower++) { 126: maxlong=newlong; 127: newlong=newlong*2+1; 128: } 129: 130: if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); } 131: 132: printf("/\* maxlong=%ld (=2**%d-1) *\/\n", maxlong, longpower); 133: 134: /****** Pointers ********************************************************/ 135: printf("/\* pointers=%d bits%s *\/\n", sizeof(p)*bits, 136: sizeof(p)>sizeof(int)?" BEWARE! larger than int!":""); 137: 138: /****** Base and size of mantissa ***************************************/ 139: a=1.0; 140: do { a=Dsum(a, a); } while (Ddiff(Ddiff(Dsum(a, 1.0), a), 1.0) == 0.0); 141: b=1.0; 142: do { b=Dsum(b, b); } while ((base=Ddiff(Dsum(a, b), a)) == 0.0); 143: ibase=base; 144: printf("/\* base=%d *\/\n", ibase); 145: 146: imant=0; b=1.0; 147: do { imant++; b=Dmul(b, base); } 148: while (Ddiff(Ddiff(Dsum(b,1.0),b),1.0) == 0.0); 149: printf("/\* Significant base digits=%d *\/\n", imant); 150: 151: /****** Various flavours of epsilon *************************************/ 152: basem1=Ddiff(base,1.0); 153: if (Ddiff(Dsum(a, basem1), a) != 0.0) irnd=1; 154: else irnd=0; 155: 156: negeps=imant+imant; 157: basein=1.0/base; 158: a=1.0; 159: for(i=1; i<=negeps; i++) a*=basein; 160: 161: b=a; 162: while (Ddiff(Ddiff(1.0, a), 1.0) == 0.0) { 163: a*=base; 164: negeps--; 165: } 166: negeps= -negeps; 167: printf("/\* Smallest x such that 1.0-base**x != 1.0=%d *\/\n", negeps); 168: 169: epsneg=a; 170: if ((ibase!=2) && (irnd==1)) { 171: /* a=(a*(1.0+a))/(1.0+1.0); => */ 172: a=Ddiv(Dmul(a, Dsum(1.0, a)), Dsum(1.0, 1.0)); 173: /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */ 174: if (Ddiff(Ddiff(1.0, a), 1.0) != 0.0) epsneg=a; 175: } 176: printf("/\* Small x such that 1.0-x != 1.0=%g *\/\n", epsneg); 177: /* it may not be the smallest */ 178: 179: machep= -imant-imant; 180: a=b; 181: while (Ddiff(Dsum(1.0, a), 1.0) == 0.0) { a*=base; machep++; } 182: printf("/\* Smallest x such that 1.0+base**x != 1.0=%d *\/\n", machep); 183: 184: eps=a; 185: if ((ibase!=2) && (irnd==1)) { 186: /* a=(a*(1.0+a))/(1.0+1.0); => */ 187: a=Ddiv(Dmul(a, Dsum(1.0, a)), Dsum(1.0, 1.0)); 188: /* if ((1.0+a)-1.0 != 0.0) eps=a; => */ 189: if (Ddiff(Dsum(1.0, a), 1.0) != 0.0) eps=a; 190: } 191: printf("/\* Smallest x such that 1.0+x != 1.0=%g *\/\n", eps); 192: 193: /****** Round or chop ***************************************************/ 194: ngrd=0; 195: if (irnd == 1) { printf("/\* Arithmetic rounds *\/\n"); } 196: else { 197: printf("/\* Arithmetic chops"); 198: if (Ddiff(Dmul(Dsum(1.0,eps),1.0),1.0) != 0.0) { 199: ngrd=1; 200: printf(" but uses guard digits"); 201: } 202: printf(" *\/\n"); 203: } 204: 205: /****** Size of and minimum normalised exponent ****************************/ 206: y=0; i=0; k=1; z=basein; z1=(1.0+eps)/base; 207: 208: /* Coarse search for the largest power of two */ 209: if (setjmp(lab)==0) /* in case of underflow trap */ 210: do { 211: y=z; y1=z1; 212: z=Dmul(y,y); z1=Dmul(z1, y); 213: a=Dmul(z,1.0); 214: z2=Ddiv(z1,y); 215: if (z2 != y1) break; 216: if ((Dsum(a,a) == 0.0) || (fabs(z) >= y)) break; 217: i++; 218: k+=k; 219: } while(1); 220: 221: if (ibase != 10) { 222: iexp=i+1; /* for the sign */ 223: mx=k+k; 224: } else { 225: iexp=2; 226: iz=ibase; 227: while (k >= iz) { iz*=ibase; iexp++; } 228: mx=iz+iz-1; 229: } 230: 231: /* Fine tune starting with y and y1 */ 232: if (setjmp(lab)==0) /* in case of underflow trap */ 233: do { 234: xmin=y; z1=y1; 235: y=Ddiv(y,base); y1=Ddiv(y1,base); 236: a=Dmul(y,1.0); 237: z2=Dmul(y1,base); 238: if (z2 != z1) break; 239: if ((Dsum(a,a) == 0.0) || (fabs(y) >= xmin)) break; 240: k++; 241: } while (1); 242: 243: if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); } 244: 245: minexp= (-k)+1; 246: 247: if ((mx <= k+k-3) && (ibase != 10)) { mx+=mx; iexp+=1; } 248: printf("/\* Number of bits used for exponent=%d *\/\n", iexp); 249: printf("/\* Minimum normalised exponent=%d *\/\n", minexp); 250: printf("/\* Minimum normalised positive number=%g *\/\n", xmin); 251: 252: /****** Minimum exponent ***************************************************/ 253: if (setjmp(lab)==0) /* in case of underflow trap */ 254: do { 255: xminner=y; 256: y=Ddiv(y,base); 257: a=Dmul(y,1.0); 258: if ((Dsum(a,a) == 0.0) || (fabs(y) >= xminner)) break; 259: } while (1); 260: 261: if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); } 262: 263: normalised=1; 264: if (xminner != 0.0 && xminner != xmin) { 265: normalised=0; 266: printf("/\* The smallest numbers are not kept normalised *\/\n"); 267: printf("/\* Smallest unnormalised positive number=%g *\/\n", 268: xminner); 269: } 270: 271: /****** Maximum exponent ***************************************************/ 272: maxexp=2; xmax=1.0; newxmax=base+1.0; 273: if (setjmp(lab) == 0) { 274: while (xmax<newxmax) { 275: xmax=newxmax; 276: newxmax=Dmul(newxmax, base); 277: if (Ddiv(newxmax, base) != xmax) break; /* ieee infinity */ 278: maxexp++; 279: } 280: } 281: if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); } 282: 283: printf("/\* Maximum exponent=%d *\/\n", maxexp); 284: 285: /****** Largest and smallest numbers ************************************/ 286: xmax=Ddiff(1.0, epsneg); 287: if (Dmul(xmax,1.0) != xmax) xmax=Ddiff(1.0, Dmul(base,epsneg)); 288: for (i=1; i<=maxexp; i++) xmax=Dmul(xmax, base); 289: printf("/\* Maximum number=%g *\/\n", xmax); 290: 291: /****** Hidden bit + sanity check ***************************************/ 292: if (ibase != 10) { 293: mantbits=log(2, (double)ibase)*imant; 294: if (mantbits+iexp+1 == sizeof(double)*bits+1) { 295: printf("/\* Double arithmetic uses a hidden bit *\/\n"); 296: } else if (mantbits+iexp+1 == sizeof(double)*bits) { 297: printf("/\* Double arithmetic doesn't use a hidden bit *\/\n"); 298: } else { 299: printf("/\* Something fishy here! %s %s *\/\n", 300: "Exponent size + mantissa size doesn't match", 301: "with the size of a double."); 302: } 303: } 304: 305: /****** The point of it all: ********************************************/ 306: printf("\n/\* Numeric package constants *\/\n"); 307: 308: BIG= power(ibase, imant)-1.0; 309: MAXNUMDIG= log(10, BIG); 310: ipower= log(10, (double)(maxint/2)); 311: Maxreal= xmax; 312: Maxexpo= log(2, (double)ibase)*maxexp; 313: Minexpo= log(2, (double)ibase)*minexp; 314: Dblbits= log(2, (double)ibase)*imant; 315: tenlogBASE= min(MAXNUMDIG/2, ipower); 316: BASE=1; for(i=1; i<=tenlogBASE; i++) BASE*=10; 317: 318: printf("#define BIG %1.1f /\* Maximum integral double *\/\n", BIG); 319: printf("#define LONG "); 320: for(i=1; i<=MAXNUMDIG; i++) printf("9"); 321: printf(".5 /\* Maximum power of ten less than BIG *\/\n"); 322: printf("#define MAXNUMDIG %d /\* The number of 9's in LONG *\/\n", 323: MAXNUMDIG); 324: printf("#define MINNUMDIG 6 /\* Don't change: this is here for consistency *\/\n"); 325: 326: printf("#define BASE %d /\* %s *\/\n", 327: BASE, "BASE**2<=BIG && BASE*2<=Maxint && -2*BASE>=Minint"); 328: if (((double)BASE)*BASE > BIG || ((double)BASE)+BASE > maxint) { 329: printf("*** BASE value wrong\n"); 330: exit(1); 331: } 332: printf("#define tenlogBASE %d /\* = log10(BASE) *\/\n", tenlogBASE); 333: printf("#define Maxreal %e /\* Maximum double *\/\n", Maxreal); 334: printf("#define Maxexpo %d /\* Maximum value such that 2**Maxexpo<=Maxreal *\/\n", 335: Maxexpo); 336: printf("#define Minexpo (%d) /\* Minimum value such that -2**Minexpo>=Minreal *\/\n", 337: Minexpo); 338: printf("#define Dblbits %d /\* Maximum value such that 2**Dblbits<=BIG *\/\n", 339: Dblbits); 340: 341: printf("#define Maxintlet %d /\* Maximum short *\/\n", maxshort); 342: printf("#define Maxint %d /\* Maximum int *\/\n", maxint); 343: 344: printf("#define Maxsmallint %d /\* BASE-1 *\/\n", BASE-1); 345: printf("#define Minsmallint (%d) /\* -BASE *\/\n", -BASE); 346: 347: /* An extra goody: the approximate amount of data-space */ 348: /* Put here because it is likely to be slower then the rest */ 349: 350: /*Allocate blocks of 1000 until no more available*/ 351: /*Don't be tempted to change this to 1024: */ 352: /*we don't know how much header information there is*/ 353: 354: for(count=0; (p=(int *)malloc(1000))!=0; count++) { } 355: 356: printf("\n/\* Memory~= %d000 *\/\n", count); 357: 358: exit(0); 359: }