Index: Objects/intobject.c =================================================================== --- Objects/intobject.c (revision 67706) +++ Objects/intobject.c (working copy) @@ -1138,6 +1138,37 @@ return NULL; } +static const long BitLengthTable128[] = +{ + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +static PyObject * +int_bit_length(PyIntObject *v) +{ + unsigned long n; + long r = 0; + + if (v->ob_ival < 0) + n = (unsigned long)((-1 - v->ob_ival) + 1); + else + n = (unsigned long)v->ob_ival; + + while (n > 127) { + r += 8; + n >>= 8; + } + r += BitLengthTable128[n]; + return PyInt_FromLong(r); +} + #if 0 static PyObject * int_is_finite(PyObject *v) @@ -1149,6 +1180,8 @@ static PyMethodDef int_methods[] = { {"conjugate", (PyCFunction)int_int, METH_NOARGS, "Returns self, the complex conjugate of any int."}, + {"bit_length", (PyCFunction)int_bit_length, METH_NOARGS, + "Returns the number of binary digits in self."}, #if 0 {"is_finite", (PyCFunction)int_is_finite, METH_NOARGS, "Returns always True."}, Index: Objects/longobject.c =================================================================== --- Objects/longobject.c (revision 67706) +++ Objects/longobject.c (working copy) @@ -3451,6 +3451,65 @@ return PyInt_FromSsize_t(res); } +static PyObject * +long_bit_length(PyLongObject *v) +{ + PyLongObject *result, *x, *y; + Py_ssize_t ndigits, msd_bits; + digit msd; + size_t nbits; + + assert(v != NULL); + assert(PyLong_Check(v)); + + nbits = _PyLong_NumBits((PyObject*)v); + if (nbits != (size_t)-1 || !PyErr_Occurred()) { + return PyInt_FromSize_t(nbits); + } + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + + ndigits = ABS(Py_SIZE(v)); + assert(ndigits != 0 && v->ob_digit[ndigits - 1] != 0); + + msd = v->ob_digit[ndigits - 1]; + msd_bits = 0; + do { + ++msd_bits; + msd >>= 1; + } while (msd); + + result = (PyLongObject *)PyLong_FromLong(ndigits - 1); + if (result == NULL) + return NULL; + x = (PyLongObject *)PyLong_FromLong(PyLong_SHIFT); + if (x == NULL) + goto error; + y = (PyLongObject *)long_mul(result, x); + Py_DECREF(x); + if (y == NULL) + goto error; + Py_DECREF(result); + result = y; + + x = (PyLongObject *)PyLong_FromLong(msd_bits); + if (x == NULL) + goto error; + y = (PyLongObject *)long_add(result, x); + Py_DECREF(x); + if (y == NULL) + goto error; + Py_DECREF(result); + result = y; + + return (PyObject *)result; + +error: + Py_DECREF(result); + return NULL; +} + #if 0 static PyObject * long_is_finite(PyObject *v) @@ -3462,6 +3521,8 @@ static PyMethodDef long_methods[] = { {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any long."}, + {"bit_length", (PyCFunction)long_bit_length, METH_NOARGS, + "returns the number of binary digits in self."}, #if 0 {"is_finite", (PyCFunction)long_is_finite, METH_NOARGS, "Returns always True."}, Index: Doc/whatsnew/2.7.rst =================================================================== --- Doc/whatsnew/2.7.rst (revision 67706) +++ Doc/whatsnew/2.7.rst (working copy) @@ -66,8 +66,21 @@ Some smaller changes made to the core Python language are: -* List of changes to be written here. +* The :func:`int` and :func:`long` types have a ``bit_length`` method + that returns the number of bits in its argument:: + >>> n = 37 + >>> n.bit_length() + 6 + >>> n = 2**123-1 + >>> n.bit_length() + 123 + >>> (n+1).bit_length() + 124 + + Contributed by Fredrik Johansson and Victor Stinner. + + .. ====================================================================== Index: Doc/library/stdtypes.rst =================================================================== --- Doc/library/stdtypes.rst (revision 67706) +++ Doc/library/stdtypes.rst (working copy) @@ -409,24 +409,26 @@ This table lists the bit-string operations sorted in ascending priority: -+------------+--------------------------------+----------+ -| Operation | Result | Notes | -+============+================================+==========+ -| ``x | y`` | bitwise :dfn:`or` of *x* and | | -| | *y* | | -+------------+--------------------------------+----------+ -| ``x ^ y`` | bitwise :dfn:`exclusive or` of | | -| | *x* and *y* | | -+------------+--------------------------------+----------+ -| ``x & y`` | bitwise :dfn:`and` of *x* and | | -| | *y* | | -+------------+--------------------------------+----------+ -| ``x << n`` | *x* shifted left by *n* bits | (1)(2) | -+------------+--------------------------------+----------+ -| ``x >> n`` | *x* shifted right by *n* bits | (1)(3) | -+------------+--------------------------------+----------+ -| ``~x`` | the bits of *x* inverted | | -+------------+--------------------------------+----------+ ++--------------------+--------------------------------+----------+ +| Operation | Result | Notes | ++====================+================================+==========+ +| ``x | y`` | bitwise :dfn:`or` of *x* and | | +| | *y* | | ++--------------------+--------------------------------+----------+ +| ``x ^ y`` | bitwise :dfn:`exclusive or` of | | +| | *x* and *y* | | ++--------------------+--------------------------------+----------+ +| ``x & y`` | bitwise :dfn:`and` of *x* and | | +| | *y* | | ++--------------------+--------------------------------+----------+ +| ``x << n`` | *x* shifted left by *n* bits | (1)(2) | ++--------------------+--------------------------------+----------+ +| ``x >> n`` | *x* shifted right by *n* bits | (1)(3) | ++--------------------+--------------------------------+----------+ +| ``~x`` | the bits of *x* inverted | | ++--------------------+--------------------------------+----------+ +| ``x.bit_length()`` | number of binary digits of *x* | (4) | ++--------------------+--------------------------------+----------+ .. index:: triple: operations on; integer; types @@ -446,7 +448,15 @@ (3) A right shift by *n* bits is equivalent to division by ``pow(2, n)``. +(4) + For a positive integer ``x``, ``x.bit_length()`` returns the unique + integer ``k`` such that ``2**(k-1) <= x < 2**k``. In other words, + ``k`` is one more than the floor of the base-2 log of ``x``. + ``(0).bit_length()`` gives ``0``, while ``(-x).bit_length()`` has + the same value as ``x.bit_length()``. The ``bit_length`` method is + new in Python 2.7. + Additional Methods on Float --------------------------- Index: Lib/test/test_int.py =================================================================== --- Lib/test/test_int.py (revision 67706) +++ Lib/test/test_int.py (working copy) @@ -240,6 +240,21 @@ self.assertEqual(int('2br45qc', 35), 4294967297L) self.assertEqual(int('1z141z5', 36), 4294967297L) + def test_bit_length(self): + self.assertEqual((0).bit_length(), 0) + self.assertEqual((1).bit_length(), 1) + self.assertEqual((-1).bit_length(), 1) + self.assertEqual((2).bit_length(), 2) + self.assertEqual((-2).bit_length(), 2) + for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64]: + a = 2**i + self.assertEqual((a-1).bit_length(), i) + self.assertEqual((1-a).bit_length(), i) + self.assertEqual((a).bit_length(), i+1) + self.assertEqual((-a).bit_length(), i+1) + self.assertEqual((a+1).bit_length(), i+1) + self.assertEqual((-a-1).bit_length(), i+1) + def test_intconversion(self): # Test __int__() class ClassicMissingMethods: Index: Lib/test/test_long.py =================================================================== --- Lib/test/test_long.py (revision 67706) +++ Lib/test/test_long.py (working copy) @@ -752,6 +752,22 @@ self.assertRaises(OverflowError, long, float('-inf')) self.assertRaises(ValueError, long, float('nan')) + def test_bit_length(self): + self.assertEqual((0L).bit_length(), 0) + self.assertEqual((1L).bit_length(), 1) + self.assertEqual((-1L).bit_length(), 1) + self.assertEqual((2L).bit_length(), 2) + self.assertEqual((-2L).bit_length(), 2) + for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64, 234]: + a = 2L**i + self.assertEqual((a-1).bit_length(), i) + self.assertEqual((1-a).bit_length(), i) + self.assertEqual((a).bit_length(), i+1) + self.assertEqual((-a).bit_length(), i+1) + self.assertEqual((a+1).bit_length(), i+1) + self.assertEqual((-a-1).bit_length(), i+1) + + def test_main(): test_support.run_unittest(LongTest)