1189462Semax/****************************************************************
2189462Semax
3189462SemaxThe author of this software is David M. Gay.
4189462Semax
5189462SemaxCopyright (C) 1998, 2000 by Lucent Technologies
6189462SemaxAll Rights Reserved
7189462Semax
8189462SemaxPermission to use, copy, modify, and distribute this software and
9189462Semaxits documentation for any purpose and without fee is hereby
10189462Semaxgranted, provided that the above copyright notice appear in all
11189462Semaxcopies and that both that the copyright notice and this
12189462Semaxpermission notice and warranty disclaimer appear in supporting
13189462Semaxdocumentation, and that the name of Lucent or any of its entities
14189462Semaxnot be used in advertising or publicity pertaining to
15189462Semaxdistribution of the software without specific, written prior
16189462Semaxpermission.
17189462Semax
18189462SemaxLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19189462SemaxINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20189462SemaxIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21189462SemaxSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22189462SemaxWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23189462SemaxIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24189462SemaxARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25189462SemaxTHIS SOFTWARE.
26189462Semax
27189462Semax****************************************************************/
28189462Semax
29189462Semax/* Please send bug reports to David M. Gay (dmg at acm dot org,
30189462Semax * with " at " changed at "@" and " dot " changed to ".").	*/
31189462Semax
32189462Semax#include "gdtoaimp.h"
33191388Semax
34189462Semax void
35191388Semax#ifdef KR_headers
36189462SemaxULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
37189462Semax#else
38189462SemaxULtodd(ULong *L, ULong *bits, Long exp, int k)
39189462Semax#endif
40189462Semax{
41191388Semax	int i, j;
42191388Semax
43191388Semax	switch(k & STRTOG_Retmask) {
44191388Semax	  case STRTOG_NoNumber:
45189462Semax	  case STRTOG_Zero:
46189462Semax		L[0] = L[1] = L[2] = L[3] = 0;
47189462Semax		break;
48191388Semax
49191388Semax	  case STRTOG_Normal:
50191388Semax		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
51191388Semax		L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff)
52191388Semax			  | ((exp + 0x3ff + 105) << 20);
53191388Semax		exp += 0x3ff + 52;
54191388Semax		if (bits[1] &= 0x1fffff) {
55191388Semax			i = hi0bits(bits[1]) - 11;
56191388Semax			if (i >= exp) {
57191388Semax				i = exp - 1;
58191388Semax				exp = 0;
59191388Semax				}
60191388Semax			else
61191388Semax				exp -= i;
62191388Semax			if (i > 0) {
63191388Semax				bits[1] = bits[1] << i | bits[0] >> (32-i);
64191388Semax				bits[0] = bits[0] << i & (ULong)0xffffffffL;
65191388Semax				}
66191388Semax			}
67191388Semax		else if (bits[0]) {
68191388Semax			i = hi0bits(bits[0]) + 21;
69191388Semax			if (i >= exp) {
70191388Semax				i = exp - 1;
71191388Semax				exp = 0;
72191388Semax				}
73191388Semax			else
74191388Semax				exp -= i;
75191388Semax			if (i < 32) {
76191388Semax				bits[1] = bits[0] >> (32 - i);
77191388Semax				bits[0] = bits[0] << i & (ULong)0xffffffffL;
78191388Semax				}
79191388Semax			else {
80191388Semax				bits[1] = bits[0] << (i - 32);
81191388Semax				bits[0] = 0;
82191388Semax				}
83191388Semax			}
84191388Semax		else {
85191388Semax			L[2] = L[3] = 0;
86191388Semax			break;
87191388Semax			}
88191388Semax		L[2+_1] = bits[0];
89191388Semax		L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
90191388Semax		break;
91191388Semax
92191388Semax	  case STRTOG_Denormal:
93191388Semax		if (bits[3])
94191388Semax			goto nearly_normal;
95191388Semax		if (bits[2])
96191388Semax			goto partly_normal;
97191388Semax		if (bits[1] & 0xffe00000)
98191388Semax			goto hardly_normal;
99191388Semax		/* completely denormal */
100191388Semax		L[2] = L[3] = 0;
101191388Semax		L[_1] = bits[0];
102191388Semax		L[_0] = bits[1];
103191388Semax		break;
104191388Semax
105191388Semax	  nearly_normal:
106191388Semax		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
107191388Semax		j = 32 - i;
108191388Semax		L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
109191388Semax			| ((65 - i) << 20);
110191388Semax		L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
111191388Semax		L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
112191388Semax		L[2+_1] = bits[0];
113191388Semax		break;
114191388Semax
115191388Semax	  partly_normal:
116191388Semax		i = hi0bits(bits[2]) - 11;
117191388Semax		if (i < 0) {
118191388Semax			j = -i;
119191388Semax			i += 32;
120191388Semax			L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20);
121191388Semax			L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
122191388Semax			L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
123191388Semax			L[2+_1] = bits[0];
124191388Semax			break;
125191388Semax			}
126191388Semax		if (i == 0) {
127191388Semax			L[_0] = (bits[2] & 0xfffff) | (33 << 20);
128191388Semax			L[_1] = bits[1];
129191388Semax			L[2+_0] = 0;
130191388Semax			L[2+_1] = bits[0];
131191388Semax			break;
132191388Semax			}
133191388Semax		j = 32 - i;
134191388Semax		L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
135191388Semax				| ((j + 1) << 20);
136191388Semax		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
137191388Semax		L[2+_0] = 0;
138191388Semax		L[2+_1] = bits[0] & ((1L << j) - 1);
139191388Semax		break;
140191388Semax
141191388Semax	  hardly_normal:
142191388Semax		j = 11 - hi0bits(bits[1]);
143191388Semax		i = 32 - j;
144191388Semax		L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
145191388Semax		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
146191388Semax		L[2+_0] = 0;
147191388Semax		L[2+_1] = bits[0] & (((ULong)1L << j) - 1);
148191388Semax		break;
149191388Semax
150191388Semax	  case STRTOG_Infinite:
151191388Semax		L[_0] = L[2+_0] = 0x7ff00000;
152191388Semax		L[_1] = L[2+_1] = 0;
153191388Semax		break;
154191388Semax
155191388Semax	  case STRTOG_NaN:
156191388Semax		L[0] = L[2] = d_QNAN0;
157191388Semax		L[1] = L[3] = d_QNAN1;
158191388Semax		break;
159191388Semax
160191388Semax	  case STRTOG_NaNbits:
161191388Semax		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
162191388Semax		L[_0] = bits[2] >> 21 | bits[3] << 11
163191388Semax			  | (ULong)0x7ff00000L;
164191388Semax		L[2+_1] = bits[0];
165191388Semax		L[2+_0] = bits[1] | (ULong)0x7ff00000L;
166191388Semax	  }
167191388Semax	if (k & STRTOG_Neg) {
168191388Semax		L[_0] |= 0x80000000L;
169191388Semax		L[2+_0] |= 0x80000000L;
170191388Semax		}
171191388Semax	}
172191388Semax
173191388Semax int
174191388Semax#ifdef KR_headers
175191388Semaxstrtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd;
176191388Semax#else
177191388Semaxstrtordd(CONST char *s, char **sp, int rounding, double *dd)
178191388Semax#endif
179191388Semax{
180191388Semax#ifdef Sudden_Underflow
181191388Semax	static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
182191388Semax#else
183191388Semax	static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
184191388Semax#endif
185191388Semax	FPI *fpi, fpi1;
186191388Semax	ULong bits[4];
187191388Semax	Long exp;
188191388Semax	int k;
189191388Semax
190191388Semax	fpi = &fpi0;
191191388Semax	if (rounding != FPI_Round_near) {
192191388Semax		fpi1 = fpi0;
193191388Semax		fpi1.rounding = rounding;
194191388Semax		fpi = &fpi1;
195191388Semax		}
196191388Semax	k = strtodg(s, sp, fpi, &exp, bits);
197191388Semax	ULtodd((ULong*)dd, bits, exp, k);
198191388Semax	return k;
199191388Semax	}
200191388Semax