Annotation of 42BSD/ucb/lisp/franz/lam4.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *rcsid =
        !             3:    "$Header: lam4.c 1.4 83/06/30 16:25:53 sklower Exp $";
        !             4: #endif
        !             5: 
        !             6: /*                                     -[Sun Jun 19 22:25:48 1983 by jkf]-
        !             7:  *     lam4.c                          $Locker:  $
        !             8:  * lambda functions
        !             9:  *
        !            10:  * (c) copyright 1982, Regents of the University of California
        !            11:  */
        !            12: 
        !            13: 
        !            14: #include "global.h"
        !            15: lispval adbig(),subbig(),mulbig();
        !            16: double Ifloat();
        !            17: lispval
        !            18: Ladd()
        !            19: {
        !            20:        register lispval work;
        !            21:        register struct argent *result, *mynp, *oldnp;
        !            22:        long restype,prunep,hi,lo=0;
        !            23:        struct sdot dummybig;
        !            24:        double flacc;
        !            25:        Savestack(4);
        !            26: 
        !            27:        oldnp = result = np;
        !            28:        restype = INT;                  /* now start as integers */
        !            29:        protect(nil);
        !            30: 
        !            31:        for(mynp = lbot; mynp < oldnp; mynp++)
        !            32:        {
        !            33:            work = mynp->val;
        !            34:            switch(TYPE(work)) {
        !            35:            case INT:
        !            36:                switch(restype) {
        !            37:                case SDOT:
        !            38:                    dmlad(result->val,1L,work->i);
        !            39:                    prunep = TRUE;
        !            40:                    /* In adding the fixnum to the sdot we may make it
        !            41:                    possible for the bignum to be represented as a fixnum */
        !            42:                    break;
        !            43:                case INT:
        !            44:                    if(exarith(lo,1L,work->i,&hi,&lo)) {
        !            45:                        work = result->val = newsdot();
        !            46:                        work->s.I = lo;
        !            47:                        work = work->s.CDR = newdot();
        !            48:                        work->s.I = hi;
        !            49:                        work->s.CDR = 0;
        !            50:                        restype = SDOT; prunep = FALSE;
        !            51:                    } 
        !            52:                    break;
        !            53:                case DOUB:
        !            54:                    result->val->r += work->i;
        !            55:                    break;
        !            56:                default: goto urk;
        !            57:                }
        !            58:                break;
        !            59:            case SDOT:
        !            60:                switch(restype) {
        !            61:                case INT:
        !            62:                    dummybig.I = lo;
        !            63:                    dummybig.CDR = 0;
        !            64:                    work=adbig(work,(lispval)&dummybig);
        !            65:                    goto code1;
        !            66:                case SDOT:
        !            67:                    work=adbig(work,result->val);
        !            68:                    /* previous result is no longer needed */
        !            69:                    pruneb(result->val);
        !            70:                code1:
        !            71:                    restype = TYPE(work); /* SDOT or INT */
        !            72:                    if(restype==INT) {
        !            73:                        lo = work->i;
        !            74:                        prunei(work);
        !            75:                    } else {
        !            76:                        prunep = FALSE; /* sdot is cannonical */
        !            77:                        result->val = work;
        !            78:                    } break;
        !            79:                case DOUB:
        !            80:                    result->val->r += Ifloat(work);
        !            81:                    break;
        !            82:                default: goto urk;
        !            83:                }
        !            84:                break;
        !            85:            case DOUB:
        !            86:                switch(restype) {
        !            87:                case SDOT:
        !            88:                    if(prunep) {
        !            89:                        lispval handy;
        !            90:                        dummybig.I = 0;
        !            91:                        dummybig.CDR = (lispval) 0;
        !            92:                        handy = adbig((lispval)&dummybig,result->val);
        !            93:                        pruneb(result->val);
        !            94:                        result->val = handy;
        !            95:                    }
        !            96:                    flacc = Ifloat(result->val) + work->r;
        !            97:                    pruneb(result->val);
        !            98:                scrimp:
        !            99:                    (result->val = newdoub())->r = flacc;
        !           100:                    restype = DOUB;
        !           101:                    break;
        !           102:                case INT:
        !           103:                    flacc = work->r + lo;
        !           104:                    goto scrimp;
        !           105:                case DOUB:
        !           106:                    result->val->r += work->r;
        !           107:                    break;
        !           108:                default: goto urk;
        !           109:                }
        !           110:                break;
        !           111:            default:
        !           112:                    errorh1(Vermisc,"Non-number to add",nil,0,FALSE,work);
        !           113:            }
        !           114:        }
        !           115:        work = result->val;
        !           116:        switch(restype){
        !           117:        case DOUB:
        !           118:                break;
        !           119:        case INT:
        !           120:                work=inewint(lo);
        !           121:                break;
        !           122:        case SDOT:
        !           123:                if(prunep) {
        !           124:                    /* wouldn't (copy result->val) be faster ? -dhl */
        !           125:                    /* It might, but isn't guaranteed to canonicalize */
        !           126: 
        !           127:                    dummybig.I = 0;
        !           128:                    dummybig.CDR = (lispval) 0;
        !           129:                    work = adbig((lispval)&dummybig,work);
        !           130:                }
        !           131:                break;
        !           132:        default:
        !           133:        urk:
        !           134:                error("Internal error in add ",FALSE);
        !           135:        }
        !           136:        Restorestack();
        !           137:        return(work);
        !           138: }
        !           139: 
        !           140: /* exarith(a,b,c,lo,hi)
        !           141:  * int a,b,c;
        !           142:  * int *lo, *hi;
        !           143:  * Exact arithmetic.
        !           144:  * a,b and c are 32 bit 2's complement integers
        !           145:  * calculates x=a*b+c to twice the precision of an int.
        !           146:  * In the vax version, the 30 low bits only are returned
        !           147:  * in *lo,and the next 32 bits of precision are returned in * hi.
        !           148:  * this works since exarith is used either for calculating the sum of
        !           149:  * two 32 bit numbers, (which is at most 33 bits), or
        !           150:  * multiplying a 30 bit number by a 32 bit numbers,
        !           151:  * which has a maximum precision of 62 bits.
        !           152:  * If *phi is 0 or -1 then
        !           153:  * x doesn't need any more than 31 bits plus sign to describe, so we
        !           154:  * place the sign in the high two bits of *plo and return 0 from this
        !           155:  * routine.  A non zero return indicates that x requires more than 31 bits
        !           156:  * to describe.
        !           157:  *
        !           158:  * The definition has been moved to vax.c.
        !           159:  */
        !           160: 
        !           161: 
        !           162: lispval
        !           163: Lsub()
        !           164: {
        !           165:        register lispval work;
        !           166:        register struct argent *result, *mynp, *oldnp;
        !           167:        long prunep,restype,hi,lo=0;
        !           168:        struct sdot dummybig;
        !           169:        double flacc;
        !           170:        lispval Lminus();
        !           171:        Savestack(4);
        !           172: 
        !           173:        oldnp = result = np;
        !           174:        mynp = lbot + 1;
        !           175:        restype = INT;
        !           176:        prunep = TRUE;
        !           177:        if(oldnp==lbot)
        !           178:                goto out;
        !           179:        if(oldnp==mynp) {
        !           180:                work = Lminus();
        !           181:                Restorestack();
        !           182:                return(work);
        !           183:        }
        !           184:        protect(nil);
        !           185:        work = lbot->val;
        !           186: 
        !           187:        /* examine the first argument and perhaps set restype to the 
        !           188:         * correct type.  If restype (result type) is INT, then the
        !           189:         * fixnum value is stored in lo.  Otherwise, if restype is 
        !           190:         * SDOT or DOUB, then the value is stored in result->val.
        !           191:         */
        !           192:        switch(TYPE(work)) {
        !           193:        case INT:
        !           194:                lo = work->i;
        !           195:                restype = INT;
        !           196:                break;
        !           197:        case SDOT:
        !           198:                /* we want to copy the sdot we are given as an argument since
        !           199:                 * the bignum arithmetic routine dmlad clobbers the values it
        !           200:                 * is given.
        !           201:                 */
        !           202:                dummybig.I = 0;         /* create a zero sdot */
        !           203:                dummybig.CDR = 0;
        !           204:                work = adbig(work,(lispval)&dummybig);
        !           205:                /* the resulting value may have been reduced from an
        !           206:                 * sdot to a fixnum.  This should never happen though
        !           207:                 * but if it does, we simplify things.
        !           208:                 */
        !           209:                restype = TYPE(work);
        !           210:                if(restype==INT) {
        !           211:                    lo = work->i;       /* has turned into an fixnum */
        !           212:                    prunei(work);       /* return fixnum cell        */
        !           213:                } else {
        !           214:                    prunep = FALSE;     /* sdot is cannonical */
        !           215:                    result->val = work;
        !           216:                } 
        !           217:                break;
        !           218: 
        !           219:        case DOUB:
        !           220:                (result->val = newdoub())->r = work->r;
        !           221:                restype = DOUB;
        !           222:        }
        !           223: 
        !           224:        /* now loop through the rest of the arguments subtracting them
        !           225:         * from the running result in result or lo
        !           226:         */
        !           227:        for(; mynp < oldnp; mynp++)
        !           228:        {
        !           229:                work = mynp->val;
        !           230:                switch(TYPE(work)) {
        !           231:                case INT:
        !           232:                        switch(restype) {
        !           233:                        case SDOT:
        !           234:                                /* subtracting a fixnum from an bignum
        !           235:                                 * use the distructive multiply (by 1)
        !           236:                                 * and add the negative of the work value.
        !           237:                                 * The result will still be pointed to
        !           238:                                 * by result->val
        !           239:                                 */
        !           240:                                dmlad(result->val,1L, -work->i);
        !           241:                                prunep = TRUE;  /* check up on exiting */
        !           242:                                break;          /* that it didn't collapse */
        !           243:                        case INT:
        !           244:                                /* subtracting a fixnum from a fixnum,
        !           245:                                 * the result could turn into a bignum
        !           246:                                 */
        !           247:                                if(exarith(lo,1L,-work->i,&hi,&lo)) {
        !           248:                                    work = result->val = newsdot();
        !           249:                                    work->s.I = lo;
        !           250:                                    work = work->s.CDR = newdot();
        !           251:                                    work->s.I = hi;
        !           252:                                    work->s.CDR = 0;
        !           253:                                    restype = SDOT; prunep = TRUE;
        !           254:                                }
        !           255:                                break;
        !           256:                        case DOUB:
        !           257:                                /* subtracting a fixnum from a flonum */
        !           258:                                result->val->r -= work->i;
        !           259:                                break;
        !           260:                        default:
        !           261:                                goto urk;
        !           262:                        }
        !           263:                        break;
        !           264:                case SDOT:
        !           265:                        switch(restype) {
        !           266:                        case INT:
        !           267:                            /* subtracting a bignum from an integer
        !           268:                             * first make a bignum of the integer and
        !           269:                             * then fall into the next case
        !           270:                             */
        !           271:                            dummybig.I = lo;
        !           272:                            dummybig.CDR = (lispval) 0;
        !           273:                            work = subbig((lispval)&dummybig,work);
        !           274:                            goto on1;
        !           275: 
        !           276:                        case SDOT:
        !           277:                            /* subtracting one bignum from another.  The
        !           278:                             * routine to do this ends up calling addbig
        !           279:                             * and should probably be written specifically
        !           280:                             * for subtraction.
        !           281:                             */
        !           282:                             work = subbig(result->val,work);
        !           283:                             pruneb(result->val);
        !           284:                        on1:
        !           285:                             /* check if the result has turned into a fixnum */
        !           286:                             restype = TYPE(work);
        !           287:                             if(restype==INT) {
        !           288:                                lo = work->i;           /* it has */
        !           289:                                prunei(work);
        !           290:                             } else {
        !           291:                                prunep = FALSE;         /* sdot is cannonical */
        !           292:                                result->val = work;
        !           293:                             } 
        !           294:                             break;
        !           295:                        case DOUB: /* Subtract bignum from float */
        !           296:                                   /* Death on overflow          */
        !           297:                            result->val->r -= Ifloat(work);
        !           298:                            break;
        !           299:                        default:
        !           300:                                goto urk;
        !           301:                        }
        !           302:                        break;
        !           303: 
        !           304:                case DOUB:
        !           305:                        switch(restype) {
        !           306:                        case SDOT:  /* subtracting a flonum from a bignum. */
        !           307: 
        !           308:                            if(prunep) {
        !           309:                                lispval handy;
        !           310:                                dummybig.I = 0;
        !           311:                                dummybig.CDR = (lispval) 0;
        !           312:                                handy = adbig((lispval)&dummybig,result->val);
        !           313:                                pruneb(result->val);
        !           314:                                result->val = handy;
        !           315:                            }
        !           316:                            flacc = Ifloat(result->val) - work->r;
        !           317:                            pruneb(result->val);
        !           318:                scrimp:     (result->val = newdoub())->r = flacc;
        !           319:                            restype = DOUB;
        !           320:                            break;
        !           321:                        case INT:
        !           322:                                /* subtracting a flonum from an fixnum. 
        !           323:                                 * The result will be an flonum.
        !           324:                                 */
        !           325:                                flacc = lo - work->r;
        !           326:                                goto scrimp;
        !           327:                        case DOUB:
        !           328:                                /* subtracting a flonum from a flonum, what
        !           329:                                 * could be easier?
        !           330:                                 */
        !           331:                                result->val->r -= work->r;
        !           332:                                break;
        !           333:                        default:
        !           334:                                goto urk;
        !           335:                        }
        !           336:                        break;
        !           337:                default:
        !           338:                        errorh1(Vermisc,"Non-number to minus",nil,FALSE,0,work);
        !           339:                }
        !           340:        }
        !           341: out:
        !           342:        work = result->val;
        !           343:        switch(restype){
        !           344:        case DOUB:
        !           345:                break;
        !           346:        case INT:
        !           347:                work = inewint(lo);
        !           348:                break;
        !           349:        case SDOT:
        !           350:                if(prunep) {
        !           351:                    dummybig.I = 0;
        !           352:                    dummybig.CDR = (lispval) 0;
        !           353:                    work = adbig((lispval)&dummybig,work);
        !           354:                }
        !           355:                break;
        !           356:        default:
        !           357:        urk:
        !           358:                error("Internal error in difference",FALSE);
        !           359:        }
        !           360:        Restorestack();
        !           361:        return(work);
        !           362: }
        !           363: 
        !           364: lispval
        !           365: Ltimes()
        !           366: {
        !           367:        register lispval work;
        !           368:        register struct argent *result, *mynp, *oldnp;
        !           369:        long restype,prunep,hi,lo=1;
        !           370:        struct sdot dummybig;
        !           371:        double flacc;
        !           372:        Savestack(4);
        !           373: 
        !           374:        oldnp = result = np;
        !           375:        restype = INT;                  /* now start as integers */
        !           376:        prunep = TRUE;
        !           377:        protect(nil);
        !           378: 
        !           379:        for(mynp = lbot; mynp < oldnp; mynp++)
        !           380:        {
        !           381:            work = mynp->val;
        !           382:            switch(TYPE(work)) {
        !           383:            case INT:
        !           384:                switch(restype) {
        !           385:                case SDOT:
        !           386:                    dmlad(result->val,work->i,0L);
        !           387:                    prunep = TRUE;
        !           388:                    /* In adding the fixnum to the sdot we may make it
        !           389:                    possible for the bignum to be represented as a fixnum */
        !           390:                    break;
        !           391:                case INT:
        !           392:                    if(exarith(lo,work->i,0L,&hi,&lo)) {
        !           393:                        work = result->val = newsdot();
        !           394:                        work->s.I = lo;
        !           395:                        work = work->s.CDR = newdot();
        !           396:                        work->s.I = hi;
        !           397:                        work->s.CDR = 0;
        !           398:                        restype = SDOT; prunep = TRUE;
        !           399:                    } 
        !           400:                    break;
        !           401:                case DOUB:
        !           402:                    result->val->r *= work->i;
        !           403:                    break;
        !           404:                default: goto urk;
        !           405:                }
        !           406:                break;
        !           407:            case SDOT:
        !           408:                switch(restype) {
        !           409:                case INT:
        !           410:                    dummybig.I = lo;
        !           411:                    dummybig.CDR = 0;
        !           412:                    work=mulbig(work,(lispval)&dummybig);
        !           413:                    goto code1;
        !           414:                case SDOT:
        !           415:                    work=mulbig(work,result->val);
        !           416:                    /* previous result is no longer needed */
        !           417:                    pruneb(result->val);
        !           418:                code1:
        !           419:                    restype = TYPE(work); /* SDOT or INT */
        !           420:                    if(restype==INT) {
        !           421:                        lo = work->i;
        !           422:                        prunei(work);
        !           423:                    } else {
        !           424:                        prunep = FALSE; /* sdot is cannonical */
        !           425:                        result->val = work;
        !           426:                    } break;
        !           427:                case DOUB:
        !           428:                    result->val->r *= Ifloat(work);
        !           429:                    break;
        !           430:                default: goto urk;
        !           431:                }
        !           432:                break;
        !           433:            case DOUB:
        !           434:                switch(restype) {
        !           435:                case SDOT:
        !           436:                    if(prunep) {
        !           437:                        lispval handy;
        !           438:                        dummybig.I = 0;
        !           439:                        dummybig.CDR = (lispval) 0;
        !           440:                        handy = adbig((lispval)&dummybig,result->val);
        !           441:                        pruneb(result->val);
        !           442:                        result->val = handy;
        !           443:                    }
        !           444:                    flacc = Ifloat(result->val) * work->r;
        !           445:                    pruneb(result->val);
        !           446:        scrimp:     (result->val = newdoub())->r = flacc;
        !           447:                    restype = DOUB;
        !           448:                    break;
        !           449:                case INT:
        !           450:                    flacc = work->r * lo;
        !           451:                    goto scrimp;
        !           452:                case DOUB:
        !           453:                    result->val->r *= work->r;
        !           454:                    break;
        !           455:                default: goto urk;
        !           456:                }
        !           457:                break;
        !           458:            default:
        !           459:                    errorh1(Vermisc,"Non-number to add",nil,0,FALSE,work);
        !           460:            }
        !           461:        }
        !           462:        work = result->val;
        !           463:        switch(restype){
        !           464:        case DOUB:
        !           465:                break;
        !           466:        case INT:
        !           467:                work = inewint(lo);
        !           468:                break;
        !           469:        case SDOT:
        !           470:                if(prunep) {
        !           471:                    dummybig.I = 0;
        !           472:                    dummybig.CDR = (lispval) 0;
        !           473:                    work = adbig((lispval)&dummybig,work);
        !           474:                }
        !           475:                break;
        !           476:        default:
        !           477:        urk:
        !           478:                error("Internal error in times",FALSE);
        !           479:        }
        !           480:        Restorestack();
        !           481:        return(work);
        !           482: }
        !           483: 
        !           484: lispval
        !           485: Lquo()
        !           486: {
        !           487:        register lispval work;
        !           488:        register struct argent *result, *mynp, *oldnp;
        !           489:        int restype; lispval quotient; double flacc;
        !           490:        struct sdot dummybig;
        !           491:        Savestack(4);
        !           492: 
        !           493:        oldnp = result = np;
        !           494:        protect(nil);
        !           495:        mynp = lbot + 1;
        !           496:        restype = INT;
        !           497:        dummybig.I = 1; dummybig.CDR = (lispval) 0;
        !           498: 
        !           499:        if(oldnp==lbot) goto out;
        !           500:        if(oldnp==mynp) mynp = lbot;
        !           501:        else {
        !           502:            /* examine the first argument and perhaps set restype to the 
        !           503:             * correct type.  If restype (result type) is INT, then the
        !           504:             * fixnum value is stored in lo.  Otherwise, if restype is 
        !           505:             * SDOT or DOUB, then the value is stored in result->val.
        !           506:             */
        !           507:            work = lbot->val;
        !           508:            switch(TYPE(work)) {
        !           509:            case INT:
        !           510:                dummybig.I = work->i;
        !           511:                break;
        !           512:            case SDOT:
        !           513:                /* we want to copy the sdot we are given as an argument since
        !           514:                 * the bignum divide routine divbig expects an argument in
        !           515:                 * canonical form.
        !           516:                 */
        !           517:                dummybig.I = 0;         /* create a zero sdot */
        !           518:                work = adbig(work,(lispval)&dummybig);
        !           519:                restype = TYPE(work);
        !           520:                if(restype==INT) {      /* Either INT or SDOT */
        !           521:                    dummybig.I=work->i; /* has turned into an fixnum */
        !           522:                    prunei(work);       /* return fixnum cell        */
        !           523:                } else {
        !           524:                    result->val = work;
        !           525:                } 
        !           526:                break;
        !           527:            case DOUB:
        !           528:                (result->val = newdoub())->r = work->r;
        !           529:                restype = DOUB;
        !           530:                break;
        !           531:            default:
        !           532:                errorh1(Vermisc,"Internal quotient error #1: ",nil,FALSE,0,
        !           533:                                         work);
        !           534:                goto urk;
        !           535:            }
        !           536:        }
        !           537: 
        !           538:        /* now loop through the rest of the arguments dividing them
        !           539:         * into the running result in result or dummybig.I
        !           540:         */
        !           541:        for(; mynp < oldnp; mynp++)
        !           542:        {
        !           543:            work = mynp->val;
        !           544:            switch(TYPE(work)) {
        !           545:            case INT:
        !           546:                if (work->i==0)
        !           547:                    kill(getpid(),8);
        !           548:                switch(restype) {
        !           549:                case SDOT:      /* there is no fast routine to destructively
        !           550:                                   divide a bignum by an int, so do it the
        !           551:                                   hard way. */
        !           552:                    dummybig.I = work->i;
        !           553:                    divbig(result->val,(lispval)&dummybig,&quotient,(lispval *)0);
        !           554:                    pruneb(result->val);
        !           555:                on1:
        !           556:                    /* check if the result has turned into a fixnum */
        !           557:                    restype = TYPE(quotient);
        !           558:                    if(restype==INT) {          /* Either INT or SDOT */
        !           559:                        dummybig.I=quotient->i; /* has turned into an fixnum */
        !           560:                        prunei(quotient);       /* return fixnum cell        */
        !           561:                    } else
        !           562:                        result->val = quotient;
        !           563:                    break;
        !           564:                case INT:       /* divide int by int */
        !           565:                    dummybig.I /= work->i;
        !           566:                    break;
        !           567:                case DOUB:
        !           568:                    result->val->r /= work->i;
        !           569:                    break;
        !           570:                default:
        !           571:                    errorh1(Vermisc,"Internal quotient error #2: ",nil,FALSE,0,
        !           572:                                         result->val);
        !           573:                    goto urk;
        !           574:                }
        !           575:                break;
        !           576:            case SDOT:
        !           577:                switch(restype) {
        !           578:                case INT:
        !           579:                    /* Although it seems that dividing an int
        !           580:                     * by a bignum can only lead to zero, it is
        !           581:                     * concievable that the bignum is improperly boxed,
        !           582:                     * i.e. actually an int.
        !           583:                     */
        !           584:                    divbig((lispval)&dummybig,work,&quotient,(lispval *)0);
        !           585:                    goto on1;
        !           586: 
        !           587:                case SDOT:
        !           588:                    /* dividing one bignum by another. */
        !           589:                    divbig(result->val,work,&quotient,(lispval *)0);
        !           590:                    pruneb(result->val);
        !           591:                    goto on1;
        !           592:                case DOUB:
        !           593:                    /* dividing a bignum into a flonum.
        !           594:                     */
        !           595:                    result->val->r /= Ifloat(work);
        !           596:                    break;
        !           597:                default:
        !           598:                    errorh1(Vermisc,"Internal quotient error #3: ",nil,FALSE,0,
        !           599:                                         result->val);
        !           600:                    goto urk;
        !           601:                }
        !           602:                break;
        !           603: 
        !           604:            case DOUB:
        !           605:                switch(restype) {
        !           606:                case SDOT: /* Divide bignum by flonum converting to flonum
        !           607:                            * May die due to overflow */
        !           608:                    flacc = Ifloat(result->val) / work->r;
        !           609:                    pruneb(result->val);
        !           610:                scrimp:
        !           611:                    (result->val = newdoub())->r = flacc;
        !           612:                    restype = DOUB;
        !           613:                    break;
        !           614:                case INT: /* dividing a flonum into a fixnum. 
        !           615:                           * The result will be a flonum. */
        !           616: 
        !           617:                    flacc = ((double) dummybig.I) / work->r;
        !           618:                    goto scrimp;
        !           619:                case DOUB: /* dividing a flonum into a flonum, what
        !           620:                            * could be easier?
        !           621:                            */
        !           622:                    result->val->r /= work->r;
        !           623:                    break;
        !           624:                default:
        !           625:                        errorh1(Vermisc,"Internal quotient error #4: ",nil,
        !           626:                                                 FALSE,0, result->val);
        !           627:                        goto urk;
        !           628:                }
        !           629:                    break;
        !           630:            default:
        !           631:                    errorh1(Vermisc,"Non-number to quotient ",nil,FALSE,0,work);
        !           632:            }
        !           633:        }
        !           634: out:
        !           635:        work = result->val;
        !           636:        switch(restype){
        !           637:        case SDOT:
        !           638:        case DOUB:
        !           639:            break;
        !           640:        case INT:
        !           641:            work = inewint(dummybig.I);
        !           642:            break;
        !           643:        default:
        !           644:        urk:
        !           645:            errorh1(Vermisc,"Internal quotient error #5: ",nil,FALSE,0,
        !           646:                                         work);
        !           647:        }
        !           648:        Restorestack();
        !           649:        return(work);
        !           650: }
        !           651: 
        !           652: 
        !           653: lispval Lfp()
        !           654: {
        !           655:        register temp = 0;
        !           656:        register struct argent *argp; 
        !           657: 
        !           658:        for(argp = lbot; argp < np; argp++)
        !           659:            if(TYPE(argp->val) != INT)
        !           660:                errorh1(Vermisc,"+: non fixnum argument ",
        !           661:                                nil,FALSE,0,argp->val);
        !           662:            else
        !           663:                temp += argp->val->i;
        !           664:        return(inewint(temp));
        !           665: }
        !           666: 
        !           667: lispval Lfm()
        !           668: {
        !           669:        register temp;
        !           670:        register struct argent *argp;
        !           671: 
        !           672:        if(lbot==np)return(inewint(0));
        !           673:           if(TYPE(lbot->val) != INT)
        !           674:                errorh1(Vermisc,"-: non fixnum argument ",
        !           675:                                nil,FALSE,0,lbot->val);
        !           676:           else
        !           677:               temp = lbot->val->i;
        !           678:        if(lbot+1==np) return(inewint(-temp));
        !           679:        for(argp = lbot+1; argp < np; argp++)
        !           680:            if(TYPE(argp->val) != INT)
        !           681:                errorh1(Vermisc,"-: non fixnum argument ",
        !           682:                                nil,FALSE,0,argp->val);
        !           683:            else
        !           684:                temp -= argp->val->i;
        !           685:        return(inewint(temp));
        !           686: }
        !           687: 
        !           688: lispval Lft()
        !           689: {
        !           690:        register temp = 1;
        !           691:        register struct argent *argp;
        !           692: 
        !           693:        for(argp = lbot; argp < np; argp++)
        !           694:            if(TYPE(argp->val) != INT)
        !           695:                errorh1(Vermisc,"*: non fixnum argument ",
        !           696:                                nil,FALSE,0,argp->val);
        !           697:            else
        !           698:                temp *= argp->val->i;
        !           699:        return(inewint(temp));
        !           700: }
        !           701: 
        !           702: lispval Lflessp()
        !           703: {
        !           704:        register struct argent *argp = lbot;
        !           705:        register old, new;
        !           706: 
        !           707:        if(np < argp + 2) return(nil);
        !           708:        old = argp->val->i; argp++;
        !           709:        for(; argp < np; argp++)
        !           710:                if(TYPE(argp->val) != INT)
        !           711:                        errorh1(Vermisc,"<: non fixnum argument ",
        !           712:                        nil,FALSE,0,argp->val);
        !           713:                else {
        !           714:                        new = argp->val->i;
        !           715:                        if(!(old < new)) return(nil);
        !           716:                        old = new;
        !           717:                }
        !           718:        return(tatom);
        !           719: }
        !           720: 
        !           721: lispval Lfd()
        !           722: {
        !           723:        register temp = 0;
        !           724:        register struct argent *argp;
        !           725: 
        !           726:        if(lbot==np)return(inewint(1));
        !           727:        if(TYPE(lbot->val) != INT)
        !           728:            errorh1(Vermisc,"/: non fixnum argument ",
        !           729:                        nil,FALSE,0,lbot->val);
        !           730:        temp = lbot->val->i;
        !           731:        if(lbot+1==np) return(inewint(1/temp));
        !           732:        for(argp = lbot+1; argp < np; argp++)
        !           733:            if(TYPE(argp->val) != INT)
        !           734:                errorh1(Vermisc,"/: non fixnum argument ",
        !           735:                        nil,FALSE,0,argp->val);
        !           736:            else
        !           737:                temp /= argp->val->i;
        !           738:        return(inewint(temp));
        !           739: }
        !           740: 
        !           741: lispval Lfadd1()
        !           742: {
        !           743:     chkarg(1,"1+");
        !           744:     if(TYPE(lbot->val) != INT)
        !           745:         errorh1(Vermisc,"1+: non fixnum argument ",
        !           746:                        nil,FALSE,0,lbot->val);
        !           747:     return(inewint(lbot->val->i + 1));
        !           748: }
        !           749: 
        !           750: /*
        !           751:  * Lfexpt      (^ 'x_a 'x_b)
        !           752:  *   exponentiation of fixnums x_a and x_b returning a fixnum
        !           753:  * result
        !           754:  */
        !           755: lispval Lfexpt()
        !           756: {
        !           757:     register int base;
        !           758:     register int exp;
        !           759:     register int res;
        !           760:     
        !           761:     chkarg(2,"^");
        !           762:     if((TYPE(lbot[0].val) != INT ) || (TYPE(lbot[1].val) != INT))
        !           763:       errorh2(Vermisc,"^: non fixnum arguments", nil,0,
        !           764:                lbot[0].val,lbot[1].val);
        !           765:                
        !           766:     base = lbot[0].val->i;
        !           767:     exp = lbot[1].val->i;
        !           768: 
        !           769:     if(base == 0)
        !           770:     {
        !           771:        /* 0^0 == 1,  0 to any other power (even negative powers)
        !           772:         *  is zero (according to Maclisp)
        !           773:         */
        !           774:        if(exp == 0) return(inewint(1));
        !           775:        else return(inewint(0));
        !           776:     }
        !           777:     else if(base == 1)
        !           778:         /*
        !           779:         *  1 to any power is 1
        !           780:         */
        !           781:        return(lbot[0].val);    /* == 1 */
        !           782:     else if(exp == 0)
        !           783:        /*
        !           784:         * anything to the zero power is 1
        !           785:         */
        !           786:        return(inewint(1));
        !           787:     else if(base == -1)
        !           788:     {
        !           789:         /*
        !           790:         * -1 to an even power is 1, to an odd is -1
        !           791:         */
        !           792:        if(exp & 1) return(lbot[0].val);
        !           793:        else return(inewint(1));
        !           794:     }
        !           795:     else if(exp < 0)
        !           796:         /*
        !           797:         * anything not 0,-1,or 1  to a negative power is 0
        !           798:         *
        !           799:         */
        !           800:         return(inewint(0));
        !           801: 
        !           802:     /* compute exponentiation.  This should check for overflows,
        !           803:        I suppose. --jkf
        !           804:      */
        !           805:     res = 1;
        !           806:     while( exp > 0)
        !           807:     {
        !           808:        if( exp & 1 )
        !           809:        {   /* odd, just multiply by one */
        !           810:            res = res * base;
        !           811:            exp--;
        !           812:        }
        !           813:        else {
        !           814:            /* even, square base */
        !           815:            base = base * base;
        !           816:            exp = exp / 2;
        !           817:        }
        !           818:     }
        !           819:     return(inewint(res));
        !           820: }
        !           821:            
        !           822:     
        !           823: 
        !           824: lispval Lfsub1()
        !           825: {
        !           826:     chkarg(1,"1-");
        !           827:     if(TYPE(lbot->val) != INT)
        !           828:         errorh1(Vermisc,"1-: non fixnum argument ",
        !           829:                        nil,FALSE,0,lbot->val);
        !           830:     return(inewint(lbot->val->i - 1));
        !           831: }
        !           832: 
        !           833: lispval
        !           834: Ldbtofl()
        !           835: {
        !           836:        float x;
        !           837:        chkarg(1,"double-to-float");
        !           838: 
        !           839:        if(TYPE(lbot->val) != DOUB)
        !           840:         errorh1(Vermisc,"double-to-float: non flonum argument ",
        !           841:                        nil,FALSE,0,lbot->val);
        !           842:        x = lbot->val->r;
        !           843:        return(inewint(*(long *)&x));
        !           844: }
        !           845: 
        !           846: lispval
        !           847: Lfltodb()
        !           848: {
        !           849:        register lispval handy;
        !           850:        chkarg(1,"float-to-double");
        !           851: 
        !           852:        if(TYPE(lbot->val) != DOUB)
        !           853:         errorh1(Vermisc,"float-to-double: non fixnum argument ",
        !           854:                        nil,FALSE,0,lbot->val);
        !           855:        handy = newdoub();
        !           856:        handy->r = *(float *)lbot->val;
        !           857:        return(handy);
        !           858: }

unix.superglobalmegacorp.com

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