Annotation of researchv10no/cmd/cfront/libC/bignum/bignum.c, revision 1.1

1.1     ! root        1: 
        !             2: // 
        !             3: // C++ multiple precision integer arithmetic library.
        !             4: //
        !             5: // Integers are encoded as INT_REPs. An INT_REP contains a 
        !             6: // reference count, to be used by the user data structure
        !             7: // INT. The beg pointer points to the beginning of the
        !             8: // heap allocated array of longs; last points to beg plus
        !             9: // the length of the array. Integers are represented in
        !            10: // base 2^16, with the least significant digit written at
        !            11: // beg, the next at beg+1, etc. The wt pointer points
        !            12: // to the long after the most significant digit. Negatives
        !            13: // are stored in twos complement notation, with the most
        !            14: // significant digit a long -1. 
        !            15: // Examples:
        !            16: //  12345678901(10) <=> 2dfdc1c35 <=> beg-> 1c35,dfdc,2
        !            17: //   3950617284     <=> eb79a2c4  <=> beg-> a2c4,eb79
        !            18: //  -3950617284     <=>           <=> beg-> 5d3c,1486,-1
        !            19: // The representations are always normalized to the shortest
        !            20: // equivalent representation. Thus, zero has length 0;
        !            21: // beg-> 5d3c,0,0 becomes beg->5d3c, and beg-> ffff,-1 becomes
        !            22: // beg-> -1.
        !            23: //
        !            24: // 2^16 was chosen as the base since it is the largest base
        !            25: // in which single precision operations can be carried out
        !            26: // using machine longs (assuming longs have >= 32 bits).
        !            27: // (This is not entirely true, as an operation in division
        !            28: // potentially produces a value of more than 32 bits; a trick
        !            29: // is used to avoid this problem.) Most of the algorithms
        !            30: // are inherently independent of BASE, as long as BASE^2
        !            31: // fits in a long. However, there are some short cuts used
        !            32: // that make use of the fact that the digits contain 16 bits
        !            33: // and that a long corresponds to 2 digits.
        !            34: //
        !            35: 
        !            36: #include "bignum.h"
        !            37: #include <ctype.h>
        !            38: 
        !            39: extern "C" {
        !            40:        extern int strlen(const char*);
        !            41:        extern char *realloc (char *, int);
        !            42:        extern void exit(int);
        !            43: }
        !            44: 
        !            45: #define NUMHDS 64               /* No. of INT_REPs allocated in a block. */
        !            46: #define BASE   65536            /* Base BASE arithmetic : 2^16 */
        !            47: #define BlockLen 9                             /* Maximum no. of decimal digits fitting in a long. */
        !            48: 
        !            49: inline int Min(int a,int b)            { return(a < b ? a : b); }
        !            50: inline int Max(int a,int b)            { return(a > b ? a : b); }
        !            51: 
        !            52: #define equalsOne(r)   ((r->wt == r->beg+1) && (*(r->beg) == 1))
        !            53: #define MakeZero(t)            t->beg=new long[0];t->wt=t->last=t->beg
        !            54: 
        !            55: enum Mode {
        !            56:        decimal, hexadecimal, octal
        !            57: };
        !            58: 
        !            59: static INT_REP *hfree;                                 // Pointer to free list of headers.
        !            60: static INT_REP OneRep("1");             // Representation of 1.
        !            61: static INT_REP TwoRep("2");             // Representation of 2.
        !            62: static INT_REP *Remainder;                             // Remainder from division, if requested.
        !            63: static INT_REP BigTen(1000000000L);            // Largest power of 10 fitting in long.
        !            64: INT_REP ZeroRep(0, 0);                                 // Representation of 0.
        !            65: static INT Zero;                                               // Guarantees refcnt of ZeroRep always > 0.
        !            66:                                                                          
        !            67: 
        !            68: /* IROutBuf:
        !            69:  * Construct for handling reverse strings of
        !            70:  * indefinite length.
        !            71:  */
        !            72: 
        !            73: #define IRBufSize 256
        !            74: 
        !            75: struct IROutBuf {
        !            76:        char *beg;
        !            77:        char *last;
        !            78:        char *wt;
        !            79: 
        !            80:        IROutBuf()                      { beg = new char[IRBufSize]; wt = beg; last = beg + IRBufSize; }
        !            81:        ~IROutBuf()                     { delete beg; }
        !            82: 
        !            83:        int Length ()           { return ((int)(wt - beg)); }
        !            84: 
        !            85:        void Flush (register iostream &i) 
        !            86:        {
        !            87:                register char *p = wt;
        !            88: 
        !            89:                while (p > beg) {
        !            90:                        i.put(*(--p));
        !            91:                }
        !            92:                wt = beg;
        !            93:        }
        !            94: 
        !            95:        void Flush (register OutFn outf)
        !            96:        {
        !            97:                register char *p = wt;
        !            98: 
        !            99:                while (p > beg) {
        !           100:                        (*outf)(*(--p));
        !           101:                }
        !           102:                (*outf)('\0');
        !           103:                wt = beg;
        !           104:        }
        !           105: 
        !           106:        void Flush (register char *buf, int len) 
        !           107:        {
        !           108:                register char *p = wt;
        !           109:                register char *endp = wt - len;
        !           110: 
        !           111:                while (p > endp) {
        !           112:                        *buf++ = *(--p);
        !           113:                }
        !           114:                *buf = '\0';
        !           115:                wt = beg;
        !           116:        }
        !           117: 
        !           118:        void Put (char c)
        !           119:        {
        !           120:                int newsize, oldsize;
        !           121: 
        !           122:                if (wt == last) {               // Need more storage.
        !           123:                        oldsize = (int)(last - beg);
        !           124:                        newsize = oldsize + IRBufSize;
        !           125:                        beg = realloc (beg, newsize);
        !           126:                        last = beg + newsize;
        !           127:                        wt = beg + oldsize;
        !           128:                }
        !           129:                *wt++ = c;
        !           130:        }
        !           131: 
        !           132: };
        !           133: static IROutBuf obuf;
        !           134: 
        !           135: /* Fatal:
        !           136:  * Fatal error; print message and exit.
        !           137:  */
        !           138: static void
        !           139: Fatal (char *msg)
        !           140: {
        !           141: 
        !           142:        fprintf (stderr, "bignum - %s\n", msg);
        !           143:        exit (1);
        !           144: }
        !           145: 
        !           146: /* MakeLong:
        !           147:  * Convert decimal string to unsigned long.
        !           148:  * We assume that the decimal will fit.
        !           149:  */   
        !           150: unsigned long MakeLong (char *sp, char *ep)
        !           151: {
        !           152:        unsigned long ret = 0;
        !           153:        int c;
        !           154: 
        !           155:        while (sp < ep) {
        !           156:                c = *sp++;
        !           157:                if(!isdigit(c))
        !           158:                        Fatal ("MakeLong - illegal decimal digit.");
        !           159: 
        !           160:                ret = 10*ret + (c - '0');
        !           161:        }
        !           162:        return(ret);    
        !           163:        
        !           164: }
        !           165: 
        !           166: /* HighBit:
        !           167:  * Given positive long v < 2^16,
        !           168:  * return number of bits val must be left
        !           169:  * shifted to be >= 2^15.
        !           170:  */
        !           171: int HighBit (register long v)
        !           172: {
        !           173:        register int ret = 0;
        !           174: 
        !           175:        while ((v & 0x8000) == 0) {
        !           176:                v <<= 1;
        !           177:                ret++;
        !           178:        }
        !           179: 
        !           180:        return (ret);
        !           181: }
        !           182: 
        !           183: /* Shift:
        !           184:  * Given an array of longs, all < 2^16, left shift them shift
        !           185:  * bits, putting numfill of the resultant words in the storage
        !           186:  * supplied by fill, using 16 bits per long.
        !           187:  */
        !           188: void Shift (long *sp, long *ep, int shift, long *fill, int numfill)
        !           189: {
        !           190:        long val;
        !           191: 
        !           192:        // Easy case; no shifting, just copy.
        !           193:        if (shift == 0) {
        !           194:                while (numfill--)
        !           195:                        *fill++ = (sp >= ep ? *sp-- : 0);
        !           196:                return;
        !           197:        }
        !           198: 
        !           199:        *fill = ((*sp--) << shift) & 0xFFFF;
        !           200:        while (numfill--) {
        !           201:                val = (sp >= ep ? *sp-- : 0);
        !           202:                *fill++ |= (val >> (16 - shift)) & 0xFFFF;
        !           203:                if (numfill == 0)
        !           204:                        break;
        !           205:                *fill = (val << shift) & 0xFFFF;
        !           206:        }
        !           207: 
        !           208: }
        !           209: 
        !           210: /* IRMorehd:
        !           211:  * Allocate more headers.
        !           212:  */
        !           213: void INT_REP::IRMorehd ()
        !           214: {
        !           215:        register INT_REP *h, *kk;
        !           216: 
        !           217:        hfree = h = (INT_REP *)new char [sizeof(INT_REP) * NUMHDS];
        !           218:        if(hfree == 0)
        !           219:                Fatal ("IRMorehd : no more memory");
        !           220: 
        !           221:        // Link the headers together using the wt pointer.
        !           222:        kk = h;
        !           223:        while (h < hfree + NUMHDS) {
        !           224:                h->wt = ((long *)++kk);
        !           225:                h++;
        !           226:        }
        !           227:        h--;
        !           228:        h->wt = ((long *)0);
        !           229: }
        !           230:    
        !           231: /* IRAllocRep:
        !           232:  * Return next available header;
        !           233:  * allocate more if necessary.
        !           234:  */
        !           235: static inline INT_REP *IRAllocRep () {
        !           236:        register INT_REP *next;
        !           237: 
        !           238:        if (hfree == 0) {
        !           239:                INT_REP::IRMorehd ();
        !           240:        }
        !           241:        next = hfree;
        !           242:        hfree = (INT_REP *)(next->wt);
        !           243:        return (next);
        !           244: }
        !           245: 
        !           246: /* StripZero:
        !           247:  * Strip trailing zeros and reset wt pointer.
        !           248:  */
        !           249: void INT_REP::StripZero()
        !           250: {
        !           251:        register long *pp;
        !           252:          
        !           253:        if(wt == beg)
        !           254:                return;
        !           255:        pp = wt - 1;
        !           256:        while ((*pp == 0) && (pp > beg))
        !           257:                pp--;
        !           258:        if (*pp != 0)
        !           259:                pp++;
        !           260:        wt = pp;
        !           261: }
        !           262: 
        !           263: /* StripMinus:
        !           264:  * If this is negative,
        !           265:  * strip trailing -1's and reset wt pointer.
        !           266:  */
        !           267: void INT_REP::StripMinus()
        !           268: {
        !           269:        register long *pp;
        !           270: 
        !           271:        if(isNegative()) {
        !           272:                pp = wt - 1;            // Points at -1.
        !           273:                if (pp > beg) {
        !           274:                        pp--;
        !           275:                        while ((*pp == (BASE-1)) && (pp > beg))
        !           276:                                pp--;
        !           277:                        if (*pp != (BASE-1))
        !           278:                                pp++;
        !           279:                        *pp++ = -1;
        !           280:                        wt = pp;
        !           281:                }
        !           282:        }
        !           283: }
        !           284: 
        !           285: /* Twos:
        !           286:  * Return largest power of 2 dividing this.
        !           287:  * Assume this is nonzero.
        !           288:  */
        !           289: int INT_REP::Twos()
        !           290: {
        !           291:        register int ret = 0;
        !           292:        register long *p, val;
        !           293: 
        !           294:        p = beg;
        !           295:        while(*p == 0) {
        !           296:                ret += 16;
        !           297:                p++;
        !           298:        }
        !           299: 
        !           300:        val = *p;
        !           301:        while ((val & 0x1) == 0) {
        !           302:                val >>= 1;
        !           303:                ret++;
        !           304:        }
        !           305:        
        !           306:        return (ret);
        !           307: }
        !           308: 
        !           309: /* FillLong:
        !           310:  * Use long to fill this.
        !           311:  * Assume storage has already been allocated.
        !           312:  */
        !           313: inline void INT_REP::FillLong(unsigned long val)
        !           314: {
        !           315:        beg[0] = val & 0xFFFF;
        !           316:        beg[1] = (val >> 16) & 0xFFFF;
        !           317:        if (val & 0xFFFF0000)
        !           318:                wt = beg + 2;
        !           319:        else if (val & 0xFFFF)
        !           320:                wt = beg + 1;
        !           321:        else 
        !           322:                wt = beg;
        !           323: }
        !           324: 
        !           325: /* Trunc:
        !           326:  * Use low order digits to fill a long.
        !           327:  * If digits are lost, set error = 1;
        !           328:  * else error = 0.
        !           329:  */
        !           330: long INT_REP::Trunc(int &error)
        !           331: {
        !           332:        long ret = 0;
        !           333:        int len;
        !           334:        register long *ptr;
        !           335: 
        !           336:        error = 0;
        !           337:        if(isZero())
        !           338:                return(ret);
        !           339: 
        !           340:        len = Length();
        !           341:        ptr = beg;
        !           342: 
        !           343:        if (isNegative()) {
        !           344:                if (len == 1)
        !           345:                        ret = -1;
        !           346:                else {
        !           347:                        ret = *ptr++;
        !           348:                        ret |= (*ptr << 16) & 0x7FFFFFFF;
        !           349:                        if ((len > 3) || ((*ptr & 0x8000) == 0))
        !           350:                                error = 1;
        !           351:                }
        !           352:        }
        !           353:        else {
        !           354:                ret = *ptr++;
        !           355:                if (len > 1) {
        !           356:                        ret |= *ptr << 16;
        !           357:                        if ((len > 2) || (*ptr & 0x8000))
        !           358:                                error = 1;
        !           359:                }
        !           360:        }
        !           361: 
        !           362:        return (ret);
        !           363: }
        !           364: 
        !           365: /* Comp:
        !           366:  * this < b  => -1
        !           367:  * this == b => 0
        !           368:  * this > b  => 1
        !           369:  */
        !           370: int INT_REP::Comp(INT_REP *b)
        !           371: {
        !           372:        INT_REP *diff;
        !           373:        int df;
        !           374: 
        !           375:        diff = Sub(b);
        !           376:        if (diff->isZero())
        !           377:                df = 0;
        !           378:        else if (diff->isNegative())
        !           379:                df = -1;
        !           380:        else
        !           381:                df = 1;
        !           382: 
        !           383:        delete diff;
        !           384:        return (df);
        !           385: }
        !           386: 
        !           387:                        
        !           388: /* Add:
        !           389:  * Return new rep, which is the sum of
        !           390:  * this and b.
        !           391:  */
        !           392: INT_REP *INT_REP::Add(INT_REP *b)
        !           393: {
        !           394:        register INT_REP *p;
        !           395:        register long n;
        !           396:        register int carry;
        !           397:        int size;
        !           398:        long *ap, *bp, *pp;
        !           399: 
        !           400:        if ((this == 0) || (b == 0))
        !           401:                Fatal ("Add - Null pointers.");
        !           402: 
        !           403:        if (isZero()) {
        !           404:                p = new INT_REP(b);
        !           405:                return (p);
        !           406:        }
        !           407:        if (b->isZero()) {
        !           408:                p = new INT_REP(this);
        !           409:                return (p);
        !           410:        }
        !           411: 
        !           412:        size = Max (Length(), b->Length());
        !           413:        p = new INT_REP(size);
        !           414: 
        !           415:        ap = this->beg;
        !           416:        bp = b->beg;
        !           417:        pp = p->beg;
        !           418:        carry = 0;
        !           419:        while(--size >= 0){
        !           420:                n = (ap == wt ? 0 : *ap++) + (bp == b->wt ? 0 : *bp++) + carry;
        !           421:                if (n >= BASE) {
        !           422:                        carry = 1;
        !           423:                        n -= BASE;
        !           424:                }
        !           425:                else if (n < 0) {
        !           426:                        carry = -1;
        !           427:                        n += BASE;
        !           428:                }
        !           429:                else carry = 0;
        !           430:                *pp++ = n;
        !           431:        }
        !           432:        p->wt = pp;
        !           433:        if(carry != 0)
        !           434:                p->Putc(carry);
        !           435: 
        !           436:        // Remove trailing zeros.
        !           437:        p->StripZero();
        !           438:        
        !           439:        // Remove redundant -1's in front of terminating -1.
        !           440:        p->StripMinus();
        !           441: 
        !           442:        return(p);
        !           443: }
        !           444: 
        !           445: /* Sub:
        !           446:  * Return new rep, which is the difference of
        !           447:  * this and b.
        !           448:  */
        !           449: INT_REP *INT_REP::Sub(INT_REP *b)
        !           450: {
        !           451:        INT_REP *nb, *diff;
        !           452: 
        !           453:        if ((this == 0) || (b == 0))
        !           454:                Fatal ("Sub - Null pointers.");
        !           455: 
        !           456:        nb = new INT_REP (b);
        !           457:        nb->Chsign();
        !           458: 
        !           459:        diff = Add(nb);
        !           460:        delete nb;
        !           461:        return (diff);
        !           462: }
        !           463: 
        !           464: /* DivMod:
        !           465:  * Return new rep, which is:
        !           466:  * mode == 0 => quotient of this and ddivr;
        !           467:  * mode == 1 => remainder of quotient of this and ddivr;
        !           468:  * mode == 2 => quotient of this and ddivr, with the
        !           469:  *              remainder stored in Remainder.
        !           470:  * Based on the multiple precision division algorithm
        !           471:  * in Knuth, v.2.
        !           472:  */
        !           473: INT_REP *INT_REP::DivMod(INT_REP *ddivr, int mode)
        !           474: {
        !           475:        register INT_REP *quot, *divd, *divr;
        !           476:        long *quotp, *divrp, *divdp;
        !           477:        int remsign, divsign, offset;
        !           478:        long carry, borrow;
        !           479:        long *ap, q;
        !           480:        unsigned long uval, delta;
        !           481:        long val;
        !           482:        int divlen, n, exp;
        !           483:        long varray[2], uarray[3];
        !           484: 
        !           485:        if ((this == 0) || (ddivr == 0))
        !           486:                Fatal ("DivMod - Null arguments.");
        !           487: 
        !           488:        if (ddivr->isZero()) 
        !           489:                Fatal ("DivMod : divide by zero.");
        !           490: 
        !           491:        // Make divisor and dividend positive.
        !           492:        Remainder = 0;
        !           493:        divsign = remsign = 0;
        !           494:        if (ddivr->isNegative ()) {
        !           495:                divr = new INT_REP(ddivr);
        !           496:                divr->Chsign();
        !           497:                divsign = ~divsign;
        !           498:        }
        !           499:        else 
        !           500:                divr = ddivr;
        !           501: 
        !           502:        divd = new INT_REP(this);
        !           503:        if (divd->isNegative()) {
        !           504:                divd->Chsign();
        !           505:                divsign = ~divsign;
        !           506:                remsign = ~remsign;
        !           507:        }
        !           508: 
        !           509:        offset = divd->Length() - divr->Length();
        !           510:        if(offset < 0) {
        !           511:                quot = new INT_REP(0);
        !           512:                goto ddone;
        !           513:        }
        !           514: 
        !           515:        // Allocate quotient.
        !           516:        quot = new INT_REP (offset + 1);
        !           517:        quot->wt = quot->last;
        !           518: 
        !           519:        val = *(divr->wt - 1);                  // Most significant "digit" in divisor.
        !           520:        divlen = divr->Length();
        !           521: 
        !           522:        // If divisor is 1 digit, handle specially.
        !           523:        if (divlen == 1) {
        !           524:                quotp = quot->beg + offset;
        !           525:                divdp = divd->beg + offset;
        !           526:                carry = 0;
        !           527: 
        !           528:                while (offset-- >= 0) {
        !           529:                        uval = carry*BASE + *divdp--;
        !           530:                        *quotp-- = uval/val;
        !           531:                        carry = uval%val;
        !           532:                }
        !           533: 
        !           534:                // Set remainder.
        !           535:                divd->beg[0] = carry;
        !           536:                divd->wt = divd->beg + 1;
        !           537: 
        !           538:                goto ddone;
        !           539:        }
        !           540: 
        !           541:        // General case.
        !           542:        // Initialize. We are essentially finding the least power of 2
        !           543:        // that we can multiply times the most significant digit of the divisor
        !           544:        // and make it >= BASE/2. The algorithm then guarantees that our
        !           545:        // "guess" for the quotient will be at most two greater than the
        !           546:        // correct answer.
        !           547: 
        !           548:        divd->Putc (0);
        !           549:        exp = HighBit (val);                    // 0 <= exp < 16.
        !           550:        Shift (divr->wt - 1, divr->beg, exp, varray, 2);
        !           551:        divdp = divd->wt - 1;
        !           552:        divd->wt -= offset;
        !           553:        quotp = quot->wt - 1;
        !           554: 
        !           555: //     fprintf(stderr, "exp = %d , v1 = %x, v2 = %x\n", exp, varray[0], varray[1]);
        !           556:        while (offset-- >= 0) {
        !           557: //             divd->Prt();
        !           558:                Shift (divdp, divd->beg, exp, uarray, 3);
        !           559: //             fprintf(stderr, "u1 = %x, u2 = %x, u3 = %x\n", uarray[0], uarray[1], uarray[2]);
        !           560: 
        !           561:                // Guess a quotient.
        !           562:                if (uarray[0] == varray[0])
        !           563:                        q = BASE-1;
        !           564:                else
        !           565:                        q = ((unsigned long)(BASE*uarray[0] + uarray[1]))/varray[0];
        !           566: //             fprintf(stderr, "initial q = %x\n",q);
        !           567: 
        !           568:                // Adjust.
        !           569:                // while q*v1 > (BASE*u0 + u1 - q*v0)BASE + u2, decrement q.
        !           570:                // To avoid an overflow problem, first check if
        !           571:                // (BASE*u0 + u1 - q*v0) >= BASE; if it is, the right side is
        !           572:                // >= BASE^2, while the left is < BASE^2 and we are done.
        !           573:                // Otherwise, the right side is < BASE^2, and we can do an
        !           574:                // ordinary arithmetic check.
        !           575:                while (1) {
        !           576:                        delta = BASE*uarray[0] + uarray[1] - q*varray[0];
        !           577:                        if (delta >= BASE) 
        !           578:                                break;
        !           579:                        if ((unsigned long)(varray[1]*q) <= (unsigned long)(delta*BASE+uarray[2]))
        !           580:                                break;
        !           581:                        q--;
        !           582:                }
        !           583: //             fprintf(stderr, "final q = %x\n",q);
        !           584:                
        !           585:                // Multiply divisor by q, and subtract from dividend.
        !           586:                n = divlen;
        !           587:                carry = 0;
        !           588:                borrow = 0;
        !           589:                ap = divdp - n;
        !           590:                divrp = divr->beg;
        !           591: 
        !           592:                while (n >= 0) {
        !           593:                        if (n > 0)
        !           594:                                uval = q*(*divrp++) + carry;
        !           595:                        else
        !           596:                                uval = carry;
        !           597: 
        !           598:                        if (uval >= BASE) {
        !           599:                                carry = uval/BASE;
        !           600:                                uval %= BASE;
        !           601:                        }
        !           602:                        else
        !           603:                                carry = 0;
        !           604:                        
        !           605:                        val = (*ap) - uval - borrow;
        !           606: //                     fprintf(stderr, "n = %d, borrow = %x, carry = %x\n",
        !           607: //                             n, borrow, carry);
        !           608: //                     fprintf(stderr, "*ap = %x, val = %x, uval = %x\n",
        !           609: //                             *ap, val, uval);
        !           610:                        if (val < 0) {
        !           611:                                val += BASE;
        !           612:                                borrow = 1;
        !           613:                        }
        !           614:                        else
        !           615:                                borrow = 0;
        !           616: 
        !           617:                        *ap++ = val;
        !           618:                        n--;
        !           619:                }
        !           620: 
        !           621:                // If guess is still too high (remainder negative => had to borrow), 
        !           622:                // subtract one from quotient and add one copy of divisor
        !           623:                // back into remainder.
        !           624:                if (borrow) {
        !           625:                        *quotp-- = q - 1;
        !           626:                        n = divlen;
        !           627:                        carry = 0;
        !           628:                        ap = divdp - n;
        !           629:                        divrp = divr->beg;
        !           630: 
        !           631:                        while (n >= 0) {
        !           632:                                if (n > 0)
        !           633:                                        uval = (*ap) + (*divrp++) + carry;
        !           634:                                else
        !           635:                                        uval = (*ap) + carry;
        !           636: //                             fprintf(stderr, "borrow n = %d, carry = %x, *ap = %x, uval = %x\n",
        !           637: //                                     n, carry, *ap, uval);
        !           638: 
        !           639:                                if (uval >= BASE) {
        !           640:                                        uval -= BASE;
        !           641:                                        carry = 1;
        !           642:                                }
        !           643:                                else
        !           644:                                        carry = 0;
        !           645:                                
        !           646:                                *ap++ = uval;
        !           647:                                n--;
        !           648:                        }
        !           649:                }
        !           650:                else
        !           651:                        *quotp-- = q;
        !           652: 
        !           653:                divdp--;
        !           654:        }
        !           655: 
        !           656: ddone:
        !           657:        if (divr != ddivr) delete divr;
        !           658:        switch (mode) {
        !           659:        case 0 : // Return quotient; delete remainder.
        !           660:                delete divd;
        !           661:                break;
        !           662:        case 1 : // Return remainder; delete quotient and pretend
        !           663:                         // that the remainder is the quotient.
        !           664:                delete quot;
        !           665:                quot = divd;
        !           666:                divsign = remsign;
        !           667:                break;
        !           668:        case 2 : // Return quotient; store remainder in Remainder.
        !           669:                divd->StripZero();
        !           670:                if (remsign < 0) divd->Chsign();                // Use correct sign.
        !           671:                Remainder = divd;
        !           672:                break;
        !           673:        }
        !           674: 
        !           675:        // Remove prefix zeros.
        !           676:        quot->StripZero();
        !           677:        if (divsign < 0) quot->Chsign();                // Use correct sign.
        !           678: 
        !           679:        return (quot);
        !           680: }
        !           681: 
        !           682: /* Exp:
        !           683:  * Return new rep, which is the first argument
        !           684:  * raised to the second argument power.
        !           685:  */
        !           686: INT_REP *INT_REP::Exp(INT_REP *exp)
        !           687: {
        !           688:        INT_REP *r;
        !           689:        INT_REP *e;
        !           690:        INT_REP *p;
        !           691:        INT_REP *t, *cp, *e1;
        !           692:        int neg = 0;
        !           693: 
        !           694:        r = new INT_REP(&OneRep);
        !           695: 
        !           696:        // Check for special cases.
        !           697:        if((exp->isZero()) || equalsOne(this))
        !           698:                return (r);
        !           699:        if(isZero()) {
        !           700:                r->SetZero();
        !           701:                return (r);
        !           702:        }
        !           703: 
        !           704:        // Create copies of arguments.
        !           705:        p = new INT_REP(this);
        !           706:        e = new INT_REP(exp);
        !           707: 
        !           708:        // Check for negative exponent.
        !           709:        if (e->isNegative()) {
        !           710:                neg++;
        !           711:                e->Chsign();
        !           712:        }
        !           713: 
        !           714:        // Compute exponentiation.
        !           715:        while (e->isNonzero()) {
        !           716:                e1 = e->DivMod(&TwoRep,2);
        !           717:                delete e;
        !           718:                e = e1;
        !           719: 
        !           720:                if (Remainder->isNonzero()) {
        !           721:                        e1 = p->Mult(r);
        !           722:                        delete r;
        !           723:                        r = e1;
        !           724:                }
        !           725:                delete Remainder;
        !           726: 
        !           727:                t = new INT_REP(p);
        !           728:                cp = p->Mult(t);
        !           729:                delete p;
        !           730:                delete t;
        !           731:                p = cp;
        !           732:        }
        !           733: 
        !           734:        delete e;
        !           735:        delete p;
        !           736: 
        !           737:        // Adjust for negative exponent.
        !           738:        if (neg) {
        !           739:                t = OneRep.Div(r);
        !           740:                delete r;
        !           741:                return (t);
        !           742:        }
        !           743:        else
        !           744:                return (r);
        !           745: 
        !           746: }
        !           747: 
        !           748: /* Mult:
        !           749:  * Return new rep, which is the product of
        !           750:  * this and ddivr.
        !           751:  */
        !           752: INT_REP *INT_REP::Mult(INT_REP *q)
        !           753: {
        !           754:        register INT_REP *mp,*mq,*mr;
        !           755:        int sign,offset,carry;
        !           756:        unsigned long mt;
        !           757:        long cq, cp, mcr;
        !           758:        long *pptr, *qptr, *rptr;
        !           759: 
        !           760:        if ((this == 0) || (q == 0))
        !           761:                Fatal ("Mult - Null pointers.");
        !           762: 
        !           763:        offset = sign = 0;
        !           764:        if (isNegative()) {
        !           765:                mp = new INT_REP (this);
        !           766:                mp->Chsign();
        !           767:                sign = ~sign;
        !           768:        }
        !           769:        else 
        !           770:                mp = this;
        !           771: 
        !           772:        if (q->isNegative()) {
        !           773:                mq = new INT_REP (q);
        !           774:                mq->Chsign();
        !           775:                sign = ~sign;
        !           776:        }
        !           777:        else
        !           778:                mq = q;
        !           779: 
        !           780:        mr = new INT_REP (mp->Length() + mq->Length());
        !           781:        mr->Zero();
        !           782:        qptr = mq->beg;
        !           783:        while (qptr < mq->wt) {
        !           784:                cq = *qptr++;
        !           785:                pptr = mp->beg;
        !           786:                rptr = mr->beg + offset;
        !           787:                carry = 0;
        !           788:                while (pptr < mp->wt) {
        !           789:                        cp = *pptr++;
        !           790:                        mcr = (rptr == mr->wt ? 0 : *rptr);
        !           791:                        mt = cp*cq + carry + mcr;
        !           792:                        carry = mt>>16;                                                 // mt/BASE.
        !           793:                        mr->Alterc(mt&0xFFFF, rptr++);                  // mt%BASE.
        !           794:                }
        !           795:                offset++;
        !           796:                if(carry != 0){
        !           797:                        mcr = (rptr == mr->wt ? 0 : *rptr);
        !           798:                        mr->Alterc(mcr+carry, rptr);                    // Why is mcr+carry < BASE?
        !           799:                }
        !           800:        }
        !           801: 
        !           802:        if(sign < 0){
        !           803:                mr->Chsign();
        !           804:        }
        !           805:        if(mp != this) delete mp;
        !           806:        if(mq != q) delete mq;
        !           807: 
        !           808:        return (mr);
        !           809: }
        !           810:                                        
        !           811: /* INT_REP:
        !           812:  * Create new rep, with
        !           813:  * size bytes of storage.
        !           814:  * If setRef == 0, do not initialize refcnt. This is used by
        !           815:  * ZeroRep in case it gets initialized after some INT with
        !           816:  * no arguments.
        !           817:  */
        !           818: INT_REP::INT_REP (int size, int setRef)
        !           819: {
        !           820:        long *ptr;
        !           821: 
        !           822:        if (this == 0)
        !           823:                this = IRAllocRep ();
        !           824:                        
        !           825:        ptr = new long[(unsigned)size];
        !           826:        if (ptr == 0)
        !           827:                Fatal ("INT_REP - Out of memory.");
        !           828: 
        !           829:        wt = beg = ptr;
        !           830:        last = ptr + size;
        !           831:        if (setRef) refcnt = 0;
        !           832: }
        !           833: 
        !           834: /* INT_REP:
        !           835:  * Create new rep, 
        !           836:  * using supplied long.
        !           837:  */
        !           838: INT_REP::INT_REP (long val)
        !           839: {
        !           840:        int neg = 0;
        !           841:        int size = 2;           // Number of longs needed to store positive 32 bits.
        !           842: 
        !           843:        if (this == 0)
        !           844:                this = IRAllocRep ();
        !           845: 
        !           846:        if (val == 0) {         // If zero, ...
        !           847:                MakeZero (this);
        !           848:                return;
        !           849:        }
        !           850: 
        !           851:        if (val < 0) {
        !           852:                neg++;
        !           853:                size++;                 // May need extra word for sign.
        !           854:        }
        !           855:        beg = new long[size];
        !           856:        if (beg == 0)
        !           857:                Fatal ("INT_REP - Out of memory.");
        !           858:        last = beg + size;
        !           859:        refcnt = 0;
        !           860:                
        !           861:        // Store bits.
        !           862:        FillLong((unsigned long)val);
        !           863: 
        !           864:        // If negative, add sign, and strip redundant signs.
        !           865:        if (neg) {
        !           866:                Putc(-1);
        !           867:                StripMinus();
        !           868:        }
        !           869:        
        !           870: }
        !           871: 
        !           872: /* INT_REP:
        !           873:  * Create new rep, 
        !           874:  * duplicating old rep.
        !           875:  */
        !           876: INT_REP::INT_REP (INT_REP *old)
        !           877: {
        !           878:        long *ptr, *oldptr;
        !           879:        int size = old->Length();
        !           880: 
        !           881:        if (this == 0)
        !           882:                this = IRAllocRep ();
        !           883:                        
        !           884:        ptr = new long[(unsigned)size];
        !           885:        if (ptr == 0)
        !           886:                Fatal ("INT_REP - Out of memory.");
        !           887:        beg = ptr;
        !           888:        wt = last = ptr + size;
        !           889:        refcnt = 0;
        !           890: 
        !           891:        oldptr = old->beg;
        !           892:        while (ptr < last) {
        !           893:                *ptr++ = *oldptr++;
        !           894:        }
        !           895: }
        !           896: 
        !           897: /* INT_REP:
        !           898:  * Create new rep, 
        !           899:  * from ascii representation s.
        !           900:  */
        !           901: INT_REP::INT_REP (char *s)
        !           902: {
        !           903:        register char *optr;
        !           904:        short minus = 0;
        !           905:        Mode mode;
        !           906:        int size;
        !           907:              
        !           908:        if (this == 0)
        !           909:                this = IRAllocRep ();
        !           910:        refcnt = 0;
        !           911:                       
        !           912:        // Handle NULL pointer or NULL string.
        !           913:        if ((s == (char *)0) || (*s == '\0')) {
        !           914:                MakeZero(this);
        !           915:                return;
        !           916:        }
        !           917:         
        !           918:        // Check for sign.
        !           919:        if (*s == '-') {
        !           920:                s++;
        !           921:                minus = 1;
        !           922:        }
        !           923: 
        !           924:        // Determine mode.
        !           925:        if (*s == '0') {
        !           926:                s++;
        !           927:                if (*s == '\0') {
        !           928:                        MakeZero(this);
        !           929:                        return;
        !           930:                }
        !           931:                else if ((*s == 'x') || (*s == 'X')) {
        !           932:                        s++;
        !           933:                        mode = hexadecimal;
        !           934:                }
        !           935:                else
        !           936:                        mode = octal;
        !           937:        }
        !           938:        else
        !           939:                mode = decimal;
        !           940: 
        !           941:        // Find end of string.
        !           942:        optr = s;
        !           943:        while(*optr) optr++;
        !           944:        if (s == optr) 
        !           945:                Fatal ("INT_REP : Improper string.");
        !           946:                         
        !           947:        // Fill representation, using correct mode.
        !           948:        if (mode == decimal)
        !           949:                FillDec (s, optr);
        !           950:        else {
        !           951:                // Allocate enough space.
        !           952:                size = (strlen(s) + 3)/4;
        !           953:                beg = new long[size];
        !           954:                if (beg == 0)
        !           955:                        Fatal ("INT_REP - Out of memory.");
        !           956:                last = beg + size;
        !           957: 
        !           958:                // Fill.
        !           959:                if (mode == hexadecimal)
        !           960:                        FillHex(s, optr);
        !           961:                else
        !           962:                        FillOct(s, optr);
        !           963: 
        !           964:                // Remove extraneous zeros.
        !           965:                StripZero();
        !           966:        }
        !           967:                           
        !           968:        // Correct for sign.
        !           969:        if (minus)
        !           970:                Chsign ();
        !           971: }
        !           972:                                
        !           973: /* ~INT_REP:
        !           974:  * destructor.
        !           975:  */
        !           976: INT_REP::~INT_REP ()
        !           977: {
        !           978:        if(beg) delete beg;
        !           979: 
        !           980:        // Put back on free list.
        !           981:        wt = (long *)hfree;
        !           982:        hfree = this;
        !           983:        this = 0;
        !           984: }
        !           985: 
        !           986: /* More:
        !           987:  * Obtain more storage for this,
        !           988:  * using realloc, and resetting
        !           989:  * pointers.
        !           990:  */
        !           991: void INT_REP::More()
        !           992: { 
        !           993:        register unsigned size;
        !           994:        register long *p;
        !           995: 
        !           996:        if ((size = (last - beg) * 2) == 0) 
        !           997:                size = 1;
        !           998:        p = (long *)realloc((char *)beg, (unsigned)(size*sizeof(long)));
        !           999:        if(p == 0)
        !          1000:                Fatal ("More: realloc failed");
        !          1001: 
        !          1002:        wt = p + (wt - beg);
        !          1003:        beg = p;
        !          1004:        last = p + size;
        !          1005: }
        !          1006: 
        !          1007: /* Zero:
        !          1008:  * Zero out all the storage.
        !          1009:  */
        !          1010: void INT_REP::Zero()
        !          1011: { 
        !          1012:        register long *pp;
        !          1013: 
        !          1014:        for (pp = beg; pp < last;)
        !          1015:                *pp++ = 0;
        !          1016: }
        !          1017: 
        !          1018: 
        !          1019: /* Prt:
        !          1020:  * Print internal information;
        !          1021:  * for debugging.
        !          1022:  */
        !          1023: void INT_REP::Prt()
        !          1024: {
        !          1025:        long *ptr = beg;
        !          1026: 
        !          1027:        while (ptr != wt)
        !          1028:                fprintf(stderr, "%x,", *ptr++);
        !          1029:        fprintf (stderr, "   : this = %x, beg = %x, last = %x, wt = %x\n",
        !          1030:                this, beg, last, wt);
        !          1031: }
        !          1032:    
        !          1033: /* PutDec:
        !          1034:  * Store decimal representation of this in obuf.
        !          1035:  * NOTE : The routine destroys this.
        !          1036:  */
        !          1037: INT_REP *INT_REP::PutDec ()
        !          1038: {
        !          1039:        register INT_REP *divd = this, *div, *mod;
        !          1040:        register long val;
        !          1041:        int count;
        !          1042: 
        !          1043:        while (1) {
        !          1044:                div = divd->DivMod (&BigTen, 2);
        !          1045:                mod = Remainder;
        !          1046: //             div->Prt();
        !          1047: //             mod->Prt();
        !          1048: 
        !          1049:                // Store remainder.
        !          1050:                val = 0;
        !          1051:                switch (mod->Length()) {
        !          1052:                case 2 :
        !          1053:                        val = (mod->beg[1]) << 16;
        !          1054:                        /* Fall through. */
        !          1055:                case 1 :
        !          1056:                        val |= (mod->beg[0]);
        !          1057:                }
        !          1058: //             fprintf (stderr, "val = %d (0x%x)\n",val, val);
        !          1059:                delete mod;
        !          1060:                delete divd;
        !          1061: 
        !          1062:                count = BlockLen;
        !          1063:                while (val) {
        !          1064:                        obuf.Put((char)(val%10 + '0'));
        !          1065:                        val /= 10;
        !          1066:                        count--;
        !          1067:                }
        !          1068: 
        !          1069:                if (div->isZero())
        !          1070:                        return (div);
        !          1071: 
        !          1072:                while (count--)
        !          1073:                        obuf.Put('0');
        !          1074:                divd = div;
        !          1075:        }
        !          1076: 
        !          1077: }
        !          1078: 
        !          1079: /* PutHex:
        !          1080:  * Store hexadecimal representation of this in obuf.
        !          1081:  */
        !          1082: INT_REP *INT_REP::PutHex ()
        !          1083: {
        !          1084:        register unsigned long  *ptr = (unsigned long *)beg;
        !          1085:        register unsigned long  val, digit;
        !          1086:        register int                    count;
        !          1087: 
        !          1088:        while (1) {
        !          1089:                val = *ptr++;
        !          1090:                count = 4;                              // 4 hex digits per long
        !          1091: 
        !          1092:                while (val) {         
        !          1093:                        if ((digit = (val & 0xF)) < 10) 
        !          1094:                                obuf.Put((char)(digit + '0'));
        !          1095:                        else
        !          1096:                                obuf.Put((char)(digit + ('A' - 10)));
        !          1097:                        val >>= 4;
        !          1098:                        count--;
        !          1099:                }
        !          1100: 
        !          1101:                if (ptr == (unsigned long *) wt)
        !          1102:                        return (this);
        !          1103: 
        !          1104:                while (count--)
        !          1105:                        obuf.Put ('0');
        !          1106:        }
        !          1107: }
        !          1108: 
        !          1109: /* PutOct:
        !          1110:  * Store octal representation of this in obuf.
        !          1111:  */
        !          1112: INT_REP *INT_REP::PutOct ()
        !          1113: {
        !          1114:        register unsigned long  *ptr = (unsigned long *)beg;
        !          1115:        register unsigned long  val = 0;
        !          1116:        register int                    count;
        !          1117:        register int                    numbits = 0;
        !          1118: 
        !          1119:        while (1) {
        !          1120:                val |= (*ptr++) << numbits;
        !          1121:                if (numbits == 2)
        !          1122:                        count = 6;
        !          1123:                else 
        !          1124:                        count = 5;
        !          1125:                numbits += 16;
        !          1126: 
        !          1127:                while (val && count) {
        !          1128:                        obuf.Put((char)((val & 0x7) + '0'));
        !          1129:                        val >>= 3;
        !          1130:                        numbits -= 3;
        !          1131:                        count--;
        !          1132:                }
        !          1133:      
        !          1134:                if (ptr == (unsigned long *) wt)
        !          1135:                        return (this);
        !          1136:                                
        !          1137:                if (count) {
        !          1138:                        numbits -= (count * 3);
        !          1139:                        while (count--) 
        !          1140:                                obuf.Put ('0');
        !          1141:                }
        !          1142:        }
        !          1143: }
        !          1144: 
        !          1145: /* Print:
        !          1146:  * Print INT_REP.
        !          1147:  * We use the output mode supplied by the iostream.
        !          1148:  * After taking care of 0 and the minus sign,
        !          1149:  * we use the appropriate function to store the
        !          1150:  * representation in obuf.
        !          1151:  * Finally, we flush obuf onto the iostream.
        !          1152:  */
        !          1153: void INT_REP::Print(iostream &i)
        !          1154: {
        !          1155:        register INT_REP *divd;
        !          1156: #ifdef HEX
        !          1157:        register long *rp;
        !          1158: #endif HEX
        !          1159:        
        !          1160:        if (Length() == 0) {
        !          1161:                i.put('0');
        !          1162:                return;
        !          1163:        }
        !          1164: 
        !          1165:        divd = new INT_REP (this);
        !          1166:        if (isNegative()) {
        !          1167:                divd->Chsign();
        !          1168:                i.put('-');
        !          1169:        }
        !          1170:                    
        !          1171: 
        !          1172:        // Print.
        !          1173: #ifdef PRE6
        !          1174:        switch (i.convbase()) {
        !          1175:        case 0 :
        !          1176:        case 10 :
        !          1177:                divd = divd->PutDec ();
        !          1178:                break;
        !          1179:        case 8 :
        !          1180:                divd = divd->PutOct ();
        !          1181:                break;
        !          1182:        case 16 :
        !          1183:                divd = divd->PutHex ();
        !          1184:                break;
        !          1185:        }
        !          1186: #else
        !          1187:        switch (i.flags()) {
        !          1188:        default :
        !          1189:        case ios::dec :
        !          1190:                divd = divd->PutDec ();
        !          1191:                break;
        !          1192:        case ios::oct :
        !          1193:                divd = divd->PutOct ();
        !          1194:                break;
        !          1195:        case ios::hex :
        !          1196:                divd = divd->PutHex ();
        !          1197:                break;
        !          1198:        }
        !          1199: #endif
        !          1200:         
        !          1201:        delete divd;
        !          1202:        obuf.Flush(i);
        !          1203: #ifdef HEX
        !          1204:        rp = wt - 1;
        !          1205:        while (rp >= beg)
        !          1206:                printf("%04x", *rp--);
        !          1207:        printf("\n");
        !          1208: #endif HEX
        !          1209: 
        !          1210: }
        !          1211:               
        !          1212: /* Print:
        !          1213:  * Print INT_REP.
        !          1214:  * We use the output function supplied by the user.
        !          1215:  * The mode parameter determines the output mode.
        !          1216:  * After taking care of 0 and the minus sign,
        !          1217:  * we use the appropriate function to store the
        !          1218:  * representation in obuf.
        !          1219:  * Finally, we flush obuf using the user's function.
        !          1220:  */
        !          1221: void INT_REP::Print(OutFn outf, int mode)
        !          1222: {
        !          1223:        register INT_REP *divd;
        !          1224:        
        !          1225:        if (Length() == 0) {
        !          1226:                (*outf)('0');
        !          1227:                (*outf)('\0');
        !          1228:                return;
        !          1229:        }
        !          1230: 
        !          1231:        divd = new INT_REP (this);
        !          1232:        if (isNegative()) {
        !          1233:                divd->Chsign();
        !          1234:                (*outf)('-');
        !          1235:        }
        !          1236:                    
        !          1237:        // Print.
        !          1238:        switch (mode) {
        !          1239:        case 0 :
        !          1240:                divd = divd->PutDec ();
        !          1241:                break;
        !          1242:        case 1 :
        !          1243:                divd = divd->PutOct ();
        !          1244:                break;
        !          1245:        case 2 :
        !          1246:                divd = divd->PutHex ();
        !          1247:                break;
        !          1248:        }
        !          1249:         
        !          1250:        delete divd;
        !          1251:        obuf.Flush(outf);
        !          1252: 
        !          1253: }
        !          1254:               
        !          1255: /* Store:
        !          1256:  * Store representation of this in given buffer,
        !          1257:  * null terminated.
        !          1258:  * Buflen tells how many characters are in the user's
        !          1259:  * buffer; -1 => unspecified.
        !          1260:  * Representation is base 10 <=> mode = 0
        !          1261:  *                   base  8 <=> mode = 1
        !          1262:  *                   base 16 <=> mode = 2
        !          1263:  * Return number of (non-null) characters.
        !          1264:  */
        !          1265: int INT_REP::Store (char *buf, int buflen, int mode)
        !          1266: {
        !          1267:        register INT_REP        *divd;
        !          1268:        int                                     length;
        !          1269:                                   
        !          1270:        if (buflen == 0)
        !          1271:                return (0);
        !          1272:        else if (buflen == 1) {
        !          1273:                *buf = '\0';
        !          1274:                return (0);
        !          1275:        }
        !          1276: 
        !          1277:        if (isZero()) {
        !          1278:                *buf++ = '0';
        !          1279:                *buf = '\0';
        !          1280:                return (1);
        !          1281:        }
        !          1282: 
        !          1283:        divd = new INT_REP (this);
        !          1284:        if (isNegative())
        !          1285:                divd->Chsign();
        !          1286:                    
        !          1287:        // Print.
        !          1288:        switch (mode) {
        !          1289:        case 0 :
        !          1290:                divd = divd->PutDec ();
        !          1291:                break;
        !          1292:        case 1 :
        !          1293:                divd = divd->PutOct ();
        !          1294:                break;
        !          1295:        case 2 :
        !          1296:                divd = divd->PutHex ();
        !          1297:                break;
        !          1298:        }
        !          1299:        delete divd;          
        !          1300: 
        !          1301:        // If necessary, add minus sign.
        !          1302:        if (isNegative())
        !          1303:                obuf.Put('-');          
        !          1304:                                     
        !          1305:        // Compute number of characters to store.
        !          1306:        length = obuf.Length ();
        !          1307:        if ((buflen > 0) && (length + 1 > buflen))
        !          1308:                length = buflen - 1;
        !          1309: 
        !          1310:        obuf.Flush(buf, length);
        !          1311: 
        !          1312:        return (length);
        !          1313: 
        !          1314: }
        !          1315: 
        !          1316: /* Chsign:
        !          1317:  * Change sign of the rep.
        !          1318:  */
        !          1319: void INT_REP::Chsign ()
        !          1320: {
        !          1321:        register long carry;
        !          1322:        register long ct;
        !          1323:        register long *readp;
        !          1324: 
        !          1325:        if (Length () == 0) return;
        !          1326: 
        !          1327:        carry = 0;
        !          1328:        readp = beg;
        !          1329:        while (readp != wt) {
        !          1330:                ct = BASE - *readp - carry;
        !          1331: 
        !          1332:                if(ct >= BASE) {
        !          1333:                        ct -= BASE;
        !          1334:                        if (ct == 1) {
        !          1335:                                *readp = 1;
        !          1336:                                return;
        !          1337:                        }
        !          1338:                        else if (carry == 1) {
        !          1339:                                wt = readp;
        !          1340:                                return;
        !          1341:                        }
        !          1342:                        else
        !          1343:                                carry = 0;
        !          1344:                }
        !          1345:                else
        !          1346:                        carry = 1;
        !          1347: 
        !          1348:                *readp++ = ct;
        !          1349:        }
        !          1350:        readp--;
        !          1351:        if (*readp == BASE-1)
        !          1352:                *readp = -1;
        !          1353:        else
        !          1354:                Putc(-1);
        !          1355: 
        !          1356: }
        !          1357:    
        !          1358: /* FillDec:
        !          1359:  * Use decimal representation to fill this.
        !          1360:  * sp points to first character, ep points
        !          1361:  * to terminating NULL. Use standard decimal
        !          1362:  * to binary conversion. Assume no
        !          1363:  * storage has already been allocated.
        !          1364:  */
        !          1365: void INT_REP::FillDec(char *sp, char *ep)
        !          1366: {
        !          1367:        char *pp;
        !          1368:        INT_REP *u, *newi, *product;
        !          1369:        unsigned long val;
        !          1370:        
        !          1371:     // Create utility INT_REP.
        !          1372:        u = new INT_REP(2);
        !          1373:        
        !          1374:        // Determine leftmost block of characters.
        !          1375:        pp = sp + ((int)(ep - sp))%BlockLen;
        !          1376: 
        !          1377:        // Convert to an INT_REP.
        !          1378:        val = MakeLong(sp, pp);
        !          1379:        u->FillLong (val);
        !          1380:        sp = pp;
        !          1381:        newi = new INT_REP (u);
        !          1382: 
        !          1383:        while (sp < ep) {
        !          1384:                product = newi->Mult(&BigTen);
        !          1385:                delete newi;
        !          1386:                val = MakeLong(sp, sp+BlockLen);
        !          1387:                u->FillLong (val);
        !          1388:                sp += BlockLen;
        !          1389:                newi = product->Add(u);
        !          1390:                delete product;
        !          1391:        }
        !          1392: 
        !          1393:        // Copy newi into this.
        !          1394:        beg = newi->beg;
        !          1395:        last = newi->last;
        !          1396:        wt = newi->wt;
        !          1397:        newi->beg = 0;
        !          1398: 
        !          1399:        // Delete temporaries.
        !          1400:        delete newi;
        !          1401:        delete u;
        !          1402:        
        !          1403: }
        !          1404: 
        !          1405: /* FillHex:
        !          1406:  * Use hex representation to fill this.
        !          1407:  * sp points to first character, ep points
        !          1408:  * to terminating NULL. Assume adequate 
        !          1409:  * storage has already been allocated.
        !          1410:  */
        !          1411: void INT_REP::FillHex(char *sp, char *ep)
        !          1412: {
        !          1413:        long *lptr = beg;
        !          1414:        long word = 0;
        !          1415:        long c;
        !          1416:        short shift = 0;
        !          1417: 
        !          1418:        while (ep > sp) {
        !          1419:                c = *(--ep);
        !          1420:                if(!isxdigit(c))
        !          1421:                        Fatal ("FillHex - Illegal hex character.");
        !          1422:                if (isdigit(c))
        !          1423:                        c -= '0';
        !          1424:                else if (islower(c))
        !          1425:                        c -= 'a' - 10;
        !          1426:                else
        !          1427:                        c -= 'A' - 10;
        !          1428: 
        !          1429:                word |= c << shift;
        !          1430:                shift += 4;
        !          1431:                if (shift == 16) {
        !          1432:                        shift = 0;
        !          1433:                        *lptr++ = word;
        !          1434:                        word = 0;
        !          1435:                }
        !          1436:        }       
        !          1437: 
        !          1438:        // Add incomplete word.
        !          1439:        if (shift)
        !          1440:                *lptr++ = word;
        !          1441:        
        !          1442:        // Set wt.
        !          1443:        wt = lptr;
        !          1444: }
        !          1445: 
        !          1446: /* FillOct:
        !          1447:  * Use octal representation to fill this.
        !          1448:  * sp points to first character, ep points
        !          1449:  * to terminating NULL. Assume adequate 
        !          1450:  * storage has already been allocated.
        !          1451:  */
        !          1452: void INT_REP::FillOct(char *sp, char *ep)
        !          1453: {
        !          1454:        long *lptr = beg;
        !          1455:        long word = 0;
        !          1456:        long c;
        !          1457:        short shift = 0;
        !          1458: 
        !          1459:        while (ep > sp) {
        !          1460:                c = *(--ep);
        !          1461:                if(!isdigit(c) || (c > '7'))
        !          1462:                        Fatal ("FillOct - Illegal octal character.");
        !          1463: 
        !          1464:                c -= '0';
        !          1465:                word |= c << shift;
        !          1466:                shift += 3;
        !          1467:                if (shift >= 16) {
        !          1468:                        *lptr++ = word & 0xFFFF;
        !          1469:                        shift -= 16;
        !          1470:                        word = c >> (3 - shift);
        !          1471:                }
        !          1472:        }       
        !          1473: 
        !          1474:        // Add incomplete word.
        !          1475:        if (shift)
        !          1476:                *lptr++ = word;
        !          1477:        
        !          1478:        // Set wt.
        !          1479:        wt = lptr;
        !          1480:        
        !          1481: }
        !          1482: 
        !          1483: /* And:
        !          1484:  * Bit-wise and.
        !          1485:  */
        !          1486: INT_REP *INT_REP::And(INT_REP *b)
        !          1487: {
        !          1488:        INT_REP *newi;
        !          1489:        int length;
        !          1490:        long *ap, *bp, *pp;
        !          1491: 
        !          1492:        if (isZero() || b->isZero())
        !          1493:                return (&ZeroRep);
        !          1494: 
        !          1495:        length = Min(Length(), b->Length());
        !          1496:        newi = new INT_REP(length);
        !          1497: 
        !          1498:        ap = beg;
        !          1499:        bp = b->beg;
        !          1500:        pp = newi->beg;
        !          1501: 
        !          1502:        while (length-- > 0)
        !          1503:                *pp++ = (*ap++) & (*bp++);
        !          1504:        newi->wt = pp;
        !          1505:                   
        !          1506:        // Strip trailing zeros.
        !          1507:        newi->StripZero();
        !          1508: 
        !          1509:        return (newi);
        !          1510: }
        !          1511: 
        !          1512: /* Or:
        !          1513:  * Bit-wise or.
        !          1514:  */
        !          1515: INT_REP *INT_REP::Or(INT_REP *b)
        !          1516: {
        !          1517:        INT_REP *newi;
        !          1518:        int length;
        !          1519:        long *ap, *bp, *pp;
        !          1520: 
        !          1521:        if (isZero()) {
        !          1522:                newi = new INT_REP(b);
        !          1523:                return newi;
        !          1524:        }       
        !          1525:        if (b->isZero()) {
        !          1526:                newi = new INT_REP(this);
        !          1527:                return newi;
        !          1528:        }       
        !          1529: 
        !          1530:        if (isNegative()) {
        !          1531:                if(b->isNegative())
        !          1532:                        length = Min(Length(), b->Length());
        !          1533:                else
        !          1534:                        length = Length();
        !          1535:        }
        !          1536:        else {
        !          1537:                if(b->isNegative())
        !          1538:                        length = b->Length();
        !          1539:                else
        !          1540:                        length = Max(Length(), b->Length());
        !          1541:        }
        !          1542:        newi = new INT_REP(length);
        !          1543: 
        !          1544:        ap = beg;
        !          1545:        bp = b->beg;
        !          1546:        pp = newi->beg;
        !          1547: 
        !          1548:        while (length-- > 0)
        !          1549:                *pp++ = (ap < wt ? *ap++ : 0) & (bp < b->wt ? *bp++ : 0);
        !          1550:        newi->wt = pp;
        !          1551: 
        !          1552:        // Strip possible trailing -1's.
        !          1553:        newi->StripMinus();
        !          1554:      
        !          1555:        return (newi);
        !          1556: 
        !          1557: }
        !          1558: 
        !          1559: /* Xor:
        !          1560:  * Bit-wise xor.
        !          1561:  */
        !          1562: INT_REP *INT_REP::Xor(INT_REP *b)
        !          1563: {
        !          1564:        INT_REP *newi;
        !          1565:        INT_REP *pos, *neg;
        !          1566:        long *ap, *bp, *pp;
        !          1567:        long extval;
        !          1568:        int length;
        !          1569: 
        !          1570:        if (isZero()) {
        !          1571:                newi = new INT_REP(b);
        !          1572:                return newi;
        !          1573:        }       
        !          1574:        if (b->isZero()) {
        !          1575:                newi = new INT_REP(this);
        !          1576:                return newi;
        !          1577:        }       
        !          1578: 
        !          1579:        if(isNegative() == b->isNegative()) {                   // Same sign.
        !          1580:                length = Max(Length(), b->Length());
        !          1581:                newi = new INT_REP(length);
        !          1582: 
        !          1583:                ap = beg;
        !          1584:                bp = b->beg;
        !          1585:                pp = newi->beg;
        !          1586:                if(isNegative())
        !          1587:                        extval = -1;
        !          1588:                else
        !          1589:                        extval = 0;
        !          1590: 
        !          1591:                while (length-- > 0)
        !          1592:                        *pp++ = ((ap < wt ? *ap++ : extval) ^ (bp < b->wt ? *bp++ : extval)) & 0xFFFF;
        !          1593:                newi->wt = pp;
        !          1594: 
        !          1595:                // Remove trailing zeros.
        !          1596:                newi->StripZero();
        !          1597:        }
        !          1598:        else {                                                                                  // Different sign.
        !          1599:                // Set neg pointing to negative value, pos pointing to positive.
        !          1600:                if (isNegative()) {
        !          1601:                        neg = this;
        !          1602:                        pos = b;
        !          1603:                }
        !          1604:                else {
        !          1605:                        neg = b;
        !          1606:                        pos = this;
        !          1607:                }
        !          1608: 
        !          1609:                length = Max(pos->Length()+1, neg->Length());           
        !          1610:                newi = new INT_REP(length);
        !          1611: 
        !          1612:                ap = pos->beg;
        !          1613:                bp = neg->beg;
        !          1614:                pp = newi->beg;
        !          1615: 
        !          1616:                while (--length > 0)
        !          1617:                        *pp++ = ((ap < pos->wt ? *ap++ : 0) ^ (bp < neg->wt ? *bp++ : -1)) & 0xFFFF;
        !          1618:                *pp++ = -1;
        !          1619:                newi->wt = pp;
        !          1620: 
        !          1621:                // Remove trailing -1's.
        !          1622:                newi->StripMinus();
        !          1623:        }
        !          1624: 
        !          1625:        return (newi);
        !          1626: }
        !          1627: 
        !          1628: /* Not:
        !          1629:  * Bit-wise not.
        !          1630:  */
        !          1631: INT_REP *INT_REP::Not()
        !          1632: {
        !          1633:        int length;
        !          1634:        long *ap, *pp;
        !          1635:        INT_REP *newi;
        !          1636: 
        !          1637:        if (isZero()) {
        !          1638:                newi = new INT_REP(1);
        !          1639:                newi->Putc(-1);
        !          1640:                return (newi);
        !          1641:        }
        !          1642: 
        !          1643:        if (isNegative()) {
        !          1644:                length = Length() - 1;
        !          1645:                newi = new INT_REP(length);
        !          1646: 
        !          1647:                ap = beg;
        !          1648:                pp = newi->beg;
        !          1649:                while(length--)
        !          1650:                        *pp++ = (~(*ap++)) & 0xFFFF;
        !          1651:                newi->wt = pp;
        !          1652:        }
        !          1653:        else {
        !          1654:                length = Length();
        !          1655:                newi = new INT_REP(length+1);
        !          1656: 
        !          1657:                ap = beg;
        !          1658:                pp = newi->beg;
        !          1659:                while(length--)
        !          1660:                        *pp++ = (~(*ap++)) & 0xFFFF;
        !          1661:                *pp++ = -1;
        !          1662:                newi->wt = pp;
        !          1663:        }
        !          1664: 
        !          1665:        return (newi);
        !          1666: }
        !          1667: 
        !          1668: /* LeftShift:
        !          1669:  * Bit-wise left shift.
        !          1670:  */
        !          1671: INT_REP *INT_REP::LeftShift(INT_REP *b)
        !          1672: {
        !          1673:        long shift;
        !          1674:        INT_REP *bb, *newi;
        !          1675:        int error;
        !          1676: 
        !          1677:        shift = b->Trunc(error);
        !          1678:        if (!error)                     // Shift can be represented as a long.
        !          1679:                return(LeftShift(shift));
        !          1680: 
        !          1681:        if (isZero()) {
        !          1682:                newi = new INT_REP(this);
        !          1683:                return newi;
        !          1684:        }
        !          1685:        if (b->isNegative()) {
        !          1686:                bb = new INT_REP(b);
        !          1687:                bb->Chsign();
        !          1688:                newi = RightShift(bb);
        !          1689:                delete bb;
        !          1690:                return (newi);
        !          1691:        }
        !          1692: 
        !          1693:        bb = TwoRep.Exp(b);
        !          1694:        newi = Mult(bb);
        !          1695:        delete bb;
        !          1696:        return (newi);
        !          1697:        
        !          1698: }
        !          1699: 
        !          1700: INT_REP *INT_REP::LeftShift(long shift)
        !          1701: { 
        !          1702:        INT_REP *newi;
        !          1703:        int length;
        !          1704:        int bitshift;
        !          1705:        long val;
        !          1706:        long *ap, *pp;
        !          1707: 
        !          1708:        // Special cases.
        !          1709:        if ((shift == 0) || isZero()) {
        !          1710:                newi = new INT_REP(this);
        !          1711:                return newi;
        !          1712:        }
        !          1713:        if (shift < 0) {
        !          1714:                return (RightShift(-1*shift));
        !          1715:        }
        !          1716: 
        !          1717:        length = Length() + ((shift + 15)>>4);  // (shift + 15)/16.
        !          1718:        bitshift = shift & 0xF;                                 // shift%16.
        !          1719:        newi = new INT_REP(length);
        !          1720:        newi->wt = newi->last;
        !          1721: 
        !          1722:        // Initialize.
        !          1723:        ap = wt-1;
        !          1724:        pp = newi->last - 1;
        !          1725: 
        !          1726:        // Shift.
        !          1727:        if(bitshift) {
        !          1728:                if (isNegative())
        !          1729:                        *pp = -1;
        !          1730:                else
        !          1731:                        *pp = 0;
        !          1732: 
        !          1733:                while (ap >= beg) {
        !          1734:                        val = *(ap--) & 0xFFFF;
        !          1735:                        *pp-- |= val >> (16 - bitshift);
        !          1736:                        *pp = (val << bitshift) & 0xFFFF;
        !          1737:                }
        !          1738:        }
        !          1739:        else {
        !          1740:                while (ap >= beg)  {
        !          1741:                        *pp-- = *ap--;
        !          1742:                }
        !          1743:                pp++;
        !          1744:        }
        !          1745: 
        !          1746:        // Fill with 0's.
        !          1747:        while (pp > newi->beg)
        !          1748:                *(--pp) = 0;
        !          1749: 
        !          1750: 
        !          1751:        if (isNegative())
        !          1752:                newi->StripMinus();
        !          1753:        else
        !          1754:                newi->StripZero();
        !          1755:        
        !          1756:        return (newi);
        !          1757: }
        !          1758: 
        !          1759: /* RightShift:
        !          1760:  * Bit-wise right shift.
        !          1761:  */
        !          1762: INT_REP *INT_REP::RightShift(INT_REP *b)
        !          1763: {
        !          1764:        long shift;
        !          1765:        INT_REP *bb, *newi;
        !          1766:        int error;
        !          1767: 
        !          1768:        shift = b->Trunc(error);
        !          1769:        if (!error)                     // Shift can be represented as a long.
        !          1770:                return(RightShift(shift));
        !          1771: 
        !          1772:        if (isZero()) {
        !          1773:                newi = new INT_REP(this);
        !          1774:                return newi;
        !          1775:        }
        !          1776:        if (b->isNegative()) {
        !          1777:                bb = new INT_REP(b);
        !          1778:                bb->Chsign();
        !          1779:                newi = LeftShift(bb);
        !          1780:                delete bb;
        !          1781:                return (newi);
        !          1782:        }
        !          1783: 
        !          1784:        bb = TwoRep.Exp(b);
        !          1785:        newi = Div(bb);
        !          1786:        delete bb;
        !          1787:        return (newi);
        !          1788:        
        !          1789: }
        !          1790: 
        !          1791: INT_REP *INT_REP::RightShift(long shift)
        !          1792: {
        !          1793:        INT_REP *newi;
        !          1794:        int length;
        !          1795:        int offset, bitshift;
        !          1796:        long val;
        !          1797:        long *ap, *pp;
        !          1798: 
        !          1799:        // Special cases.
        !          1800:        if ((shift == 0) || isZero()) {
        !          1801:                newi = new INT_REP(this);
        !          1802:                return newi;
        !          1803:        }
        !          1804:        if (shift < 0) {
        !          1805:                return (LeftShift(-1*shift));
        !          1806:        }
        !          1807: 
        !          1808:        offset = shift>>4;                              // shift/16.
        !          1809:        // If offset >= Length(), shifting produces either 0 or -1.
        !          1810:        if (offset >= Length()) {
        !          1811:                if (isNegative()) {
        !          1812:                        newi = new INT_REP(1);
        !          1813:                        newi->Putc(-1);
        !          1814:                        return newi;
        !          1815:                }
        !          1816:                else {
        !          1817:                        newi = new INT_REP(0);
        !          1818:                        return newi;
        !          1819:                }
        !          1820:        }
        !          1821: 
        !          1822:        length = Length() - offset;
        !          1823:        bitshift = shift & 0xF;                 // shift%16.
        !          1824:        newi = new INT_REP(length);
        !          1825:        newi->wt = newi->last;
        !          1826: 
        !          1827:        // Initialize.
        !          1828:        ap = beg + offset;
        !          1829:        pp = newi->beg;
        !          1830: 
        !          1831:        // Shift.
        !          1832:        if (bitshift) {
        !          1833:                *pp = (*ap++ >> bitshift) & 0xFFFF;
        !          1834: 
        !          1835:                while (ap < wt) {
        !          1836:                        val = *ap++ & 0xFFFF;
        !          1837:                        *pp++ |= (val << (16 - bitshift)) & 0xFFFF;
        !          1838:                        *pp = (val >> bitshift);
        !          1839:                }
        !          1840: 
        !          1841:                if (isNegative()) {
        !          1842:                        *pp = -1;
        !          1843:                        newi->StripMinus();
        !          1844:                }
        !          1845:                else
        !          1846:                        newi->StripZero();
        !          1847:        }
        !          1848:        else {
        !          1849:                while (ap < wt) 
        !          1850:                        *pp++ = *ap++;
        !          1851:        }
        !          1852:        
        !          1853:        return (newi);
        !          1854: }
        !          1855: 
        !          1856: /* GCD:
        !          1857:  * Returns greatest common divisor.
        !          1858:  */
        !          1859: INT_REP *INT_REP::GCD(INT_REP *b)
        !          1860: {
        !          1861:        INT_REP *newi;
        !          1862:        INT_REP *t, *u, *v, *tmp;
        !          1863:        int k, l;
        !          1864: 
        !          1865:        // If this or b is 0.
        !          1866:        if (isZero()) {
        !          1867:                newi = new INT_REP (b);
        !          1868:                if (b->isNegative())
        !          1869:                        newi->Chsign();
        !          1870:                return (newi);
        !          1871:        }
        !          1872:        if (b->isZero()) {
        !          1873:                newi = new INT_REP (this);
        !          1874:                if (this->isNegative())
        !          1875:                        newi->Chsign();
        !          1876:                return (newi);
        !          1877:        }
        !          1878: 
        !          1879:        // Make this and b positive.
        !          1880:        if (isNegative()) {
        !          1881:                u = new INT_REP (this);
        !          1882:                u->Chsign();
        !          1883:        }
        !          1884:        else
        !          1885:                u = this;
        !          1886:        if (b->isNegative()) {
        !          1887:                v = new INT_REP (b);
        !          1888:                v->Chsign();
        !          1889:        }
        !          1890:        else
        !          1891:                v = b;
        !          1892: 
        !          1893:        // Compute highest power of 2 dividing both this and b;
        !          1894:        // divide out this power.
        !          1895:        k = Min (Twos(), b->Twos());
        !          1896:        tmp = u->RightShift(k);
        !          1897:        if (u != this) delete u;
        !          1898:        u = tmp;
        !          1899:        tmp = v->RightShift(k);
        !          1900:        if (v != b) delete v;
        !          1901:        v = tmp;
        !          1902: 
        !          1903:        // Initialize.
        !          1904:        if (u->isOdd()) {
        !          1905:                t = new INT_REP (v);
        !          1906:                t->Chsign();
        !          1907:        }
        !          1908:        else 
        !          1909:                t = new INT_REP (u);
        !          1910:        
        !          1911:        // Loop.
        !          1912:        while (t->isNonzero()) {
        !          1913:                
        !          1914:                // Remove powers of 2 from t.
        !          1915:                l = t->Twos();
        !          1916:                tmp = t->RightShift (l);
        !          1917:                delete t;
        !          1918:                t = tmp;
        !          1919: 
        !          1920:                if (t->isNegative()) {
        !          1921:                        delete v;
        !          1922:                        v = new INT_REP (t);
        !          1923:                        v->Chsign();
        !          1924:                }
        !          1925:                else {
        !          1926:                        delete u;
        !          1927:                        u = new INT_REP (t);
        !          1928:                }
        !          1929: 
        !          1930:                delete t;
        !          1931:                t = u->Sub(v);
        !          1932:        }
        !          1933: 
        !          1934:        // Add in power of 2 computed above.
        !          1935:        newi = u->LeftShift (k);
        !          1936: 
        !          1937:        delete u;
        !          1938:        delete v;
        !          1939: 
        !          1940:        return (newi);
        !          1941: }
        !          1942: 

unix.superglobalmegacorp.com

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