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

Reply via email to