1 /* $OpenBSD: etodec.c,v 1.1 2011/07/02 18:11:01 martynas Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "ehead.h" 20 void emovi(), emovo(), ecleaz(), eshdn8(), emdnorm(); 21 void todec(); 22 /* 23 ; convert DEC double precision to e type 24 ; double d; 25 ; short e[NE]; 26 ; dectoe( &d, e ); 27 */ 28 void dectoe( d, e ) 29 unsigned short *d; 30 unsigned short *e; 31 { 32 unsigned short y[NI]; 33 register unsigned short r, *p; 34 35 ecleaz(y); /* start with a zero */ 36 p = y; /* point to our number */ 37 r = *d; /* get DEC exponent word */ 38 if( *d & (unsigned int )0x8000 ) 39 *p = 0xffff; /* fill in our sign */ 40 ++p; /* bump pointer to our exponent word */ 41 r &= 0x7fff; /* strip the sign bit */ 42 if( r == 0 ) /* answer = 0 if high order DEC word = 0 */ 43 goto done; 44 45 46 r >>= 7; /* shift exponent word down 7 bits */ 47 r += EXONE - 0201; /* subtract DEC exponent offset */ 48 /* add our e type exponent offset */ 49 *p++ = r; /* to form our exponent */ 50 51 r = *d++; /* now do the high order mantissa */ 52 r &= 0177; /* strip off the DEC exponent and sign bits */ 53 r |= 0200; /* the DEC understood high order mantissa bit */ 54 *p++ = r; /* put result in our high guard word */ 55 56 *p++ = *d++; /* fill in the rest of our mantissa */ 57 *p++ = *d++; 58 *p = *d; 59 60 eshdn8(y); /* shift our mantissa down 8 bits */ 61 done: 62 emovo( y, e ); 63 } 64 65 66 67 /* 68 ; convert e type to DEC double precision 69 ; double d; 70 ; short e[NE]; 71 ; etodec( e, &d ); 72 */ 73 #if 0 74 static unsigned short decbit[NI] = {0,0,0,0,0,0,0200,0}; 75 void etodec( x, d ) 76 unsigned short *x, *d; 77 { 78 unsigned short xi[NI]; 79 register unsigned short r; 80 int i, j; 81 82 emovi( x, xi ); 83 *d = 0; 84 if( xi[0] != 0 ) 85 *d = 0100000; 86 r = xi[E]; 87 if( r < (EXONE - 128) ) 88 goto zout; 89 i = xi[M+4]; 90 if( (i & 0200) != 0 ) 91 { 92 if( (i & 0377) == 0200 ) 93 { 94 if( (i & 0400) != 0 ) 95 { 96 /* check all less significant bits */ 97 for( j=M+5; j<NI; j++ ) 98 { 99 if( xi[j] != 0 ) 100 goto yesrnd; 101 } 102 } 103 goto nornd; 104 } 105 yesrnd: 106 eaddm( decbit, xi ); 107 r -= enormlz(xi); 108 } 109 110 nornd: 111 112 r -= EXONE; 113 r += 0201; 114 if( r < 0 ) 115 { 116 zout: 117 *d++ = 0; 118 *d++ = 0; 119 *d++ = 0; 120 *d++ = 0; 121 return; 122 } 123 if( r >= 0377 ) 124 { 125 *d++ = 077777; 126 *d++ = -1; 127 *d++ = -1; 128 *d++ = -1; 129 return; 130 } 131 r &= 0377; 132 r <<= 7; 133 eshup8( xi ); 134 xi[M] &= 0177; 135 r |= xi[M]; 136 *d++ |= r; 137 *d++ = xi[M+1]; 138 *d++ = xi[M+2]; 139 *d++ = xi[M+3]; 140 } 141 #else 142 143 extern int rndprc; 144 145 void etodec( x, d ) 146 unsigned short *x, *d; 147 { 148 unsigned short xi[NI]; 149 long exp; 150 int rndsav; 151 152 emovi( x, xi ); 153 exp = (long )xi[E] - (EXONE - 0201); /* adjust exponent for offsets */ 154 /* round off to nearest or even */ 155 rndsav = rndprc; 156 rndprc = 56; 157 emdnorm( xi, 0, 0, exp, 64 ); 158 rndprc = rndsav; 159 todec( xi, d ); 160 } 161 162 void todec( x, y ) 163 unsigned short *x, *y; 164 { 165 unsigned short i; 166 unsigned short *p; 167 168 p = x; 169 *y = 0; 170 if( *p++ ) 171 *y = 0100000; 172 i = *p++; 173 if( i == 0 ) 174 { 175 *y++ = 0; 176 *y++ = 0; 177 *y++ = 0; 178 *y++ = 0; 179 return; 180 } 181 if( i > 0377 ) 182 { 183 *y++ |= 077777; 184 *y++ = 0xffff; 185 *y++ = 0xffff; 186 *y++ = 0xffff; 187 return; 188 } 189 i &= 0377; 190 i <<= 7; 191 eshup8( x ); 192 x[M] &= 0177; 193 i |= x[M]; 194 *y++ |= i; 195 *y++ = x[M+1]; 196 *y++ = x[M+2]; 197 *y++ = x[M+3]; 198 } 199 #endif 200