Annotation of linux/kernel/math/convert.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * linux/kernel/math/convert.c
                      3:  *
1.1.1.3 ! root        4:  * Copyright (C) 1991, 1992 Linus Torvalds
1.1       root        5:  */
                      6: 
                      7: #include <linux/math_emu.h>
                      8: 
                      9: /*
                     10:  * NOTE!!! There is some "non-obvious" optimisations in the temp_to_long
                     11:  * and temp_to_short conversion routines: don't touch them if you don't
                     12:  * know what's going on. They are the adding of one in the rounding: the
                     13:  * overflow bit is also used for adding one into the exponent. Thus it
                     14:  * looks like the overflow would be incorrectly handled, but due to the
                     15:  * way the IEEE numbers work, things are correct.
                     16:  *
                     17:  * There is no checking for total overflow in the conversions, though (ie
                     18:  * if the temp-real number simply won't fit in a short- or long-real.)
                     19:  */
                     20: 
                     21: void short_to_temp(const short_real * a, temp_real * b)
                     22: {
                     23:        if (!(*a & 0x7fffffff)) {
                     24:                b->a = b->b = 0;
                     25:                if (*a)
                     26:                        b->exponent = 0x8000;
                     27:                else
                     28:                        b->exponent = 0;
                     29:                return;
                     30:        }
                     31:        b->exponent = ((*a>>23) & 0xff)-127+16383;
                     32:        if (*a<0)
                     33:                b->exponent |= 0x8000;
                     34:        b->b = (*a<<8) | 0x80000000;
                     35:        b->a = 0;
                     36: }
                     37: 
                     38: void long_to_temp(const long_real * a, temp_real * b)
                     39: {
                     40:        if (!a->a && !(a->b & 0x7fffffff)) {
                     41:                b->a = b->b = 0;
                     42:                if (a->b)
                     43:                        b->exponent = 0x8000;
                     44:                else
                     45:                        b->exponent = 0;
                     46:                return;
                     47:        }
                     48:        b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383;
                     49:        if (a->b<0)
                     50:                b->exponent |= 0x8000;
                     51:        b->b = 0x80000000 | (a->b<<11) | (((unsigned long)a->a)>>21);
                     52:        b->a = a->a<<11;
                     53: }
                     54: 
                     55: void temp_to_short(const temp_real * a, short_real * b)
                     56: {
                     57:        if (!(a->exponent & 0x7fff)) {
                     58:                *b = (a->exponent)?0x80000000:0;
                     59:                return;
                     60:        }
                     61:        *b = ((((long) a->exponent)-16383+127) << 23) & 0x7f800000;
                     62:        if (a->exponent < 0)
                     63:                *b |= 0x80000000;
                     64:        *b |= (a->b >> 8) & 0x007fffff;
                     65:        switch (ROUNDING) {
                     66:                case ROUND_NEAREST:
                     67:                        if ((a->b & 0xff) > 0x80)
                     68:                                ++*b;
                     69:                        break;
                     70:                case ROUND_DOWN:
                     71:                        if ((a->exponent & 0x8000) && (a->b & 0xff))
                     72:                                ++*b;
                     73:                        break;
                     74:                case ROUND_UP:
                     75:                        if (!(a->exponent & 0x8000) && (a->b & 0xff))
                     76:                                ++*b;
                     77:                        break;
                     78:        }
                     79: }
                     80: 
                     81: void temp_to_long(const temp_real * a, long_real * b)
                     82: {
                     83:        if (!(a->exponent & 0x7fff)) {
                     84:                b->a = 0;
                     85:                b->b = (a->exponent)?0x80000000:0;
                     86:                return;
                     87:        }
                     88:        b->b = (((0x7fff & (long) a->exponent)-16383+1023) << 20) & 0x7ff00000;
                     89:        if (a->exponent < 0)
                     90:                b->b |= 0x80000000;
                     91:        b->b |= (a->b >> 11) & 0x000fffff;
                     92:        b->a = a->b << 21;
                     93:        b->a |= (a->a >> 11) & 0x001fffff;
                     94:        switch (ROUNDING) {
                     95:                case ROUND_NEAREST:
                     96:                        if ((a->a & 0x7ff) > 0x400)
                     97:                                __asm__("addl $1,%0 ; adcl $0,%1"
                     98:                                        :"=r" (b->a),"=r" (b->b)
                     99:                                        :"0" (b->a),"1" (b->b));
                    100:                        break;
                    101:                case ROUND_DOWN:
                    102:                        if ((a->exponent & 0x8000) && (a->b & 0xff))
                    103:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    104:                                        :"=r" (b->a),"=r" (b->b)
                    105:                                        :"0" (b->a),"1" (b->b));
                    106:                        break;
                    107:                case ROUND_UP:
                    108:                        if (!(a->exponent & 0x8000) && (a->b & 0xff))
                    109:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    110:                                        :"=r" (b->a),"=r" (b->b)
                    111:                                        :"0" (b->a),"1" (b->b));
                    112:                        break;
                    113:        }
                    114: }
                    115: 
1.1.1.2   root      116: void frndint(const temp_real * a, temp_real * b)
                    117: {
                    118:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
                    119:        unsigned long underflow;
                    120: 
                    121:        if ((shift < 0) || (shift == 16383+63)) {
                    122:                *b = *a;
                    123:                return;
                    124:        }
                    125:        b->a = b->b = underflow = 0;
                    126:        b->exponent = a->exponent;
                    127:        if (shift < 32) {
                    128:                b->b = a->b; b->a = a->a;
                    129:        } else if (shift < 64) {
                    130:                b->a = a->b; underflow = a->a;
                    131:                shift -= 32;
                    132:                b->exponent += 32;
                    133:        } else if (shift < 96) {
                    134:                underflow = a->b;
                    135:                shift -= 64;
                    136:                b->exponent += 64;
                    137:        } else {
                    138:                underflow = 1;
                    139:                shift = 0;
                    140:        }
                    141:        b->exponent += shift;
                    142:        __asm__("shrdl %2,%1,%0"
                    143:                :"=r" (underflow),"=r" (b->a)
                    144:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
                    145:        __asm__("shrdl %2,%1,%0"
                    146:                :"=r" (b->a),"=r" (b->b)
                    147:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
                    148:        __asm__("shrl %1,%0"
                    149:                :"=r" (b->b)
                    150:                :"c" ((char) shift),"0" (b->b));
                    151:        switch (ROUNDING) {
                    152:                case ROUND_NEAREST:
                    153:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
                    154:                                :"=r" (b->a),"=r" (b->b)
                    155:                                :"0" (b->a),"1" (b->b)
                    156:                                ,"r" (0x7fffffff + (b->a & 1))
                    157:                                ,"m" (*&underflow));
                    158:                        break;
                    159:                case ROUND_UP:
                    160:                        if ((b->exponent >= 0) && underflow)
                    161:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    162:                                        :"=r" (b->a),"=r" (b->b)
                    163:                                        :"0" (b->a),"1" (b->b));
                    164:                        break;
                    165:                case ROUND_DOWN:
                    166:                        if ((b->exponent < 0) && underflow)
                    167:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    168:                                        :"=r" (b->a),"=r" (b->b)
                    169:                                        :"0" (b->a),"1" (b->b));
                    170:                        break;
                    171:        }
                    172:        if (b->a || b->b)
                    173:                while (b->b >= 0) {
                    174:                        b->exponent--;
                    175:                        __asm__("addl %0,%0 ; adcl %1,%1"
                    176:                                :"=r" (b->a),"=r" (b->b)
                    177:                                :"0" (b->a),"1" (b->b));
                    178:                }
                    179:        else
                    180:                b->exponent = 0;
                    181: }
                    182: 
1.1       root      183: void real_to_int(const temp_real * a, temp_int * b)
                    184: {
                    185:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
                    186:        unsigned long underflow;
                    187: 
                    188:        b->a = b->b = underflow = 0;
                    189:        b->sign = (a->exponent < 0);
                    190:        if (shift < 0) {
                    191:                set_OE();
                    192:                return;
                    193:        }
                    194:        if (shift < 32) {
                    195:                b->b = a->b; b->a = a->a;
                    196:        } else if (shift < 64) {
                    197:                b->a = a->b; underflow = a->a;
                    198:                shift -= 32;
                    199:        } else if (shift < 96) {
                    200:                underflow = a->b;
                    201:                shift -= 64;
1.1.1.2   root      202:        } else {
                    203:                underflow = 1;
                    204:                shift = 0;
                    205:        }
1.1       root      206:        __asm__("shrdl %2,%1,%0"
                    207:                :"=r" (underflow),"=r" (b->a)
                    208:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
                    209:        __asm__("shrdl %2,%1,%0"
                    210:                :"=r" (b->a),"=r" (b->b)
                    211:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
                    212:        __asm__("shrl %1,%0"
                    213:                :"=r" (b->b)
                    214:                :"c" ((char) shift),"0" (b->b));
                    215:        switch (ROUNDING) {
                    216:                case ROUND_NEAREST:
                    217:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
                    218:                                :"=r" (b->a),"=r" (b->b)
                    219:                                :"0" (b->a),"1" (b->b)
                    220:                                ,"r" (0x7fffffff + (b->a & 1))
                    221:                                ,"m" (*&underflow));
                    222:                        break;
                    223:                case ROUND_UP:
                    224:                        if (!b->sign && underflow)
                    225:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    226:                                        :"=r" (b->a),"=r" (b->b)
                    227:                                        :"0" (b->a),"1" (b->b));
                    228:                        break;
                    229:                case ROUND_DOWN:
                    230:                        if (b->sign && underflow)
                    231:                                __asm__("addl $1,%0 ; adcl $0,%1"
                    232:                                        :"=r" (b->a),"=r" (b->b)
                    233:                                        :"0" (b->a),"1" (b->b));
                    234:                        break;
                    235:        }
                    236: }
                    237: 
                    238: void int_to_real(const temp_int * a, temp_real * b)
                    239: {
                    240:        b->a = a->a;
                    241:        b->b = a->b;
                    242:        if (b->a || b->b)
                    243:                b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
                    244:        else {
                    245:                b->exponent = 0;
                    246:                return;
                    247:        }
                    248:        while (b->b >= 0) {
                    249:                b->exponent--;
                    250:                __asm__("addl %0,%0 ; adcl %1,%1"
                    251:                        :"=r" (b->a),"=r" (b->b)
                    252:                        :"0" (b->a),"1" (b->b));
                    253:        }
                    254: }

unix.superglobalmegacorp.com

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