Home | History | Annotate | Line # | Download | only in gdtoa
strtordd.c revision 1.1.1.2
      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