strtordd.c revision 112158
1/****************************************************************
2
3The author of this software is David M. Gay.
4
5Copyright (C) 1998, 2000 by Lucent Technologies
6All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and
9its documentation for any purpose and without fee is hereby
10granted, provided that the above copyright notice appear in all
11copies and that both that the copyright notice and this
12permission notice and warranty disclaimer appear in supporting
13documentation, and that the name of Lucent or any of its entities
14not be used in advertising or publicity pertaining to
15distribution of the software without specific, written prior
16permission.
17
18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25THIS SOFTWARE.
26
27****************************************************************/
28
29/* Please send bug reports to
30	David M. Gay
31	Bell Laboratories, Room 2C-463
32	600 Mountain Avenue
33	Murray Hill, NJ 07974-0636
34	U.S.A.
35	dmg@bell-labs.com
36 */
37
38#include "gdtoaimp.h"
39
40 void
41#ifdef KR_headers
42ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
43#else
44ULtodd(ULong *L, ULong *bits, Long exp, int k)
45#endif
46{
47	int i, j;
48
49	switch(k & STRTOG_Retmask) {
50	  case STRTOG_NoNumber:
51	  case STRTOG_Zero:
52		L[0] = L[1] = L[2] = L[3] = 0;
53		break;
54
55	  case STRTOG_Normal:
56		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
57		L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
58			  | exp + 0x3ff + 105 << 20;
59		exp += 0x3ff + 52;
60		if (bits[1] &= 0x1fffff) {
61			i = hi0bits(bits[1]) - 11;
62			if (i >= exp) {
63				i = exp - 1;
64				exp = 0;
65				}
66			else
67				exp -= i;
68			if (i > 0) {
69				bits[1] = bits[1] << i | bits[0] >> 32-i;
70				bits[0] = bits[0] << i & (ULong)0xffffffffL;
71				}
72			}
73		else if (bits[0]) {
74			i = hi0bits(bits[0]) + 21;
75			if (i >= exp) {
76				i = exp - 1;
77				exp = 0;
78				}
79			else
80				exp -= i;
81			if (i < 32) {
82				bits[1] = bits[0] >> 32 - i;
83				bits[0] = bits[0] << i & (ULong)0xffffffffL;
84				}
85			else {
86				bits[1] = bits[0] << i - 32;
87				bits[0] = 0;
88				}
89			}
90		else {
91			L[2] = L[3] = 0;
92			break;
93			}
94		L[2+_1] = bits[0];
95		L[2+_0] = bits[1] & 0xfffff | exp << 20;
96		break;
97
98	  case STRTOG_Denormal:
99		if (bits[3])
100			goto nearly_normal;
101		if (bits[2])
102			goto partly_normal;
103		if (bits[1] & 0xffe00000)
104			goto hardly_normal;
105		/* completely denormal */
106		L[2] = L[3] = 0;
107		L[_1] = bits[0];
108		L[_0] = bits[1];
109		break;
110
111	  nearly_normal:
112		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
113		j = 32 - i;
114		L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
115			| 65 - i << 20;
116		L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
117		L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
118		L[2+_1] = bits[0];
119		break;
120
121	  partly_normal:
122		i = hi0bits(bits[2]) - 11;
123		if (i < 0) {
124			j = -i;
125			i += 32;
126			L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
127			L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
128			L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
129			L[2+_1] = bits[0];
130			break;
131			}
132		if (i == 0) {
133			L[_0] = bits[2] & 0xfffff | 33 << 20;
134			L[_1] = bits[1];
135			L[2+_0] = 0;
136			L[2+_1] = bits[0];
137			break;
138			}
139		j = 32 - i;
140		L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
141				| j + 1 << 20;
142		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
143		L[2+_0] = 0;
144		L[2+_1] = bits[0] & (1L << j) - 1;
145		break;
146
147	  hardly_normal:
148		j = 11 - hi0bits(bits[1]);
149		i = 32 - j;
150		L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
151		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
152		L[2+_0] = 0;
153		L[2+_1] = bits[0] & ((ULong)1L << j) - 1;
154		break;
155
156	  case STRTOG_Infinite:
157		L[_0] = L[2+_0] = 0x7ff00000;
158		L[_1] = L[2+_1] = 0;
159		break;
160
161	  case STRTOG_NaN:
162		L[_0] = L[2+_0] = 0x7fffffff;
163		L[_1] = L[2+_1] = (ULong)-1;
164		break;
165
166	  case STRTOG_NaNbits:
167		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
168		L[_0] = bits[2] >> 21 | bits[3] << 11
169			  | (ULong)0x7ff00000L;
170		L[2+_1] = bits[0];
171		L[2+_0] = bits[1] | (ULong)0x7ff00000L;
172	  }
173	if (k & STRTOG_Neg) {
174		L[_0] |= 0x80000000L;
175		L[2+_0] |= 0x80000000L;
176		}
177	}
178
179 int
180#ifdef KR_headers
181strtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd;
182#else
183strtordd(CONST char *s, char **sp, int rounding, double *dd)
184#endif
185{
186#ifdef Sudden_Underflow
187	static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
188#else
189	static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
190#endif
191	FPI *fpi, fpi1;
192	ULong bits[4];
193	Long exp;
194	int k;
195
196	fpi = &fpi0;
197	if (rounding != FPI_Round_near) {
198		fpi1 = fpi0;
199		fpi1.rounding = rounding;
200		fpi = &fpi1;
201		}
202	k = strtodg(s, sp, fpi, &exp, bits);
203	ULtodd((ULong*)dd, bits, exp, k);
204	return k;
205	}
206