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