|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ ! 2: ! 3: /* ! 4: $Header: b1num.c,v 1.4 85/08/22 16:51:59 timo Exp $ ! 5: */ ! 6: ! 7: /* B numbers, basic external interface */ ! 8: ! 9: #include "b.h" ! 10: #include "b0con.h" ! 11: #include "b1obj.h" ! 12: #include "b1num.h" ! 13: ! 14: /* ! 15: * This file contains operations on numbers that are not predefined ! 16: * B functions (the latter are defined in `bfun.c'). ! 17: * This includes conversion of numeric B values to C `int's and ! 18: * `double's, (numval() and intval()), ! 19: * but also utilities for comparing numeric values and hashing a numeric ! 20: * value to something usable as initialization for the random generator ! 21: * without chance of overflow (so numval(v) is unusable). ! 22: * It is also possible to build numbers of all types using mk_integer, ! 23: * mk_exact (or mk_rat) and mk_approx. Note the rather irregular ! 24: * (historical!) argument structure for these: mk_approx has a ! 25: * `double' argument, where mk_exact and mk_rat have two values ! 26: * which must be `integer' (not `int's!) as arguments. ! 27: * The random number generator used by the DRAW and CHOOSE statements ! 28: * is also in this file. ! 29: */ ! 30: ! 31: /* ! 32: * ival is used internally by intval() and large(). ! 33: * It converts an integer to double precision, yielding ! 34: * a huge value when overflow occurs (but giving no error). ! 35: */ ! 36: ! 37: Hidden double ival(u) integer u; { ! 38: double x = 0; ! 39: register int i; ! 40: ! 41: if (IsSmallInt(u)) return SmallIntVal(u); ! 42: for (i = Length(u)-1; i >= 0; --i) { ! 43: if (x >= Maxreal/BASE) ! 44: return Msd(u) < 0 ? -Maxreal : Maxreal; ! 45: x = x*BASE + Digit(u, i); ! 46: } ! 47: ! 48: return x; ! 49: } ! 50: ! 51: ! 52: /* Determine if a value may be converted to an int */ ! 53: ! 54: Visible bool large(v) value v; { ! 55: double r; ! 56: if (!Is_number(v) || !integral(v)) { ! 57: error(MESS(1300, "number not an integer")); ! 58: return No; ! 59: } ! 60: if (Rational(v)) v= (value) Numerator((rational)v); ! 61: r= ival((integer)v); ! 62: if (r > Maxint) return Yes; ! 63: return No; ! 64: } ! 65: ! 66: /* return the C `int' value of a B numeric value, if it exists. */ ! 67: ! 68: Visible int intval(v) value v; { ! 69: /* v must be an Integral number or a Rational with Denominator==1 ! 70: which may result from n round x [via mk_exact]!. */ ! 71: double i; ! 72: if (IsSmallInt(v)) i= SmallIntVal(v); ! 73: else { ! 74: if (!Is_number(v)) syserr(MESS(1301, "intval on non-number")); ! 75: if (!integral(v)) { ! 76: error(MESS(1302, "number not an integer")); ! 77: return 0; ! 78: } ! 79: if (Rational(v)) v= (value) Numerator((rational)v); ! 80: i= ival((integer)v); ! 81: } ! 82: if (i > Maxint || i < -Maxint) { ! 83: error(MESS(1303, "exceedingly large integer")); ! 84: return 0; ! 85: } ! 86: return (int) i; ! 87: } ! 88: ! 89: ! 90: /* convert an int to an intlet */ ! 91: ! 92: Visible intlet propintlet(i) int i; { ! 93: if (i > Maxintlet || i < -Maxintlet) { ! 94: error(MESS(1304, "exceedingly large integer")); ! 95: return 0; ! 96: } ! 97: return i; ! 98: } ! 99: ! 100: ! 101: /* ! 102: * determine if a number is integer ! 103: */ ! 104: ! 105: Visible bool integral(v) value v; { ! 106: if (Integral(v) || (Rational(v) && Denominator((rational)v) == int_1)) ! 107: return Yes; ! 108: else return No; ! 109: } ! 110: ! 111: /* ! 112: * mk_exact makes an exact number out of two integers. ! 113: * The third argument is the desired number of digits after the decimal ! 114: * point when the number is printed (see comments in `bfun.c' for ! 115: * `round' and code in `bnuC.c'). ! 116: * This printing size (if positive) is hidden in the otherwise nearly ! 117: * unused * 'Size' field of the value struct ! 118: * (cf. definition of Rational(v) etc.). ! 119: */ ! 120: ! 121: Visible value mk_exact(p, q, len) integer p, q; int len; { ! 122: rational r = mk_rat(p, q, len); ! 123: ! 124: if (Denominator(r) == int_1 && len <= 0) { ! 125: integer i = (integer) Copy(Numerator(r)); ! 126: release((value) r); ! 127: return (value) i; ! 128: } ! 129: ! 130: return (value) r; ! 131: } ! 132: ! 133: #define uSMALL 1 ! 134: #define uINT 2 ! 135: #define uRAT 4 ! 136: #define uAPP 8 ! 137: #define vSMALL 16 ! 138: #define vINT 32 ! 139: #define vRAT 64 ! 140: #define vAPP 128 ! 141: ! 142: Visible relation numcomp(u, v) value u, v; { ! 143: int tu, tv; relation s; ! 144: ! 145: if (IsSmallInt(u)) tu = uSMALL; ! 146: else if (Length(u) >= 0) tu = uINT; ! 147: else if (Length(u) <= -2) tu = uRAT; ! 148: else tu = uAPP; ! 149: if (IsSmallInt(v)) tv = vSMALL; ! 150: else if (Length(v) >= 0) tv = vINT; ! 151: else if (Length(v) <= -2) tv = vRAT; ! 152: else tv = vAPP; ! 153: ! 154: switch (tu|tv) { ! 155: ! 156: case uSMALL|vSMALL: return SmallIntVal(u) - SmallIntVal(v); ! 157: ! 158: case uSMALL|vINT: ! 159: case uINT|vSMALL: ! 160: case uINT|vINT: return int_comp((integer)u, (integer)v); ! 161: ! 162: case uSMALL|vRAT: ! 163: case uINT|vRAT: ! 164: u = (value) mk_rat((integer)u, int_1, 0); ! 165: s = rat_comp((rational)u, (rational)v); ! 166: release(u); ! 167: return s; ! 168: ! 169: case uRAT|vRAT: ! 170: return rat_comp((rational)u, (rational)v); ! 171: ! 172: case uRAT|vSMALL: ! 173: case uRAT|vINT: ! 174: v = (value) mk_rat((integer)v, int_1, 0); ! 175: s = rat_comp((rational)u, (rational)v); ! 176: release(v); ! 177: return s; ! 178: ! 179: case uSMALL|vAPP: ! 180: case uINT|vAPP: ! 181: case uRAT|vAPP: ! 182: u = approximate(u); ! 183: s = app_comp((real)u, (real)v); ! 184: release(u); ! 185: return s == 0 ? -1 : s; /* u < ~u = v */ ! 186: ! 187: case uAPP|vAPP: ! 188: return app_comp((real)u, (real)v); ! 189: ! 190: case uAPP|vSMALL: ! 191: case uAPP|vINT: ! 192: case uAPP|vRAT: ! 193: v = approximate(v); ! 194: s = app_comp((real)u, (real)v); ! 195: release(v); ! 196: return s == 0 ? 1 : s; /* u = ~v > v */ ! 197: ! 198: default: syserr(MESS(1305, "num_comp")); /* NOTREACHED */ ! 199: ! 200: } ! 201: } ! 202: ! 203: ! 204: /* ! 205: * Deliver 10**n, where n is a (maybe negative!) C integer. ! 206: * The result is a value (integer or rational, actually). ! 207: */ ! 208: ! 209: Visible value tento(n) int n; { ! 210: if (n < 0) { ! 211: integer i= int_tento(-n); ! 212: value v= (value) mk_exact(int_1, i, 0); ! 213: release((value) i); ! 214: return v; ! 215: } ! 216: return (value) int_tento(n); ! 217: } ! 218: ! 219: ! 220: /* ! 221: * numval returns the numerical value of any numeric B value ! 222: * as a C `double'. ! 223: */ ! 224: ! 225: Visible double numval(u) value u; { ! 226: double expo, frac; ! 227: ! 228: if (!Is_number(u)) { ! 229: error(MESS(1306, "value not a number")); ! 230: return 0.0; ! 231: } ! 232: u = approximate(u); ! 233: expo = Expo((real)u), frac = Frac((real)u); ! 234: release(u); ! 235: if (expo > Maxexpo) { ! 236: error(MESS(1307, "approximate number too large to be handled")); ! 237: return 0.0; ! 238: } ! 239: if(expo < Minexpo) return 0.0; ! 240: return ldexp(frac, (int)expo); ! 241: } ! 242: ! 243: ! 244: /* ! 245: * Random numbers ! 246: */ ! 247: ! 248: ! 249: /* ! 250: * numhash produces a `double' number that depends on the value of ! 251: * v, useful for initializing the random generator. ! 252: * Needs rewriting, so that for instance numhash(n) never equals n. ! 253: * The magic numbers here are chosen at random. ! 254: */ ! 255: ! 256: Visible double numhash(v) value v; { ! 257: if (Integral(v)) { ! 258: double d = 0; ! 259: register int i; ! 260: ! 261: if (IsSmallInt(v)) return SmallIntVal(v); ! 262: for (i = Length(v) - 1; i >= 0; --i) { ! 263: d *= 2; ! 264: d += Digit((integer)v, i); ! 265: } ! 266: ! 267: return d; ! 268: } ! 269: ! 270: if (Rational(v)) ! 271: return .777 * numhash((value) Numerator((rational)v)) + ! 272: .123 * numhash((value) Denominator((rational)v)); ! 273: ! 274: return numval(v); /* Which fails for HUGE reals. Never mind. */ ! 275: } ! 276: ! 277: ! 278: /* Initialize the random generator */ ! 279: ! 280: double lastran; ! 281: ! 282: Hidden Procedure setran (seed) double seed; { ! 283: double x; ! 284: ! 285: x = seed >= 0 ? seed : -seed; ! 286: while (x >= 1) x /= 10; ! 287: lastran = floor(67108864.0*x); ! 288: } ! 289: ! 290: Visible Procedure set_random(v) value v; { ! 291: setran((double) hash(v)); ! 292: } ! 293: ! 294: ! 295: /* Return a random number in [0, 1). */ ! 296: ! 297: Visible value random() { ! 298: double p; ! 299: ! 300: p = 26353589.0 * lastran + 1; ! 301: lastran = p - 67108864.0*floor(p/67108864.0); ! 302: ! 303: return (value) mk_approx(lastran / 67108864.0, 0.0); ! 304: } ! 305: ! 306: Visible Procedure initnum() { ! 307: rat_init(); ! 308: setran((double) SEED); ! 309: } ! 310: ! 311: Visible Procedure endnum() { ! 312: endrat(); ! 313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.