From e7c175efdafc8a76621c7331d4cfae9654ebea5b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 17 Sep 2016 17:50:50 +0100 Subject: Issue #27222: various cleanups in long_rshift. Thanks Oren Milman. --- Objects/longobject.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index a453241b3f..0822f9bcb3 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4296,22 +4296,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 +4323,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 * -- cgit v1.2.1 From a92d1fa671171aa0da569aa91c7c75612a3ecacc Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 17 Sep 2016 19:44:13 +0100 Subject: Issue #27441: Remove some redundant assignments to ob_size in longobject.c. Thanks Oren Milman. --- Objects/longobject.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index 0822f9bcb3..0ecbab1fba 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -315,7 +315,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; @@ -1102,7 +1101,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; -- cgit v1.2.1 From f90cefa36daf2409987e60421306c2a5948cd367 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 17 Sep 2016 20:01:56 +0100 Subject: Issue #27111: Minor simplication to long_add and long_sub fast path code. Thanks Oren Milman. --- Objects/longobject.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index 0ecbab1fba..6e569b218d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3103,9 +3103,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) { @@ -3139,9 +3137,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) -- cgit v1.2.1 From a501fdb581467719292dbdeec07242d10de3555d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 8 Nov 2016 20:34:22 +0200 Subject: Issue #28621: Sped up converting int to float by reusing faster bits counting implementation. Patch by Adrian Wielgosik. --- Objects/longobject.c | 60 ++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index 6e569b218d..10dde726a2 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -708,12 +708,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)); @@ -724,12 +745,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; @@ -1414,26 +1433,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. @@ -5079,7 +5078,8 @@ static PyObject * long_bit_length(PyLongObject *v) { PyLongObject *result, *x, *y; - Py_ssize_t ndigits, msd_bits = 0; + Py_ssize_t ndigits; + int msd_bits; digit msd; assert(v != NULL); @@ -5090,11 +5090,7 @@ long_bit_length(PyLongObject *v) return PyLong_FromLong(0); msd = v->ob_digit[ndigits-1]; - while (msd >= 32) { - msd_bits += 6; - msd >>= 6; - } - msd_bits += (long)(BitLengthTable[msd]); + msd_bits = bits_in_digit(msd); if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT) return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits); -- cgit v1.2.1 From 5d858465b6ebdafa05f86309457848cc26913b6a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Nov 2016 10:16:47 +0200 Subject: Added the const qualifier to char* variables that refer to readonly internal UTF-8 represenatation of Unicode objects. --- Objects/longobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index b0f6b8c953..822ed1632f 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2491,7 +2491,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); -- cgit v1.2.1 From ba86008aac6890c5c4a2c6d30ea8110f228d483e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Nov 2016 12:16:46 +0200 Subject: Issue #19569: Compiler warnings are now emitted if use most of deprecated functions. --- Objects/longobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index 822ed1632f..c95f9467ad 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2479,7 +2479,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); -- cgit v1.2.1 From 366f4ee4da4420842eac26b3fa00c2b01d4515a6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 1 Dec 2016 14:43:22 +0100 Subject: Replace PyObject_CallFunctionObjArgs() with fastcall * PyObject_CallFunctionObjArgs(func, NULL) => _PyObject_CallNoArg(func) * PyObject_CallFunctionObjArgs(func, arg, NULL) => _PyObject_CallArg1(func, arg) PyObject_CallFunctionObjArgs() allocates 40 bytes on the C stack and requires extra work to "parse" C arguments to build a C array of PyObject*. _PyObject_CallNoArg() and _PyObject_CallArg1() are simpler and don't allocate memory on the C stack. This change is part of the fastcall project. The change on listsort() is related to the issue #23507. --- Objects/longobject.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index c95f9467ad..b9f6327759 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5282,8 +5282,7 @@ long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(bytes); if (type != &PyLong_Type) { - Py_SETREF(long_obj, PyObject_CallFunctionObjArgs((PyObject *)type, - long_obj, NULL)); + Py_SETREF(long_obj, _PyObject_CallArg1((PyObject *)type, long_obj)); } return long_obj; -- cgit v1.2.1 From 39ae5bedd90f9caf9a78efa82f4d11e838933b3a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 4 Dec 2016 22:59:09 +0100 Subject: Backed out changeset b9c9691c72c5 Issue #28858: The change b9c9691c72c5 introduced a regression. It seems like _PyObject_CallArg1() uses more stack memory than PyObject_CallFunctionObjArgs(). --- Objects/longobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index b9f6327759..c95f9467ad 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5282,7 +5282,8 @@ long_from_bytes(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(bytes); if (type != &PyLong_Type) { - Py_SETREF(long_obj, _PyObject_CallArg1((PyObject *)type, long_obj)); + Py_SETREF(long_obj, PyObject_CallFunctionObjArgs((PyObject *)type, + long_obj, NULL)); } return long_obj; -- cgit v1.2.1 From 62992ef31b28b380da92b990a53e2105a4612309 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 1 Feb 2017 23:12:20 +0200 Subject: Issue #20185: Converted the int class to Argument Clinic. Based on patch by Vajrasky Kok. --- Objects/longobject.c | 246 +++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 135 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index c95f9467ad..f37fbd7222 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -9,6 +9,12 @@ #include #include +#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 @@ -4863,10 +4869,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 * @@ -4879,16 +4890,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, @@ -5066,31 +5081,50 @@ 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; 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]; + msd = ((PyLongObject *)self)->ob_digit[ndigits-1]; msd_bits = bits_in_digit(msd); if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT) @@ -5127,15 +5161,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) @@ -5144,32 +5169,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_EqualToASCIIString(byteorder, "little")) little_endian = 1; - else if (_PyUnicode_EqualToASCIIString(byteorder_str, "big")) + else if (_PyUnicode_EqualToASCIIString(byteorder, "big")) little_endian = 0; else { PyErr_SetString(PyExc_ValueError, @@ -5177,18 +5208,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"); @@ -5199,7 +5218,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; @@ -5208,51 +5228,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}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OU|O:from_bytes", kwlist, - &obj, &byteorder_str, - &is_signed_obj)) - return NULL; + PyObject *long_obj, *bytes; - 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_EqualToASCIIString(byteorder, "little")) little_endian = 1; - else if (_PyUnicode_EqualToASCIIString(byteorder_str, "big")) + else if (_PyUnicode_EqualToASCIIString(byteorder, "big")) little_endian = 0; else { PyErr_SetString(PyExc_ValueError, @@ -5260,19 +5268,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; @@ -5289,35 +5285,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, @@ -5327,10 +5304,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 */ }; -- cgit v1.2.1 From 4f4c038c0cd2a312cf9155e75f1be041b5085edd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 2 Feb 2017 16:54:45 +0200 Subject: Issue #29421: Make int.to_bytes() and int.from_bytes() slightly faster (10-20% for small integers). --- Objects/longobject.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'Objects/longobject.c') diff --git a/Objects/longobject.c b/Objects/longobject.c index f37fbd7222..0bf6cee6c1 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -22,6 +22,9 @@ class int "PyObject *" "&PyLong_Type" #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] : \ @@ -5198,9 +5201,9 @@ int_to_bytes_impl(PyObject *self, Py_ssize_t length, PyObject *byteorder, int little_endian; PyObject *bytes; - if (_PyUnicode_EqualToASCIIString(byteorder, "little")) + if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little)) little_endian = 1; - else if (_PyUnicode_EqualToASCIIString(byteorder, "big")) + else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big)) little_endian = 0; else { PyErr_SetString(PyExc_ValueError, @@ -5258,9 +5261,9 @@ int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj, int little_endian; PyObject *long_obj, *bytes; - if (_PyUnicode_EqualToASCIIString(byteorder, "little")) + if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little)) little_endian = 1; - else if (_PyUnicode_EqualToASCIIString(byteorder, "big")) + else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big)) little_endian = 0; else { PyErr_SetString(PyExc_ValueError, -- cgit v1.2.1