diff options
author | Jeffrey Yasskin <jyasskin@gmail.com> | 2008-01-03 02:21:52 (GMT) |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@gmail.com> | 2008-01-03 02:21:52 (GMT) |
commit | 2f3c16be73a8562d357b9b13bbb8088e275840a7 (patch) | |
tree | 5334d4bd6c8b6456da10c0be232fb8bf95b1aca7 /Objects/floatobject.c | |
parent | 27edd829d7673a642cf5b37c3011454ec33cb715 (diff) | |
download | cpython-2f3c16be73a8562d357b9b13bbb8088e275840a7.zip cpython-2f3c16be73a8562d357b9b13bbb8088e275840a7.tar.gz cpython-2f3c16be73a8562d357b9b13bbb8088e275840a7.tar.bz2 |
Backport PEP 3141 from the py3k branch to the trunk. This includes r50877 (just
the complex_pow part), r56649, r56652, r56715, r57296, r57302, r57359, r57361,
r57372, r57738, r57739, r58017, r58039, r58040, and r59390, and new
documentation. The only significant difference is that round(x) returns a float
to preserve backward-compatibility. See http://bugs.python.org/issue1689.
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r-- | Objects/floatobject.c | 108 |
1 files changed, 82 insertions, 26 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 5d0b920..574b96a 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -986,9 +986,10 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) * bugs so we have to figure it out ourselves. */ if (iw != floor(iw)) { - PyErr_SetString(PyExc_ValueError, "negative number " - "cannot be raised to a fractional power"); - return NULL; + /* Negative numbers raised to fractional powers + * become complex. + */ + return PyComplex_Type.tp_as_number->nb_power(v, w, z); } /* iw is an exact integer, albeit perhaps a very large one. * -1 raised to an exact integer should never be exceptional. @@ -1035,17 +1036,6 @@ float_neg(PyFloatObject *v) } static PyObject * -float_pos(PyFloatObject *v) -{ - if (PyFloat_CheckExact(v)) { - Py_INCREF(v); - return (PyObject *)v; - } - else - return PyFloat_FromDouble(v->ob_fval); -} - -static PyObject * float_abs(PyFloatObject *v) { return PyFloat_FromDouble(fabs(v->ob_fval)); @@ -1083,14 +1073,7 @@ float_coerce(PyObject **pv, PyObject **pw) } static PyObject * -float_long(PyObject *v) -{ - double x = PyFloat_AsDouble(v); - return PyLong_FromDouble(x); -} - -static PyObject * -float_int(PyObject *v) +float_trunc(PyObject *v) { double x = PyFloat_AsDouble(v); double wholepart; /* integral portion of x, rounded toward 0 */ @@ -1116,6 +1099,54 @@ float_int(PyObject *v) } static PyObject * +float_round(PyObject *v, PyObject *args) +{ +#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */ + double x; + double f; + double flr, cil; + double rounded; + int i; + int ndigits = UNDEF_NDIGITS; + + if (!PyArg_ParseTuple(args, "|i", &ndigits)) + return NULL; + + x = PyFloat_AsDouble(v); + + if (ndigits != UNDEF_NDIGITS) { + f = 1.0; + i = abs(ndigits); + while (--i >= 0) + f = f*10.0; + if (ndigits < 0) + x /= f; + else + x *= f; + } + + flr = floor(x); + cil = ceil(x); + + if (x-flr > 0.5) + rounded = cil; + else if (x-flr == 0.5) + rounded = fmod(flr, 2) == 0 ? flr : cil; + else + rounded = flr; + + if (ndigits != UNDEF_NDIGITS) { + if (ndigits < 0) + rounded *= f; + else + rounded /= f; + } + + return PyFloat_FromDouble(rounded); +#undef UNDEF_NDIGITS +} + +static PyObject * float_float(PyObject *v) { if (PyFloat_CheckExact(v)) @@ -1302,7 +1333,20 @@ PyDoc_STRVAR(float_setformat_doc, "Overrides the automatic determination of C-level floating point type.\n" "This affects how floats are converted to and from binary strings."); +static PyObject * +float_getzero(PyObject *v, void *closure) +{ + return PyFloat_FromDouble(0.0); +} + static PyMethodDef float_methods[] = { + {"conjugate", (PyCFunction)float_float, METH_NOARGS, + "Returns self, the complex conjugate of any float."}, + {"__trunc__", (PyCFunction)float_trunc, METH_NOARGS, + "Returns the Integral closest to x between 0 and x."}, + {"__round__", (PyCFunction)float_round, METH_VARARGS, + "Returns the Integral closest to x, rounding half toward even.\n" + "When an argument is passed, works like built-in round(x, ndigits)."}, {"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS}, {"__getformat__", (PyCFunction)float_getformat, METH_O|METH_CLASS, float_getformat_doc}, @@ -1311,6 +1355,18 @@ static PyMethodDef float_methods[] = { {NULL, NULL} /* sentinel */ }; +static PyGetSetDef float_getset[] = { + {"real", + (getter)float_float, (setter)NULL, + "the real part of a complex number", + NULL}, + {"imag", + (getter)float_getzero, (setter)NULL, + "the imaginary part of a complex number", + NULL}, + {NULL} /* Sentinel */ +}; + PyDoc_STRVAR(float_doc, "float(x) -> floating point number\n\ \n\ @@ -1326,7 +1382,7 @@ static PyNumberMethods float_as_number = { float_divmod, /*nb_divmod*/ float_pow, /*nb_power*/ (unaryfunc)float_neg, /*nb_negative*/ - (unaryfunc)float_pos, /*nb_positive*/ + (unaryfunc)float_float, /*nb_positive*/ (unaryfunc)float_abs, /*nb_absolute*/ (inquiry)float_nonzero, /*nb_nonzero*/ 0, /*nb_invert*/ @@ -1336,8 +1392,8 @@ static PyNumberMethods float_as_number = { 0, /*nb_xor*/ 0, /*nb_or*/ float_coerce, /*nb_coerce*/ - float_int, /*nb_int*/ - float_long, /*nb_long*/ + float_trunc, /*nb_int*/ + float_trunc, /*nb_long*/ float_float, /*nb_float*/ 0, /* nb_oct */ 0, /* nb_hex */ @@ -1389,7 +1445,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_iternext */ float_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + float_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ |