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