Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ce9de2f

Browse files
committed
PyLong_From{Unsigned,}Long: count the # of digits first, so no more space
is allocated than needed (used to allocate 80 bytes of digit space no matter how small the long input). This also runs faster, at least on 32- bit boxes.
1 parent ff70d3c commit ce9de2f

1 file changed

Lines changed: 41 additions & 21 deletions

File tree

Objects/longobject.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,34 @@ _PyLong_New(int size)
5757
PyObject *
5858
PyLong_FromLong(long ival)
5959
{
60-
/* Assume a C long fits in at most 5 'digits' */
61-
/* Works on both 32- and 64-bit machines */
62-
PyLongObject *v = _PyLong_New(5);
60+
PyLongObject *v;
61+
unsigned long t; /* unsigned so >> doesn't propagate sign bit */
62+
int ndigits = 0;
63+
int negative = 0;
64+
65+
if (ival < 0) {
66+
ival = -ival;
67+
negative = 1;
68+
}
69+
70+
/* Count the number of Python digits.
71+
We used to pick 5 ("big enough for anything"), but that's a
72+
waste of time and space given that 5*15 = 75 bits are rarely
73+
needed. */
74+
t = (unsigned long)ival;
75+
while (t) {
76+
++ndigits;
77+
t >>= SHIFT;
78+
}
79+
v = _PyLong_New(ndigits);
6380
if (v != NULL) {
64-
unsigned long t = ival;
65-
int i;
66-
if (ival < 0) {
67-
t = -ival;
68-
v->ob_size = -(v->ob_size);
69-
}
70-
for (i = 0; i < 5; i++) {
71-
v->ob_digit[i] = (digit) (t & MASK);
81+
digit *p = v->ob_digit;
82+
v->ob_size = negative ? -ndigits : ndigits;
83+
t = (unsigned long)ival;
84+
while (t) {
85+
*p++ = (digit)(t & MASK);
7286
t >>= SHIFT;
7387
}
74-
v = long_normalize(v);
7588
}
7689
return (PyObject *)v;
7790
}
@@ -81,17 +94,24 @@ PyLong_FromLong(long ival)
8194
PyObject *
8295
PyLong_FromUnsignedLong(unsigned long ival)
8396
{
84-
/* Assume a C long fits in at most 5 'digits' */
85-
/* Works on both 32- and 64-bit machines */
86-
PyLongObject *v = _PyLong_New(5);
97+
PyLongObject *v;
98+
unsigned long t;
99+
int ndigits = 0;
100+
101+
/* Count the number of Python digits. */
102+
t = (unsigned long)ival;
103+
while (t) {
104+
++ndigits;
105+
t >>= SHIFT;
106+
}
107+
v = _PyLong_New(ndigits);
87108
if (v != NULL) {
88-
unsigned long t = ival;
89-
int i;
90-
for (i = 0; i < 5; i++) {
91-
v->ob_digit[i] = (digit) (t & MASK);
92-
t >>= SHIFT;
109+
digit *p = v->ob_digit;
110+
v->ob_size = ndigits;
111+
while (ival) {
112+
*p++ = (digit)(ival & MASK);
113+
ival >>= SHIFT;
93114
}
94-
v = long_normalize(v);
95115
}
96116
return (PyObject *)v;
97117
}

0 commit comments

Comments
 (0)