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 */
dectoe(d,e)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
etodec(x,d)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
todec(x,y)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