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