mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Optimize Array#rotate!(n) for n = 1 and n = -1
For the most common cases of `rotate!` one place to the right or to the left, instead of doing some reversals of the array we just keep a single value in a temporary value, use memmove and then put the temporary value where it should be.
This commit is contained in:
parent
a0d1fd16d1
commit
e5c441a4a2
Notes:
git
2019-12-29 13:13:05 +09:00
1 changed files with 15 additions and 5 deletions
20
array.c
20
array.c
|
@ -2618,10 +2618,20 @@ rotate_count(long cnt, long len)
|
||||||
static void
|
static void
|
||||||
ary_rotate_ptr(VALUE *ptr, long len, long cnt)
|
ary_rotate_ptr(VALUE *ptr, long len, long cnt)
|
||||||
{
|
{
|
||||||
--len;
|
if (cnt == 1) {
|
||||||
if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
|
VALUE tmp = *ptr;
|
||||||
if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
|
memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
|
||||||
if (len > 0) ary_reverse(ptr, ptr + len);
|
*(ptr + len - 1) = tmp;
|
||||||
|
} else if (cnt == len - 1) {
|
||||||
|
VALUE tmp = *(ptr + len - 1);
|
||||||
|
memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
|
||||||
|
*ptr = tmp;
|
||||||
|
} else {
|
||||||
|
--len;
|
||||||
|
if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
|
||||||
|
if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
|
||||||
|
if (len > 0) ary_reverse(ptr, ptr + len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -2631,7 +2641,7 @@ rb_ary_rotate(VALUE ary, long cnt)
|
||||||
|
|
||||||
if (cnt != 0) {
|
if (cnt != 0) {
|
||||||
long len = RARRAY_LEN(ary);
|
long len = RARRAY_LEN(ary);
|
||||||
if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
|
if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
|
||||||
RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
|
RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue