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

1.1     ! root        1: /*
        !             2:  * linux/kernel/math/convert.c
        !             3:  *
        !             4:  * (C) 1991 Linus Torvalds
        !             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: 
        !           116: void real_to_int(const temp_real * a, temp_int * b)
        !           117: {
        !           118:        int shift =  16383 + 63 - (a->exponent & 0x7fff);
        !           119:        unsigned long underflow;
        !           120: 
        !           121:        b->a = b->b = underflow = 0;
        !           122:        b->sign = (a->exponent < 0);
        !           123:        if (shift < 0) {
        !           124:                set_OE();
        !           125:                return;
        !           126:        }
        !           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:        } else if (shift < 96) {
        !           133:                underflow = a->b;
        !           134:                shift -= 64;
        !           135:        } else
        !           136:                return;
        !           137:        __asm__("shrdl %2,%1,%0"
        !           138:                :"=r" (underflow),"=r" (b->a)
        !           139:                :"c" ((char) shift),"0" (underflow),"1" (b->a));
        !           140:        __asm__("shrdl %2,%1,%0"
        !           141:                :"=r" (b->a),"=r" (b->b)
        !           142:                :"c" ((char) shift),"0" (b->a),"1" (b->b));
        !           143:        __asm__("shrl %1,%0"
        !           144:                :"=r" (b->b)
        !           145:                :"c" ((char) shift),"0" (b->b));
        !           146:        switch (ROUNDING) {
        !           147:                case ROUND_NEAREST:
        !           148:                        __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
        !           149:                                :"=r" (b->a),"=r" (b->b)
        !           150:                                :"0" (b->a),"1" (b->b)
        !           151:                                ,"r" (0x7fffffff + (b->a & 1))
        !           152:                                ,"m" (*&underflow));
        !           153:                        break;
        !           154:                case ROUND_UP:
        !           155:                        if (!b->sign && underflow)
        !           156:                                __asm__("addl $1,%0 ; adcl $0,%1"
        !           157:                                        :"=r" (b->a),"=r" (b->b)
        !           158:                                        :"0" (b->a),"1" (b->b));
        !           159:                        break;
        !           160:                case ROUND_DOWN:
        !           161:                        if (b->sign && underflow)
        !           162:                                __asm__("addl $1,%0 ; adcl $0,%1"
        !           163:                                        :"=r" (b->a),"=r" (b->b)
        !           164:                                        :"0" (b->a),"1" (b->b));
        !           165:                        break;
        !           166:        }
        !           167: }
        !           168: 
        !           169: void int_to_real(const temp_int * a, temp_real * b)
        !           170: {
        !           171:        b->a = a->a;
        !           172:        b->b = a->b;
        !           173:        if (b->a || b->b)
        !           174:                b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
        !           175:        else {
        !           176:                b->exponent = 0;
        !           177:                return;
        !           178:        }
        !           179:        while (b->b >= 0) {
        !           180:                b->exponent--;
        !           181:                __asm__("addl %0,%0 ; adcl %1,%1"
        !           182:                        :"=r" (b->a),"=r" (b->b)
        !           183:                        :"0" (b->a),"1" (b->b));
        !           184:        }
        !           185: }

unix.superglobalmegacorp.com

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