_PyLong_NumBits(): The definition of this was too specific to the quirky
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.
This commit is contained in:
parent
89fc4f3e56
commit
5b8132ffa3
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue