mirror of https://github.com/python/cpython
gh-116560: Add PyLong_GetSign() public function (#116561)
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
367adc91fb
commit
61d3ab32da
|
@ -494,6 +494,19 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
||||||
.. versionadded:: 3.13
|
.. versionadded:: 3.13
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyLong_GetSign(PyObject *obj, int *sign)
|
||||||
|
|
||||||
|
Get the sign of the integer object *obj*.
|
||||||
|
|
||||||
|
On success, set *\*sign* to the integer sign (0, -1 or +1 for zero, negative or
|
||||||
|
positive integer, respectively) and return 0.
|
||||||
|
|
||||||
|
On failure, return -1 with an exception set. This function always succeeds
|
||||||
|
if *obj* is a :c:type:`PyLongObject` or its subtype.
|
||||||
|
|
||||||
|
.. versionadded:: 3.14
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: int PyUnstable_Long_IsCompact(const PyLongObject* op)
|
.. c:function:: int PyUnstable_Long_IsCompact(const PyLongObject* op)
|
||||||
|
|
||||||
Return 1 if *op* is compact, 0 otherwise.
|
Return 1 if *op* is compact, 0 otherwise.
|
||||||
|
|
|
@ -255,6 +255,9 @@ C API Changes
|
||||||
New Features
|
New Features
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
* Add :c:func:`PyLong_GetSign` function to get the sign of :class:`int` objects.
|
||||||
|
(Contributed by Sergey B Kirpichev in :gh:`116560`.)
|
||||||
|
|
||||||
Porting to Python 3.14
|
Porting to Python 3.14
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,13 @@ PyAPI_FUNC(PyObject*) PyLong_FromUnsignedNativeBytes(const void* buffer,
|
||||||
PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op);
|
PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op);
|
||||||
PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op);
|
PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op);
|
||||||
|
|
||||||
// _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0.
|
/* PyLong_GetSign. Get the sign of an integer object:
|
||||||
// v must not be NULL, and must be a normalized long.
|
0, -1 or +1 for zero, negative or positive integer, respectively.
|
||||||
// There are no error cases.
|
|
||||||
|
- On success, set '*sign' to the integer sign, and return 0.
|
||||||
|
- On failure, set an exception, and return -1. */
|
||||||
|
PyAPI_FUNC(int) PyLong_GetSign(PyObject *v, int *sign);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
|
PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
|
||||||
|
|
||||||
/* _PyLong_NumBits. Return the number of bits needed to represent the
|
/* _PyLong_NumBits. Return the number of bits needed to represent the
|
||||||
|
|
|
@ -721,6 +721,22 @@ class LongTests(unittest.TestCase):
|
||||||
self.assertEqual(expect_u, fromnativebytes(v_be, n, 4, 1),
|
self.assertEqual(expect_u, fromnativebytes(v_be, n, 4, 1),
|
||||||
f"PyLong_FromNativeBytes(buffer, {n}, <big|unsigned>)")
|
f"PyLong_FromNativeBytes(buffer, {n}, <big|unsigned>)")
|
||||||
|
|
||||||
|
def test_long_getsign(self):
|
||||||
|
# Test PyLong_GetSign()
|
||||||
|
getsign = _testcapi.pylong_getsign
|
||||||
|
self.assertEqual(getsign(1), 1)
|
||||||
|
self.assertEqual(getsign(123456), 1)
|
||||||
|
self.assertEqual(getsign(-2), -1)
|
||||||
|
self.assertEqual(getsign(0), 0)
|
||||||
|
self.assertEqual(getsign(True), 1)
|
||||||
|
self.assertEqual(getsign(IntSubclass(-11)), -1)
|
||||||
|
self.assertEqual(getsign(False), 0)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, getsign, 1.0)
|
||||||
|
self.assertRaises(TypeError, getsign, Index(123))
|
||||||
|
|
||||||
|
# CRASHES getsign(NULL)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add :c:func:`PyLong_GetSign` function. Patch by Sergey B Kirpichev.
|
|
@ -92,6 +92,19 @@ pylong_fromnativebytes(PyObject *module, PyObject *args)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
pylong_getsign(PyObject *module, PyObject *arg)
|
||||||
|
{
|
||||||
|
int sign;
|
||||||
|
NULLABLE(arg);
|
||||||
|
if (PyLong_GetSign(arg, &sign) == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyLong_FromLong(sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
pylong_aspid(PyObject *module, PyObject *arg)
|
pylong_aspid(PyObject *module, PyObject *arg)
|
||||||
{
|
{
|
||||||
|
@ -109,6 +122,7 @@ static PyMethodDef test_methods[] = {
|
||||||
{"pylong_fromunicodeobject", pylong_fromunicodeobject, METH_VARARGS},
|
{"pylong_fromunicodeobject", pylong_fromunicodeobject, METH_VARARGS},
|
||||||
{"pylong_asnativebytes", pylong_asnativebytes, METH_VARARGS},
|
{"pylong_asnativebytes", pylong_asnativebytes, METH_VARARGS},
|
||||||
{"pylong_fromnativebytes", pylong_fromnativebytes, METH_VARARGS},
|
{"pylong_fromnativebytes", pylong_fromnativebytes, METH_VARARGS},
|
||||||
|
{"pylong_getsign", pylong_getsign, METH_O},
|
||||||
{"pylong_aspid", pylong_aspid, METH_O},
|
{"pylong_aspid", pylong_aspid, METH_O},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
};
|
||||||
|
|
|
@ -770,6 +770,18 @@ _PyLong_Sign(PyObject *vv)
|
||||||
return _PyLong_NonCompactSign(v);
|
return _PyLong_NonCompactSign(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyLong_GetSign(PyObject *vv, int *sign)
|
||||||
|
{
|
||||||
|
if (!PyLong_Check(vv)) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "expect int, got %T", vv);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sign = _PyLong_Sign(vv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bit_length_digit(digit x)
|
bit_length_digit(digit x)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue