|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: /* $Header: B1fun.c,v 1.1 84/06/28 00:48:54 timo Exp $ */ ! 3: ! 4: /* B functions */ ! 5: #include "b.h" ! 6: #include "b1obj.h" ! 7: #include "b2sem.h" ! 8: #include "B1num.h" ! 9: ! 10: #define Maxlen(x, y) (Length(x) > Length(y) ? Length(x) : Length(y)) ! 11: #define Sumlen(x, y) (Length(x) + Length(y)) ! 12: ! 13: value sum(x, y) register value x, y; { ! 14: value r, z; ! 15: Checknum(x); Checknum(y); ! 16: if (!Exact(x) || !Exact(y)) return mk_approx(Numval(x) + Numval(y)); ! 17: z= mk_exact(Denominator(x), Denominator(y), 0); ! 18: r= mk_exact(Numerator(x)*Denominator(z)+Numerator(y)*Numerator(z), ! 19: Denominator(x)*Denominator(z), Maxlen(x, y)); ! 20: release(z); ! 21: return r; ! 22: } ! 23: ! 24: value negated(x) register value x; { ! 25: Checknum(x); ! 26: if (!Exact(x)) return mk_approx(-Numval(x)); ! 27: return mk_exact(-Numerator(x), Denominator(x), Length(x)); ! 28: } ! 29: ! 30: value diff(x, y) register value x, y; { ! 31: value r, my; ! 32: r= sum(x, my= negated(y)); ! 33: release(my); ! 34: return r; ! 35: } ! 36: ! 37: value inverse(x) value x;{ ! 38: Checknum(x); ! 39: if (Numval(x) == 0) error("in x/y, y is zero"); ! 40: if (!Exact(x)) return mk_approx(1.0/Numval(x)); ! 41: return mk_exact(Denominator(x), Numerator(x), Length(x)); ! 42: } ! 43: ! 44: value prod(x, y) register value x, y; { ! 45: value a, b, r; ! 46: Checknum(x); Checknum(y); ! 47: if (!Exact(x) || !Exact(y)) return mk_approx(Numval(x) * Numval(y)); ! 48: a= mk_exact(Numerator(x), Denominator(y), 0); ! 49: b= mk_exact(Numerator(y), Denominator(x), 0); ! 50: r= mk_exact(Numerator(a)*Numerator(b), Denominator(a)*Denominator(b), ! 51: Sumlen(x, y)); ! 52: release(a); release(b); ! 53: return r; ! 54: } ! 55: ! 56: value quot(x, y) register value x, y; { ! 57: value r, iy; ! 58: r= prod(x, iy= inverse(y)); ! 59: release(iy); ! 60: return r; ! 61: } ! 62: ! 63: #define Even(x) ((x) == Two*floor((x)/Two)) ! 64: value power(x, y) register value x, y; { ! 65: Checknum(x); Checknum(y); ! 66: if (Exact(y)) { ! 67: integer py= Numerator(y), qy= Denominator(y); ! 68: if (Integral(y) && Exact(x)) { ! 69: integer px, qx, ppx, pqx, Ppx, Pqx; ! 70: if (py == Zero) return mk_int(One); ! 71: if (py > Zero) { ! 72: px= Numerator(x); ! 73: qx= Denominator(x); ! 74: } else { ! 75: py= -py; ! 76: px= Denominator(x); ! 77: qx= Numerator(x); ! 78: } ! 79: ppx= pqx= One; ! 80: Ppx= px; Pqx= qx; ! 81: while (py >= Two) { ! 82: if (!Even(py)) { ! 83: ppx*= Ppx; pqx*= Pqx; ! 84: } ! 85: Ppx*= Ppx; Pqx*= Pqx; ! 86: py= floor(py/Two); ! 87: } ! 88: ppx*= Ppx; pqx*= Pqx; ! 89: return mk_exact(ppx, pqx, 0); ! 90: } /* END Integral(y) && Exact(x) */ ! 91: else { ! 92: double vx= Numval(x); ! 93: short sx= vx < 0 ? -1 : vx == 0 ? 0 : 1; ! 94: if (sx < 0 && Even(qy)) ! 95: error("in x**(p/q), x is negative and q is even"); ! 96: if (sx == 0 && py < Zero) ! 97: error("0**y with negative y"); ! 98: if (sx < 0 && Even(py)) sx= 1; ! 99: return mk_approx(sx * pow(fabs(vx), py/qy)); ! 100: } ! 101: } /* END Exact(y) */ ! 102: else { ! 103: double vx= Numval(x), vy= Approxval(y); ! 104: if (vy == 0) return mk_approx(1.0); ! 105: if (vx < 0) ! 106: error("in x**y, x is negative and y is not exact"); ! 107: if (vx == 0 && vy < 0) ! 108: error("0E0**y with negative y"); ! 109: return mk_approx(pow(vx, vy)); ! 110: } ! 111: } ! 112: ! 113: value root2(n, x) register value n, x; { ! 114: value r, in; ! 115: Checknum(n); ! 116: if (Numval(n) == 0) error("in x root y, x is zero"); ! 117: r= power(x, in= inverse(n)); ! 118: release(in); ! 119: return r; ! 120: } ! 121: ! 122: value absval(x) register value x; { ! 123: Checknum(x); ! 124: if (!Exact(x)) return mk_approx(fabs(Numval(x))); ! 125: return mk_exact((integer) fabs((double) Numerator(x)), Denominator(x), Length(x)); ! 126: } ! 127: ! 128: value signum(x) register value x; { ! 129: double v= numval(x); ! 130: return mk_int(v < 0 ? -One : v == 0 ? Zero : One); ! 131: } ! 132: ! 133: value floorf(x) register value x; { ! 134: return mk_int(floor(numval(x))); ! 135: } ! 136: ! 137: value ceilf(x) register value x; { ! 138: return mk_int(ceil(numval(x))); ! 139: } ! 140: ! 141: value round1(x) register value x; { ! 142: return mk_int(floor(numval(x) + .5)); ! 143: } ! 144: ! 145: value round2(n, x) register value n, x; { ! 146: value ten, tenp, xtenp, r0, r; ! 147: Checknum(n); ! 148: if (!Integral(n)) error("in n round x, n is not an integer"); ! 149: ten= mk_integer(10); ! 150: tenp= power(ten, n); ! 151: xtenp= prod(x, tenp); ! 152: r0= round1(xtenp); ! 153: r= mk_exact(Numerator(r0), Numerator(tenp), propintlet((int) Numerator(n))); ! 154: release(ten); release(tenp); release(xtenp); release(r0); ! 155: return r; ! 156: } ! 157: ! 158: value mod(a, n) register value a, n; { ! 159: value f, p, d; ! 160: Checknum(a); Checknum(n); ! 161: f= mk_int(floor(Numval(a) / Numval(n))); ! 162: p= prod(n, f); ! 163: d= diff(a, p); ! 164: release(f); release(p); ! 165: return d; ! 166: } ! 167: ! 168: double lastran; ! 169: ! 170: setran (seed) double seed; ! 171: {double x; ! 172: x= seed >= 0 ? seed : -seed; ! 173: while (x >= 1) x/= 10; ! 174: lastran= floor(67108864.0 * x); ! 175: } ! 176: ! 177: set_random(v) value v; { ! 178: setran((double) hash(v)); ! 179: } ! 180: ! 181: value random() /* 0 <= r < 1 */ ! 182: {double p; ! 183: p= 26353589.0 * lastran + 1; ! 184: lastran= p - 67108864.0 * floor (p / 67108864.0); ! 185: return mk_approx(lastran / 67108864.0); ! 186: } ! 187: ! 188: value root1(v) value v; { ! 189: value two= mk_integer(2); ! 190: v= root2(two, v); ! 191: release(two); ! 192: return(v); ! 193: } ! 194: ! 195: value pi() { return mk_approx(3.141592653589793238462); } ! 196: value e() { return mk_approx(exp(1.0)); } ! 197: ! 198: value sin1(v) value v; { return mk_approx(sin(numval(v))); } ! 199: value cos1(v) value v; { return mk_approx(cos(numval(v))); } ! 200: value tan1(v) value v; { return mk_approx(tan(numval(v))); } ! 201: value atn1(v) value v; { return mk_approx(atan(numval(v))); } ! 202: value exp1(v) value v; { return mk_approx(exp(numval(v))); } ! 203: value log1(v) value v; { return mk_approx(log(numval(v))); } ! 204: ! 205: value log2(u, v) value u, v;{ ! 206: return mk_approx(log(numval(v)) / log(numval(u))); ! 207: } ! 208: ! 209: value atn2(u, v) value u, v; { ! 210: return mk_approx(atan2(numval(v), numval(u))); ! 211: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.