Annotation of 43BSD/contrib/B/src/bint/b1fun.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.