Commit a8b3a0db authored by Jeffrey Yasskin's avatar Jeffrey Yasskin

Move __builtins__.trunc() to math.trunc() per

http://mail.python.org/pipermail/python-dev/2008-January/076626.html and issue
1965.
parent 8399f1b9
...@@ -1145,14 +1145,6 @@ available. They are listed here in alphabetical order. ...@@ -1145,14 +1145,6 @@ available. They are listed here in alphabetical order.
.. versionadded:: 2.2 .. versionadded:: 2.2
.. function:: trunc(x)
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
a long integer). Delegates to ``x.__trunc__()``.
.. versionadded:: 2.6
.. function:: tuple([iterable]) .. function:: tuple([iterable])
Return a tuple whose items are the same and in the same order as *iterable*'s Return a tuple whose items are the same and in the same order as *iterable*'s
......
...@@ -103,6 +103,14 @@ Number-theoretic and representation functions: ...@@ -103,6 +103,14 @@ Number-theoretic and representation functions:
Return the fractional and integer parts of *x*. Both results carry the sign of Return the fractional and integer parts of *x*. Both results carry the sign of
*x*, and both are floats. *x*, and both are floats.
.. function:: trunc(x)
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
a long integer). Delegates to ``x.__trunc__()``.
.. versionadded:: 2.6
Note that :func:`frexp` and :func:`modf` have a different call/return pattern Note that :func:`frexp` and :func:`modf` have a different call/return pattern
than their C equivalents: they take a single argument and return a pair of than their C equivalents: they take a single argument and return a pair of
values, rather than returning their second return value through an 'output values, rather than returning their second return value through an 'output
......
"""Unit tests for numbers.py.""" """Unit tests for numbers.py."""
import math
import operator
import unittest import unittest
from test import test_support
from numbers import Number
from numbers import Exact, Inexact
from numbers import Complex, Real, Rational, Integral from numbers import Complex, Real, Rational, Integral
import operator from numbers import Exact, Inexact
from numbers import Number
from test import test_support
class TestNumbers(unittest.TestCase): class TestNumbers(unittest.TestCase):
def test_int(self): def test_int(self):
...@@ -49,8 +50,8 @@ class TestNumbers(unittest.TestCase): ...@@ -49,8 +50,8 @@ class TestNumbers(unittest.TestCase):
self.failUnless(issubclass(complex, Inexact)) self.failUnless(issubclass(complex, Inexact))
c1, c2 = complex(3, 2), complex(4,1) c1, c2 = complex(3, 2), complex(4,1)
# XXX: This is not ideal, but see the comment in builtin_trunc(). # XXX: This is not ideal, but see the comment in math_trunc().
self.assertRaises(AttributeError, trunc, c1) self.assertRaises(AttributeError, math.trunc, c1)
self.assertRaises(TypeError, float, c1) self.assertRaises(TypeError, float, c1)
self.assertRaises(TypeError, int, c1) self.assertRaises(TypeError, int, c1)
......
...@@ -1766,38 +1766,6 @@ class BuiltinTest(unittest.TestCase): ...@@ -1766,38 +1766,6 @@ class BuiltinTest(unittest.TestCase):
raise ValueError raise ValueError
self.assertRaises(ValueError, sum, BadSeq()) self.assertRaises(ValueError, sum, BadSeq())
def test_trunc(self):
self.assertEqual(trunc(1), 1)
self.assertEqual(trunc(-1), -1)
self.assertEqual(type(trunc(1)), int)
self.assertEqual(type(trunc(1.5)), int)
self.assertEqual(trunc(1.5), 1)
self.assertEqual(trunc(-1.5), -1)
self.assertEqual(trunc(1.999999), 1)
self.assertEqual(trunc(-1.999999), -1)
self.assertEqual(trunc(-0.999999), -0)
self.assertEqual(trunc(-100.999), -100)
class TestTrunc(object):
def __trunc__(self):
return 23
class TestNoTrunc(object):
pass
self.assertEqual(trunc(TestTrunc()), 23)
self.assertRaises(TypeError, trunc)
self.assertRaises(TypeError, trunc, 1, 2)
# XXX: This is not ideal, but see the comment in builtin_trunc().
self.assertRaises(AttributeError, trunc, TestNoTrunc())
t = TestNoTrunc()
t.__trunc__ = lambda *args: args
self.assertEquals((), trunc(t))
self.assertRaises(TypeError, trunc, t, 0)
def test_tuple(self): def test_tuple(self):
self.assertEqual(tuple(()), ()) self.assertEqual(tuple(()), ())
t0_3 = (0, 1, 2, 3) t0_3 = (0, 1, 2, 3)
......
...@@ -25,10 +25,11 @@ with the corresponding argument. ...@@ -25,10 +25,11 @@ with the corresponding argument.
""" """
from __future__ import with_statement from __future__ import with_statement
import unittest
import glob import glob
import math
import os, sys import os, sys
import pickle, copy import pickle, copy
import unittest
from decimal import * from decimal import *
from test.test_support import (TestSkipped, run_unittest, run_doctest, from test.test_support import (TestSkipped, run_unittest, run_doctest,
is_resource_enabled) is_resource_enabled)
...@@ -1225,7 +1226,7 @@ class DecimalPythonAPItests(unittest.TestCase): ...@@ -1225,7 +1226,7 @@ class DecimalPythonAPItests(unittest.TestCase):
# should work the same as to_integral in the ROUND_DOWN mode # should work the same as to_integral in the ROUND_DOWN mode
d = Decimal(s) d = Decimal(s)
r = d.to_integral(ROUND_DOWN) r = d.to_integral(ROUND_DOWN)
self.assertEqual(Decimal(trunc(d)), r) self.assertEqual(Decimal(math.trunc(d)), r)
class ContextAPItests(unittest.TestCase): class ContextAPItests(unittest.TestCase):
......
...@@ -237,6 +237,37 @@ class MathTests(unittest.TestCase): ...@@ -237,6 +237,37 @@ class MathTests(unittest.TestCase):
self.ftest('tanh(0)', math.tanh(0), 0) self.ftest('tanh(0)', math.tanh(0), 0)
self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0) self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
def test_trunc(self):
self.assertEqual(math.trunc(1), 1)
self.assertEqual(math.trunc(-1), -1)
self.assertEqual(type(math.trunc(1)), int)
self.assertEqual(type(math.trunc(1.5)), int)
self.assertEqual(math.trunc(1.5), 1)
self.assertEqual(math.trunc(-1.5), -1)
self.assertEqual(math.trunc(1.999999), 1)
self.assertEqual(math.trunc(-1.999999), -1)
self.assertEqual(math.trunc(-0.999999), -0)
self.assertEqual(math.trunc(-100.999), -100)
class TestTrunc(object):
def __trunc__(self):
return 23
class TestNoTrunc(object):
pass
self.assertEqual(math.trunc(TestTrunc()), 23)
self.assertRaises(TypeError, math.trunc)
self.assertRaises(TypeError, math.trunc, 1, 2)
# XXX: This is not ideal, but see the comment in math_trunc().
self.assertRaises(AttributeError, math.trunc, TestNoTrunc())
t = TestNoTrunc()
t.__trunc__ = lambda *args: args
self.assertEquals((), math.trunc(t))
self.assertRaises(TypeError, math.trunc, t, 0)
def testCopysign(self): def testCopysign(self):
self.assertEqual(math.copysign(1, 42), 1.0) self.assertEqual(math.copysign(1, 42), 1.0)
self.assertEqual(math.copysign(0., 42), 0.0) self.assertEqual(math.copysign(0., 42), 0.0)
......
...@@ -195,7 +195,7 @@ class RationalTest(unittest.TestCase): ...@@ -195,7 +195,7 @@ class RationalTest(unittest.TestCase):
self.assertEqual(R.from_float(0.0).approximate(10000), R(0)) self.assertEqual(R.from_float(0.0).approximate(10000), R(0))
def testConversions(self): def testConversions(self):
self.assertTypedEquals(-1, trunc(R(-11, 10))) self.assertTypedEquals(-1, math.trunc(R(-11, 10)))
self.assertTypedEquals(-1, int(R(-11, 10))) self.assertTypedEquals(-1, int(R(-11, 10)))
self.assertEquals(False, bool(R(0, 1))) self.assertEquals(False, bool(R(0, 1)))
...@@ -322,11 +322,11 @@ class RationalTest(unittest.TestCase): ...@@ -322,11 +322,11 @@ class RationalTest(unittest.TestCase):
# Because 10**23 can't be represented exactly as a float: # Because 10**23 can't be represented exactly as a float:
self.assertFalse(R(10**23) == float(10**23)) self.assertFalse(R(10**23) == float(10**23))
# The first test demonstrates why these are important. # The first test demonstrates why these are important.
self.assertFalse(1e23 < float(R(trunc(1e23) + 1))) self.assertFalse(1e23 < float(R(math.trunc(1e23) + 1)))
self.assertTrue(1e23 < R(trunc(1e23) + 1)) self.assertTrue(1e23 < R(math.trunc(1e23) + 1))
self.assertFalse(1e23 <= R(trunc(1e23) - 1)) self.assertFalse(1e23 <= R(math.trunc(1e23) - 1))
self.assertTrue(1e23 > R(trunc(1e23) - 1)) self.assertTrue(1e23 > R(math.trunc(1e23) - 1))
self.assertFalse(1e23 >= R(trunc(1e23) + 1)) self.assertFalse(1e23 >= R(math.trunc(1e23) + 1))
def testBigComplexComparisons(self): def testBigComplexComparisons(self):
self.assertFalse(R(10**23) == complex(10**23)) self.assertFalse(R(10**23) == complex(10**23))
......
...@@ -154,6 +154,21 @@ FUNC1(tan, tan, ...@@ -154,6 +154,21 @@ FUNC1(tan, tan,
FUNC1(tanh, tanh, FUNC1(tanh, tanh,
"tanh(x)\n\nReturn the hyperbolic tangent of x.") "tanh(x)\n\nReturn the hyperbolic tangent of x.")
static PyObject *
math_trunc(PyObject *self, PyObject *number)
{
/* XXX: The py3k branch gets better errors for this by using
_PyType_Lookup(), but since float's mro isn't set in py2.6,
we just use PyObject_CallMethod here. */
return PyObject_CallMethod(number, "__trunc__", NULL);
}
PyDoc_STRVAR(math_trunc_doc,
"trunc(x:Real) -> Integral\n"
"\n"
"Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic"
"method.");
static PyObject * static PyObject *
math_frexp(PyObject *self, PyObject *arg) math_frexp(PyObject *self, PyObject *arg)
{ {
...@@ -377,6 +392,7 @@ static PyMethodDef math_methods[] = { ...@@ -377,6 +392,7 @@ static PyMethodDef math_methods[] = {
{"sqrt", math_sqrt, METH_O, math_sqrt_doc}, {"sqrt", math_sqrt, METH_O, math_sqrt_doc},
{"tan", math_tan, METH_O, math_tan_doc}, {"tan", math_tan, METH_O, math_tan_doc},
{"tanh", math_tanh, METH_O, math_tanh_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc},
{"trunc", math_trunc, METH_O, math_trunc_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
...@@ -2044,20 +2044,6 @@ PyDoc_STRVAR(vars_doc, ...@@ -2044,20 +2044,6 @@ PyDoc_STRVAR(vars_doc,
Without arguments, equivalent to locals().\n\ Without arguments, equivalent to locals().\n\
With an argument, equivalent to object.__dict__."); With an argument, equivalent to object.__dict__.");
static PyObject *
builtin_trunc(PyObject *self, PyObject *number)
{
/* XXX: The py3k branch gets better errors for this by using
_PyType_Lookup(), but since float's mro isn't set in py2.6,
we just use PyObject_CallMethod here. */
return PyObject_CallMethod(number, "__trunc__", NULL);
}
PyDoc_STRVAR(trunc_doc,
"trunc(Real) -> Integral\n\
\n\
returns the integral closest to x between 0 and x.");
static PyObject* static PyObject*
builtin_sum(PyObject *self, PyObject *args) builtin_sum(PyObject *self, PyObject *args)
...@@ -2406,7 +2392,6 @@ static PyMethodDef builtin_methods[] = { ...@@ -2406,7 +2392,6 @@ static PyMethodDef builtin_methods[] = {
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc}, {"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
#endif #endif
{"vars", builtin_vars, METH_VARARGS, vars_doc}, {"vars", builtin_vars, METH_VARARGS, vars_doc},
{"trunc", builtin_trunc, METH_O, trunc_doc},
{"zip", builtin_zip, METH_VARARGS, zip_doc}, {"zip", builtin_zip, METH_VARARGS, zip_doc},
{NULL, NULL}, {NULL, NULL},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment