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

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

unix.superglobalmegacorp.com

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