strtordd.c revision 165743
119304Speter/****************************************************************
219304Speter
319304SpeterThe author of this software is David M. Gay.
419304Speter
519304SpeterCopyright (C) 1998, 2000 by Lucent Technologies
619304SpeterAll Rights Reserved
719304Speter
819304SpeterPermission to use, copy, modify, and distribute this software and
919304Speterits documentation for any purpose and without fee is hereby
1019304Spetergranted, provided that the above copyright notice appear in all
1119304Spetercopies and that both that the copyright notice and this
1219304Speterpermission notice and warranty disclaimer appear in supporting
13258231Sgjbdocumentation, and that the name of Lucent or any of its entities
1419304Speternot be used in advertising or publicity pertaining to
1519304Speterdistribution of the software without specific, written prior
1619304Speterpermission.
1719304Speter
18254225SpeterLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1919304SpeterINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
2019304SpeterIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
2119304SpeterSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2219304SpeterWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23254225SpeterIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2419304SpeterARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2519304SpeterTHIS SOFTWARE.
2619304Speter
2719304Speter****************************************************************/
2819304Speter
29254225Speter/* Please send bug reports to David M. Gay (dmg at acm dot org,
30254225Speter * with " at " changed at "@" and " dot " changed to ".").	*/
3119304Speter
3219304Speter#include "gdtoaimp.h"
3319304Speter
3419304Speter void
3519304Speter#ifdef KR_headers
3619304SpeterULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
3719304Speter#else
3819304SpeterULtodd(ULong *L, ULong *bits, Long exp, int k)
3919304Speter#endif
40254225Speter{
4119304Speter	int i, j;
4219304Speter
4319304Speter	switch(k & STRTOG_Retmask) {
4419304Speter	  case STRTOG_NoNumber:
4519304Speter	  case STRTOG_Zero:
4619304Speter		L[0] = L[1] = L[2] = L[3] = 0;
4719304Speter		break;
4819304Speter
4919304Speter	  case STRTOG_Normal:
5019304Speter		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
5119304Speter		L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
5219304Speter			  | exp + 0x3ff + 105 << 20;
5319304Speter		exp += 0x3ff + 52;
5419304Speter		if (bits[1] &= 0x1fffff) {
5519304Speter			i = hi0bits(bits[1]) - 11;
5619304Speter			if (i >= exp) {
5719304Speter				i = exp - 1;
58254225Speter				exp = 0;
5919304Speter				}
6019304Speter			else
6119304Speter				exp -= i;
6219304Speter			if (i > 0) {
6319304Speter				bits[1] = bits[1] << i | bits[0] >> 32-i;
6419304Speter				bits[0] = bits[0] << i & (ULong)0xffffffffL;
6519304Speter				}
6619304Speter			}
6719304Speter		else if (bits[0]) {
6819304Speter			i = hi0bits(bits[0]) + 21;
6919304Speter			if (i >= exp) {
7019304Speter				i = exp - 1;
7119304Speter				exp = 0;
7219304Speter				}
7319304Speter			else
7419304Speter				exp -= i;
7519304Speter			if (i < 32) {
76254225Speter				bits[1] = bits[0] >> 32 - i;
7719304Speter				bits[0] = bits[0] << i & (ULong)0xffffffffL;
7819304Speter				}
7919304Speter			else {
8019304Speter				bits[1] = bits[0] << i - 32;
8119304Speter				bits[0] = 0;
8219304Speter				}
8319304Speter			}
8419304Speter		else {
8519304Speter			L[2] = L[3] = 0;
8619304Speter			break;
8719304Speter			}
8819304Speter		L[2+_1] = bits[0];
8919304Speter		L[2+_0] = bits[1] & 0xfffff | exp << 20;
9019304Speter		break;
9119304Speter
92254225Speter	  case STRTOG_Denormal:
9319304Speter		if (bits[3])
9419304Speter			goto nearly_normal;
9519304Speter		if (bits[2])
9619304Speter			goto partly_normal;
97254225Speter		if (bits[1] & 0xffe00000)
98254225Speter			goto hardly_normal;
9919304Speter		/* completely denormal */
10019304Speter		L[2] = L[3] = 0;
10119304Speter		L[_1] = bits[0];
10219304Speter		L[_0] = bits[1];
10319304Speter		break;
10419304Speter
10519304Speter	  nearly_normal:
10619304Speter		i = hi0bits(bits[3]) - 11;	/* i >= 12 */
10719304Speter		j = 32 - i;
10819304Speter		L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
10919304Speter			| 65 - i << 20;
11019304Speter		L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
11119304Speter		L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
11219304Speter		L[2+_1] = bits[0];
113254225Speter		break;
11419304Speter
11519304Speter	  partly_normal:
116254225Speter		i = hi0bits(bits[2]) - 11;
11719304Speter		if (i < 0) {
11819304Speter			j = -i;
11919304Speter			i += 32;
12019304Speter			L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
12119304Speter			L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
12219304Speter			L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
12319304Speter			L[2+_1] = bits[0];
12419304Speter			break;
12519304Speter			}
12619304Speter		if (i == 0) {
12719304Speter			L[_0] = bits[2] & 0xfffff | 33 << 20;
12819304Speter			L[_1] = bits[1];
12919304Speter			L[2+_0] = 0;
13019304Speter			L[2+_1] = bits[0];
13119304Speter			break;
13219304Speter			}
13319304Speter		j = 32 - i;
13419304Speter		L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
13519304Speter				| j + 1 << 20;
13619304Speter		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
13719304Speter		L[2+_0] = 0;
13819304Speter		L[2+_1] = bits[0] & (1L << j) - 1;
13919304Speter		break;
14019304Speter
14119304Speter	  hardly_normal:
14219304Speter		j = 11 - hi0bits(bits[1]);
14319304Speter		i = 32 - j;
144254225Speter		L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
14519304Speter		L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
14619304Speter		L[2+_0] = 0;
147254225Speter		L[2+_1] = bits[0] & ((ULong)1L << j) - 1;
14819304Speter		break;
14919304Speter
15019304Speter	  case STRTOG_Infinite:
15119304Speter		L[_0] = L[2+_0] = 0x7ff00000;
152254225Speter		L[_1] = L[2+_1] = 0;
15319304Speter		break;
15419304Speter
15519304Speter	  case STRTOG_NaN:
15619304Speter		L[0] = L[2] = d_QNAN0;
15719304Speter		L[1] = L[3] = d_QNAN1;
15819304Speter		break;
15919304Speter
16019304Speter	  case STRTOG_NaNbits:
16119304Speter		L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
16219304Speter		L[_0] = bits[2] >> 21 | bits[3] << 11
16319304Speter			  | (ULong)0x7ff00000L;
16419304Speter		L[2+_1] = bits[0];
16519304Speter		L[2+_0] = bits[1] | (ULong)0x7ff00000L;
16619304Speter	  }
16719304Speter	if (k & STRTOG_Neg) {
168254225Speter		L[_0] |= 0x80000000L;
16919304Speter		L[2+_0] |= 0x80000000L;
170254225Speter		}
17119304Speter	}
17219304Speter
17319304Speter int
17419304Speter#ifdef KR_headers
175254225Speterstrtordd(s, sp, rounding, dd) CONST char *s; char **sp; int rounding; double *dd;
17619304Speter#else
17719304Speterstrtordd(CONST char *s, char **sp, int rounding, double *dd)
17819304Speter#endif
17919304Speter{
180254225Speter#ifdef Sudden_Underflow
18119304Speter	static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
18219304Speter#else
18319304Speter	static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
18419304Speter#endif
18519304Speter	FPI *fpi, fpi1;
18619304Speter	ULong bits[4];
18719304Speter	Long exp;
18819304Speter	int k;
18919304Speter
19019304Speter	fpi = &fpi0;
191254225Speter	if (rounding != FPI_Round_near) {
19219304Speter		fpi1 = fpi0;
19319304Speter		fpi1.rounding = rounding;
19419304Speter		fpi = &fpi1;
19519304Speter		}
19619304Speter	k = strtodg(s, sp, fpi, &exp, bits);
19719304Speter	ULtodd((ULong*)dd, bits, exp, k);
19819304Speter	return k;
19919304Speter	}
20019304Speter