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

Skip to content

Commit c29cc6a

Browse files
committed
#1569291: speed up array.repeat() by making only O(log n) memcpy() calls; the code follows unicode_repeat.
1 parent 9d87119 commit c29cc6a

3 files changed

Lines changed: 25 additions & 9 deletions

File tree

Lib/test/test_array.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,12 @@ def test_mul(self):
504504
array.array(self.typecode)
505505
)
506506

507+
a = 5 * array.array(self.typecode, self.example[:1])
508+
self.assertEqual(
509+
a,
510+
array.array(self.typecode, [a[0]] * 5)
511+
)
512+
507513
self.assertRaises(TypeError, a.__mul__, "bad")
508514

509515
def test_imul(self):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Core and Builtins
4545
Library
4646
-------
4747

48+
- Issue #1569291: Speed up array.repeat().
49+
4850
- Provide an interface to set the optimization level of compilation in
4951
py_compile, compileall and zipfile.PyZipFile.
5052

Modules/arraymodule.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -674,11 +674,9 @@ array_concat(arrayobject *a, PyObject *bb)
674674
static PyObject *
675675
array_repeat(arrayobject *a, Py_ssize_t n)
676676
{
677-
Py_ssize_t i;
678677
Py_ssize_t size;
679678
arrayobject *np;
680-
char *p;
681-
Py_ssize_t nbytes;
679+
Py_ssize_t oldbytes, newbytes;
682680
if (n < 0)
683681
n = 0;
684682
if ((Py_SIZE(a) != 0) && (n > PY_SSIZE_T_MAX / Py_SIZE(a))) {
@@ -688,13 +686,23 @@ array_repeat(arrayobject *a, Py_ssize_t n)
688686
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
689687
if (np == NULL)
690688
return NULL;
691-
p = np->ob_item;
692-
nbytes = Py_SIZE(a) * a->ob_descr->itemsize;
693-
for (i = 0; i < n; i++) {
694-
memcpy(p, a->ob_item, nbytes);
695-
p += nbytes;
689+
if (n == 0)
690+
return (PyObject *)np;
691+
oldbytes = Py_SIZE(a) * a->ob_descr->itemsize;
692+
newbytes = oldbytes * n;
693+
/* this follows the code in unicode_repeat */
694+
if (oldbytes == 1) {
695+
memset(np->ob_item, a->ob_item[0], newbytes);
696+
} else {
697+
Py_ssize_t done = oldbytes;
698+
Py_MEMCPY(np->ob_item, a->ob_item, oldbytes);
699+
while (done < newbytes) {
700+
Py_ssize_t ncopy = (done <= newbytes-done) ? done : newbytes-done;
701+
Py_MEMCPY(np->ob_item+done, np->ob_item, ncopy);
702+
done += ncopy;
703+
}
696704
}
697-
return (PyObject *) np;
705+
return (PyObject *)np;
698706
}
699707

700708
static int

0 commit comments

Comments
 (0)