📄 num_get_float.cpp
字号:
uint64 prodhi, prodlo; /* 128b product */
int exp_hi, exp_lo; /* exp = exp_hi*32 + exp_lo */
int hi, lo, tlo, thi; /* offsets in power of ten table */
int norm; /* number of bits of normalization */
int num_hi; /* number of high exponent powers */
bexp = 0;
if (exp > 0) { /* split exponent */
exp_lo = exp;
exp_hi = 0;
if (exp_lo > 27) {
exp_lo++;
while (exp_lo > 27) {
exp_hi++;
exp_lo -= 28;
}
}
tlo = TEN_1;
thi = TEN_27;
num_hi = NUM_HI_P;
}
else if (exp < 0) {
exp_lo = exp;
exp_hi = 0;
while (exp_lo < 0) {
exp_hi++;
exp_lo += 28;
}
tlo = TEN_1;
thi = TEN_M28;
num_hi = NUM_HI_N;
}
else { /* no scaling needed */
return;
}
while (exp_hi) { /* scale */
hi = (min) (exp_hi, num_hi); /* only a few large powers of 10 */
exp_hi -= hi; /* could iterate in extreme case */
hi += thi-1;
_Stl_mult64(p, _Stl_tenpow[hi], prodhi, prodlo);
_Stl_norm_and_round(p, norm, prodhi, prodlo);
bexp += _Stl_twoexp[hi] - norm;
}
if (exp_lo) {
lo = tlo + exp_lo -1;
_Stl_mult64(p, _Stl_tenpow[lo], prodhi, prodlo);
_Stl_norm_and_round(p, norm, prodhi, prodlo);
bexp += _Stl_twoexp[lo] - norm;
}
return;
}
// First argument is a buffer of values from 0 to 9, NOT ascii.
// Second argument is number of digits in buffer, 1 <= digits <= 17.
// Third argument is base-10 exponent.
#if defined (__SC__) || defined (__MRC__)
//*TY 04/06/2000 - powermac's 68K emulator utilizes apple's SANE floating point, which is not compatible with IEEE format.
_STLP_MOVE_TO_STD_NAMESPACE
_STLP_END_NAMESPACE
# include <fp.h>
_STLP_BEGIN_NAMESPACE
_STLP_MOVE_TO_PRIV_NAMESPACE
static inline double _Stl_atod(char *buffer, int ndigit, int dexp) {
decimal d; // ref. inside macintosh powerpc numerics p.9-13
d.sgn = 0;
d.exp = dexp;
d.sig.length = ndigit;
for (int i = 0; i < ndigit; ++i) {
d.sig.text[i] = buffer[i] + '0';
}
return dec2num(&d);
}
#else /* IEEE representation */
# if !defined (__linux__)
static double _Stl_atod(char *buffer, int ndigit, int dexp) {
uint64 value; /* Value develops as follows:
* 1) decimal digits as an integer
* 2) left adjusted fraction
* 3) right adjusted fraction
* 4) exponent and fraction
*/
uint32 guard; /* First guard bit */
uint64 rest; /* Remaining guard bits */
int bexp; /* binary exponent */
int nzero; /* number of non-zero bits */
int sexp; /* scaling exponent */
char *bufferend; /* pointer to char after last digit */
/* Check for zero and treat it as a special case */
if (buffer == 0){
return 0.0;
}
/* Convert the decimal digits to a binary integer. */
bufferend = buffer + ndigit;
value = 0;
while (buffer < bufferend) {
value *= 10;
value += *buffer++;
}
/* Check for zero and treat it as a special case */
if (value == 0) {
return 0.0;
}
/* Normalize value */
bexp = 64; /* convert from 64b int to fraction */
/* Count number of non-zeroes in value */
nzero = 0;
if ((value >> 32) != 0) { nzero = 32; } //*TY 03/25/2000 - added explicit comparison to zero to avoid uint64 to bool conversion operator
if ((value >> (16 + nzero)) != 0) { nzero += 16; }
if ((value >> ( 8 + nzero)) != 0) { nzero += 8; }
if ((value >> ( 4 + nzero)) != 0) { nzero += 4; }
if ((value >> ( 2 + nzero)) != 0) { nzero += 2; }
if ((value >> ( 1 + nzero)) != 0) { nzero += 1; }
if ((value >> ( nzero)) != 0) { nzero += 1; }
/* Normalize */
value <<= /*(uint64)*/ (64 - nzero); //*TY 03/25/2000 - removed extraneous cast to uint64
bexp -= 64 - nzero;
/* At this point we have a 64b fraction and a binary exponent
* but have yet to incorporate the decimal exponent.
*/
/* multiply by 10^dexp */
_Stl_tenscale(value, dexp, sexp);
bexp += sexp;
if (bexp <= -1022) { /* HI denorm or underflow */
bexp += 1022;
if (bexp < -53) { /* guaranteed underflow */
value = 0;
}
else { /* denorm or possible underflow */
int lead0 = 12 - bexp; /* 12 sign and exponent bits */
/* we must special case right shifts of more than 63 */
if (lead0 > 64) {
rest = value;
guard = 0;
value = 0;
}
else if (lead0 == 64) {
rest = value & ((ULL(1)<< 63)-1);
#if !defined(__SC__)
guard = (uint32) ((value>> 63) & 1 );
#else
guard = to_ulong((value>> 63) & 1 ); //*TY 03/25/2000 - use member function instead of problematic conversion operator utilization
#endif
value = 0;
}
else {
rest = value & (((ULL(1) << lead0)-1)-1);
#if !defined(__SC__)
guard = (uint32) (((value>> lead0)-1) & 1);
#else //*TY 03/25/2000 -
guard = to_ulong(((value>> lead0)-1) & 1);
#endif //*TY 03/25/2000 -
value >>= /*(uint64)*/ lead0; /* exponent is zero */
}
/* Round */
if (guard && ((value & 1) || rest) ) {
++value;
if (value == (ULL(1) << 52)) { /* carry created normal number */
value = 0;
_Stl_set_exponent(value, 1);
}
}
}
}
else { /* not zero or denorm */
/* Round to 53 bits */
rest = value & (1<<10)-1;
value >>= 10;
#if !defined(__SC__)
guard = (uint32) value & 1;
#else //*TY 03/25/2000 -
guard = to_ulong(value & 1);
#endif
value >>= 1;
/* value&1 guard rest Action
*
* dc 0 dc none
* 1 1 dc round
* 0 1 0 none
* 0 1 !=0 round
*/
if (guard) {
if (((value&1)!=0) || (rest!=0)) {
++value; /* round */
if ((value >> 53) != 0) { /* carry all the way across */
value >>= 1; /* renormalize */
++bexp;
}
}
}
/*
* Check for overflow
* IEEE Double Precision Format
* (From Table 7-8 of Kane and Heinrich)
*
* Fraction bits 52
* Emax +1023
* Emin -1022
* Exponent bias +1023
* Exponent bits 11
* Integer bit hidden
* Total width in bits 64
*/
if (bexp > 1024) { /* overflow */
return numeric_limits<double>::infinity();
}
else { /* value is normal */
value &= ~(ULL(1) << 52); /* hide hidden bit */
_Stl_set_exponent(value, bexp + 1022); /* add bias */
}
}
_STLP_STATIC_ASSERT(sizeof(value) == sizeof(double))
return *((double *) &value);
}
# else // __linux__
static double _Stl_atod(char *buffer, int ndigit, int dexp) {
ieee754_double v;
char *bufferend; /* pointer to char after last digit */
/* Check for zero and treat it as a special case */
if (buffer == 0) {
return 0.0;
}
/* Convert the decimal digits to a binary integer. */
bufferend = buffer + ndigit;
_ll vv;
vv.i64 = 0L;
while (buffer < bufferend) {
vv.i64 *= 10;
vv.i64 += *buffer++;
}
/* Check for zero and treat it as a special case */
if (vv.i64 == 0){
return 0.0;
}
/* Normalize value */
int bexp = 64; /* convert from 64b int to fraction */
/* Count number of non-zeroes in value */
int nzero = 0;
if ((vv.i64 >> 32) !=0 ) { nzero = 32; } //*TY 03/25/2000 - added explicit comparison to zero to avoid uint64 to bool conversion operator
if ((vv.i64 >> (16 + nzero)) != 0) { nzero += 16; }
if ((vv.i64 >> ( 8 + nzero)) != 0) { nzero += 8; }
if ((vv.i64 >> ( 4 + nzero)) != 0) { nzero += 4; }
if ((vv.i64 >> ( 2 + nzero)) != 0) { nzero += 2; }
if ((vv.i64 >> ( 1 + nzero)) != 0) { nzero += 1; }
if ((vv.i64 >> ( nzero)) != 0) { nzero += 1; }
/* Normalize */
nzero = 64 - nzero;
vv.i64 <<= nzero; //*TY 03/25/2000 - removed extraneous cast to uint64
bexp -= nzero;
/* At this point we have a 64b fraction and a binary exponent
* but have yet to incorporate the decimal exponent.
*/
/* multiply by 10^dexp */
int sexp;
_Stl_tenscale(vv.i64, dexp, sexp);
bexp += sexp;
if (bexp <= -1022) { /* HI denorm or underflow */
bexp += 1022;
if (bexp < -53) { /* guaranteed underflow */
vv.i64 = 0;
}
else { /* denorm or possible underflow */
int lead0;
uint64_t rest;
uint32_t guard;
lead0 = 12-bexp; /* 12 sign and exponent bits */
/* we must special case right shifts of more than 63 */
if (lead0 > 64) {
rest = vv.i64;
guard = 0;
vv.i64 = 0;
}
else if (lead0 == 64) {
rest = vv.i64 & ((ULL(1) << 63)-1);
#if !defined(__SC__)
guard = (uint32) ((vv.i64 >> 63) & 1 );
#else
guard = to_ulong((vv.i64 >> 63) & 1 ); //*TY 03/25/2000 - use member function instead of problematic conversion operator utilization
#endif
vv.i64 = 0;
}
else {
rest = vv.i64 & (((ULL(1) << lead0)-1)-1);
#if !defined(__SC__)
guard = (uint32) (((vv.i64 >> lead0)-1) & 1);
#else //*TY 03/25/2000 -
guard = to_ulong(((vv.i64 >> lead0)-1) & 1);
#endif //*TY 03/25/2000 -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -