]> granicus.if.org Git - python/commitdiff
_PyLong_NumBits(): The definition of this was too specific to the quirky
authorTim Peters <tim.peters@gmail.com>
Fri, 31 Jan 2003 15:52:05 +0000 (15:52 +0000)
committerTim Peters <tim.peters@gmail.com>
Fri, 31 Jan 2003 15:52:05 +0000 (15:52 +0000)
needs of pickling longs.  Backed off to a definition that's much easier
to understand.  The pickler will have to work a little harder, but other
uses are more likely to be correct <0.5 wink>.

_PyLong_Sign():  New teensy function to characterize a long, as to <0, ==0,
or >0.

Include/longobject.h
Modules/_testcapimodule.c
Objects/longobject.c

index 3b808fb4f3fc6403c576c03e5c34a1f945c9f37e..1ac213cae43d06bdbcbd539c2b49ce7172d02446 100644 (file)
@@ -44,11 +44,17 @@ PyAPI_FUNC(PyObject *) PyLong_FromString(char *, char **, int);
 PyAPI_FUNC(PyObject *) PyLong_FromUnicode(Py_UNICODE*, int, int);
 #endif
 
-/* _PyLong_NumBits.  Return the number of bits needed to represent a long
-   in contiguous 2's-complement form, including 1 for the sign bit.  For
-   example, this returns 1 for 0, and 2 for 1 and -1.  Note that the
-   ceiling of this divided by 8 is the number of bytes needed by
-   _PyLong_AsByteArray to store the long in 256's-complement form.
+/* _PyLong_Sign.  Return 0 if v is 0, -1 if v < 0, +1 if v > 0.
+   v must not be NULL, and must be a normalized long.
+   There are no error cases.
+*/
+PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
+
+
+PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v);
+/* _PyLong_NumBits.  Return the number of bits needed to represent the
+   absolute value of a long.  For example, this returns 1 for 1 and -1, 2
+   for 2 and -2, and 2 for 3 and -3.  It returns 0 for 0.
    v must not be NULL, and must be a normalized long.
    (size_t)-1 is returned and OverflowError set if the true result doesn't
    fit in a size_t.
index 9359188f9841cc114ab334aef27255b4c45fb050..4c3c2aa692c86a7367e0c4291209fc2ea426fbd0 100644 (file)
@@ -334,37 +334,43 @@ test_u_code(PyObject *self)
 
 #endif
 
-/* Simple test of _PyLong_NumBits. */
+/* Simple test of _PyLong_NumBits and _PyLong_Sign. */
 static PyObject *
 test_long_numbits(PyObject *self)
 {
-       struct pair {
+       struct triple {
                long input;
-               size_t output;
-       } testcases[] = {{0, 1},
-                        {1L, 2},
-                        {-1L, 2},
-                        {2L, 3},
-                        {-2L, 3},
-                        {3L, 3},
-                        {-3L, 3},
-                        {4L, 4},
-                        {-4L, 4},
-                        {0x7fffL, 16},         /* one Python long digit */
-                        {-0x7fffL, 16},
-                        {0xfffffffL, 29},
-                        {-0xfffffffL, 29}};
+               size_t nbits;
+               int sign;
+       } testcases[] = {{0, 0, 0},
+                        {1L, 1, 1},
+                        {-1L, 1, -1},
+                        {2L, 2, 1},
+                        {-2L, 2, -1},
+                        {3L, 2, 1},
+                        {-3L, 2, -1},
+                        {4L, 3, 1},
+                        {-4L, 3, -1},
+                        {0x7fffL, 15, 1},      /* one Python long digit */
+                        {-0x7fffL, 15, -1},
+                        {0xffffL, 16, 1},
+                        {-0xffffL, 16, -1},
+                        {0xfffffffL, 28, 1},
+                        {-0xfffffffL, 28, -1}};
        int i;
 
-       for (i = 0; i < sizeof(testcases) / sizeof(struct pair); ++i) {
-               long input = testcases[i].input;
-               PyObject *plong = PyLong_FromLong(input);
+       for (i = 0; i < sizeof(testcases) / sizeof(struct triple); ++i) {
+               PyObject *plong = PyLong_FromLong(testcases[i].input);
                size_t nbits = _PyLong_NumBits(plong);
+               int sign = _PyLong_Sign(plong);
 
                Py_DECREF(plong);
-               if (nbits != testcases[i].output)
+               if (nbits != testcases[i].nbits)
                        return raiseTestError("test_long_numbits",
-                                             "wrong result");
+                                       "wrong result for _PyLong_NumBits");
+               if (sign != testcases[i].sign)
+                       return raiseTestError("test_long_numbits",
+                                       "wrong result for _PyLong_Sign");
        }
        Py_INCREF(Py_None);
        return Py_None;
index 7a04f1e4daddb002fb166f5428b287cb24472525..2279fc33dbf68a8ede087b835837f98e0a082c12 100644 (file)
@@ -260,25 +260,34 @@ PyLong_AsUnsignedLong(PyObject *vv)
        return x;
 }
 
+int
+_PyLong_Sign(PyObject *vv)
+{
+       PyLongObject *v = (PyLongObject *)vv;
+       const int ndigits = v->ob_size;
+
+       assert(v != NULL);
+       assert(PyLong_Check(v));
+       assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
+
+       return ndigits == 0 ? 0 : (ndigits < 0 ? -1 : 1);
+}
+
 size_t
 _PyLong_NumBits(PyObject *vv)
 {
        PyLongObject *v = (PyLongObject *)vv;
-       size_t result = 1;      /* for the sign bit */
-       size_t ndigits = ABS(v->ob_size);
+       size_t result = 0;
+       int ndigits = ABS(v->ob_size);
 
        assert(v != NULL);
        assert(PyLong_Check(v));
        assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
        if (ndigits > 0) {
-               size_t product;
                digit msd = v->ob_digit[ndigits - 1];
 
-               product = (ndigits - 1) * SHIFT;
-               if (product / SHIFT != ndigits - 1)
-                       goto Overflow;
-               result += product;
-               if (result < product)
+               result = (ndigits - 1) * SHIFT;
+               if (result / SHIFT != ndigits - 1)
                        goto Overflow;
                do {
                        ++result;