mirror of
https://github.com/python/cpython.git
synced 2025-08-17 15:21:26 +00:00
Merged revisions 72564 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r72564 | mark.dickinson | 2009-05-11 16:33:08 +0100 (Mon, 11 May 2009) | 2 lines Issue #5981: Fix some float.fromhex bugs related to inf and nan handling. ........
This commit is contained in:
parent
fd9258d0dd
commit
ce05717daa
3 changed files with 73 additions and 17 deletions
|
@ -391,6 +391,11 @@ class HexFloatTestCase(unittest.TestCase):
|
||||||
'snan',
|
'snan',
|
||||||
'NaNs',
|
'NaNs',
|
||||||
'nna',
|
'nna',
|
||||||
|
'an',
|
||||||
|
'nf',
|
||||||
|
'nfinity',
|
||||||
|
'inity',
|
||||||
|
'iinity',
|
||||||
'0xnan',
|
'0xnan',
|
||||||
'',
|
'',
|
||||||
' ',
|
' ',
|
||||||
|
@ -439,6 +444,32 @@ class HexFloatTestCase(unittest.TestCase):
|
||||||
'got %r instead' % (x, result))
|
'got %r instead' % (x, result))
|
||||||
|
|
||||||
|
|
||||||
|
def test_whitespace(self):
|
||||||
|
value_pairs = [
|
||||||
|
('inf', INF),
|
||||||
|
('-Infinity', -INF),
|
||||||
|
('nan', NAN),
|
||||||
|
('1.0', 1.0),
|
||||||
|
('-0x.2', -0.125),
|
||||||
|
('-0.0', -0.0)
|
||||||
|
]
|
||||||
|
whitespace = [
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
'\t',
|
||||||
|
'\n',
|
||||||
|
'\n \t',
|
||||||
|
'\f',
|
||||||
|
'\v',
|
||||||
|
'\r'
|
||||||
|
]
|
||||||
|
for inp, expected in value_pairs:
|
||||||
|
for lead in whitespace:
|
||||||
|
for trail in whitespace:
|
||||||
|
got = fromHex(lead + inp + trail)
|
||||||
|
self.identical(got, expected)
|
||||||
|
|
||||||
|
|
||||||
def test_from_hex(self):
|
def test_from_hex(self):
|
||||||
MIN = self.MIN;
|
MIN = self.MIN;
|
||||||
MAX = self.MAX;
|
MAX = self.MAX;
|
||||||
|
|
|
@ -12,6 +12,11 @@ What's New in Python 2.6.3
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #5981: Fix two minor inf/nan issues in float.fromhex: (1) inf
|
||||||
|
and nan strings with trailing whitespace were incorrectly rejected
|
||||||
|
and (2) the interpretation of fromhex('-nan') didn't match that of
|
||||||
|
float('-nan').
|
||||||
|
|
||||||
- Issue #5890: in subclasses of 'property' the __doc__ attribute was
|
- Issue #5890: in subclasses of 'property' the __doc__ attribute was
|
||||||
shadowed by classtype's, even if it was None. property now
|
shadowed by classtype's, even if it was None. property now
|
||||||
inserts the __doc__ into the subclass instance __dict__.
|
inserts the __doc__ into the subclass instance __dict__.
|
||||||
|
|
|
@ -1263,6 +1263,20 @@ Return a hexadecimal representation of a floating-point number.\n\
|
||||||
>>> 3.14159.hex()\n\
|
>>> 3.14159.hex()\n\
|
||||||
'0x1.921f9f01b866ep+1'");
|
'0x1.921f9f01b866ep+1'");
|
||||||
|
|
||||||
|
/* Case-insensitive string match used for nan and inf detection. t should be
|
||||||
|
lower-case and null-terminated. Return a nonzero result if the first
|
||||||
|
strlen(t) characters of s match t and 0 otherwise. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
case_insensitive_match(const char *s, const char *t)
|
||||||
|
{
|
||||||
|
while(*t && tolower(*s) == *t) {
|
||||||
|
s++;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
return *t ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a hexadecimal string to a float. */
|
/* Convert a hexadecimal string to a float. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1329,7 +1343,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
********************/
|
********************/
|
||||||
|
|
||||||
/* leading whitespace and optional sign */
|
/* leading whitespace and optional sign */
|
||||||
while (isspace(*s))
|
while (*s && isspace(Py_CHARMASK(*s)))
|
||||||
s++;
|
s++;
|
||||||
if (*s == '-') {
|
if (*s == '-') {
|
||||||
s++;
|
s++;
|
||||||
|
@ -1339,13 +1353,20 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
s++;
|
s++;
|
||||||
|
|
||||||
/* infinities and nans */
|
/* infinities and nans */
|
||||||
if (PyOS_strnicmp(s, "nan", 4) == 0) {
|
if (*s == 'i' || *s == 'I') {
|
||||||
x = Py_NAN;
|
if (!case_insensitive_match(s+1, "nf"))
|
||||||
|
goto parse_error;
|
||||||
|
s += 3;
|
||||||
|
x = Py_HUGE_VAL;
|
||||||
|
if (case_insensitive_match(s, "inity"))
|
||||||
|
s += 5;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
if (PyOS_strnicmp(s, "inf", 4) == 0 ||
|
if (*s == 'n' || *s == 'N') {
|
||||||
PyOS_strnicmp(s, "infinity", 9) == 0) {
|
if (!case_insensitive_match(s+1, "an"))
|
||||||
x = sign*Py_HUGE_VAL;
|
goto parse_error;
|
||||||
|
s += 3;
|
||||||
|
x = Py_NAN;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,12 +1419,6 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
else
|
else
|
||||||
exp = 0;
|
exp = 0;
|
||||||
|
|
||||||
/* optional trailing whitespace leading to the end of the string */
|
|
||||||
while (isspace(*s))
|
|
||||||
s++;
|
|
||||||
if (s != s_end)
|
|
||||||
goto parse_error;
|
|
||||||
|
|
||||||
/* for 0 <= j < ndigits, HEX_DIGIT(j) gives the jth most significant digit */
|
/* for 0 <= j < ndigits, HEX_DIGIT(j) gives the jth most significant digit */
|
||||||
#define HEX_DIGIT(j) hex_from_char(*((j) < fdigits ? \
|
#define HEX_DIGIT(j) hex_from_char(*((j) < fdigits ? \
|
||||||
coeff_end-(j) : \
|
coeff_end-(j) : \
|
||||||
|
@ -1417,7 +1432,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
while (ndigits > 0 && HEX_DIGIT(ndigits-1) == 0)
|
while (ndigits > 0 && HEX_DIGIT(ndigits-1) == 0)
|
||||||
ndigits--;
|
ndigits--;
|
||||||
if (ndigits == 0 || exp < LONG_MIN/2) {
|
if (ndigits == 0 || exp < LONG_MIN/2) {
|
||||||
x = sign * 0.0;
|
x = 0.0;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
if (exp > LONG_MAX/2)
|
if (exp > LONG_MAX/2)
|
||||||
|
@ -1433,7 +1448,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
|
|
||||||
/* catch almost all nonextreme cases of overflow and underflow here */
|
/* catch almost all nonextreme cases of overflow and underflow here */
|
||||||
if (top_exp < DBL_MIN_EXP - DBL_MANT_DIG) {
|
if (top_exp < DBL_MIN_EXP - DBL_MANT_DIG) {
|
||||||
x = sign * 0.0;
|
x = 0.0;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
if (top_exp > DBL_MAX_EXP)
|
if (top_exp > DBL_MAX_EXP)
|
||||||
|
@ -1448,7 +1463,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
/* no rounding required */
|
/* no rounding required */
|
||||||
for (i = ndigits-1; i >= 0; i--)
|
for (i = ndigits-1; i >= 0; i--)
|
||||||
x = 16.0*x + HEX_DIGIT(i);
|
x = 16.0*x + HEX_DIGIT(i);
|
||||||
x = sign * ldexp(x, (int)(exp));
|
x = ldexp(x, (int)(exp));
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
/* rounding required. key_digit is the index of the hex digit
|
/* rounding required. key_digit is the index of the hex digit
|
||||||
|
@ -1482,10 +1497,15 @@ float_fromhex(PyObject *cls, PyObject *arg)
|
||||||
goto overflow_error;
|
goto overflow_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x = sign * ldexp(x, (int)(exp+4*key_digit));
|
x = ldexp(x, (int)(exp+4*key_digit));
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
result_as_float = Py_BuildValue("(d)", x);
|
/* optional trailing whitespace leading to the end of the string */
|
||||||
|
while (*s && isspace(Py_CHARMASK(*s)))
|
||||||
|
s++;
|
||||||
|
if (s != s_end)
|
||||||
|
goto parse_error;
|
||||||
|
result_as_float = Py_BuildValue("(d)", sign * x);
|
||||||
if (result_as_float == NULL)
|
if (result_as_float == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
result = PyObject_CallObject(cls, result_as_float);
|
result = PyObject_CallObject(cls, result_as_float);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue