STINNER Victor <[EMAIL PROTECTED]> added the comment:
[Mark Dickinson]
> (1) the number of bits should be computed first directly using ...
_PyLong_NumBits() : done. But the result type is always long.
> (2) Just as a matter of style, I think "if (x == NULL)" is preferable
done
> (4) I quite like the idea of having numbits be a property rather than a
> method---might still be worth considering?
I agree, so in the new patch, numbits is now a property.
[Fredrik Johansson]
> In stdtypes.rst, x.numbits should be listed in the table under
> "Bit-string Operations on Integer Types"
done
--
10
>>> x=1023L; x.numbits
10L
>>> x=2**(2**10); n=x.numbits; n, n.numbits
(1025L, 11L)
Added file: http://bugs.python.org/file11990/numbits-4.patch
_______________________________________
Python tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue3439>
_______________________________________
Index: Objects/intobject.c
===================================================================
--- Objects/intobject.c (révision 67177)
+++ Objects/intobject.c (copie de travail)
@@ -1138,6 +1138,27 @@
return NULL;
}
+static PyObject *
+int_numbits(PyIntObject *v)
+{
+ unsigned long n;
+ long result = 0;
+
+ if (v->ob_ival < 0) {
+ /* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then
+ ANSI C says that the result of -ival is undefined when ival
+ == LONG_MIN. Hence the following workaround. */
+ n = (unsigned long)(-1 - v->ob_ival) + 1;
+ } else {
+ n = (unsigned long)v->ob_ival;
+ }
+ while (n) {
+ ++result;
+ n >>= 1;
+ }
+ return PyInt_FromLong(result);
+}
+
#if 0
static PyObject *
int_is_finite(PyObject *v)
@@ -1161,6 +1182,10 @@
};
static PyGetSetDef int_getset[] = {
+ {"numbits",
+ (getter)int_numbits, (setter)NULL,
+ "Returns the number of binary digits in self.",
+ NULL},
{"real",
(getter)int_int, (setter)NULL,
"the real part of a complex number",
Index: Objects/longobject.c
===================================================================
--- Objects/longobject.c (révision 67177)
+++ Objects/longobject.c (copie de travail)
@@ -3451,6 +3451,64 @@
return PyInt_FromSsize_t(res);
}
+static PyObject *
+long_numbits(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 PyLong_FromSize_t(nbits);
+
+ ndigits = ABS(Py_SIZE(v));
+ assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
+
+ if (ndigits == 0)
+ return PyLong_FromLong(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)
@@ -3476,6 +3534,10 @@
};
static PyGetSetDef long_getset[] = {
+ {"numbits",
+ (getter)long_numbits, (setter)NULL,
+ "returns the number of binary digits in self.",
+ NULL},
{"real",
(getter)long_long, (setter)NULL,
"the real part of a complex number",
Index: Lib/test/test_int.py
===================================================================
--- Lib/test/test_int.py (révision 67177)
+++ Lib/test/test_int.py (copie de travail)
@@ -240,6 +240,21 @@
self.assertEqual(int('2br45qc', 35), 4294967297L)
self.assertEqual(int('1z141z5', 36), 4294967297L)
+ def test_numbits(self):
+ self.assertEqual((0).numbits(), 0)
+ self.assertEqual((1).numbits(), 1)
+ self.assertEqual((-1).numbits(), 1)
+ self.assertEqual((2).numbits(), 2)
+ self.assertEqual((-2).numbits(), 2)
+ for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64]:
+ a = 2**i
+ self.assertEqual((a-1).numbits(), i)
+ self.assertEqual((1-a).numbits(), i)
+ self.assertEqual((a).numbits(), i+1)
+ self.assertEqual((-a).numbits(), i+1)
+ self.assertEqual((a+1).numbits(), i+1)
+ self.assertEqual((-a-1).numbits(), i+1)
+
def test_intconversion(self):
# Test __int__()
class ClassicMissingMethods:
Index: Lib/test/test_long.py
===================================================================
--- Lib/test/test_long.py (révision 67177)
+++ Lib/test/test_long.py (copie de travail)
@@ -752,6 +752,22 @@
self.assertRaises(OverflowError, long, float('-inf'))
self.assertRaises(ValueError, long, float('nan'))
+ def test_numbits(self):
+ self.assertEqual((0L).numbits(), 0)
+ self.assertEqual((1L).numbits(), 1)
+ self.assertEqual((-1L).numbits(), 1)
+ self.assertEqual((2L).numbits(), 2)
+ self.assertEqual((-2L).numbits(), 2)
+ for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64, 234]:
+ a = 2L**i
+ self.assertEqual((a-1).numbits(), i)
+ self.assertEqual((1-a).numbits(), i)
+ self.assertEqual((a).numbits(), i+1)
+ self.assertEqual((-a).numbits(), i+1)
+ self.assertEqual((a+1).numbits(), i+1)
+ self.assertEqual((-a-1).numbits(), i+1)
+
+
def test_main():
test_support.run_unittest(LongTest)
--- Doc/library/stdtypes.rst.orig 2008-11-12 01:15:39.000000000 +0100
+++ Doc/library/stdtypes.rst 2008-11-12 01:13:35.000000000 +0100
@@ -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.numbits`` | number of binary digits of *x* | |
++---------------+--------------------------------+----------+
.. index::
triple: operations on; integer; types
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com