Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__

methods (respectively).  With Keir Mierle.
This commit is contained in:
Guido van Rossum 2007-08-23 22:56:55 +00:00
parent 2fa33db12b
commit 13e05de9ef
2 changed files with 70 additions and 6 deletions

View File

@ -58,6 +58,19 @@ class MathTests(unittest.TestCase):
self.ftest('ceil(-1.0)', math.ceil(-1.0), -1) self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
self.ftest('ceil(-1.5)', math.ceil(-1.5), -1) self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
class TestCeil:
def __ceil__(self):
return 42
class TestNoCeil:
pass
self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
self.assertRaises(TypeError, math.ceil, TestNoCeil())
t = TestNoCeil()
t.__ceil__ = lambda *args: args
self.assertRaises(TypeError, math.ceil, t)
self.assertRaises(TypeError, math.ceil, t, 0)
def testCos(self): def testCos(self):
self.assertRaises(TypeError, math.cos) self.assertRaises(TypeError, math.cos)
self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0) self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
@ -101,6 +114,19 @@ class MathTests(unittest.TestCase):
self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167) self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167) self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
class TestFloor:
def __floor__(self):
return 42
class TestNoFloor:
pass
self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
self.assertRaises(TypeError, math.floor, TestNoFloor())
t = TestNoFloor()
t.__floor__ = lambda *args: args
self.assertRaises(TypeError, math.floor, t)
self.assertRaises(TypeError, math.floor, t, 0)
def testFmod(self): def testFmod(self):
self.assertRaises(TypeError, math.fmod) self.assertRaises(TypeError, math.fmod)
self.ftest('fmod(10,1)', math.fmod(10,1), 0) self.ftest('fmod(10,1)', math.fmod(10,1), 0)

View File

@ -107,9 +107,28 @@ FUNC1(atan, atan,
FUNC2(atan2, atan2, FUNC2(atan2, atan2,
"atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n" "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
"Unlike atan(y/x), the signs of both x and y are considered.") "Unlike atan(y/x), the signs of both x and y are considered.")
FUNC1(ceil, ceil,
"ceil(x)\n\nReturn the ceiling of x as a float.\n" static PyObject * math_ceil(PyObject *self, PyObject *number) {
"This is the smallest integral value >= x.") static PyObject *ceil_str = NULL;
PyObject *method;
if (ceil_str == NULL) {
ceil_str = PyUnicode_FromString("__ceil__");
if (ceil_str == NULL)
return NULL;
}
method = _PyType_Lookup(Py_Type(number), ceil_str);
if (method == NULL)
return math_1(number, ceil);
else
return PyObject_CallFunction(method, "O", number);
}
PyDoc_STRVAR(math_ceil_doc,
"ceil(x)\n\nReturn the ceiling of x as a float.\n"
"This is the smallest integral value >= x.");
FUNC1(cos, cos, FUNC1(cos, cos,
"cos(x)\n\nReturn the cosine of x (measured in radians).") "cos(x)\n\nReturn the cosine of x (measured in radians).")
FUNC1(cosh, cosh, FUNC1(cosh, cosh,
@ -118,9 +137,28 @@ FUNC1(exp, exp,
"exp(x)\n\nReturn e raised to the power of x.") "exp(x)\n\nReturn e raised to the power of x.")
FUNC1(fabs, fabs, FUNC1(fabs, fabs,
"fabs(x)\n\nReturn the absolute value of the float x.") "fabs(x)\n\nReturn the absolute value of the float x.")
FUNC1(floor, floor,
"floor(x)\n\nReturn the floor of x as a float.\n" static PyObject * math_floor(PyObject *self, PyObject *number) {
"This is the largest integral value <= x.") static PyObject *floor_str = NULL;
PyObject *method;
if (floor_str == NULL) {
floor_str = PyUnicode_FromString("__floor__");
if (floor_str == NULL)
return NULL;
}
method = _PyType_Lookup(Py_Type(number), floor_str);
if (method == NULL)
return math_1(number, floor);
else
return PyObject_CallFunction(method, "O", number);
}
PyDoc_STRVAR(math_floor_doc,
"floor(x)\n\nReturn the floor of x as a float.\n"
"This is the largest integral value <= x.");
FUNC2(fmod, fmod, FUNC2(fmod, fmod,
"fmod(x,y)\n\nReturn fmod(x, y), according to platform C." "fmod(x,y)\n\nReturn fmod(x, y), according to platform C."
" x % y may differ.") " x % y may differ.")