1112158Sdas/****************************************************************
2112158Sdas
3112158SdasThe author of this software is David M. Gay.
4112158Sdas
5112158SdasCopyright (C) 1998, 2000 by Lucent Technologies
6112158SdasAll Rights Reserved
7112158Sdas
8112158SdasPermission to use, copy, modify, and distribute this software and
9112158Sdasits documentation for any purpose and without fee is hereby
10112158Sdasgranted, provided that the above copyright notice appear in all
11112158Sdascopies and that both that the copyright notice and this
12112158Sdaspermission notice and warranty disclaimer appear in supporting
13112158Sdasdocumentation, and that the name of Lucent or any of its entities
14112158Sdasnot be used in advertising or publicity pertaining to
15112158Sdasdistribution of the software without specific, written prior
16112158Sdaspermission.
17112158Sdas
18112158SdasLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19112158SdasINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20112158SdasIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21112158SdasSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22112158SdasWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23112158SdasIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24112158SdasARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25112158SdasTHIS SOFTWARE.
26112158Sdas
27112158Sdas****************************************************************/
28112158Sdas
29165743Sdas/* Please send bug reports to David M. Gay (dmg at acm dot org,
30165743Sdas * with " at " changed at "@" and " dot " changed to ".").	*/
31112158Sdas
32112158Sdas#include "gdtoaimp.h"
33112158Sdas
34112158Sdas void
35112158Sdas#ifdef KR_headers
36112158SdasULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
37112158Sdas#else
38112158SdasULtodd(ULong *L, ULong *bits, Long exp, int k)
39112158Sdas#endif
40112158Sdas{
41112158Sdas	int i, j;
42112158Sdas
43112158Sdas	switch(k & STRTOG_Retmask) {
44112158Sdas	  case STRTOG_NoNumber:
45112158Sdas	  case STRTOG_Zero:
46112158Sdas		L[0] = L[1] = L[2] = L[3] = 0;
47112158Sdas		break;
48112158Sdas
49112158Sdas	  case STRTOG_Normal:
50112158Sdas		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
51219557Sdas		L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff)
52219557Sdas			  | ((exp + 0x3ff + 105) << 20);
53112158Sdas		exp += 0x3ff + 52;
54112158Sdas		if (bits[1] &= 0x1fffff) {
55112158Sdas			i = hi0bits(bits[1]) - 11;
56112158Sdas			if (i >= exp) {
57112158Sdas				i = exp - 1;
58112158Sdas				exp = 0;
59112158Sdas				}
60112158Sdas			else
61112158Sdas				exp -= i;
62112158Sdas			if (i > 0) {
63219557Sdas				bits[1] = bits[1] << i | bits[0] >> (32-i);
64112158Sdas				bits[0] = bits[0] << i & (ULong)0xffffffffL;
65112158Sdas				}
66112158Sdas			}
67112158Sdas		else if (bits[0]) {
68112158Sdas			i = hi0bits(bits[0]) + 21;
69112158Sdas			if (i >= exp) {
70112158Sdas				i = exp - 1;
71112158Sdas				exp = 0;
72112158Sdas				}
73112158Sdas			else
74112158Sdas				exp -= i;
75112158Sdas			if (i < 32) {
76219557Sdas				bits[1] = bits[0] >> (32 - i);
77112158Sdas				bits[0] = bits[0] << i & (ULong)0xffffffffL;
78112158Sdas				}
79112158Sdas			else {
80219557Sdas				bits[1] = bits[0] << (i - 32);
81112158Sdas				bits[0] = 0;
82112158Sdas				}
83112158Sdas			}
84112158Sdas		else {
85112158Sdas			L[2] = L[3] = 0;
86112158Sdas			break;
87112158Sdas			}
88112158Sdas		L[2+_1] = bits[0];
89219557Sdas		L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
90112158Sdas		break;
91112158Sdas
92112158Sdas	  case STRTOG_Denormal:
93112158Sdas		if (bits[3])
94112158Sdas			goto nearly_normal;
95112158Sdas		if (bits[2])
96112158Sdas			goto partly_normal;
97112158Sdas		if (bits[1] & 0xffe00000)
98112158Sdas			goto hardly_normal;
99112158Sdas		/* completely denormal */
100112158Sdas		L[2] = L[3] = 0;
101112158Sdas		L[_1] = bits[0];
102112158Sdas		L[_0] = bits[1];
103112158Sdas		break;
104112158Sdas
105112158Sdas	  nearly_normal:
106112158Sdas		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
107112158Sdas		j = 32 - i;
108219557Sdas		L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
109219557Sdas			| ((65 - i) << 20);
110112158Sdas		L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
111219557Sdas		L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
112112158Sdas		L[2+_1] = bits[0];
113112158Sdas		break;
114112158Sdas
115112158Sdas	  partly_normal:
116112158Sdas		i = hi0bits(bits[2]) - 11;
117112158Sdas		if (i < 0) {
118112158Sdas			j = -i;
119112158Sdas			i += 32;
120219557Sdas			L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20);
121112158Sdas			L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
122219557Sdas			L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
123112158Sdas			L[2+_1] = bits[0];
124112158Sdas			break;
125112158Sdas			}
126112158Sdas		if (i == 0) {
127219557Sdas			L[_0] = (bits[2] & 0xfffff) | (33 << 20);
128112158Sdas			L[_1] = bits[1];
129112158Sdas			L[2+_0] = 0;
130112158Sdas			L[2+_1] = bits[0];
131112158Sdas			break;
132112158Sdas			}
133112158Sdas		j = 32 - i;
134219557Sdas		L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
135219557Sdas				| ((j + 1) << 20);
136112158Sdas		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
137112158Sdas		L[2+_0] = 0;
138219557Sdas		L[2+_1] = bits[0] & ((1L << j) - 1);
139112158Sdas		break;
140112158Sdas
141112158Sdas	  hardly_normal:
142112158Sdas		j = 11 - hi0bits(bits[1]);
143112158Sdas		i = 32 - j;
144219557Sdas		L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
145112158Sdas		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
146112158Sdas		L[2+_0] = 0;
147219557Sdas		L[2+_1] = bits[0] & (((ULong)1L << j) - 1);
148112158Sdas		break;
149112158Sdas
150112158Sdas	  case STRTOG_Infinite:
151112158Sdas		L[_0] = L[2+_0] = 0x7ff00000;
152112158Sdas		L[_1] = L[2+_1] = 0;
153112158Sdas		break;
154112158Sdas
155112158Sdas	  case STRTOG_NaN:
156165743Sdas		L[0] = L[2] = d_QNAN0;
157165743Sdas		L[1] = L[3] = d_QNAN1;
158112158Sdas		break;
159112158Sdas
160112158Sdas	  case STRTOG_NaNbits:
161112158Sdas		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
162112158Sdas		L[_0] = bits[2] >> 21 | bits[3] << 11
163112158Sdas			  | (ULong)0x7ff00000L;
164112158Sdas		L[2+_1] = bits[0];
165112158Sdas		L[2+_0] = bits[1] | (ULong)0x7ff00000L;
166112158Sdas	  }
167112158Sdas	if (k & STRTOG_Neg) {
168112158Sdas		L[_0] |= 0x80000000L;
169112158Sdas		L[2+_0] |= 0x80000000L;
170112158Sdas		}
171112158Sdas	}
172112158Sdas
173112158Sdas int
174112158Sdas#ifdef KR_headers
175112158Sdasstrtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd;
176112158Sdas#else
177112158Sdasstrtordd(CONST char *s, char **sp, int rounding, double *dd)
178112158Sdas#endif
179112158Sdas{
180112158Sdas#ifdef Sudden_Underflow
181112158Sdas	static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
182112158Sdas#else
183112158Sdas	static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
184112158Sdas#endif
185112158Sdas	FPI *fpi, fpi1;
186112158Sdas	ULong bits[4];
187112158Sdas	Long exp;
188112158Sdas	int k;
189112158Sdas
190112158Sdas	fpi = &fpi0;
191112158Sdas	if (rounding != FPI_Round_near) {
192112158Sdas		fpi1 = fpi0;
193112158Sdas		fpi1.rounding = rounding;
194112158Sdas		fpi = &fpi1;
195112158Sdas		}
196112158Sdas	k = strtodg(s, sp, fpi, &exp, bits);
197112158Sdas	ULtodd((ULong*)dd, bits, exp, k);
198112158Sdas	return k;
199112158Sdas	}
200