xref: /openbsd-src/regress/lib/libc/cephes/etodec.c (revision b7275c8844bfe6dc0cf95984cd963da8316ddba7)
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