Skip to content

Commit d63235b

Browse files
committed
Create a macro PYLONG_FROM_SIGNED, and leverage it in functions PyLong_FromLong, PyLong_FromLongLong and PyLong_FromSsize_t so the repetitive code is removed.
1 parent d7d066c commit d63235b

File tree

1 file changed

+40
-104
lines changed

1 file changed

+40
-104
lines changed

Objects/longobject.c

Lines changed: 40 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,43 @@ maybe_small_long(PyLongObject *v)
115115
if (PyErr_CheckSignals()) PyTryBlock \
116116
} while(0)
117117

118+
#define PYLONG_FROM_SIGNED(INT_TYPE, ival) \
119+
do { \
120+
if (IS_SMALL_INT(ival)) { \
121+
return get_small_int((sdigit)(ival)); \
122+
} \
123+
if (-(INT_TYPE)PyLong_MASK <= (ival) && (ival) <= (INT_TYPE)PyLong_MASK) { \
124+
return _PyLong_FromMedium((sdigit)(ival)); \
125+
} \
126+
/* Count digits (at least two - smaller cases were handled above). */ \
127+
size_t abs_ival, t; /* Use size_t for unsigned operations */ \
128+
if ((ival) < 0) { \
129+
/* avoid signed overflow when ival = minimum value */ \
130+
abs_ival = (size_t)(-1-(ival))+1; \
131+
} else { \
132+
abs_ival = (size_t)(ival); \
133+
} \
134+
/* Do shift in two steps to avoid possible undefined behavior. */ \
135+
t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \
136+
Py_ssize_t ndigits = 2; \
137+
while (t) { \
138+
++ndigits; \
139+
t >>= PyLong_SHIFT; \
140+
} \
141+
PyLongObject *v = _PyLong_New(ndigits); \
142+
if (v == NULL) { \
143+
return NULL; \
144+
} \
145+
digit *p = v->long_value.ob_digit; \
146+
_PyLong_SetSignAndDigitCount(v, (ival) < 0 ? -1 : 1, ndigits); \
147+
t = abs_ival; \
148+
while (t) { \
149+
*p++ = (digit)(t & PyLong_MASK); \
150+
t >>= PyLong_SHIFT; \
151+
} \
152+
return (PyObject *)v; \
153+
} while(0)
154+
118155
/* Normalize (remove leading zeros from) an int object.
119156
Doesn't attempt to free the storage--in most cases, due to the nature
120157
of the algorithms used, this could save at most be one word anyway. */
@@ -318,40 +355,7 @@ _PyLong_Negate(PyLongObject **x_p)
318355
PyObject *
319356
PyLong_FromLong(long ival)
320357
{
321-
PyLongObject *v;
322-
unsigned long abs_ival, t;
323-
int ndigits;
324-
325-
/* Handle small and medium cases. */
326-
if (IS_SMALL_INT(ival)) {
327-
return get_small_int((sdigit)ival);
328-
}
329-
if (-(long)PyLong_MASK <= ival && ival <= (long)PyLong_MASK) {
330-
return _PyLong_FromMedium((sdigit)ival);
331-
}
332-
333-
/* Count digits (at least two - smaller cases were handled above). */
334-
abs_ival = ival < 0 ? 0U-(unsigned long)ival : (unsigned long)ival;
335-
/* Do shift in two steps to avoid possible undefined behavior. */
336-
t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT;
337-
ndigits = 2;
338-
while (t) {
339-
++ndigits;
340-
t >>= PyLong_SHIFT;
341-
}
342-
343-
/* Construct output value. */
344-
v = _PyLong_New(ndigits);
345-
if (v != NULL) {
346-
digit *p = v->long_value.ob_digit;
347-
_PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits);
348-
t = abs_ival;
349-
while (t) {
350-
*p++ = (digit)(t & PyLong_MASK);
351-
t >>= PyLong_SHIFT;
352-
}
353-
}
354-
return (PyObject *)v;
358+
PYLONG_FROM_SIGNED(long, ival);
355359
}
356360

357361
#define PYLONG_FROM_UINT(INT_TYPE, ival) \
@@ -1459,83 +1463,15 @@ PyLong_AsVoidPtr(PyObject *vv)
14591463
PyObject *
14601464
PyLong_FromLongLong(long long ival)
14611465
{
1462-
PyLongObject *v;
1463-
unsigned long long abs_ival, t;
1464-
int ndigits;
1465-
1466-
/* Handle small and medium cases. */
1467-
if (IS_SMALL_INT(ival)) {
1468-
return get_small_int((sdigit)ival);
1469-
}
1470-
if (-(long long)PyLong_MASK <= ival && ival <= (long long)PyLong_MASK) {
1471-
return _PyLong_FromMedium((sdigit)ival);
1472-
}
1473-
1474-
/* Count digits (at least two - smaller cases were handled above). */
1475-
abs_ival = ival < 0 ? 0U-(unsigned long long)ival : (unsigned long long)ival;
1476-
/* Do shift in two steps to avoid possible undefined behavior. */
1477-
t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT;
1478-
ndigits = 2;
1479-
while (t) {
1480-
++ndigits;
1481-
t >>= PyLong_SHIFT;
1482-
}
1483-
1484-
/* Construct output value. */
1485-
v = _PyLong_New(ndigits);
1486-
if (v != NULL) {
1487-
digit *p = v->long_value.ob_digit;
1488-
_PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits);
1489-
t = abs_ival;
1490-
while (t) {
1491-
*p++ = (digit)(t & PyLong_MASK);
1492-
t >>= PyLong_SHIFT;
1493-
}
1494-
}
1495-
return (PyObject *)v;
1466+
PYLONG_FROM_SIGNED(long long, ival);
14961467
}
14971468

14981469
/* Create a new int object from a C Py_ssize_t. */
14991470

15001471
PyObject *
15011472
PyLong_FromSsize_t(Py_ssize_t ival)
15021473
{
1503-
PyLongObject *v;
1504-
size_t abs_ival;
1505-
size_t t; /* unsigned so >> doesn't propagate sign bit */
1506-
int ndigits = 0;
1507-
int negative = 0;
1508-
1509-
if (IS_SMALL_INT(ival)) {
1510-
return get_small_int((sdigit)ival);
1511-
}
1512-
1513-
if (ival < 0) {
1514-
/* avoid signed overflow when ival = SIZE_T_MIN */
1515-
abs_ival = (size_t)(-1-ival)+1;
1516-
negative = 1;
1517-
}
1518-
else {
1519-
abs_ival = (size_t)ival;
1520-
}
1521-
1522-
/* Count the number of Python digits. */
1523-
t = abs_ival;
1524-
while (t) {
1525-
++ndigits;
1526-
t >>= PyLong_SHIFT;
1527-
}
1528-
v = _PyLong_New(ndigits);
1529-
if (v != NULL) {
1530-
digit *p = v->long_value.ob_digit;
1531-
_PyLong_SetSignAndDigitCount(v, negative ? -1 : 1, ndigits);
1532-
t = abs_ival;
1533-
while (t) {
1534-
*p++ = (digit)(t & PyLong_MASK);
1535-
t >>= PyLong_SHIFT;
1536-
}
1537-
}
1538-
return (PyObject *)v;
1474+
PYLONG_FROM_SIGNED(Py_ssize_t, ival);
15391475
}
15401476

15411477
/* Get a C long long int from an int object or any object that has an

0 commit comments

Comments
 (0)