summaryrefslogtreecommitdiff
path: root/Objects/longobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/longobject.c')
-rw-r--r--Objects/longobject.c342
1 files changed, 154 insertions, 188 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c
index ad239ce84e..0bf6cee6c1 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -9,6 +9,12 @@
#include <ctype.h>
#include <stddef.h>
+#include "clinic/longobject.c.h"
+/*[clinic input]
+class int "PyObject *" "&PyLong_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/
+
#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS 257
#endif
@@ -16,6 +22,9 @@
#define NSMALLNEGINTS 5
#endif
+_Py_IDENTIFIER(little);
+_Py_IDENTIFIER(big);
+
/* convert a PyLong of size 1, 0 or -1 to an sdigit */
#define MEDIUM_VALUE(x) (assert(-1 <= Py_SIZE(x) && Py_SIZE(x) <= 1), \
Py_SIZE(x) < 0 ? -(sdigit)(x)->ob_digit[0] : \
@@ -315,7 +324,6 @@ PyLong_FromUnsignedLong(unsigned long ival)
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
- Py_SIZE(v) = ndigits;
while (ival) {
*p++ = (digit)(ival & PyLong_MASK);
ival >>= PyLong_SHIFT;
@@ -709,12 +717,33 @@ _PyLong_Sign(PyObject *vv)
return Py_SIZE(v) == 0 ? 0 : (Py_SIZE(v) < 0 ? -1 : 1);
}
+/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
+ 2**k if d is nonzero, else 0. */
+
+static const unsigned char BitLengthTable[32] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+static int
+bits_in_digit(digit d)
+{
+ int d_bits = 0;
+ while (d >= 32) {
+ d_bits += 6;
+ d >>= 6;
+ }
+ d_bits += (int)BitLengthTable[d];
+ return d_bits;
+}
+
size_t
_PyLong_NumBits(PyObject *vv)
{
PyLongObject *v = (PyLongObject *)vv;
size_t result = 0;
Py_ssize_t ndigits;
+ int msd_bits;
assert(v != NULL);
assert(PyLong_Check(v));
@@ -725,12 +754,10 @@ _PyLong_NumBits(PyObject *vv)
if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
goto Overflow;
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
- do {
- ++result;
- if (result == 0)
- goto Overflow;
- msd >>= 1;
- } while (msd);
+ msd_bits = bits_in_digit(msd);
+ if (SIZE_MAX - msd_bits < result)
+ goto Overflow;
+ result += msd_bits;
}
return result;
@@ -1102,7 +1129,6 @@ PyLong_FromUnsignedLongLong(unsigned long long ival)
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
- Py_SIZE(v) = ndigits;
while (ival) {
*p++ = (digit)(ival & PyLong_MASK);
ival >>= PyLong_SHIFT;
@@ -1416,26 +1442,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
Py_RETURN_NOTIMPLEMENTED; \
} while(0)
-/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
- 2**k if d is nonzero, else 0. */
-
-static const unsigned char BitLengthTable[32] = {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-};
-
-static int
-bits_in_digit(digit d)
-{
- int d_bits = 0;
- while (d >= 32) {
- d_bits += 6;
- d >>= 6;
- }
- d_bits += (int)BitLengthTable[d];
- return d_bits;
-}
-
/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
* is modified in place, by adding y to it. Carries are propagated as far as
* x[m-1], and the remaining carry (0 or 1) is returned.
@@ -2482,7 +2488,7 @@ _PyLong_FromBytes(const char *s, Py_ssize_t len, int base)
PyObject *
PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
{
- PyObject *v, *unicode = PyUnicode_FromUnicode(u, length);
+ PyObject *v, *unicode = PyUnicode_FromWideChar(u, length);
if (unicode == NULL)
return NULL;
v = PyLong_FromUnicodeObject(unicode, base);
@@ -2494,7 +2500,8 @@ PyObject *
PyLong_FromUnicodeObject(PyObject *u, int base)
{
PyObject *result, *asciidig;
- char *buffer, *end = NULL;
+ const char *buffer;
+ char *end = NULL;
Py_ssize_t buflen;
asciidig = _PyUnicode_TransformDecimalAndSpaceToASCII(u);
@@ -3105,9 +3112,7 @@ long_add(PyLongObject *a, PyLongObject *b)
CHECK_BINOP(a, b);
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
- PyObject *result = PyLong_FromLong(MEDIUM_VALUE(a) +
- MEDIUM_VALUE(b));
- return result;
+ return PyLong_FromLong(MEDIUM_VALUE(a) + MEDIUM_VALUE(b));
}
if (Py_SIZE(a) < 0) {
if (Py_SIZE(b) < 0) {
@@ -3141,9 +3146,7 @@ long_sub(PyLongObject *a, PyLongObject *b)
CHECK_BINOP(a, b);
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
- PyObject* r;
- r = PyLong_FromLong(MEDIUM_VALUE(a)-MEDIUM_VALUE(b));
- return r;
+ return PyLong_FromLong(MEDIUM_VALUE(a) - MEDIUM_VALUE(b));
}
if (Py_SIZE(a) < 0) {
if (Py_SIZE(b) < 0)
@@ -4296,22 +4299,22 @@ long_rshift(PyLongObject *a, PyLongObject *b)
PyLongObject *a1, *a2;
a1 = (PyLongObject *) long_invert(a);
if (a1 == NULL)
- goto rshift_error;
+ return NULL;
a2 = (PyLongObject *) long_rshift(a1, b);
Py_DECREF(a1);
if (a2 == NULL)
- goto rshift_error;
+ return NULL;
z = (PyLongObject *) long_invert(a2);
Py_DECREF(a2);
}
else {
shiftby = PyLong_AsSsize_t((PyObject *)b);
if (shiftby == -1L && PyErr_Occurred())
- goto rshift_error;
+ return NULL;
if (shiftby < 0) {
PyErr_SetString(PyExc_ValueError,
"negative shift count");
- goto rshift_error;
+ return NULL;
}
wordshift = shiftby / PyLong_SHIFT;
newsize = Py_ABS(Py_SIZE(a)) - wordshift;
@@ -4323,19 +4326,15 @@ long_rshift(PyLongObject *a, PyLongObject *b)
himask = PyLong_MASK ^ lomask;
z = _PyLong_New(newsize);
if (z == NULL)
- goto rshift_error;
- if (Py_SIZE(a) < 0)
- Py_SIZE(z) = -(Py_SIZE(z));
+ return NULL;
for (i = 0, j = wordshift; i < newsize; i++, j++) {
z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask;
if (i+1 < newsize)
z->ob_digit[i] |= (a->ob_digit[j+1] << hishift) & himask;
}
- z = long_normalize(z);
+ z = maybe_small_long(long_normalize(z));
}
- rshift_error:
- return (PyObject *) maybe_small_long(z);
-
+ return (PyObject *)z;
}
static PyObject *
@@ -4873,10 +4872,15 @@ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)newobj;
}
+/*[clinic input]
+int.__getnewargs__
+[clinic start generated code]*/
+
static PyObject *
-long_getnewargs(PyLongObject *v)
+int___getnewargs___impl(PyObject *self)
+/*[clinic end generated code: output=839a49de3f00b61b input=5904770ab1fb8c75]*/
{
- return Py_BuildValue("(N)", _PyLong_Copy(v));
+ return Py_BuildValue("(N)", _PyLong_Copy((PyLongObject *)self));
}
static PyObject *
@@ -4889,16 +4893,20 @@ long_get1(PyLongObject *v, void *context) {
return PyLong_FromLong(1L);
}
+/*[clinic input]
+int.__format__
+
+ format_spec: unicode
+ /
+[clinic start generated code]*/
+
static PyObject *
-long__format__(PyObject *self, PyObject *args)
+int___format___impl(PyObject *self, PyObject *format_spec)
+/*[clinic end generated code: output=b4929dee9ae18689 input=e31944a9b3e428b7]*/
{
- PyObject *format_spec;
_PyUnicodeWriter writer;
int ret;
- if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
- return NULL;
-
_PyUnicodeWriter_Init(&writer);
ret = _PyLong_FormatAdvancedWriter(
&writer,
@@ -5076,35 +5084,51 @@ long_round(PyObject *self, PyObject *args)
return result;
}
-static PyObject *
-long_sizeof(PyLongObject *v)
+/*[clinic input]
+int.__sizeof__ -> Py_ssize_t
+
+Returns size in memory, in bytes.
+[clinic start generated code]*/
+
+static Py_ssize_t
+int___sizeof___impl(PyObject *self)
+/*[clinic end generated code: output=3303f008eaa6a0a5 input=9b51620c76fc4507]*/
{
Py_ssize_t res;
- res = offsetof(PyLongObject, ob_digit) + Py_ABS(Py_SIZE(v))*sizeof(digit);
- return PyLong_FromSsize_t(res);
+ res = offsetof(PyLongObject, ob_digit) + Py_ABS(Py_SIZE(self))*sizeof(digit);
+ return res;
}
+/*[clinic input]
+int.bit_length
+
+Number of bits necessary to represent self in binary.
+
+>>> bin(37)
+'0b100101'
+>>> (37).bit_length()
+6
+[clinic start generated code]*/
+
static PyObject *
-long_bit_length(PyLongObject *v)
+int_bit_length_impl(PyObject *self)
+/*[clinic end generated code: output=fc1977c9353d6a59 input=e4eb7a587e849a32]*/
{
PyLongObject *result, *x, *y;
- Py_ssize_t ndigits, msd_bits = 0;
+ Py_ssize_t ndigits;
+ int msd_bits;
digit msd;
- assert(v != NULL);
- assert(PyLong_Check(v));
+ assert(self != NULL);
+ assert(PyLong_Check(self));
- ndigits = Py_ABS(Py_SIZE(v));
+ ndigits = Py_ABS(Py_SIZE(self));
if (ndigits == 0)
return PyLong_FromLong(0);
- msd = v->ob_digit[ndigits-1];
- while (msd >= 32) {
- msd_bits += 6;
- msd >>= 6;
- }
- msd_bits += (long)(BitLengthTable[msd]);
+ msd = ((PyLongObject *)self)->ob_digit[ndigits-1];
+ msd_bits = bits_in_digit(msd);
if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT)
return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits);
@@ -5140,15 +5164,6 @@ long_bit_length(PyLongObject *v)
return NULL;
}
-PyDoc_STRVAR(long_bit_length_doc,
-"int.bit_length() -> int\n\
-\n\
-Number of bits necessary to represent self in binary.\n\
->>> bin(37)\n\
-'0b100101'\n\
->>> (37).bit_length()\n\
-6");
-
#if 0
static PyObject *
long_is_finite(PyObject *v)
@@ -5157,32 +5172,38 @@ long_is_finite(PyObject *v)
}
#endif
+/*[clinic input]
+int.to_bytes
+
+ length: Py_ssize_t
+ Length of bytes object to use. An OverflowError is raised if the
+ integer is not representable with the given number of bytes.
+ byteorder: unicode
+ The byte order used to represent the integer. If byteorder is 'big',
+ the most significant byte is at the beginning of the byte array. If
+ byteorder is 'little', the most significant byte is at the end of the
+ byte array. To request the native byte order of the host system, use
+ `sys.byteorder' as the byte order value.
+ *
+ signed as is_signed: bool = False
+ Determines whether two's complement is used to represent the integer.
+ If signed is False and a negative integer is given, an OverflowError
+ is raised.
+
+Return an array of bytes representing an integer.
+[clinic start generated code]*/
static PyObject *
-long_to_bytes(PyLongObject *v, PyObject *args, PyObject *kwds)
+int_to_bytes_impl(PyObject *self, Py_ssize_t length, PyObject *byteorder,
+ int is_signed)
+/*[clinic end generated code: output=89c801df114050a3 input=ddac63f4c7bf414c]*/
{
- PyObject *byteorder_str;
- PyObject *is_signed_obj = NULL;
- Py_ssize_t length;
int little_endian;
- int is_signed;
PyObject *bytes;
- static char *kwlist[] = {"length", "byteorder", "signed", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "nU|O:to_bytes", kwlist,
- &length, &byteorder_str,
- &is_signed_obj))
- return NULL;
-
- if (args != NULL && Py_SIZE(args) > 2) {
- PyErr_SetString(PyExc_TypeError,
- "'signed' is a keyword-only argument");
- return NULL;
- }
- if (_PyUnicode_EqualToASCIIString(byteorder_str, "little"))
+ if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
little_endian = 1;
- else if (_PyUnicode_EqualToASCIIString(byteorder_str, "big"))
+ else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big))
little_endian = 0;
else {
PyErr_SetString(PyExc_ValueError,
@@ -5190,18 +5211,6 @@ long_to_bytes(PyLongObject *v, PyObject *args, PyObject *kwds)
return NULL;
}
- if (is_signed_obj != NULL) {
- int cmp = PyObject_IsTrue(is_signed_obj);
- if (cmp < 0)
- return NULL;
- is_signed = cmp ? 1 : 0;
- }
- else {
- /* If the signed argument was omitted, use False as the
- default. */
- is_signed = 0;
- }
-
if (length < 0) {
PyErr_SetString(PyExc_ValueError,
"length argument must be non-negative");
@@ -5212,7 +5221,8 @@ long_to_bytes(PyLongObject *v, PyObject *args, PyObject *kwds)
if (bytes == NULL)
return NULL;
- if (_PyLong_AsByteArray(v, (unsigned char *)PyBytes_AS_STRING(bytes),
+ if (_PyLong_AsByteArray((PyLongObject *)self,
+ (unsigned char *)PyBytes_AS_STRING(bytes),
length, little_endian, is_signed) < 0) {
Py_DECREF(bytes);
return NULL;
@@ -5221,51 +5231,39 @@ long_to_bytes(PyLongObject *v, PyObject *args, PyObject *kwds)
return bytes;
}
-PyDoc_STRVAR(long_to_bytes_doc,
-"int.to_bytes(length, byteorder, *, signed=False) -> bytes\n\
-\n\
-Return an array of bytes representing an integer.\n\
-\n\
-The integer is represented using length bytes. An OverflowError is\n\
-raised if the integer is not representable with the given number of\n\
-bytes.\n\
-\n\
-The byteorder argument determines the byte order used to represent the\n\
-integer. If byteorder is 'big', the most significant byte is at the\n\
-beginning of the byte array. If byteorder is 'little', the most\n\
-significant byte is at the end of the byte array. To request the native\n\
-byte order of the host system, use `sys.byteorder' as the byte order value.\n\
-\n\
-The signed keyword-only argument determines whether two's complement is\n\
-used to represent the integer. If signed is False and a negative integer\n\
-is given, an OverflowError is raised.");
+/*[clinic input]
+@classmethod
+int.from_bytes
+
+ bytes as bytes_obj: object
+ Holds the array of bytes to convert. The argument must either
+ support the buffer protocol or be an iterable object producing bytes.
+ Bytes and bytearray are examples of built-in objects that support the
+ buffer protocol.
+ byteorder: unicode
+ The byte order used to represent the integer. If byteorder is 'big',
+ the most significant byte is at the beginning of the byte array. If
+ byteorder is 'little', the most significant byte is at the end of the
+ byte array. To request the native byte order of the host system, use
+ `sys.byteorder' as the byte order value.
+ *
+ signed as is_signed: bool = False
+ Indicates whether two's complement is used to represent the integer.
+
+Return the integer represented by the given array of bytes.
+[clinic start generated code]*/
static PyObject *
-long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds)
+int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj,
+ PyObject *byteorder, int is_signed)
+/*[clinic end generated code: output=efc5d68e31f9314f input=cdf98332b6a821b0]*/
{
- PyObject *byteorder_str;
- PyObject *is_signed_obj = NULL;
int little_endian;
- int is_signed;
- PyObject *obj;
- PyObject *bytes;
- PyObject *long_obj;
- static char *kwlist[] = {"bytes", "byteorder", "signed", NULL};
+ PyObject *long_obj, *bytes;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OU|O:from_bytes", kwlist,
- &obj, &byteorder_str,
- &is_signed_obj))
- return NULL;
-
- if (args != NULL && Py_SIZE(args) > 2) {
- PyErr_SetString(PyExc_TypeError,
- "'signed' is a keyword-only argument");
- return NULL;
- }
-
- if (_PyUnicode_EqualToASCIIString(byteorder_str, "little"))
+ if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
little_endian = 1;
- else if (_PyUnicode_EqualToASCIIString(byteorder_str, "big"))
+ else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big))
little_endian = 0;
else {
PyErr_SetString(PyExc_ValueError,
@@ -5273,19 +5271,7 @@ long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
- if (is_signed_obj != NULL) {
- int cmp = PyObject_IsTrue(is_signed_obj);
- if (cmp < 0)
- return NULL;
- is_signed = cmp ? 1 : 0;
- }
- else {
- /* If the signed argument was omitted, use False as the
- default. */
- is_signed = 0;
- }
-
- bytes = PyObject_Bytes(obj);
+ bytes = PyObject_Bytes(bytes_obj);
if (bytes == NULL)
return NULL;
@@ -5302,35 +5288,16 @@ long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds)
return long_obj;
}
-PyDoc_STRVAR(long_from_bytes_doc,
-"int.from_bytes(bytes, byteorder, *, signed=False) -> int\n\
-\n\
-Return the integer represented by the given array of bytes.\n\
-\n\
-The bytes argument must be a bytes-like object (e.g. bytes or bytearray).\n\
-\n\
-The byteorder argument determines the byte order used to represent the\n\
-integer. If byteorder is 'big', the most significant byte is at the\n\
-beginning of the byte array. If byteorder is 'little', the most\n\
-significant byte is at the end of the byte array. To request the native\n\
-byte order of the host system, use `sys.byteorder' as the byte order value.\n\
-\n\
-The signed keyword-only argument indicates whether two's complement is\n\
-used to represent the integer.");
-
static PyMethodDef long_methods[] = {
{"conjugate", (PyCFunction)long_long, METH_NOARGS,
"Returns self, the complex conjugate of any int."},
- {"bit_length", (PyCFunction)long_bit_length, METH_NOARGS,
- long_bit_length_doc},
+ INT_BIT_LENGTH_METHODDEF
#if 0
{"is_finite", (PyCFunction)long_is_finite, METH_NOARGS,
"Returns always True."},
#endif
- {"to_bytes", (PyCFunction)long_to_bytes,
- METH_VARARGS|METH_KEYWORDS, long_to_bytes_doc},
- {"from_bytes", (PyCFunction)long_from_bytes,
- METH_VARARGS|METH_KEYWORDS|METH_CLASS, long_from_bytes_doc},
+ INT_TO_BYTES_METHODDEF
+ INT_FROM_BYTES_METHODDEF
{"__trunc__", (PyCFunction)long_long, METH_NOARGS,
"Truncating an Integral returns itself."},
{"__floor__", (PyCFunction)long_long, METH_NOARGS,
@@ -5340,10 +5307,9 @@ static PyMethodDef long_methods[] = {
{"__round__", (PyCFunction)long_round, METH_VARARGS,
"Rounding an Integral returns itself.\n"
"Rounding with an ndigits argument also returns an integer."},
- {"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
- {"__format__", (PyCFunction)long__format__, METH_VARARGS},
- {"__sizeof__", (PyCFunction)long_sizeof, METH_NOARGS,
- "Returns size in memory, in bytes"},
+ INT___GETNEWARGS___METHODDEF
+ INT___FORMAT___METHODDEF
+ INT___SIZEOF___METHODDEF
{NULL, NULL} /* sentinel */
};