Annotation of 43BSD/bin/as/bignum2.c, revision 1.1.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.