ruby-changes:34725
From: nagachika <ko1@a...>
Date: Sun, 13 Jul 2014 23:16:46 +0900 (JST)
Subject: [ruby-changes:34725] nagachika:r46808 (ruby_2_1): merge revision(s) r46417, r46418: [Backport #9939]
nagachika 2014-07-13 23:16:37 +0900 (Sun, 13 Jul 2014) New Revision: 46808 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46808 Log: merge revision(s) r46417,r46418: [Backport #9939] * array.c (yield_indexed_values): extract from permute0(), rpermute0(), and rcombinate0(). * array.c (rb_ary_combination): iterate on a shared copy, and use array of indexes instead of array of chosen objects. [ruby-core:63149] [Bug #9939] Modified directories: branches/ruby_2_1/ Modified files: branches/ruby_2_1/ChangeLog branches/ruby_2_1/array.c branches/ruby_2_1/test/ruby/test_array.rb branches/ruby_2_1/version.h Index: ruby_2_1/array.c =================================================================== --- ruby_2_1/array.c (revision 46807) +++ ruby_2_1/array.c (revision 46808) @@ -4683,6 +4683,25 @@ rb_ary_cycle(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4683 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray)) /* + * Build a ruby array of the corresponding values and yield it to the + * associated block. + * Return the class of +values+ for reentry check. + */ +static int +yield_indexed_values(const VALUE values, const long r, const long *const p) +{ + const VALUE result = rb_ary_new2(r); + VALUE *const result_array = RARRAY_PTR(result); + const VALUE *const values_array = RARRAY_CONST_PTR(values); + long i; + + for (i = 0; i < r; i++) result_array[i] = values_array[p[i]]; + ARY_SET_LEN(result, r); + rb_yield(result); + return !RBASIC(values)->klass; +} + +/* * Recursively compute permutations of +r+ elements of the set * <code>[0..n-1]</code>. * @@ -4699,7 +4718,7 @@ rb_ary_cycle(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4718 static void permute0(long n, long r, long *p, long index, char *used, VALUE values) { - long i,j; + long i; for (i = 0; i < n; i++) { if (used[i] == 0) { p[index] = i; @@ -4710,17 +4729,7 @@ permute0(long n, long r, long *p, long i https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4729 used[i] = 0; /* index unused */ } else { - /* We have a complete permutation of array indexes */ - /* Build a ruby array of the corresponding values */ - /* And yield it to the associated block */ - VALUE result = rb_ary_new2(r); - VALUE *result_array = RARRAY_PTR(result); - const VALUE *values_array = RARRAY_PTR(values); - - for (j = 0; j < r; j++) result_array[j] = values_array[p[j]]; - ARY_SET_LEN(result, r); - rb_yield(result); - if (RBASIC(values)->klass) { + if (!yield_indexed_values(values, r, p)) { rb_raise(rb_eRuntimeError, "permute reentered"); } } @@ -4889,21 +4898,19 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4898 } } else { - volatile VALUE t0 = tmpbuf(n+1, sizeof(long)); - long *stack = (long*)RSTRING_PTR(t0); - volatile VALUE cc = tmpary(n); - VALUE *chosen = RARRAY_PTR(cc); + VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */ + volatile VALUE t0; + long *stack = ALLOCV_N(long, t0, n+1); long lev = 0; - MEMZERO(stack, long, n); + RBASIC_CLEAR_CLASS(ary0); + MEMZERO(stack+1, long, n); stack[0] = -1; for (;;) { - chosen[lev] = RARRAY_AREF(ary, stack[lev+1]); for (lev++; lev < n; lev++) { - chosen[lev] = RARRAY_AREF(ary, stack[lev+1] = stack[lev]+1); + stack[lev+1] = stack[lev]+1; } - rb_yield(rb_ary_new4(n, chosen)); - if (RBASIC(t0)->klass) { + if (!yield_indexed_values(ary0, n, stack+1)) { rb_raise(rb_eRuntimeError, "combination reentered"); } do { @@ -4912,8 +4919,8 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4919 } while (stack[lev+1]+n == len+lev+1); } done: - tmpbuf_discard(t0); - tmpary_discard(cc); + ALLOCV_END(t0); + RBASIC_SET_CLASS_RAW(ary0, rb_cArray); } return ary; } @@ -4934,24 +4941,14 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L4941 static void rpermute0(long n, long r, long *p, long index, VALUE values) { - long i, j; + long i; for (i = 0; i < n; i++) { p[index] = i; if (index < r-1) { /* if not done yet */ rpermute0(n, r, p, index+1, values); /* recurse */ } else { - /* We have a complete permutation of array indexes */ - /* Build a ruby array of the corresponding values */ - /* And yield it to the associated block */ - VALUE result = rb_ary_new2(r); - VALUE *result_array = RARRAY_PTR(result); - const VALUE *values_array = RARRAY_PTR(values); - - for (j = 0; j < r; j++) result_array[j] = values_array[p[j]]; - ARY_SET_LEN(result, r); - rb_yield(result); - if (RBASIC(values)->klass) { + if (!yield_indexed_values(values, r, p)) { rb_raise(rb_eRuntimeError, "repeated permute reentered"); } } @@ -5032,7 +5029,6 @@ rb_ary_repeated_permutation(VALUE ary, V https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L5029 static void rcombinate0(long n, long r, long *p, long index, long rest, VALUE values) { - long j; if (rest > 0) { for (; index < n; ++index) { p[r-rest] = index; @@ -5040,14 +5036,7 @@ rcombinate0(long n, long r, long *p, lon https://github.com/ruby/ruby/blob/trunk/ruby_2_1/array.c#L5036 } } else { - VALUE result = rb_ary_new2(r); - VALUE *result_array = RARRAY_PTR(result); - const VALUE *values_array = RARRAY_PTR(values); - - for (j = 0; j < r; ++j) result_array[j] = values_array[p[j]]; - ARY_SET_LEN(result, r); - rb_yield(result); - if (RBASIC(values)->klass) { + if (!yield_indexed_values(values, r, p)) { rb_raise(rb_eRuntimeError, "repeated combination reentered"); } } Index: ruby_2_1/ChangeLog =================================================================== --- ruby_2_1/ChangeLog (revision 46807) +++ ruby_2_1/ChangeLog (revision 46808) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ChangeLog#L1 +Sun Jul 13 23:10:03 2014 Nobuyoshi Nakada <nobu@r...> + + * array.c (yield_indexed_values): extract from permute0(), + rpermute0(), and rcombinate0(). + Sun Jul 13 23:02:36 2014 Nobuyoshi Nakada <nobu@r...> * array.c (rb_ary_permutation): `p` is the array of size `r`, as Index: ruby_2_1/version.h =================================================================== --- ruby_2_1/version.h (revision 46807) +++ ruby_2_1/version.h (revision 46808) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/version.h#L1 #define RUBY_VERSION "2.1.2" #define RUBY_RELEASE_DATE "2014-07-13" -#define RUBY_PATCHLEVEL 172 +#define RUBY_PATCHLEVEL 173 #define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_MONTH 7 Index: ruby_2_1/test/ruby/test_array.rb =================================================================== --- ruby_2_1/test/ruby/test_array.rb (revision 46807) +++ ruby_2_1/test/ruby/test_array.rb (revision 46808) @@ -2291,6 +2291,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_1/test/ruby/test_array.rb#L2291 assert_equal(:called, (0..100).to_a.combination(50) { break :called }, "[ruby-core:29240] ... must be yielded even if 100C50 > signed integer") end + def test_combination_clear + bug9939 = '[ruby-core:63149] [Bug #9939]' + assert_separately([], <<-'end;') + 100_000.times {Array.new(1000)} + a = [*0..100] + a.combination(3) {|*,x| a.clear} + end; + end + def test_product2 a = (0..100).to_a assert_raise(RangeError) do Property changes on: ruby_2_1 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r46417-46418 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/