Annotation of 42BSD/bin/as/bignum2.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     Copyright (c) 1982 Regents of the University of California
        !             3:  */
        !             4: #ifndef lint
        !             5: static char sccsid[] = "@(#)bignum2.c 4.3 2/14/82";
        !             6: #endif not lint
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include "as.h"
        !            10: Bignum Znumber;                        /* zero reference */
        !            11: #define        MINEXP          -32768          /* never generate; reserved for id 0 */
        !            12: 
        !            13: Bignum intconvert(number, convto)
        !            14:        Bignum  number;
        !            15:        int     convto;
        !            16: {
        !            17:        reg     int     i;
        !            18:        if (number.num_tag == convto)
        !            19:                return(number);
        !            20:        if (ty_nbyte[number.num_tag] > ty_nbyte[convto] && (passno == 2)){
        !            21:                yywarning("Conversion between %s and %s looses significance",
        !            22:                        ty_string[number.num_tag],
        !            23:                        ty_string[convto]);
        !            24:        }
        !            25:        for (i = ty_nbyte[convto]; i < ty_nbyte[TYPO]; i++)
        !            26:                number.num_uchar[i] = 0;
        !            27:        return(number);
        !            28: }
        !            29: 
        !            30: #define        CONV(src, dst)  (((src) << TYPLG) + (dst))
        !            31: 
        !            32: Bignum floatconvert(number, convto)
        !            33:        Bignum  number;
        !            34:        int     convto;
        !            35: {
        !            36:        reg     u_int   *bp;            /* r11 */
        !            37:                int     loss = 0;
        !            38:                int     gain = 0;
        !            39:                int     mixs = 0;
        !            40:                Ovf     ovf;
        !            41: 
        !            42:        if (number.num_tag == convto)
        !            43:                return(number);
        !            44:        bp = &number.num_uint[0];
        !            45: #ifdef lint
        !            46:        *bp = *bp;
        !            47: #endif lint
        !            48: 
        !            49:        switch(CONV(number.num_tag, convto)){
        !            50: 
        !            51:        case CONV(TYPF, TYPD):  asm("cvtfd (r11), (r11)"); break;
        !            52:        case CONV(TYPF, TYPG):  mixs++; break;
        !            53:        case CONV(TYPF, TYPH):  mixs++; break;
        !            54: 
        !            55:        case CONV(TYPD, TYPF):  asm("cvtdf (r11), (r11)"); break;
        !            56:        case CONV(TYPD, TYPG):  mixs++; break;
        !            57:        case CONV(TYPD, TYPH):  mixs++; break;
        !            58: 
        !            59:        case CONV(TYPG, TYPF):  mixs++; break;
        !            60:        case CONV(TYPG, TYPD):  mixs++; break;
        !            61:        case CONV(TYPG, TYPH):  mixs++; break;
        !            62: 
        !            63:        case CONV(TYPH, TYPF):  mixs++; break;
        !            64:        case CONV(TYPH, TYPD):  mixs++; break;
        !            65:        case CONV(TYPH, TYPG):  mixs++; break;
        !            66:        default:        panic("Bad floating point conversion?");
        !            67:        }
        !            68:        if ((gain || mixs || loss) && (passno == 2)){
        !            69:                yywarning("Converting from %s to %s: %s ",
        !            70:                        ty_string[number.num_tag],
        !            71:                        ty_string[convto],
        !            72:                        gain ? "gains significance" :
        !            73:                        (loss ? "looses significance" : "mixs exponent formats")
        !            74:                );
        !            75:        }
        !            76:        if (mixs){
        !            77:                number = bignumconvert(number, convto, &ovf);
        !            78:                if (ovf && passno == 2){
        !            79:                        yywarning("Floating conversion over/underflowed\n");
        !            80:                }
        !            81:        } else {
        !            82:                number.num_tag = convto;
        !            83:        }
        !            84:        return(number);
        !            85: }
        !            86: 
        !            87: /* 
        !            88:  *     Convert a big number between various representations
        !            89:  */
        !            90: Bignum bignumconvert(number, toconv, ovfp)
        !            91:        Bignum  number;
        !            92:        int     toconv;
        !            93:        Ovf     *ovfp;
        !            94: {
        !            95:        int     tag;
        !            96: 
        !            97:        *ovfp = 0;
        !            98:        tag = number.num_tag;
        !            99:        if (tag == toconv)
        !           100:                return(number);
        !           101:        if (tag == TYPUNPACKED){
        !           102:                return(bignumpack(number, toconv, ovfp));
        !           103:        }
        !           104:        if (toconv == TYPUNPACKED){
        !           105:                return(bignumunpack(number, ovfp));
        !           106:        }
        !           107:        return(bignumpack(bignumunpack(number, ovfp), toconv, ovfp));
        !           108: }
        !           109: 
        !           110: Bignum bignumunpack(Packed, ovfp)
        !           111:        Bignum  Packed;
        !           112:                Ovf     *ovfp;
        !           113: {
        !           114:                Bignum  Mantissa;
        !           115:                Bignum  Enumber;
        !           116:        reg     int     i;
        !           117:                int     j;
        !           118:                int     k;
        !           119:        reg     struct  ty_bigdesc      *p;
        !           120:        reg     chptr   packed;
        !           121:        reg     chptr   mantissa;
        !           122:        reg     chptr   enumber;
        !           123:                u_short exponent;
        !           124:                int     sign;
        !           125:                int     mask;
        !           126: 
        !           127:        p = &ty_bigdesc[Packed.num_tag];
        !           128: 
        !           129:        *ovfp = 0;
        !           130:        Mantissa = Znumber;
        !           131:        sign = 0;
        !           132:        exponent = 0;
        !           133:        mantissa = CH_FIELD(Mantissa);
        !           134:        enumber = CH_FIELD(Enumber);
        !           135:        packed = CH_FIELD(Packed);
        !           136: 
        !           137:        if (isclear(packed)){
        !           138:                Mantissa.num_tag = TYPUNPACKED;
        !           139:                Mantissa.num_exponent = MINEXP;
        !           140:                return(Mantissa);
        !           141:        }
        !           142:        /*
        !           143:         *      map the packed number into the mantissa, using
        !           144:         *      the unpacking map
        !           145:         */
        !           146:        mapnumber(mantissa, packed, 16, p->b_upmmap);
        !           147:        /*
        !           148:         *      perform the mantissa shifting.
        !           149:         *      This may appear to overflow; all that is lost
        !           150:         *      is low order bits of the exponent.
        !           151:         */
        !           152:        (void)numshift(p->b_mlshift, mantissa, mantissa);
        !           153:        /*
        !           154:         *      handle sign and exponent
        !           155:         */
        !           156:        switch(Packed.num_tag){
        !           157:        case TYPB:
        !           158:        case TYPW:
        !           159:        case TYPL:
        !           160:        case TYPO:
        !           161:        case TYPQ:
        !           162:                sign = 0;
        !           163:                exponent = p->b_eexcess;
        !           164:                if (mantissa[HOC] & SIGNBIT){
        !           165:                        sign = -1;
        !           166:                        *ovfp |= numnegate(mantissa, mantissa);
        !           167:                }
        !           168:                /*
        !           169:                 *      Normalize the packed by left shifting,
        !           170:                 *      adjusting the exponent as we go.
        !           171:                 *      Do a binary weighted left shift for some speed.
        !           172:                 */
        !           173:                k = 0;
        !           174:                for (j = 4; j >= 0; --j){
        !           175:                        i = 1 << j;     /* 16, 8, 4, 2, 1 */
        !           176:                        while(1){
        !           177:                                if (k >= p->b_msigbits)
        !           178:                                        break;
        !           179:                                mask = ONES(i) << (CH_BITS - i);
        !           180:                                if (mantissa[HOC] & mask)
        !           181:                                        break;
        !           182:                                (void)numshift(i, mantissa, mantissa);
        !           183:                                k += i;
        !           184:                                exponent -= i;
        !           185:                        }
        !           186:                }
        !           187:                assert(mantissa[HOC] & SIGNBIT, "integer <<ing");
        !           188:                /*
        !           189:                 *      now, kick the most significant bit off the top
        !           190:                 */
        !           191:                (void)numshift(1, mantissa, mantissa);
        !           192:                break;
        !           193:        default:
        !           194:                /*
        !           195:                 *      map the exponent into the local area.
        !           196:                 */
        !           197:                Enumber = Znumber;
        !           198:                mapnumber(enumber, packed, 2, p->b_upemap);
        !           199:                /*
        !           200:                 *      Extract the exponent, and get rid
        !           201:                 *      of the sign bit
        !           202:                 */
        !           203:                exponent = Enumber.num_ushort[0] & ONES(15);
        !           204:                /*
        !           205:                 *      shift the exponent, and get rid of high order
        !           206:                 *      trash
        !           207:                 */
        !           208:                exponent >>= p->b_ershift;
        !           209:                exponent &= ONES(p->b_esigbits);
        !           210:                /*
        !           211:                 *      un excess the exponent
        !           212:                 */
        !           213:                exponent -= p->b_eexcess;
        !           214:                /*
        !           215:                 *      extract and extend the sign bit
        !           216:                 */
        !           217:                sign = (Enumber.num_ushort[0] & ~ONES(15)) ? -1 : 0;
        !           218:        }
        !           219:        /*
        !           220:         *      Assemble the pieces, and return the number
        !           221:         */
        !           222:        Mantissa.num_tag = TYPUNPACKED;
        !           223:        Mantissa.num_sign = sign;
        !           224:        Mantissa.num_exponent = exponent;
        !           225:        return(Mantissa);
        !           226: }
        !           227: 
        !           228: Bignum bignumpack(Unpacked, toconv, ovfp)
        !           229:        Bignum  Unpacked;
        !           230:        int     toconv;
        !           231:        Ovf     *ovfp;
        !           232: {
        !           233:        Bignum  Back;
        !           234:        Bignum  Enumber;
        !           235:        Bignum  Temp;
        !           236: 
        !           237:                short   exponent;
        !           238:                char    sign;
        !           239:        reg     struct  ty_bigdesc      *p;
        !           240:        reg     chptr   back;
        !           241:        reg     chptr   enumber;
        !           242:        reg     chptr   temp;
        !           243:        reg     chptr   unpacked;
        !           244: 
        !           245:                int     i,j;
        !           246: 
        !           247:        if (Unpacked.num_tag != TYPUNPACKED)
        !           248:                panic("Argument to bignumpack is not unpacked");
        !           249: 
        !           250:        *ovfp = 0;
        !           251:        Back = Znumber;
        !           252:        Temp = Znumber;
        !           253:        Back.num_tag = toconv;
        !           254: 
        !           255:        back = CH_FIELD(Back);
        !           256:        temp = CH_FIELD(Temp);
        !           257:        enumber = CH_FIELD(Enumber);
        !           258:        unpacked = CH_FIELD(Unpacked);
        !           259:        p = &ty_bigdesc[toconv];
        !           260: 
        !           261:        exponent = Unpacked.num_exponent;
        !           262:        sign = Unpacked.num_sign;
        !           263:        if (exponent == MINEXP)
        !           264:                return(Back);   /* identically zero */
        !           265: 
        !           266:        switch(toconv){
        !           267:        case TYPB:
        !           268:        case TYPW:
        !           269:        case TYPL:
        !           270:        case TYPQ:
        !           271:        case TYPO:
        !           272:                /*
        !           273:                 *      Put back in the assumed high order fraction
        !           274:                 *      bit that is always a 1.
        !           275:                 */
        !           276:                (void)numshift(-1, temp, unpacked);
        !           277:                temp[HOC] |= SIGNBIT;
        !           278:                if (exponent > p->b_eexcess){
        !           279:                        /*
        !           280:                         *      Construct the largest positive integer
        !           281:                         */
        !           282:                        (void)numclear(temp);
        !           283:                        (void)num1comp(temp, temp);
        !           284:                        temp[HOC] &= ~SIGNBIT;
        !           285:                        sign = sign;
        !           286:                        *ovfp |= OVF_OVERFLOW;
        !           287:                } else
        !           288:                if (exponent <= 0){
        !           289:                        /*
        !           290:                         *      chop the temp; underflow to integer 0
        !           291:                         */
        !           292:                        (void)numclear(temp);
        !           293:                        sign = 0;
        !           294:                        *ovfp |= OVF_UNDERFLOW;
        !           295:                } else {
        !           296:                        /*
        !           297:                         *      denormalize the temp.
        !           298:                         *      This will again chop, by shifting
        !           299:                         *      bits off the right end into oblivion.
        !           300:                         */
        !           301:                        for (j = 4; j >= 0; --j){
        !           302:                                i = 1 << j;     /* 16, 8, 4, 2, 1 */
        !           303:                                while(exponent + i <= p->b_eexcess){
        !           304:                                        numshift(-i, temp, temp);
        !           305:                                        exponent += i;
        !           306:                                }
        !           307:                        }
        !           308:                }
        !           309:                /*
        !           310:                 *      negate the temp if the sign is set
        !           311:                 */
        !           312:                if (sign)
        !           313:                        *ovfp |= numnegate(temp, temp);
        !           314:                /*
        !           315:                 *      Stuff the temp number into the return area
        !           316:                 */
        !           317:                mapnumber(back, temp, 16, p->b_pmmap);
        !           318:                return(Back);
        !           319:        default:
        !           320:                /*
        !           321:                 *      Shift the mantissa to the right, filling in zeroes on
        !           322:                 *      the left.  This aligns the least significant bit
        !           323:                 *      on the bottom of a byte, something that upround
        !           324:                 *      will use.
        !           325:                 *      Put the result into a temporary.
        !           326:                 *      Even though the shift may be zero, there
        !           327:                 *      is still a copy involved here.
        !           328:                 */
        !           329:                (void)numshift(-(p->b_mlshift), temp, unpacked);
        !           330:                /*
        !           331:                 *      Perform the rounding by adding in 0.5 ulp's
        !           332:                 */
        !           333:                exponent = upround(&Temp, p, exponent);
        !           334:                /*
        !           335:                 *      Do a range check on the exponent, in preparation
        !           336:                 *      to stuffing it in.
        !           337:                 */
        !           338:                if ((short)(exponent + p->b_eexcess) == 0){
        !           339:                        /*
        !           340:                         *      Sorry, no gradual underflow on the
        !           341:                         *      VAX.  Chop this beasty totally to zero
        !           342:                         */
        !           343:                        goto zeroret;
        !           344:                } else
        !           345:                if ((short)(exponent + p->b_eexcess) < 0){
        !           346:                        /*
        !           347:                         *      True underflow will happen;
        !           348:                         *      Chop everything to positive zero
        !           349:                         */
        !           350:                  zeroret:
        !           351:                        (void)numclear(temp);
        !           352:                        exponent = 0;
        !           353:                        sign = 0;       /* avoid reserved operand! */
        !           354:                        *ovfp |= OVF_UNDERFLOW;
        !           355:                } else
        !           356:                if ((unsigned)(exponent + p->b_eexcess)
        !           357:                    >= (unsigned)(1 << p->b_esigbits)){
        !           358:                        /*
        !           359:                         *      Construct the largest magnitude possible
        !           360:                         *      floating point unpacked: 0.{1}111111111
        !           361:                         */
        !           362:                        (void)numclear(temp);
        !           363:                        (void)num1comp(temp, temp);
        !           364:                        exponent = ONES(p->b_esigbits);
        !           365:                        sign = sign;
        !           366:                        *ovfp |= OVF_OVERFLOW;
        !           367:                } else {
        !           368:                        /*
        !           369:                         *      The exponent will fit.
        !           370:                         *      Bias it up, and the common code will stuff it.
        !           371:                         */
        !           372:                        exponent += p->b_eexcess;
        !           373:                }
        !           374:                exponent <<= p->b_ershift;
        !           375:                /*
        !           376:                 *      mask out trash for the sign, and put in the sign.
        !           377:                 */
        !           378:                exponent &= ONES(15);
        !           379:                if (sign)
        !           380:                        exponent |= ~ONES(15);
        !           381:                Enumber.num_ushort[0] = exponent;
        !           382:                /*
        !           383:                 *      Map the unpacked exponent into the value going back
        !           384:                 */
        !           385:                mapnumber(back, enumber, 2, p->b_pemap);
        !           386:                /*
        !           387:                 *      Stuff the unpacked mantissa into the return area
        !           388:                 */
        !           389:                mapnumber(back, temp, 16, p->b_pmmap);
        !           390:                return(Back);
        !           391:        }
        !           392:        /*NOTREACHED*/
        !           393: }
        !           394: 
        !           395: mapnumber(chp1, chp2, nbytes, themap)
        !           396:                chptr   chp1, chp2;
        !           397:                int     nbytes;
        !           398:                char    *themap;
        !           399: {
        !           400:        reg     int     i;
        !           401:        reg     u_char  *p1, *p2;
        !           402: 
        !           403:        p1 = (u_char *)chp1;
        !           404:        p2 = (u_char *)chp2;
        !           405:        for (i = 0; i < nbytes; i++){
        !           406:                switch(themap[i]){
        !           407:                case NOTAKE:
        !           408:                        break;
        !           409:                default:
        !           410:                        p1[themap[i]] |= p2[i];
        !           411:                        break;
        !           412:                }
        !           413:        }
        !           414: }
        !           415: 
        !           416: #define        UPSHIFT 2
        !           417: /*
        !           418:  *     round in 1/2 ulp in the number, possibly modifying
        !           419:  *     the binary exponent if there was total carry out.
        !           420:  *     Return the modified exponent
        !           421:  */
        !           422: int upround(numberp, p, exponent)
        !           423:        reg     Bignum  *numberp;
        !           424:        reg     struct  ty_bigdesc      *p;
        !           425:                int     exponent;
        !           426: {
        !           427:        reg     u_char  *bytep;
        !           428:                int     nbytes;
        !           429:                int     byteindex;
        !           430:                int     hofractionbit;
        !           431:                int     ovffractionbit;
        !           432:        reg     int     ovfbitindex;
        !           433:        reg     chptr   number;
        !           434:        static  Bignum  ulp;
        !           435: 
        !           436:        /*
        !           437:         *      Find out the byte index of the byte containing the ulp
        !           438:         */
        !           439:        number = CH_FIELD(numberp[0]);
        !           440:        bytep = numberp->num_uchar;
        !           441: 
        !           442:        nbytes = (p->b_msigbits - 1) + p->b_mlshift;
        !           443:        assert((nbytes % 8) == 0, "mantissa sig bits");
        !           444:        nbytes /= 8;
        !           445:        byteindex = 15 - nbytes;
        !           446:        assert(byteindex >= 0, "ulp in outer space");
        !           447:        /*
        !           448:         *      Shift the number to the right by two places,
        !           449:         *      so that we can do full arithmetic without overflowing
        !           450:         *      to the left.
        !           451:         */
        !           452:        numshift(-UPSHIFT, number, number);
        !           453:        /*
        !           454:         *      Construct the missing high order fraction bit
        !           455:         */
        !           456:        ovfbitindex = 8 - (p->b_mlshift + UPSHIFT);
        !           457:        assert(ovfbitindex >= 0, "Shifted byte 15 into byte 14");
        !           458:        hofractionbit = (0x01 << ovfbitindex);
        !           459:        ovffractionbit = (0x02 << ovfbitindex);
        !           460:        bytep[15] |= hofractionbit;
        !           461:        /*
        !           462:         *      construct the unit in the last place, and it
        !           463:         *      to the fraction
        !           464:         */
        !           465:        ulp.num_uchar[byteindex] |= (0x80 >> UPSHIFT);
        !           466:        numaddv(number, number, CH_FIELD(ulp));
        !           467:        ulp.num_uchar[byteindex] &= ~(0x80 >> UPSHIFT);
        !           468:        /*
        !           469:         *      Check if there was an overflow,
        !           470:         *      and adjust by shifting.
        !           471:         *      Also, bring the number back into canonical
        !           472:         *      unpacked form by left shifting by two to undeo
        !           473:         *      what we did before.
        !           474:         */
        !           475:        if (bytep[15] & ovffractionbit){
        !           476:                exponent += 1;
        !           477:                numshift(UPSHIFT - 1, number, number);
        !           478:        } else {
        !           479:                numshift(UPSHIFT, number, number);
        !           480:        }
        !           481:        /*
        !           482:         *      Clear off trash in the unused bits of the high
        !           483:         *      order byte of the number
        !           484:         */
        !           485:        bytep[15] &= ONES(8 - p->b_mlshift);
        !           486:        return(exponent);
        !           487: }
        !           488: #ifdef DEBUG
        !           489: bignumprint(number)
        !           490:        Bignum  number;
        !           491: {
        !           492:        printf("Bignum: %s (exp: %d, sign: %d) 0x%08x%08x%08x%08x",
        !           493:                ty_string[number.num_tag],
        !           494:                number.num_exponent,
        !           495:                number.num_sign,
        !           496:                number.num_uint[3],
        !           497:                number.num_uint[2],
        !           498:                number.num_uint[1],
        !           499:                number.num_uint[0]);
        !           500:        switch(number.num_tag){
        !           501:        case TYPB:
        !           502:        case TYPW:
        !           503:        case TYPL:
        !           504:        case TYPQ:
        !           505:        case TYPO:
        !           506:        case TYPUNPACKED:
        !           507:                break;
        !           508:        case TYPF:
        !           509:                printf(" == %10.8e", number.num_num.numFf_float.Ff_value);
        !           510:                break;
        !           511:        case TYPD:
        !           512:                printf(" == %20.17e", number.num_num.numFd_float.Fd_value);
        !           513:                break;
        !           514:        case TYPG:
        !           515:        case TYPH:
        !           516:                break;
        !           517:        }
        !           518: }
        !           519: 
        !           520: numprintovf(ovf)
        !           521:        Ovf     ovf;
        !           522: {
        !           523:        int     i;
        !           524:        static struct   ovftab{
        !           525:                Ovf     which;
        !           526:                char    *print;
        !           527:        } ovftab[] = {
        !           528:                OVF_POSOVF,     "posovf",
        !           529:                OVF_MAXINT,     "maxint",
        !           530:                OVF_ADDV,       "addv",
        !           531:                OVF_LSHIFT,     "lshift",
        !           532:                OVF_F,          "F float",
        !           533:                OVF_D,          "D float",
        !           534:                OVF_G,          "G float",
        !           535:                OVF_H,          "H float",
        !           536:                OVF_OVERFLOW,   "cvt overflow",
        !           537:                OVF_UNDERFLOW,  "cvt underflow",
        !           538:                0,              0
        !           539:        };
        !           540:        for(i = 0; ovftab[i].which; i++){
        !           541:                if (ovf & ovftab[i].which)
        !           542:                        printf("Overflow(%s) ", ovftab[i].print);
        !           543:        }
        !           544: }
        !           545: #endif DEBUG

unix.superglobalmegacorp.com

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