mirror of
https://github.com/python/cpython.git
synced 2025-01-19 15:05:15 +08:00
Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
methods (respectively). With Keir Mierle.
This commit is contained in:
parent
2fa33db12b
commit
13e05de9ef
@ -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)
|
||||||
|
@ -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.")
|
||||||
|
Loading…
Reference in New Issue
Block a user