mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
array.c: non-recursive rcombinate0
* array.c (rcombinate0): remove recursion, by looping with indexes stored in `p`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4802149e44
commit
b654e0719a
3 changed files with 30 additions and 14 deletions
|
@ -1,4 +1,7 @@
|
||||||
Sat Jun 14 10:53:49 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sat Jun 14 10:54:08 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* array.c (rcombinate0): remove recursion, by looping with indexes
|
||||||
|
stored in `p`.
|
||||||
|
|
||||||
* array.c (rpermute0): remove recursion, by looping with indexes
|
* array.c (rpermute0): remove recursion, by looping with indexes
|
||||||
stored in `p`.
|
stored in `p`.
|
||||||
|
|
29
array.c
29
array.c
|
@ -5087,19 +5087,26 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
|
rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
|
||||||
{
|
{
|
||||||
if (rest > 0) {
|
long i = 0, index = 0;
|
||||||
for (; index < n; ++index) {
|
|
||||||
p[r-rest] = index;
|
p[index] = i;
|
||||||
rcombinate0(n, r, p, index, rest-1, values);
|
for (;;) {
|
||||||
|
if (++index < r-1) {
|
||||||
|
p[index] = i;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
for (; i < n; ++i) {
|
||||||
else {
|
p[index] = i;
|
||||||
if (!yield_indexed_values(values, r, p)) {
|
if (!yield_indexed_values(values, r, p)) {
|
||||||
rb_raise(rb_eRuntimeError, "repeated combination reentered");
|
rb_raise(rb_eRuntimeError, "repeated combination reentered");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
if (index <= 0) return;
|
||||||
|
} while ((i = ++p[--index]) >= n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -5163,13 +5170,13 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
|
||||||
/* yield nothing */
|
/* yield nothing */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
volatile VALUE t0 = tmpbuf(n, sizeof(long));
|
volatile VALUE t0;
|
||||||
long *p = (long*)RSTRING_PTR(t0);
|
long *p = ALLOCV_N(long, t0, n);
|
||||||
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
|
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
|
||||||
RBASIC_CLEAR_CLASS(ary0);
|
RBASIC_CLEAR_CLASS(ary0);
|
||||||
|
|
||||||
rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
|
rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
|
||||||
tmpbuf_discard(t0);
|
ALLOCV_END(t0);
|
||||||
RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
|
RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
|
||||||
}
|
}
|
||||||
return ary;
|
return ary;
|
||||||
|
|
|
@ -1815,6 +1815,12 @@ class TestArray < Test::Unit::TestCase
|
||||||
|
|
||||||
a = @cls[0, 1, 2, 3, 4][1, 4].repeated_combination(2)
|
a = @cls[0, 1, 2, 3, 4][1, 4].repeated_combination(2)
|
||||||
assert_empty(a.reject {|x| !x.include?(0)})
|
assert_empty(a.reject {|x| !x.include?(0)})
|
||||||
|
|
||||||
|
assert_separately([], <<-"end;") # do
|
||||||
|
assert_nothing_raised(SystemStackError) do
|
||||||
|
assert_equal(:ok, Array.new(100_000, nil).repeated_combination(500_000) {break :ok})
|
||||||
|
end
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_take
|
def test_take
|
||||||
|
|
Loading…
Reference in a new issue