diff options
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r-- | Objects/floatobject.c | 105 |
1 files changed, 57 insertions, 48 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index d92bec35b5f..da600f4aa82 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -215,35 +215,49 @@ double PyFloat_AsDouble(PyObject *op) { PyNumberMethods *nb; - PyFloatObject *fo; + PyObject *res; double val; - if (op && PyFloat_Check(op)) - return PyFloat_AS_DOUBLE((PyFloatObject*) op); - if (op == NULL) { PyErr_BadArgument(); return -1; } - if ((nb = Py_TYPE(op)->tp_as_number) == NULL || nb->nb_float == NULL) { - PyErr_SetString(PyExc_TypeError, "a float is required"); - return -1; + if (PyFloat_Check(op)) { + return PyFloat_AS_DOUBLE(op); } - fo = (PyFloatObject*) (*nb->nb_float) (op); - if (fo == NULL) - return -1; - if (!PyFloat_Check(fo)) { - Py_DECREF(fo); - PyErr_SetString(PyExc_TypeError, - "nb_float should return float object"); + nb = Py_TYPE(op)->tp_as_number; + if (nb == NULL || nb->nb_float == NULL) { + PyErr_Format(PyExc_TypeError, "must be real number, not %.50s", + op->ob_type->tp_name); return -1; } - val = PyFloat_AS_DOUBLE(fo); - Py_DECREF(fo); + res = (*nb->nb_float) (op); + if (res == NULL) { + return -1; + } + if (!PyFloat_CheckExact(res)) { + if (!PyFloat_Check(res)) { + PyErr_Format(PyExc_TypeError, + "%.50s.__float__ returned non-float (type %.50s)", + op->ob_type->tp_name, res->ob_type->tp_name); + Py_DECREF(res); + return -1; + } + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "%.50s.__float__ returned non-float (type %.50s). " + "The ability to return an instance of a strict subclass of float " + "is deprecated, and may be removed in a future version of Python.", + op->ob_type->tp_name, res->ob_type->tp_name)) { + Py_DECREF(res); + return -1; + } + } + val = PyFloat_AS_DOUBLE(res); + Py_DECREF(res); return val; } @@ -1195,7 +1209,7 @@ Return a hexadecimal representation of a floating-point number.\n\ static PyObject * float_fromhex(PyObject *cls, PyObject *arg) { - PyObject *result_as_float, *result; + PyObject *result; double x; long exp, top_exp, lsb, key_digit; char *s, *coeff_start, *s_store, *coeff_end, *exp_start, *s_end; @@ -1410,11 +1424,10 @@ float_fromhex(PyObject *cls, PyObject *arg) s++; if (s != s_end) goto parse_error; - result_as_float = Py_BuildValue("(d)", negate ? -x : x); - if (result_as_float == NULL) - return NULL; - result = PyObject_CallObject(cls, result_as_float); - Py_DECREF(result_as_float); + result = PyFloat_FromDouble(negate ? -x : x); + if (cls != (PyObject *)&PyFloat_Type && result != NULL) { + Py_SETREF(result, PyObject_CallFunctionObjArgs(cls, result, NULL)); + } return result; overflow_error: @@ -1451,29 +1464,23 @@ float_as_integer_ratio(PyObject *v, PyObject *unused) int exponent; int i; - PyObject *prev; PyObject *py_exponent = NULL; PyObject *numerator = NULL; PyObject *denominator = NULL; PyObject *result_pair = NULL; PyNumberMethods *long_methods = PyLong_Type.tp_as_number; -#define INPLACE_UPDATE(obj, call) \ - prev = obj; \ - obj = call; \ - Py_DECREF(prev); \ - CONVERT_TO_DOUBLE(v, self); if (Py_IS_INFINITY(self)) { - PyErr_SetString(PyExc_OverflowError, - "Cannot pass infinity to float.as_integer_ratio."); - return NULL; + PyErr_SetString(PyExc_OverflowError, + "cannot convert Infinity to integer ratio"); + return NULL; } if (Py_IS_NAN(self)) { - PyErr_SetString(PyExc_ValueError, - "Cannot pass NaN to float.as_integer_ratio."); - return NULL; + PyErr_SetString(PyExc_ValueError, + "cannot convert NaN to integer ratio"); + return NULL; } PyFPE_START_PROTECT("as_integer_ratio", goto error); @@ -1489,29 +1496,31 @@ float_as_integer_ratio(PyObject *v, PyObject *unused) to be truncated by PyLong_FromDouble(). */ numerator = PyLong_FromDouble(float_part); - if (numerator == NULL) goto error; + if (numerator == NULL) + goto error; + denominator = PyLong_FromLong(1); + if (denominator == NULL) + goto error; + py_exponent = PyLong_FromLong(Py_ABS(exponent)); + if (py_exponent == NULL) + goto error; /* fold in 2**exponent */ - denominator = PyLong_FromLong(1); - py_exponent = PyLong_FromLong(labs((long)exponent)); - if (py_exponent == NULL) goto error; - INPLACE_UPDATE(py_exponent, - long_methods->nb_lshift(denominator, py_exponent)); - if (py_exponent == NULL) goto error; if (exponent > 0) { - INPLACE_UPDATE(numerator, - long_methods->nb_multiply(numerator, py_exponent)); - if (numerator == NULL) goto error; + Py_SETREF(numerator, + long_methods->nb_lshift(numerator, py_exponent)); + if (numerator == NULL) + goto error; } else { - Py_DECREF(denominator); - denominator = py_exponent; - py_exponent = NULL; + Py_SETREF(denominator, + long_methods->nb_lshift(denominator, py_exponent)); + if (denominator == NULL) + goto error; } result_pair = PyTuple_Pack(2, numerator, denominator); -#undef INPLACE_UPDATE error: Py_XDECREF(py_exponent); Py_XDECREF(denominator); |