summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/floatobject.c67
-rw-r--r--Objects/longobject.c36
2 files changed, 93 insertions, 10 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 908258c..09efa12 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -743,14 +743,7 @@ float_bool(PyFloatObject *v)
}
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 */
@@ -776,6 +769,55 @@ 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);
+ }
+
+ return PyLong_FromDouble(rounded);
+#undef UNDEF_NDIGITS
+}
+
+static PyObject *
float_float(PyObject *v)
{
if (PyFloat_CheckExact(v))
@@ -976,6 +1018,11 @@ float_getzero(PyObject *v, void *closure)
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},
@@ -1020,8 +1067,8 @@ static PyNumberMethods float_as_number = {
0, /*nb_xor*/
0, /*nb_or*/
(coercion)0, /*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 */
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 518e607..ddf359d 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -3592,9 +3592,45 @@ long_getN(PyLongObject *v, void *context) {
return PyLong_FromLong((intptr_t)context);
}
+static PyObject *
+long_round(PyObject *self, PyObject *args)
+{
+#define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */
+ int ndigits = UNDEF_NDIGITS;
+ double x;
+ PyObject *res;
+
+ if (!PyArg_ParseTuple(args, "|i", &ndigits))
+ return NULL;
+
+ if (ndigits == UNDEF_NDIGITS)
+ return long_long(self);
+
+ /* If called with two args, defer to float.__round__(). */
+ x = PyLong_AsDouble(self);
+ if (x == -1.0 && PyErr_Occurred())
+ return NULL;
+ self = PyFloat_FromDouble(x);
+ if (self == NULL)
+ return NULL;
+ res = PyObject_CallMethod(self, "__round__", "i", ndigits);
+ Py_DECREF(self);
+ return res;
+#undef UNDEF_NDIGITS
+}
+
static PyMethodDef long_methods[] = {
{"conjugate", (PyCFunction)long_long, METH_NOARGS,
"Returns self, the complex conjugate of any int."},
+ {"__trunc__", (PyCFunction)long_long, METH_NOARGS,
+ "Truncating an Integral returns itself."},
+ {"__floor__", (PyCFunction)long_long, METH_NOARGS,
+ "Flooring an Integral returns itself."},
+ {"__ceil__", (PyCFunction)long_long, METH_NOARGS,
+ "Ceiling of an Integral returns itself."},
+ {"__round__", (PyCFunction)long_round, METH_VARARGS,
+ "Rounding an Integral returns itself.\n"
+ "Rounding with an ndigits arguments defers to float.__round__."},
{"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
{NULL, NULL} /* sentinel */
};