Annotation of 43BSD/contrib/B/src/bint/b1nuG.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
                      2: 
                      3: /*
                      4:   $Header: b1nuG.c,v 1.4 85/08/22 16:50:59 timo Exp $
                      5: */
                      6: 
                      7: #include "b.h"
                      8: #include "b0con.h"
                      9: #include "b1obj.h"
                     10: #include "b1num.h"
                     11: 
                     12: 
                     13: /*
                     14:  * Routines for greatest common divisor calculation
                     15:  * Cf. Knuth II Sec. 4.5.2. Algorithm B
                     16:  * "Binary gcd algorithm"
                     17:  * The labels correspond with those in the book
                     18:  *
                     19:  * Assumptions about built-in arithmetic:
                     20:  * x>>1 == x/2  (if x >= 0)
                     21:  * 1<<k == 2**k (if it fits in a word)
                     22:  */
                     23: 
                     24: /* Single-precision gcd for integers > 0 */
                     25: 
                     26: Hidden digit dig_gcd(u, v) register digit u, v; {
                     27:        register digit t;
                     28:        register int k = 0;
                     29: 
                     30:        if (u <= 0 || v <= 0) syserr(MESS(900, "dig_gcd of number(s) <= 0"));
                     31: 
                     32:  /*B1*/        while (Even(u) && Even(v)) ++k, u >>= 1, v >>= 1;
                     33: 
                     34:  /*B2*/        if (Even(u)) t = u;
                     35:        else {  t = -v;
                     36:                goto B4;
                     37:        }
                     38: 
                     39:        do {
                     40:  /*B3*/                do {
                     41:                        t /= 2;
                     42:  B4:                   ;
                     43:                } while (Even(t));
                     44: 
                     45:  /*B5*/                if (t > 0) u = t;
                     46:                else v = -t;
                     47: 
                     48:  /*B6*/                t = u-v;
                     49:        } while (t);
                     50: 
                     51:        return u * (1<<k);
                     52: }
                     53: 
                     54: 
                     55: Visible integer int_half(v) integer v; {
                     56:        register int i;
                     57:        register long carry;
                     58: 
                     59:        if (IsSmallInt(v))      return (integer) MkSmallInt(SmallIntVal(v) / 2);
                     60: 
                     61:        if (Msd(v) < 0) {
                     62:                i = Length(v)-2;
                     63:                if (i < 0) {
                     64:                        release((value) v);
                     65:                        return int_0;
                     66:                }
                     67:                carry = BASE;
                     68:        }
                     69:        else {
                     70:                carry = 0;
                     71:                i = Length(v)-1;
                     72:        }
                     73: 
                     74:        if (Refcnt(v) > 1) uniql((value *) &v);
                     75: 
                     76:        for (; i >= 0; --i) {
                     77:                carry += Digit(v,i);
                     78:                Digit(v,i) = carry/2;
                     79:                carry = carry&1 ? BASE : 0;
                     80:        }
                     81: 
                     82:        return int_canon(v);
                     83: }
                     84: 
                     85: 
                     86: Hidden integer twice(v) integer v; {
                     87:        digit carry = 0;
                     88:        int i;
                     89: 
                     90:        if (IsSmallInt(v)) return mk_int(2.0 * SmallIntVal(v));
                     91: 
                     92:        if (Refcnt(v) > 1) uniql((value *) &v);
                     93: 
                     94:        for (i = 0; i < Length(v); ++i) {
                     95:                carry += Digit(v,i) * 2;
                     96:                if (carry >= BASE)
                     97:                        Digit(v,i) = carry-BASE, carry = 1;
                     98:                else
                     99:                        Digit(v,i) = carry, carry = 0;
                    100:        }
                    101: 
                    102:        if (carry) {    /* Enlarge the number */
                    103:                v = (integer) regrab_num((value) v, Length(v)+1);
                    104:                Digit(v, Length(v)-1) = carry;
                    105:        }
                    106: 
                    107:        return v;
                    108: }
                    109: 
                    110: 
                    111: Hidden bool even(u) integer u; {
                    112:        if (IsSmallInt(u))
                    113:                return Even(SmallIntVal(u));
                    114:        return Even(Lsd(u));
                    115: }
                    116: 
                    117: 
                    118: /* Multi-precision gcd of integers > 0 */
                    119: 
                    120: Visible integer int_gcd(u1, v1) integer u1, v1; {
                    121:        struct integer uu1, vv1;
                    122: 
                    123:        if (Msd(u1) <= 0 || Msd(v1) <= 0)
                    124:                syserr(MESS(901, "gcd of number(s) <= 0"));
                    125: 
                    126:        if (u1==int_1 || v1==int_1) return int_1;
                    127:                /* Speed-up for e.g. 1E-100000 */
                    128: 
                    129:        if (IsSmallInt(u1) && IsSmallInt(v1))
                    130:                return (integer)
                    131:                        MkSmallInt(dig_gcd(SmallIntVal(u1), SmallIntVal(v1)));
                    132: 
                    133:        FreezeSmallInt(u1, uu1);
                    134:        FreezeSmallInt(v1, vv1);
                    135: 
                    136:        /* Multi-precision binary gcd algorithm */
                    137: 
                    138:        {       long k = 0;
                    139:                integer t, u, v;
                    140: 
                    141:                u = (integer) Copy((value) u1);
                    142:                v = (integer) Copy((value) v1);
                    143: 
                    144:  /*B1*/                while (even(u) && even(v)) {
                    145:                        u = int_half(u);
                    146:                        v = int_half(v);
                    147:                        if (++k < 0) {
                    148:                                /*It's a number we can't cope with,
                    149:                                  with too many common factors 2.
                    150:                                  Though the user can't help it,
                    151:                                  the least we can do is to allow
                    152:                                  continuation of the session.
                    153:                                */
                    154:                                error(MESS(902, "exceptionally large rational number"));
                    155:                                k = 0;
                    156:                        }
                    157:                }
                    158: 
                    159:  /*B2*/                if (even(u)) t = (integer) Copy(u);
                    160:                else {
                    161:                        t = int_neg(v);
                    162:                        goto B4;
                    163:                }
                    164: 
                    165:                do {
                    166:  /*B3*/                        do {
                    167:                                t = int_half(t);
                    168:  B4:                           ;
                    169:                        } while (even(t));
                    170: 
                    171:  /*B5*/                        if (Msd(t) >= 0) {
                    172:                                release((value) u);
                    173:                                u = t;
                    174:                        }
                    175:                        else {
                    176:                                release((value) v);
                    177:                                v = int_neg(t);
                    178:                                release((value) t);
                    179:                        }
                    180: 
                    181:  /*B6*/                        t = int_diff(u, v);
                    182:                        /* t cannot be int_1 since both u and v are odd! */
                    183:                } while (t != int_0);
                    184: 
                    185:                release((value) t);
                    186:                release((value) v);
                    187: 
                    188:                while (--k >= 0) u = twice(u);
                    189:                
                    190:                return u;
                    191:        }
                    192: }

unix.superglobalmegacorp.com

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