diff options
author | Raymond Hettinger <python@rcn.com> | 2013-01-12 06:29:50 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2013-01-12 06:29:50 (GMT) |
commit | 464d89b3ce911a63e9da14f10054bc853367eaff (patch) | |
tree | 5bcf3a7e6c7899337be1065b25fff6631583b71c /Modules | |
parent | eb9e885f7810d578e1999315948e20f7b030b702 (diff) | |
download | cpython-464d89b3ce911a63e9da14f10054bc853367eaff.zip cpython-464d89b3ce911a63e9da14f10054bc853367eaff.tar.gz cpython-464d89b3ce911a63e9da14f10054bc853367eaff.tar.bz2 |
Issue #16398: Optimize deque.rotate()
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_collectionsmodule.c | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 1ff95ff..6e7f1e7 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -414,9 +414,10 @@ static int _deque_rotate(dequeobject *deque, Py_ssize_t n) { Py_ssize_t i, len=deque->len, halflen=(len+1)>>1; - PyObject *item, *rv; + PyObject *item; + block *prevblock, *leftblock, *rightblock; - if (len == 0) + if (len <= 1) return 0; if (n > halflen || n < -halflen) { n %= len; @@ -426,23 +427,66 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n) n += len; } + assert(deque->len > 1); + deque->state++; + leftblock = deque->leftblock; + rightblock = deque->rightblock; for (i=0 ; i<n ; i++) { - item = deque_pop(deque, NULL); + item = rightblock->data[deque->rightindex]; assert (item != NULL); - rv = deque_appendleft(deque, item); - Py_DECREF(item); - if (rv == NULL) - return -1; - Py_DECREF(rv); + deque->rightindex--; + if (deque->rightindex == -1) { + assert(rightblock != NULL); + prevblock = rightblock->leftlink; + assert(leftblock != rightblock); + freeblock(rightblock); + prevblock->rightlink = NULL; + deque->rightblock = rightblock = prevblock; + deque->rightindex = BLOCKLEN - 1; + } + if (deque->leftindex == 0) { + block *b = newblock(NULL, leftblock, deque->len); + if (b == NULL) { + deque->len--; + Py_DECREF(item); + return -1; + } + assert(leftblock->leftlink == NULL); + leftblock->leftlink = b; + deque->leftblock = leftblock = b; + deque->leftindex = BLOCKLEN; + } + deque->leftindex--; + leftblock->data[deque->leftindex] = item; } for (i=0 ; i>n ; i--) { - item = deque_popleft(deque, NULL); + assert(leftblock != NULL); + item = leftblock->data[deque->leftindex]; assert (item != NULL); - rv = deque_append(deque, item); - Py_DECREF(item); - if (rv == NULL) - return -1; - Py_DECREF(rv); + deque->leftindex++; + if (deque->leftindex == BLOCKLEN) { + assert(leftblock != rightblock); + prevblock = leftblock->rightlink; + freeblock(leftblock); + assert(prevblock != NULL); + prevblock->leftlink = NULL; + deque->leftblock = leftblock = prevblock; + deque->leftindex = 0; + } + if (deque->rightindex == BLOCKLEN-1) { + block *b = newblock(rightblock, NULL, deque->len); + if (b == NULL) { + deque->len--; + Py_DECREF(item); + return -1; + } + assert(rightblock->rightlink == NULL); + rightblock->rightlink = b; + deque->rightblock = rightblock = b; + deque->rightindex = -1; + } + deque->rightindex++; + rightblock->data[deque->rightindex] = item; } return 0; } |