ruby-changes:35250
From: usa <ko1@a...>
Date: Sun, 31 Aug 2014 15:56:52 +0900 (JST)
Subject: [ruby-changes:35250] usa:r47332 (ruby_2_0_0): merge revision(s) 46417, 46418: [Backport #9939]
usa 2014-08-31 15:56:43 +0900 (Sun, 31 Aug 2014) New Revision: 47332 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47332 Log: merge revision(s) 46417,46418: [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_0_0/ Modified files: branches/ruby_2_0_0/ChangeLog branches/ruby_2_0_0/array.c branches/ruby_2_0_0/test/ruby/test_array.rb branches/ruby_2_0_0/version.h Index: ruby_2_0_0/array.c =================================================================== --- ruby_2_0_0/array.c (revision 47331) +++ ruby_2_0_0/array.c (revision 47332) @@ -4529,6 +4529,25 @@ rb_ary_cycle(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4529 #define tmpary_discard(a) (ary_discard(a), RBASIC(a)->klass = 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_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>. * @@ -4545,7 +4564,7 @@ rb_ary_cycle(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4564 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; @@ -4556,17 +4575,7 @@ permute0(long n, long r, long *p, long i https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4575 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"); } } @@ -4731,21 +4740,19 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4740 } } 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(ary0)->klass = 0; + MEMZERO(stack+1, long, n); stack[0] = -1; for (;;) { - chosen[lev] = RARRAY_PTR(ary)[stack[lev+1]]; for (lev++; lev < n; lev++) { - chosen[lev] = RARRAY_PTR(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 { @@ -4754,8 +4761,8 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4761 } while (stack[lev+1]+n == len+lev+1); } done: - tmpbuf_discard(t0); - tmpary_discard(cc); + ALLOCV_END(t0); + RBASIC(ary0)->klass = rb_cArray; } return ary; } @@ -4776,24 +4783,14 @@ rb_ary_combination(VALUE ary, VALUE num) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4783 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"); } } @@ -4872,7 +4869,6 @@ rb_ary_repeated_permutation(VALUE ary, V https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4869 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; @@ -4880,14 +4876,7 @@ rcombinate0(long n, long r, long *p, lon https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/array.c#L4876 } } 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_0_0/ChangeLog =================================================================== --- ruby_2_0_0/ChangeLog (revision 47331) +++ ruby_2_0_0/ChangeLog (revision 47332) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ChangeLog#L1 +Sun Aug 31 15:46:23 2014 Nobuyoshi Nakada <nobu@r...> + + * array.c (yield_indexed_values): extract from permute0(), + rpermute0(), and rcombinate0(). + Sun Aug 31 15:23:25 2014 Nobuyoshi Nakada <nobu@r...> * array.c (rb_ary_permutation): `p` is the array of size `r`, as Index: ruby_2_0_0/version.h =================================================================== --- ruby_2_0_0/version.h (revision 47331) +++ ruby_2_0_0/version.h (revision 47332) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/version.h#L1 #define RUBY_VERSION "2.0.0" #define RUBY_RELEASE_DATE "2014-08-31" -#define RUBY_PATCHLEVEL 532 +#define RUBY_PATCHLEVEL 533 #define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_MONTH 8 Index: ruby_2_0_0/test/ruby/test_array.rb =================================================================== --- ruby_2_0_0/test/ruby/test_array.rb (revision 47331) +++ ruby_2_0_0/test/ruby/test_array.rb (revision 47332) @@ -2201,6 +2201,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/ruby/test_array.rb#L2201 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_0_0 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r46417-46418 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/