Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5b8132f

Browse files
committed
_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.
1 parent 89fc4f3 commit 5b8132f

3 files changed

Lines changed: 55 additions & 34 deletions

File tree

Include/longobject.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,17 @@ PyAPI_FUNC(PyObject *) PyLong_FromString(char *, char **, int);
4444
PyAPI_FUNC(PyObject *) PyLong_FromUnicode(Py_UNICODE*, int, int);
4545
#endif
4646

47-
/* _PyLong_NumBits. Return the number of bits needed to represent a long
48-
in contiguous 2's-complement form, including 1 for the sign bit. For
49-
example, this returns 1 for 0, and 2 for 1 and -1. Note that the
50-
ceiling of this divided by 8 is the number of bytes needed by
51-
_PyLong_AsByteArray to store the long in 256's-complement form.
47+
/* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0.
48+
v must not be NULL, and must be a normalized long.
49+
There are no error cases.
50+
*/
51+
PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
52+
53+
54+
PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v);
55+
/* _PyLong_NumBits. Return the number of bits needed to represent the
56+
absolute value of a long. For example, this returns 1 for 1 and -1, 2
57+
for 2 and -2, and 2 for 3 and -3. It returns 0 for 0.
5258
v must not be NULL, and must be a normalized long.
5359
(size_t)-1 is returned and OverflowError set if the true result doesn't
5460
fit in a size_t.

Modules/_testcapimodule.c

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -334,37 +334,43 @@ test_u_code(PyObject *self)
334334

335335
#endif
336336

337-
/* Simple test of _PyLong_NumBits. */
337+
/* Simple test of _PyLong_NumBits and _PyLong_Sign. */
338338
static PyObject *
339339
test_long_numbits(PyObject *self)
340340
{
341-
struct pair {
341+
struct triple {
342342
long input;
343-
size_t output;
344-
} testcases[] = {{0, 1},
345-
{1L, 2},
346-
{-1L, 2},
347-
{2L, 3},
348-
{-2L, 3},
349-
{3L, 3},
350-
{-3L, 3},
351-
{4L, 4},
352-
{-4L, 4},
353-
{0x7fffL, 16}, /* one Python long digit */
354-
{-0x7fffL, 16},
355-
{0xfffffffL, 29},
356-
{-0xfffffffL, 29}};
343+
size_t nbits;
344+
int sign;
345+
} testcases[] = {{0, 0, 0},
346+
{1L, 1, 1},
347+
{-1L, 1, -1},
348+
{2L, 2, 1},
349+
{-2L, 2, -1},
350+
{3L, 2, 1},
351+
{-3L, 2, -1},
352+
{4L, 3, 1},
353+
{-4L, 3, -1},
354+
{0x7fffL, 15, 1}, /* one Python long digit */
355+
{-0x7fffL, 15, -1},
356+
{0xffffL, 16, 1},
357+
{-0xffffL, 16, -1},
358+
{0xfffffffL, 28, 1},
359+
{-0xfffffffL, 28, -1}};
357360
int i;
358361

359-
for (i = 0; i < sizeof(testcases) / sizeof(struct pair); ++i) {
360-
long input = testcases[i].input;
361-
PyObject *plong = PyLong_FromLong(input);
362+
for (i = 0; i < sizeof(testcases) / sizeof(struct triple); ++i) {
363+
PyObject *plong = PyLong_FromLong(testcases[i].input);
362364
size_t nbits = _PyLong_NumBits(plong);
365+
int sign = _PyLong_Sign(plong);
363366

364367
Py_DECREF(plong);
365-
if (nbits != testcases[i].output)
368+
if (nbits != testcases[i].nbits)
366369
return raiseTestError("test_long_numbits",
367-
"wrong result");
370+
"wrong result for _PyLong_NumBits");
371+
if (sign != testcases[i].sign)
372+
return raiseTestError("test_long_numbits",
373+
"wrong result for _PyLong_Sign");
368374
}
369375
Py_INCREF(Py_None);
370376
return Py_None;

Objects/longobject.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -260,25 +260,34 @@ PyLong_AsUnsignedLong(PyObject *vv)
260260
return x;
261261
}
262262

263+
int
264+
_PyLong_Sign(PyObject *vv)
265+
{
266+
PyLongObject *v = (PyLongObject *)vv;
267+
const int ndigits = v->ob_size;
268+
269+
assert(v != NULL);
270+
assert(PyLong_Check(v));
271+
assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
272+
273+
return ndigits == 0 ? 0 : (ndigits < 0 ? -1 : 1);
274+
}
275+
263276
size_t
264277
_PyLong_NumBits(PyObject *vv)
265278
{
266279
PyLongObject *v = (PyLongObject *)vv;
267-
size_t result = 1; /* for the sign bit */
268-
size_t ndigits = ABS(v->ob_size);
280+
size_t result = 0;
281+
int ndigits = ABS(v->ob_size);
269282

270283
assert(v != NULL);
271284
assert(PyLong_Check(v));
272285
assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
273286
if (ndigits > 0) {
274-
size_t product;
275287
digit msd = v->ob_digit[ndigits - 1];
276288

277-
product = (ndigits - 1) * SHIFT;
278-
if (product / SHIFT != ndigits - 1)
279-
goto Overflow;
280-
result += product;
281-
if (result < product)
289+
result = (ndigits - 1) * SHIFT;
290+
if (result / SHIFT != ndigits - 1)
282291
goto Overflow;
283292
do {
284293
++result;

0 commit comments

Comments
 (0)