mirror of https://github.com/python/cpython
bpo-44946: Streamline operators and creation of ints for common case of single 'digit'. (GH-27832)
This commit is contained in:
parent
f9242d50b1
commit
15d50d7ed8
|
@ -26,15 +26,27 @@ class int "PyObject *" "&PyLong_Type"
|
||||||
_Py_IDENTIFIER(little);
|
_Py_IDENTIFIER(little);
|
||||||
_Py_IDENTIFIER(big);
|
_Py_IDENTIFIER(big);
|
||||||
|
|
||||||
/* convert a PyLong of size 1, 0 or -1 to an sdigit */
|
/* Is this PyLong of size 1, 0 or -1? */
|
||||||
#define MEDIUM_VALUE(x) (assert(-1 <= Py_SIZE(x) && Py_SIZE(x) <= 1), \
|
#define IS_MEDIUM_VALUE(x) (((size_t)Py_SIZE(x)) + 1U < 3U)
|
||||||
Py_SIZE(x) < 0 ? -(sdigit)(x)->ob_digit[0] : \
|
|
||||||
(Py_SIZE(x) == 0 ? (sdigit)0 : \
|
/* convert a PyLong of size 1, 0 or -1 to a C integer */
|
||||||
(sdigit)(x)->ob_digit[0]))
|
static inline stwodigits
|
||||||
|
medium_value(PyLongObject *x)
|
||||||
|
{
|
||||||
|
assert(IS_MEDIUM_VALUE(x));
|
||||||
|
return ((stwodigits)Py_SIZE(x)) * x->ob_digit[0];
|
||||||
|
}
|
||||||
|
|
||||||
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
|
||||||
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
|
||||||
|
|
||||||
|
static inline int is_medium_int(stwodigits x)
|
||||||
|
{
|
||||||
|
/* Take care that we are comparing unsigned values. */
|
||||||
|
twodigits x_plus_mask = ((twodigits)x) + PyLong_MASK;
|
||||||
|
return x_plus_mask < ((twodigits)PyLong_MASK) + PyLong_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_small_int(sdigit ival)
|
get_small_int(sdigit ival)
|
||||||
{
|
{
|
||||||
|
@ -47,33 +59,16 @@ get_small_int(sdigit ival)
|
||||||
static PyLongObject *
|
static PyLongObject *
|
||||||
maybe_small_long(PyLongObject *v)
|
maybe_small_long(PyLongObject *v)
|
||||||
{
|
{
|
||||||
if (v && Py_ABS(Py_SIZE(v)) <= 1) {
|
if (v && IS_MEDIUM_VALUE(v)) {
|
||||||
sdigit ival = MEDIUM_VALUE(v);
|
stwodigits ival = medium_value(v);
|
||||||
if (IS_SMALL_INT(ival)) {
|
if (IS_SMALL_INT(ival)) {
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
return (PyLongObject *)get_small_int(ival);
|
return (PyLongObject *)get_small_int((sdigit)ival);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a freshly-allocated int is already shared, it must
|
|
||||||
be a small integer, so negating it must go to PyLong_FromLong */
|
|
||||||
Py_LOCAL_INLINE(void)
|
|
||||||
_PyLong_Negate(PyLongObject **x_p)
|
|
||||||
{
|
|
||||||
PyLongObject *x;
|
|
||||||
|
|
||||||
x = (PyLongObject *)*x_p;
|
|
||||||
if (Py_REFCNT(x) == 1) {
|
|
||||||
Py_SET_SIZE(x, -Py_SIZE(x));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*x_p = (PyLongObject *)PyLong_FromLong(-MEDIUM_VALUE(x));
|
|
||||||
Py_DECREF(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For int multiplication, use the O(N**2) school algorithm unless
|
/* For int multiplication, use the O(N**2) school algorithm unless
|
||||||
* both operands contain more than KARATSUBA_CUTOFF digits (this
|
* both operands contain more than KARATSUBA_CUTOFF digits (this
|
||||||
* being an internal Python int digit, in base BASE).
|
* being an internal Python int digit, in base BASE).
|
||||||
|
@ -121,18 +116,21 @@ PyLongObject *
|
||||||
_PyLong_New(Py_ssize_t size)
|
_PyLong_New(Py_ssize_t size)
|
||||||
{
|
{
|
||||||
PyLongObject *result;
|
PyLongObject *result;
|
||||||
/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +
|
|
||||||
sizeof(digit)*size. Previous incarnations of this code used
|
|
||||||
sizeof(PyVarObject) instead of the offsetof, but this risks being
|
|
||||||
incorrect in the presence of padding between the PyVarObject header
|
|
||||||
and the digits. */
|
|
||||||
if (size > (Py_ssize_t)MAX_LONG_DIGITS) {
|
if (size > (Py_ssize_t)MAX_LONG_DIGITS) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"too many digits in integer");
|
"too many digits in integer");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* Fast operations for single digit integers (including zero)
|
||||||
|
* assume that there is always at least one digit present. */
|
||||||
|
Py_ssize_t ndigits = size ? size : 1;
|
||||||
|
/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +
|
||||||
|
sizeof(digit)*size. Previous incarnations of this code used
|
||||||
|
sizeof(PyVarObject) instead of the offsetof, but this risks being
|
||||||
|
incorrect in the presence of padding between the PyVarObject header
|
||||||
|
and the digits. */
|
||||||
result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) +
|
result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) +
|
||||||
size*sizeof(digit));
|
ndigits*sizeof(digit));
|
||||||
if (!result) {
|
if (!result) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -152,9 +150,9 @@ _PyLong_Copy(PyLongObject *src)
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i = -(i);
|
i = -(i);
|
||||||
if (i < 2) {
|
if (i < 2) {
|
||||||
sdigit ival = MEDIUM_VALUE(src);
|
stwodigits ival = medium_value(src);
|
||||||
if (IS_SMALL_INT(ival)) {
|
if (IS_SMALL_INT(ival)) {
|
||||||
return get_small_int(ival);
|
return get_small_int((sdigit)ival);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = _PyLong_New(i);
|
result = _PyLong_New(i);
|
||||||
|
@ -167,65 +165,126 @@ _PyLong_Copy(PyLongObject *src)
|
||||||
return (PyObject *)result;
|
return (PyObject *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new int object from a C long int */
|
static PyObject *
|
||||||
|
_PyLong_FromMedium(sdigit x)
|
||||||
PyObject *
|
|
||||||
PyLong_FromLong(long ival)
|
|
||||||
{
|
{
|
||||||
PyLongObject *v;
|
assert(!IS_SMALL_INT(x));
|
||||||
unsigned long abs_ival;
|
assert(is_medium_int(x));
|
||||||
unsigned long t; /* unsigned so >> doesn't propagate sign bit */
|
/* We could use a freelist here */
|
||||||
int ndigits = 0;
|
PyLongObject *v = PyObject_Malloc(sizeof(PyLongObject));
|
||||||
int sign;
|
if (v == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
if (IS_SMALL_INT(ival)) {
|
return NULL;
|
||||||
return get_small_int((sdigit)ival);
|
|
||||||
}
|
}
|
||||||
|
Py_ssize_t sign = x < 0 ? -1: 1;
|
||||||
|
digit abs_x = x < 0 ? -x : x;
|
||||||
|
_PyObject_InitVar((PyVarObject*)v, &PyLong_Type, sign);
|
||||||
|
v->ob_digit[0] = abs_x;
|
||||||
|
return (PyObject*)v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_PyLong_FromLarge(stwodigits ival)
|
||||||
|
{
|
||||||
|
twodigits abs_ival;
|
||||||
|
int sign;
|
||||||
|
assert(!is_medium_int(ival));
|
||||||
|
|
||||||
if (ival < 0) {
|
if (ival < 0) {
|
||||||
/* negate: can't write this as abs_ival = -ival since that
|
/* negate: can't write this as abs_ival = -ival since that
|
||||||
invokes undefined behaviour when ival is LONG_MIN */
|
invokes undefined behaviour when ival is LONG_MIN */
|
||||||
abs_ival = 0U-(unsigned long)ival;
|
abs_ival = 0U-(twodigits)ival;
|
||||||
sign = -1;
|
sign = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
abs_ival = (unsigned long)ival;
|
abs_ival = (twodigits)ival;
|
||||||
sign = ival == 0 ? 0 : 1;
|
sign = 1;
|
||||||
}
|
}
|
||||||
|
/* Must be at least two digits */
|
||||||
/* Fast path for single-digit ints */
|
assert(abs_ival >> PyLong_SHIFT != 0);
|
||||||
if (!(abs_ival >> PyLong_SHIFT)) {
|
twodigits t = abs_ival >> (PyLong_SHIFT * 2);
|
||||||
v = _PyLong_New(1);
|
Py_ssize_t ndigits = 2;
|
||||||
if (v) {
|
|
||||||
Py_SET_SIZE(v, sign);
|
|
||||||
v->ob_digit[0] = Py_SAFE_DOWNCAST(
|
|
||||||
abs_ival, unsigned long, digit);
|
|
||||||
}
|
|
||||||
return (PyObject*)v;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PyLong_SHIFT==15
|
|
||||||
/* 2 digits */
|
|
||||||
if (!(abs_ival >> 2*PyLong_SHIFT)) {
|
|
||||||
v = _PyLong_New(2);
|
|
||||||
if (v) {
|
|
||||||
Py_SET_SIZE(v, 2 * sign);
|
|
||||||
v->ob_digit[0] = Py_SAFE_DOWNCAST(
|
|
||||||
abs_ival & PyLong_MASK, unsigned long, digit);
|
|
||||||
v->ob_digit[1] = Py_SAFE_DOWNCAST(
|
|
||||||
abs_ival >> PyLong_SHIFT, unsigned long, digit);
|
|
||||||
}
|
|
||||||
return (PyObject*)v;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Larger numbers: loop to determine number of digits */
|
|
||||||
t = abs_ival;
|
|
||||||
while (t) {
|
while (t) {
|
||||||
++ndigits;
|
++ndigits;
|
||||||
t >>= PyLong_SHIFT;
|
t >>= PyLong_SHIFT;
|
||||||
}
|
}
|
||||||
v = _PyLong_New(ndigits);
|
PyLongObject *v = _PyLong_New(ndigits);
|
||||||
|
if (v != NULL) {
|
||||||
|
digit *p = v->ob_digit;
|
||||||
|
Py_SET_SIZE(v, ndigits * sign);
|
||||||
|
t = abs_ival;
|
||||||
|
while (t) {
|
||||||
|
*p++ = Py_SAFE_DOWNCAST(
|
||||||
|
t & PyLong_MASK, twodigits, digit);
|
||||||
|
t >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (PyObject *)v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new int object from a C word-sized int */
|
||||||
|
static inline PyObject *
|
||||||
|
_PyLong_FromSTwoDigits(stwodigits x)
|
||||||
|
{
|
||||||
|
if (IS_SMALL_INT(x)) {
|
||||||
|
return get_small_int((sdigit)x);
|
||||||
|
}
|
||||||
|
assert(x != 0);
|
||||||
|
if (is_medium_int(x)) {
|
||||||
|
return _PyLong_FromMedium((sdigit)x);
|
||||||
|
}
|
||||||
|
return _PyLong_FromLarge(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a freshly-allocated int is already shared, it must
|
||||||
|
be a small integer, so negating it must go to PyLong_FromLong */
|
||||||
|
Py_LOCAL_INLINE(void)
|
||||||
|
_PyLong_Negate(PyLongObject **x_p)
|
||||||
|
{
|
||||||
|
PyLongObject *x;
|
||||||
|
|
||||||
|
x = (PyLongObject *)*x_p;
|
||||||
|
if (Py_REFCNT(x) == 1) {
|
||||||
|
Py_SET_SIZE(x, -Py_SIZE(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x_p = (PyLongObject *)_PyLong_FromSTwoDigits(-medium_value(x));
|
||||||
|
Py_DECREF(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new int object from a C long int */
|
||||||
|
PyObject *
|
||||||
|
PyLong_FromLong(long ival)
|
||||||
|
{
|
||||||
|
if (IS_SMALL_INT(ival)) {
|
||||||
|
return get_small_int((sdigit)ival);
|
||||||
|
}
|
||||||
|
unsigned long abs_ival;
|
||||||
|
int sign;
|
||||||
|
if (ival < 0) {
|
||||||
|
/* negate: can't write this as abs_ival = -ival since that
|
||||||
|
invokes undefined behaviour when ival is LONG_MIN */
|
||||||
|
abs_ival = 0U-(twodigits)ival;
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
abs_ival = (unsigned long)ival;
|
||||||
|
sign = 1;
|
||||||
|
}
|
||||||
|
/* Fast path for single-digit ints */
|
||||||
|
if (!(abs_ival >> PyLong_SHIFT)) {
|
||||||
|
return _PyLong_FromMedium((sdigit)ival);
|
||||||
|
}
|
||||||
|
/* Must be at least two digits.
|
||||||
|
* Do shift in two steps to avoid undefined behavior. */
|
||||||
|
unsigned long t = (abs_ival >> PyLong_SHIFT) >> PyLong_SHIFT;
|
||||||
|
Py_ssize_t ndigits = 2;
|
||||||
|
while (t) {
|
||||||
|
++ndigits;
|
||||||
|
t >>= PyLong_SHIFT;
|
||||||
|
}
|
||||||
|
PyLongObject *v = _PyLong_New(ndigits);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
digit *p = v->ob_digit;
|
digit *p = v->ob_digit;
|
||||||
Py_SET_SIZE(v, ndigits * sign);
|
Py_SET_SIZE(v, ndigits * sign);
|
||||||
|
@ -2860,12 +2919,12 @@ PyLong_AsDouble(PyObject *v)
|
||||||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
if (Py_ABS(Py_SIZE(v)) <= 1) {
|
if (IS_MEDIUM_VALUE(v)) {
|
||||||
/* Fast path; single digit long (31 bits) will cast safely
|
/* Fast path; single digit long (31 bits) will cast safely
|
||||||
to double. This improves performance of FP/long operations
|
to double. This improves performance of FP/long operations
|
||||||
by 20%.
|
by 20%.
|
||||||
*/
|
*/
|
||||||
return (double)MEDIUM_VALUE((PyLongObject *)v);
|
return (double)medium_value((PyLongObject *)v);
|
||||||
}
|
}
|
||||||
x = _PyLong_Frexp((PyLongObject *)v, &exponent);
|
x = _PyLong_Frexp((PyLongObject *)v, &exponent);
|
||||||
if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) {
|
if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) {
|
||||||
|
@ -3067,8 +3126,8 @@ long_add(PyLongObject *a, PyLongObject *b)
|
||||||
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
|
|
||||||
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
|
if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
|
||||||
return PyLong_FromLong(MEDIUM_VALUE(a) + MEDIUM_VALUE(b));
|
return _PyLong_FromSTwoDigits(medium_value(a) + medium_value(b));
|
||||||
}
|
}
|
||||||
if (Py_SIZE(a) < 0) {
|
if (Py_SIZE(a) < 0) {
|
||||||
if (Py_SIZE(b) < 0) {
|
if (Py_SIZE(b) < 0) {
|
||||||
|
@ -3101,8 +3160,8 @@ long_sub(PyLongObject *a, PyLongObject *b)
|
||||||
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
|
|
||||||
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
|
if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
|
||||||
return PyLong_FromLong(MEDIUM_VALUE(a) - MEDIUM_VALUE(b));
|
return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b));
|
||||||
}
|
}
|
||||||
if (Py_SIZE(a) < 0) {
|
if (Py_SIZE(a) < 0) {
|
||||||
if (Py_SIZE(b) < 0) {
|
if (Py_SIZE(b) < 0) {
|
||||||
|
@ -3536,9 +3595,9 @@ long_mul(PyLongObject *a, PyLongObject *b)
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
|
|
||||||
/* fast path for single-digit multiplication */
|
/* fast path for single-digit multiplication */
|
||||||
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
|
if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
|
||||||
stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b);
|
stwodigits v = medium_value(a) * medium_value(b);
|
||||||
return PyLong_FromLongLong((long long)v);
|
return _PyLong_FromSTwoDigits(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
z = k_mul(a, b);
|
z = k_mul(a, b);
|
||||||
|
@ -4343,8 +4402,8 @@ long_invert(PyLongObject *v)
|
||||||
{
|
{
|
||||||
/* Implement ~x as -(x+1) */
|
/* Implement ~x as -(x+1) */
|
||||||
PyLongObject *x;
|
PyLongObject *x;
|
||||||
if (Py_ABS(Py_SIZE(v)) <=1)
|
if (IS_MEDIUM_VALUE(v))
|
||||||
return PyLong_FromLong(-(MEDIUM_VALUE(v)+1));
|
return _PyLong_FromSTwoDigits(~medium_value(v));
|
||||||
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_GetOne());
|
x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_GetOne());
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -4358,8 +4417,8 @@ static PyObject *
|
||||||
long_neg(PyLongObject *v)
|
long_neg(PyLongObject *v)
|
||||||
{
|
{
|
||||||
PyLongObject *z;
|
PyLongObject *z;
|
||||||
if (Py_ABS(Py_SIZE(v)) <= 1)
|
if (IS_MEDIUM_VALUE(v))
|
||||||
return PyLong_FromLong(-MEDIUM_VALUE(v));
|
return _PyLong_FromSTwoDigits(-medium_value(v));
|
||||||
z = (PyLongObject *)_PyLong_Copy(v);
|
z = (PyLongObject *)_PyLong_Copy(v);
|
||||||
if (z != NULL)
|
if (z != NULL)
|
||||||
Py_SET_SIZE(z, -(Py_SIZE(v)));
|
Py_SET_SIZE(z, -(Py_SIZE(v)));
|
||||||
|
@ -4704,28 +4763,37 @@ long_bitwise(PyLongObject *a,
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_and(PyObject *a, PyObject *b)
|
long_and(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
PyObject *c;
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
c = long_bitwise((PyLongObject*)a, '&', (PyLongObject*)b);
|
PyLongObject *x = (PyLongObject*)a;
|
||||||
return c;
|
PyLongObject *y = (PyLongObject*)b;
|
||||||
|
if (IS_MEDIUM_VALUE(x) && IS_MEDIUM_VALUE(y)) {
|
||||||
|
return _PyLong_FromSTwoDigits(medium_value(x) & medium_value(y));
|
||||||
|
}
|
||||||
|
return long_bitwise(x, '&', y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_xor(PyObject *a, PyObject *b)
|
long_xor(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
PyObject *c;
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
c = long_bitwise((PyLongObject*)a, '^', (PyLongObject*)b);
|
PyLongObject *x = (PyLongObject*)a;
|
||||||
return c;
|
PyLongObject *y = (PyLongObject*)b;
|
||||||
|
if (IS_MEDIUM_VALUE(x) && IS_MEDIUM_VALUE(y)) {
|
||||||
|
return _PyLong_FromSTwoDigits(medium_value(x) ^ medium_value(y));
|
||||||
|
}
|
||||||
|
return long_bitwise(x, '^', y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_or(PyObject *a, PyObject *b)
|
long_or(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
PyObject *c;
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
c = long_bitwise((PyLongObject*)a, '|', (PyLongObject*)b);
|
PyLongObject *x = (PyLongObject*)a;
|
||||||
return c;
|
PyLongObject *y = (PyLongObject*)b;
|
||||||
|
if (IS_MEDIUM_VALUE(x) && IS_MEDIUM_VALUE(y)) {
|
||||||
|
return _PyLong_FromSTwoDigits(medium_value(x) | medium_value(y));
|
||||||
|
}
|
||||||
|
return long_bitwise(x, '|', y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
Loading…
Reference in New Issue