Annotation of 43BSD/ucb/lisp/franz/divbig.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *rcsid =
                      3:    "$Header: divbig.c,v 1.4 83/11/26 12:10:16 sklower Exp $";
                      4: #endif
                      5: 
                      6: /*                                     -[Sat Jan 29 12:22:36 1983 by jkf]-
                      7:  *     divbig.c                                $Locker:  $
                      8:  * bignum division
                      9:  *
                     10:  * (c) copyright 1982, Regents of the University of California
                     11:  */
                     12: 
                     13: 
                     14: #include "global.h"
                     15: 
                     16: #define b 0x40000000
                     17: #define toint(p) ((int) (p))
                     18: 
                     19: divbig(dividend, divisor, quotient, remainder)
                     20: lispval dividend, divisor, *quotient, *remainder;
                     21: {
                     22:        register *ujp, *vip;
                     23:        int *alloca(), d, negflag = 0, m, n, carry, rem, qhat, j;
                     24:        int borrow, negrem = 0;
                     25:        long *utop = sp(), *ubot, *vbot, *qbot;
                     26:        register lispval work; lispval export();
                     27:        Keepxs();
                     28: 
                     29:        /* copy dividend */
                     30:        for(work = dividend; work; work = work ->s.CDR)
                     31:                stack(work->s.I);
                     32:        ubot = sp();
                     33:        if(*ubot < 0) {         /* knuth's division alg works only for pos
                     34:                                        bignums                         */
                     35:                negflag ^= 1;
                     36:                negrem = 1;
                     37:                dsmult(utop-1,ubot,-1);
                     38:        }
                     39:        stack(0);
                     40:        ubot = sp();
                     41: 
                     42:        
                     43:        /*copy divisor */
                     44:        for(work = divisor; work; work = work->s.CDR)
                     45:                stack(work->s.I);
                     46: 
                     47:        vbot = sp();
                     48:        stack(0);
                     49:        if(*vbot < 0) {
                     50:                negflag ^= 1;
                     51:                dsmult(ubot-1,vbot,-1);
                     52:        }
                     53: 
                     54:        /* check validity of data */
                     55:        n = ubot - vbot;
                     56:        m = utop - ubot - n - 1;
                     57:        if (n == 1) {
                     58:                /* do destructive division by  a single. */
                     59:                rem = dsdiv(utop-1,ubot,*vbot);
                     60:                if(negrem)
                     61:                        rem = -rem;
                     62:                if(negflag)
                     63:                        dsmult(utop-1,ubot,-1);
                     64:                if(remainder)
                     65:                        *remainder = inewint(rem);
                     66:                if(quotient)
                     67:                        *quotient = export(utop,ubot);
                     68:                Freexs();
                     69:                return;
                     70:        }
                     71:        if (m < 0) {
                     72:                if (remainder)
                     73:                        *remainder = dividend;
                     74:                if(quotient)
                     75:                        *quotient = inewint(0);
                     76:                Freexs();
                     77:                return;
                     78:        }
                     79:        qbot = alloca(toint(utop) + toint(vbot) - 2 * toint(ubot));
                     80: d1:
                     81:        d = b /(*vbot +1);
                     82:        dsmult(utop-1,ubot,d);
                     83:        dsmult(ubot-1,vbot,d);
                     84: 
                     85: d2:    for(j=0,ujp=ubot; j <= m; j++,ujp++) {
                     86: 
                     87:        d3:     
                     88:                qhat = calqhat(ujp,vbot);
                     89:        d4:
                     90:                if((borrow = mlsb(ujp + n, ujp, ubot, -qhat)) < 0) {
                     91:                        adback(ujp + n, ujp, ubot);
                     92:                        qhat--;
                     93:                }
                     94:                qbot[j] = qhat;
                     95:        }
                     96: d8:    if(remainder) {
                     97:                dsdiv(utop-1, utop - n, d);
                     98:                if(negrem) dsmult(utop-1,utop-n,-1);
                     99:                *remainder = export(utop,utop-n);
                    100:        }
                    101:        if(quotient) {
                    102:                if(negflag)
                    103:                        dsmult(qbot+m,qbot,-1);
                    104:                *quotient = export(qbot + m + 1, qbot);
                    105:        }
                    106:        Freexs();
                    107: }
                    108: /*
                    109:  * asm code commented out due to optimizer bug
                    110:  * also, this file is now shared with the 68k version!
                    111: calqhat(ujp,v1p)
                    112: register int *ujp, *v1p;
                    113: {
                    114: asm("  cmpl    (r10),(r11)             # v[1] == u[j] ??");
                    115: asm("  beql    2f                      ");
                    116: asm("  # calculate qhat and rhat simultaneously,");
                    117: asm("  #  qhat in r0");
                    118: asm("  #  rhat in r1");
                    119: asm("  emul    (r11),$0x40000000,4(r11),r4 # u[j]b+u[j+1] into r4,r5");
                    120: asm("  ediv    (r10),r4,r0,r1          # qhat = ((u[j]b+u[j+1])/v[1]) into r0");
                    121: asm("                                  # (u[j]b+u[j+1] -qhat*v[1]) into r1");
                    122: asm("                                  # called rhat");
                    123: asm("1:");
                    124: asm("  # check if v[2]*qhat > rhat*b+u[j+2]");
                    125: asm("  emul    r0,4(r10),$0,r2         # qhat*v[2] into r3,r2");
                    126: asm("  emul    r1,$0x40000000,8(r11),r8 #rhat*b + u[j+2] into r9,r8");
                    127: asm("  # give up if r3,r2 <= r9,r8, otherwise iterate");
                    128: asm("  subl2   r8,r2                   # perform r3,r2 - r9,r8");
                    129: asm("  sbwc    r9,r3");
                    130: asm("  bleq    3f                      # give up if negative or equal");
                    131: asm("  decl    r0                      # otherwise, qhat = qhat - 1");
                    132: asm("  addl2   (r10),r1                # since dec'ed qhat, inc rhat by v[1]");
                    133: asm("  jbr     1b");
                    134: asm("2:        ");
                    135: asm("  # get here if v[1]==u[j]");
                    136: asm("  # set qhat to b-1");
                    137: asm("  # rhat is easily calculated since if we substitute b-1 for qhat in");
                    138: asm("  # the formula, then it simplifies to (u[j+1] + v[1])");
                    139: asm("  # ");
                    140: asm("  addl3   4(r11),(r10),r1         # rhat = u[j+1] + v[1]");
                    141: asm("  movl    $0x3fffffff,r0          # qhat = b-1");
                    142: asm("  jbr     1b");
                    143: asm("3:");
                    144: }
                    145: mlsb(utop,ubot,vtop,nqhat)
                    146: register int *utop, *ubot, *vtop;
                    147: register int nqhat;
                    148: {
                    149: asm("  clrl    r0");
                    150: asm("loop2:    addl2   (r11),r0");
                    151: asm("  emul    r8,-(r9),r0,r2");
                    152: asm("  extzv   $0,$30,r2,(r11)");
                    153: asm("  extv    $30,$32,r2,r0");
                    154: asm("  acbl    r10,$-4,r11,loop2");
                    155: }
                    156: adback(utop,ubot,vtop)
                    157: register int *utop, *ubot, *vtop;
                    158: {
                    159: asm("  clrl    r0");
                    160: asm("loop3:    addl2   -(r9),r0");
                    161: asm("  addl2   (r11),r0");
                    162: asm("  extzv   $0,$30,r0,(r11)");
                    163: asm("  extv    $30,$2,r0,r0");
                    164: asm("  acbl    r10,$-4,r11,loop3");
                    165: }
                    166: dsdiv(top,bot,div)
                    167: register int* bot;
                    168: {
                    169: asm("  clrl    r0");
                    170: asm("loop4:    emul    r0,$0x40000000,(r11),r1");
                    171: asm("  ediv    12(ap),r1,(r11),r0");
                    172: asm("  acbl    4(ap),$4,r11,loop4");
                    173: }
                    174: dsmult(top,bot,mult)
                    175: register int* top;
                    176: {
                    177: asm("  clrl    r0");
                    178: asm("loop5:    emul    12(ap),(r11),r0,r1");
                    179: asm("  extzv   $0,$30,r1,(r11)");
                    180: asm("  extv    $30,$32,r1,r0");
                    181: asm("  acbl    8(ap),$-4,r11,loop5");
                    182: asm("  movl    r1,4(r11)");
                    183: }
                    184: */
                    185: lispval
                    186: export(top,bot)
                    187: register long *top, *bot;
                    188: {
                    189:        register lispval p;
                    190:        lispval result;
                    191: 
                    192:        top--; /* screwey convention matches original
                    193:                  vax assembler convenience */
                    194:        while(bot < top)
                    195:        {
                    196:                if(*bot==0)
                    197:                        bot++;
                    198:                else if(*bot==-1)
                    199:                        *++bot |= 0xc0000000;
                    200:                else break;
                    201:        }
                    202:        if(bot==top) return(inewint(*bot));
                    203:        result = p = newsdot();
                    204:        protect(p);
                    205:        p->s.I = *top--;
                    206:        while(top >= bot) {
                    207:                p = p->s.CDR = newdot();
                    208:                p->s.I = *top--;
                    209:        }
                    210:        p->s.CDR = 0;
                    211:        np--;
                    212:        return(result);
                    213: }
                    214: 
                    215: #define MAXINT 0x80000000L
                    216: 
                    217: Ihau(fix)
                    218: register int fix;
                    219: {
                    220:        register count;
                    221:        if(fix==MAXINT)
                    222:                return(32);
                    223:        if(fix < 0)
                    224:                fix = -fix;
                    225:        for(count = 0; fix; count++)
                    226:                fix /= 2;
                    227:        return(count);
                    228: }
                    229: lispval
                    230: Lhau()
                    231: {
                    232:        register count;
                    233:        register lispval handy;
                    234:        register dum1,dum2;
                    235:        lispval Labsval();
                    236: 
                    237:        handy = lbot->val;
                    238: top:
                    239:        switch(TYPE(handy)) {
                    240:        case INT:
                    241:                count = Ihau(handy->i);
                    242:                break;
                    243:        case SDOT:
                    244:                handy = Labsval();
                    245:                for(count = 0; handy->s.CDR!=((lispval) 0); handy = handy->s.CDR)
                    246:                        count += 30;
                    247:                count += Ihau(handy->s.I);
                    248:                break;
                    249:        default:
                    250:                handy = errorh1(Vermisc,"Haulong: bad argument",nil,
                    251:                               TRUE,997,handy);
                    252:                goto top;
                    253:        }
                    254:        return(inewint(count));
                    255: }
                    256: lispval
                    257: Lhaipar()
                    258: {
                    259:        register lispval work;
                    260:        register n;
                    261:        register int *top = sp() - 1;
                    262:        register int *bot;
                    263:        int mylen;
                    264: 
                    265:        /*chkarg(2);*/
                    266:        work = lbot->val;
                    267:                                        /* copy data onto stack */
                    268: on1:
                    269:        switch(TYPE(work)) {
                    270:        case INT:
                    271:                stack(work->i);
                    272:                break;
                    273:        case SDOT:
                    274:                for(; work!=((lispval) 0); work = work->s.CDR)
                    275:                        stack(work->s.I);
                    276:                break;
                    277:        default:
                    278:                work = errorh1(Vermisc,"Haipart: bad first argument",nil,
                    279:                                TRUE,996,work);
                    280:                goto on1;
                    281:        }
                    282:        bot = sp();
                    283:        if(*bot < 0) {
                    284:                stack(0);
                    285:                dsmult(top,bot,-1);
                    286:                bot--;
                    287:        }
                    288:        for(; *bot==0 && bot < top; bot++);
                    289:                                /* recalculate haulong internally */
                    290:        mylen = (top - bot) * 30 + Ihau(*bot);
                    291:                                /* get second argument            */
                    292:        work = lbot[1].val;
                    293:        while(TYPE(work)!=INT)
                    294:                work = errorh1(Vermisc,"Haipart: 2nd arg not int",nil,
                    295:                                TRUE,995,work);
                    296:        n = work->i;
                    297:        if(n >= mylen || -n >= mylen)
                    298:                goto done;
                    299:        if(n==0) return(inewint(0));
                    300:        if(n > 0) {
                    301:                                /* Here we want n most significant bits
                    302:                                   so chop off mylen - n bits */
                    303:                stack(0);
                    304:                n = mylen - n;
                    305:                for(n; n >= 30; n -= 30)
                    306:                        top--;
                    307:                if(top < bot)
                    308:                        error("Internal error in haipart #1",FALSE);
                    309:                dsdiv(top,bot,1<<n);
                    310: 
                    311:        } else {
                    312:                                /* here we want abs(n) low order bits */
                    313:                stack(0);
                    314:                bot = top + 1;
                    315:                for(; n <= 0; n += 30)
                    316:                        bot--;
                    317:                n = 30 - n;
                    318:                *bot &= ~ (-1<<n);
                    319:        }
                    320: done:
                    321:        return(export(top + 1,bot));
                    322: }
                    323: #define STICKY 1
                    324: #define TOEVEN 2
                    325: lispval
                    326: Ibiglsh(bignum,count,mode)
                    327: lispval bignum, count;
                    328: {
                    329:        register lispval work;
                    330:        register n;
                    331:        register int *top = sp() - 1;
                    332:        register int *bot;
                    333:        int mylen, guard = 0, sticky = 0, round = 0;
                    334:        lispval export();
                    335: 
                    336:                                /* get second argument            */
                    337:        work = count;
                    338:        while(TYPE(work)!=INT)
                    339:                work = errorh1(Vermisc,"Bignum-shift: 2nd arg not int",nil,
                    340:                                TRUE,995,work);
                    341:        n = work->i;
                    342:        if(n==0) return(bignum);
                    343:        for(; n >= 30; n -= 30) {/* Here we want to multiply by 2^n
                    344:                                   so start by copying n/30 zeroes
                    345:                                   onto stack */
                    346:                stack(0);
                    347:        }
                    348: 
                    349:        work = bignum;          /* copy data onto stack */
                    350: on1:
                    351:        switch(TYPE(work)) {
                    352:        case INT:
                    353:                stack(work->i);
                    354:                break;
                    355:        case SDOT:
                    356:                for(; work!=((lispval) 0); work = work->s.CDR)
                    357:                        stack(work->s.I);
                    358:                break;
                    359:        default:
                    360:                work = errorh1(Vermisc,"Bignum-shift: bad bignum argument",nil,
                    361:                                TRUE,996,work);
                    362:                goto on1;
                    363:        }
                    364:        bot = sp();
                    365:        if(n >= 0) {
                    366:                stack(0);
                    367:                bot--;
                    368:                dsmult(top,bot,1<<n);
                    369:        } else {
                    370:                        /* Trimming will only work without leading
                    371:                           zeroes without my having to think
                    372:                           a lot harder about it, if the inputs
                    373:                           are canonical */
                    374:                for(n = -n; n > 30; n -= 30) {
                    375:                        if(guard) sticky |= 1;
                    376:                        guard = round;
                    377:                        if(top > bot) {
                    378:                                round = *top;
                    379:                                top --;
                    380:                        } else  {
                    381:                                round = *top;
                    382:                                *top >>= 30;
                    383:                        }
                    384:                }
                    385:                if(n > 0) {
                    386:                        if(guard) sticky |= 1;
                    387:                        guard = round;
                    388:                        round = dsrsh(top,bot,-n,-1<<n);
                    389:                }
                    390:                stack(0); /*so that dsadd1 will work;*/
                    391:                if (mode==STICKY) {
                    392:                        if(((*top&1)==0) && (round | guard | sticky))
                    393:                                dsadd1(top,bot);
                    394:                } else if (mode==TOEVEN) {
                    395:                        int mask;
                    396: 
                    397:                        if(n==0) n = 30;
                    398:                        mask = (1<<(n-1));
                    399:                        if(! (round & mask) ) goto chop;
                    400:                        mask -= 1;
                    401:                        if(  ((round&mask)==0)
                    402:                          && guard==0
                    403:                          && sticky==0
                    404:                          && (*top&1)==0 ) goto chop;
                    405:                        dsadd1(top,bot);
                    406:                }
                    407:                chop:;
                    408:        }
                    409:        work = export(top + 1,bot);
                    410:        return(work);
                    411: }
                    412: 
                    413: /*From drb  Mon Jul 27 01:25:56 1981
                    414: To: sklower
                    415: 
                    416: The idea is that the answer/2
                    417: is equal to the exact answer/2 rounded towards - infinity.  The final bit
                    418: of the answer is the "or" of the true final bit, together with all true
                    419: bits after the binary point.  In other words, the 1's bit of the answer
                    420: is almost always 1.  THE FINAL BIT OF THE ANSWER IS 0 IFF n*2^i = THE
                    421: ANSWER RETURNED EXACTLY, WITH A 0 FINAL BIT.
                    422: 
                    423: 
                    424: To try again, more succintly:  the answer is correct to within 1, and
                    425: the 1's bit of the answer will be 0 only if the answer is exactly
                    426: correct. */
                    427: 
                    428: lispval
                    429: Lsbiglsh()
                    430: {
                    431:        register struct argent *mylbot = lbot;
                    432:        chkarg(2,"sticky-bignum-leftshift");
                    433:        return(Ibiglsh(lbot->val,lbot[1].val,STICKY));
                    434: }
                    435: lispval
                    436: Lbiglsh()
                    437: {
                    438:        register struct argent *mylbot = lbot;
                    439:        chkarg(2,"bignum-leftshift");
                    440:        return(Ibiglsh(lbot->val,lbot[1].val,TOEVEN));
                    441: }
                    442: lispval
                    443: HackHex() /* this is a one minute function so drb and kls can debug biglsh */
                    444: /* (HackHex i) returns a string which is the result of printing i in hex */
                    445: {
                    446:        register struct argent *mylbot = lbot;
                    447:        char buf[32];
                    448:        sprintf(buf,"%lx",lbot->val->i);
                    449:        return((lispval)inewstr(buf));
                    450: }

unix.superglobalmegacorp.com

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