|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2:
3: /*
4: $Header: b1fun.c,v 1.4 85/08/22 16:48:24 timo Exp $
5: */
6:
7: /* Functions defined on numeric values. */
8:
9: #include <errno.h> /* For EDOM and ERANGE */
10:
11: #include "b.h"
12: #include "b0con.h"
13: #include "b1obj.h"
14: #include "b1num.h"
15:
16: /*
17: * The visible routines here implement predefined B arithmetic operators,
18: * taking one or two numeric values as operands, and returning a numeric
19: * value.
20: * No type checking of operands is done: this must be done by the caller.
21: */
22:
23: typedef value (*valfun)();
24: typedef rational (*ratfun)();
25: typedef real (*appfun)();
26: typedef double (*mathfun)();
27:
28: /*
29: * For the arithmetic functions (+, -, *, /) the same action is needed:
30: * 1) if both operands are Integral, use function from int_* submodule;
31: * 2) if both are Exact, use function from rat_* submodule (after possibly
32: * converting one of them from Integral to Rational);
33: * 3) otherwise, make both approximate and use function from app_*
34: * submodule.
35: * The functions performing the appropriate action for each of the submodules
36: * are passed as parameters.
37: * Division is a slight exception, since i/j can be a rational.
38: * See `quot' below.
39: */
40:
41: Hidden value dyop(u, v, int_fun, rat_fun, app_fun)
42: value u, v;
43: valfun int_fun;
44: ratfun rat_fun;
45: appfun app_fun;
46: {
47: if (Integral(u) && Integral(v)) /* Use integral operation */
48: return (*int_fun)(u, v);
49:
50: if (Exact(u) && Exact(v)) {
51: rational u1, v1, a;
52:
53: /* Use rational operation */
54:
55: u1 = Integral(u) ? mk_rat((integer)u, int_1, 0) :
56: (rational) Copy(u);
57: v1 = Integral(v) ? mk_rat((integer)v, int_1, 0) :
58: (rational) Copy(v);
59: a = (*rat_fun)(u1, v1);
60: release((value) u1);
61: release((value) v1);
62:
63: if (Denominator(a) == int_1 && Roundsize(a) == 0) {
64: integer b = (integer) Copy(Numerator(a));
65: release((value) a);
66: return (value) b;
67: }
68:
69: return (value) a;
70: }
71:
72: /* Use approximate operation */
73:
74: {
75: real u1, v1, a;
76: u1 = Approximate(u) ? (real) Copy(u) : (real) approximate(u);
77: v1 = Approximate(v) ? (real) Copy(v) : (real) approximate(v);
78: a = (*app_fun)(u1, v1);
79: release((value) u1);
80: release((value) v1);
81:
82: return (value) a;
83: }
84: }
85:
86:
87: Hidden integer isum(u, v) integer u, v; {
88: return int_sum(u, v);
89: }
90:
91: Visible value sum(u, v) value u, v; {
92: if (IsSmallInt(u) && IsSmallInt(v))
93: return mk_integer(SmallIntVal(u) + SmallIntVal(v));
94: return dyop(u, v, (value (*)())isum, rat_sum, app_sum);
95: }
96:
97: Hidden integer idiff(u, v) integer u, v; {
98: return int_diff(u, v);
99: }
100:
101: Visible value diff(u, v) value u, v; {
102: if (IsSmallInt(u) && IsSmallInt(v))
103: return mk_integer(SmallIntVal(u) - SmallIntVal(v));
104: return dyop(u, v, (value (*)())idiff, rat_diff, app_diff);
105: }
106:
107: Visible value prod(u, v) value u, v; {
108: if (IsSmallInt(u) && IsSmallInt(v))
109: return (value)
110: mk_int((double)SmallIntVal(u) * (double)SmallIntVal(v));
111: return dyop(u, v, (value (*)())int_prod, rat_prod, app_prod);
112: }
113:
114:
115: /*
116: * We cannot use int_quot (which performs integer division with truncation).
117: * Here is the routine we need.
118: */
119:
120: Hidden value xxx_quot(u, v) integer u, v; {
121:
122: if (v == int_0) {
123: error(MESS(400, "in i/j, j is zero"));
124: return (value) Copy(u);
125: }
126:
127: return mk_exact(u, v, 0);
128: }
129:
130: Visible value quot(u, v) value u, v; {
131: return dyop(u, v, xxx_quot, rat_quot, app_quot);
132: }
133:
134:
135: /*
136: * Unary minus and abs follow the same principle but with only one operand.
137: */
138:
139: Visible value negated(u) value u; {
140: if (IsSmallInt(u)) return mk_integer(-SmallIntVal(u));
141: if (Integral(u))
142: return (value) int_neg((integer)u);
143: if (Rational(u))
144: return (value) rat_neg((rational)u);
145: return (value) app_neg((real)u);
146: }
147:
148:
149: Visible value absval(u) value u; {
150: if (Integral(u)) {
151: if (Msd((integer)u) < 0)
152: return (value) int_neg((integer)u);
153: } else if (Rational(u)) {
154: if (Msd(Numerator((rational)u)) < 0)
155: return (value) rat_neg((rational)u);
156: } else if (Approximate(u) && Frac((real)u) < 0)
157: return (value) app_neg((real)u);
158:
159: return Copy(u);
160: }
161:
162:
163: /*
164: * The remaining operators follow less similar paths and some of
165: * them contain quite subtle code.
166: */
167:
168: Visible value mod(u, v) value u, v; {
169: value p, q, m, n;
170:
171: if (v == (value)int_0 ||
172: Rational(v) && Numerator((rational)v) == int_0 ||
173: Approximate(v) && Frac((real)v) == 0) {
174: error(MESS(401, "in x mod y, y is zero"));
175: return Copy(u);
176: }
177:
178: if (Integral(u) && Integral(v))
179: return (value) int_mod((integer)u, (integer)v);
180:
181: /* Compute `u-v*floor(u/v)', as in the formal definition of `u mod v'. */
182:
183: q = quot(u, v);
184: n = floorf(q);
185: release(q);
186: p = prod(n, v);
187: release(n);
188: m = diff(u, p);
189: release(p);
190:
191: return m;
192: }
193:
194:
195: /*
196: * u**v has the most special cases of all the predefined arithmetic functions.
197: */
198:
199: Visible value power(u, v) value u, v; {
200: real ru, rv, rw;
201: if (Exact(u) && (Integral(v) ||
202: /* Next check catches for integers disguised as rationals: */
203: Rational(v) && Denominator((rational)v) == int_1)) {
204: rational a;
205: integer b = Integral(v) ? (integer)v : Numerator((rational)v);
206: /* Now b is really an integer. */
207:
208: u = Integral(u) ? (value) mk_rat((integer)u, int_1, 0) :
209: Copy(u);
210:
211: a = rat_power((rational)u, b);
212: release(u);
213: if (Denominator(a) == int_1) { /* Make integral result */
214: b = (integer) Copy(Numerator(a));
215: release((value) a);
216: return (value)b;
217: }
218: return (value)a;
219: }
220:
221: if (Exact(v)) {
222: integer vn, vd;
223: int s;
224: ru = (real) approximate(u);
225: s = (Frac(ru) > 0) - (Frac(ru) < 0);
226:
227: if (s < 0) rv = app_neg(ru), release((value)ru), ru = rv;
228: if (Integral(v)) {
229: vn = (integer)v;
230: vd = int_1;
231: } else {
232: vd = Denominator((rational)v);
233: if (s < 0 && Even(Lsd(vd)))
234: error(MESS(402, "in x**(p/q), x is negative and q is even"));
235: vn = Numerator((rational)v);
236: }
237: if (vn == int_0) {
238: release((value)ru);
239: return one;
240: }
241: if (s == 0 && Msd(vn) < 0) {
242: error(MESS(403, "in 0**y, y is negative"));
243: return (value) ru;
244: }
245: if (s < 0 && Even(Lsd(vn)))
246: s = 1;
247: rv = (real) approximate(v);
248: rw = app_power(ru, rv);
249: release((value)ru), release((value)rv);
250: if (s < 0) ru = app_neg(rw), release((value)rw), rw = ru;
251: return (value) rw;
252: }
253:
254: /* Everything else: we now know u or v is approximate */
255:
256: ru = (real) approximate(u);
257: if (Frac(ru) < 0) {
258: error(MESS(404, "in x**y, x is negative and y is not exact"));
259: return (value) ru;
260: }
261: rv = (real) approximate(v);
262: if (Frac(ru) == 0 && Frac(rv) < 0) {
263: error(MESS(405, "in 0**y, y is negative"));
264: release((value)rv);
265: return (value) ru;
266: }
267: rw = app_power(ru, rv);
268: release((value)ru), release((value)rv);
269: return (value) rw;
270: }
271:
272:
273: /*
274: * floor: for approximate numbers app_floor() is used;
275: * for integers it is a no-op; other exact numbers effectively calculate
276: * u - (u mod 1).
277: */
278:
279: Visible value floorf(u) value u; {
280: integer quo, rem, v;
281: digit div;
282:
283: if (Integral(u)) return Copy(u);
284: if (Approximate(u)) return app_floor((real)u);
285:
286: /* It is a rational number */
287:
288: div = int_ldiv(Numerator((rational)u), Denominator((rational)u),
289: &quo, &rem);
290: if (div < 0 && rem != int_0) { /* Correction for negative noninteger */
291: v = int_diff(quo, int_1);
292: release((value) quo);
293: quo = v;
294: }
295: release((value) rem);
296: return (value) quo;
297: }
298:
299:
300: /*
301: * ceiling x is defined as -floor(-x);
302: * and that's how it's implemented, except for integers.
303: */
304:
305: Visible value ceilf(u) value u; {
306: value v;
307: if (Integral(u)) return Copy(u);
308: u = negated(u);
309: v = floorf(u);
310: release(u);
311: u = negated(v);
312: release(v);
313: return u;
314: }
315:
316:
317: /*
318: * round u is defined as floor(u+0.5), which is what is done here,
319: * except for integers which are left unchanged.
320: */
321:
322: Visible value round1(u) value u; {
323: value v, w;
324:
325: if (Integral(u)) return Copy(u);
326:
327: v = sum(u, (value)rat_half);
328: w = floorf(v);
329: release(v);
330:
331: return w;
332: }
333:
334:
335: /*
336: * u round v is defined as 10**-u * round(v*10**u).
337: * A complication is that u round v is always printed with exactly u digits
338: * after the decimal point, even if this involves trailing zeros,
339: * or if v is an integer.
340: * Consequently, the result is always kept as a rational, even if it can be
341: * simplified to an integer, and the size field of the rational number
342: * (which is made negative to distinguish it from integers, and < -1 to
343: * distinguish it from approximate numbers) is used to store the number of
344: * significant digits.
345: * Thus a size of -2 means a normal rational number, and a size < -2
346: * means a rounded number to be printed with (-2 - length) digits
347: * after the decimal point. This last expression can be retrieved using
348: * the macro Roundsize(v) which should only be applied to Rational
349: * numbers.
350: */
351:
352: Visible value round2(u, v) value u, v; {
353: value w, tenp;
354: int i;
355:
356: if (!Integral(u)) {
357: error(MESS(406, "in n round x, n is not an integer"));
358: i = 0;
359: } else
360: i = propintlet(intval(u));
361:
362: tenp = tento(i);
363:
364: v = prod(v, tenp);
365: w = round1(v);
366:
367: release(v);
368: v = quot(w, tenp);
369: release(w);
370: release(tenp);
371:
372: if (i > 0) { /* Set number of digits to be printed */
373: if (propintlet(-2 - i) < -2) {
374: if (Rational(v))
375: Length(v) = -2 - i;
376: else if (Integral(v)) {
377: w = v;
378: v = mk_exact((integer) w, int_1, i);
379: release(w);
380: }
381: }
382: }
383:
384: return v;
385: }
386:
387:
388: /*
389: * sign u inspects the sign of either u, u's numerator or u's fractional part.
390: */
391:
392: Visible value signum(u) value u; {
393: int s;
394:
395: if (Exact(u)) {
396: if (Rational(u))
397: u = (value) Numerator((rational)u);
398: s = u==(value)int_0 ? 0 : Msd((integer)u) < 0 ? -1 : 1;
399: } else
400: s = Frac((real)u) > 0 ? 1 : Frac((real)u) < 0 ? -1 : 0;
401:
402: return MkSmallInt(s);
403: }
404:
405:
406: /*
407: * ~u makes an approximate number of any numerical value.
408: */
409:
410: Visible value approximate(u) value u; {
411: double x, e, expo;
412: register int i;
413: if (Approximate(u)) return Copy(u);
414: if (IsSmallInt(u))
415: x = SmallIntVal(u), expo = 0;
416: else if (Rational(u)) {
417: rational r = (rational) u;
418: integer p = Numerator(r), q;
419: double xp, xq;
420: int lp, lq;
421: if (p == int_0)
422: return Copy((value)app_0);
423: q = Denominator(r);
424: lp = IsSmallInt(p) ? 1 : Length(p);
425: lq = IsSmallInt(q) ? 1 : Length(q);
426: xp = 0, xq = 0;
427: expo = lp - lq;
428: if (IsSmallInt(p)) { xp = SmallIntVal(p); --expo; }
429: else {
430: for (i = Length(p)-1; i >= 0; --i) {
431: xp = xp*BASE + Digit(p, i);
432: --expo;
433: if (xp < -Maxreal/BASE || xp > Maxreal/BASE)
434: break;
435: }
436: }
437: if (IsSmallInt(q)) { xq = SmallIntVal(q); ++expo; }
438: else {
439: for (i = Length(q)-1; i >= 0; --i) {
440: xq = xq*BASE + Digit(q, i);
441: ++expo;
442: if (xq > Maxreal/BASE)
443: break;
444: }
445: }
446: x = xp/xq;
447: }
448: else if (Integral(u)) {
449: integer p = (integer) u;
450: if (Length(p) == 0)
451: return Copy((value)app_0);
452: x = 0;
453: expo = Length(p);
454: for (i = Length(p)-1; i >= 0; --i) {
455: x = x*BASE + Digit(p, i);
456: --expo;
457: if (x < -Maxreal/BASE || x > Maxreal/BASE)
458: break;
459: }
460: }
461: while (expo < 0 && fabs(x) > BASE/Maxreal) ++expo, x /= BASE;
462: while (expo > 0 && fabs(x) < Maxreal/BASE) --expo, x *= BASE;
463: if (expo != 0) {
464: expo = expo*twologBASE + 1;
465: e = floor(expo);
466: x *= .5 * exp((expo-e) * logtwo);
467: }
468: else
469: e = 0;
470: return (value) mk_approx(x, e);
471: }
472:
473:
474: /*
475: * numerator v returns the numerator of v, whenever v is an exact number.
476: * For integers, that is v itself.
477: */
478:
479: Visible value numerator(v) value v; {
480: if (!Exact(v)) {
481: error(MESS(407, "*/ on approximate number"));
482: return zero;
483: }
484:
485: if (Integral(v)) return Copy(v);
486:
487: return (value) Copy(Numerator((rational)v));
488: }
489:
490:
491: /*
492: * /*v returns the denominator of v, whenever v is an exact number.
493: * For integers, that is 1.
494: */
495:
496: Visible value denominator(v) value v; {
497: if (!Exact(v)) {
498: error(MESS(408, "/* on approximate number"));
499: return zero;
500: }
501:
502: if (Integral(v)) return one;
503:
504: return (value) Copy(Denominator((rational)v));
505: }
506:
507:
508: /*
509: * u root v is defined as v**(1/u), where u is usually but need not be
510: * an integer.
511: */
512:
513: Visible value root2(u, v) value u, v; {
514: if (u == (value)int_0 ||
515: Rational(u) && Numerator((rational)u) == int_0 ||
516: Approximate(u) && Frac((real)u) == 0) {
517: error(MESS(409, "in n root x, n is zero"));
518: v = Copy(v);
519: } else {
520: u = quot((value)int_1, u);
521: v = power(v, u);
522: release(u);
523: }
524:
525: return v;
526: }
527:
528: /* root x is computed more exactly than n root x, by doing
529: one iteration step extra. This ~guarantees root(n**2) = n. */
530:
531: Visible value root1(v) value v; {
532: value r = root2((value)int_2, v);
533: value v_over_r, theirsum, result;
534: if (Approximate(r) && Frac((real)r) == 0.0) return (value)r;
535: v_over_r = quot(v, r);
536: theirsum = sum(r, v_over_r), release(r), release(v_over_r);
537: result = quot(theirsum, (value)int_2), release(theirsum);
538: return result;
539: }
540:
541: /* The rest of the mathematical functions */
542:
543: Visible value pi() { return (value) mk_approx(3.141592653589793238463, 0.0); }
544: Visible value e() { return (value) mk_approx(2.718281828459045235360, 0.0); }
545:
546: Hidden value trig(v, fun, zeroflag) value v; mathfun fun; bool zeroflag; {
547: real w = (real) approximate(v);
548: double expo = Expo(w), frac = Frac(w), x, result;
549: extern int errno;
550: if (expo <= Minexpo/2) {
551: if (zeroflag) return (value) w; /* sin small x = x, etc. */
552: frac = 0, expo = 0;
553: }
554: release((value)w);
555: if (expo > Maxexpo) errno = EDOM;
556: else {
557: x = ldexp(frac, (int)expo);
558: if (x >= Maxtrig || x <= -Maxtrig) errno = EDOM;
559: else {
560: errno = 0;
561: result = (*fun)(x);
562: }
563: }
564: if (errno != 0) {
565: if (errno == ERANGE)
566: error(MESS(410, "the result is too large to be representable"));
567: else if (errno == EDOM)
568: error(MESS(411, "x is too large to compute a meaningful result"));
569: else error(MESS(412, "math library error"));
570: return Copy((value)app_0);
571: }
572: return (value) mk_approx(result, 0.0);
573: }
574:
575: Visible value sin1(v) value v; { return trig(v, sin, Yes); }
576: Visible value cos1(v) value v; { return trig(v, cos, No); }
577: Visible value tan1(v) value v; { return trig(v, tan, Yes); }
578:
579: Visible value atn1(v) value v; {
580: real w = (real) approximate(v);
581: double expo = Expo(w), frac = Frac(w);
582: if (expo <= Minexpo + 2) return (value) w; /* atan of small x = x */
583: release((value)w);
584: if (expo > Maxexpo) expo = Maxexpo;
585: return (value) mk_approx(atan(ldexp(frac, (int)expo)), 0.0);
586: }
587:
588: Visible value exp1(v) value v; {
589: real w = (real) approximate(v);
590: real x = app_exp(w);
591: release((value)w);
592: return (value) x;
593: }
594:
595: Visible value log1(v) value v; {
596: real w = (real) approximate(v);
597: real x = app_log(w);
598: release((value)w);
599: return (value) x;
600: }
601:
602: Visible value log2(u, v) value u, v;{
603: value w;
604: u = log1(u);
605: v = log1(v);
606: w = quot(v, u);
607: release(u), release(v);
608: return w;
609: }
610:
611: Visible value atn2(u, v) value u, v; {
612: real ru = (real) approximate(u), rv = (real) approximate(v);
613: double uexpo = Expo(ru), ufrac = Frac(ru);
614: double vexpo = Expo(rv), vfrac = Frac(rv);
615: release((value)ru), release((value)rv);
616: if (uexpo > Maxexpo) uexpo = Maxexpo;
617: if (vexpo > Maxexpo) vexpo = Maxexpo;
618: return (value) mk_approx(
619: atan2(
620: vexpo < Minexpo ? 0.0 : ldexp(vfrac, (int)vexpo),
621: uexpo < Minexpo ? 0.0 : ldexp(ufrac, (int)uexpo)),
622: 0.0);
623: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.