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