Feature #2673 » enum_len.patch
| array.c (working copy) | ||
|---|---|---|
| { | ||
| long i; | ||
| RETURN_ENUMERATOR(ary, 0, 0); | ||
| RETURN_ENUMERATOR_WITH_LEN(ary, 0, 0, ary); | ||
| for (i=0; i<RARRAY_LEN(ary); i++) { | ||
| rb_yield(RARRAY_PTR(ary)[i]); | ||
| } | ||
| ... | ... | |
| } | ||
| } | ||
| static inline long | ||
| permu_len(long n, long r) | ||
| { | ||
| int i; | ||
| long nlen = 0; | ||
| if (0 <= r && r <= n) { | ||
| nlen = 1; | ||
| for (i = 0; i < r; ++i) | ||
| nlen *= n - i; | ||
| } | ||
| return nlen; | ||
| } | ||
| /* | ||
| * call-seq: | ||
| * ary.permutation { |p| block } -> array | ||
| ... | ... | |
| long r, n, i; | ||
| n = RARRAY_LEN(ary); /* Array length */ | ||
| RETURN_ENUMERATOR(ary, argc, argv); /* Return enumerator if no block */ | ||
| rb_scan_args(argc, argv, "01", &num); | ||
| r = NIL_P(num) ? n : NUM2LONG(num); /* Permutation size from argument */ | ||
| RETURN_ENUMERATOR_WITH_LEN(ary, argc, argv, INT2NUM(permu_len(n, r))); | ||
| if (r < 0 || n < r) { | ||
| /* no permutations: yield nothing */ | ||
| ... | ... | |
| long n, i, len; | ||
| n = NUM2LONG(num); | ||
| RETURN_ENUMERATOR(ary, 1, &num); | ||
| len = RARRAY_LEN(ary); | ||
| RETURN_ENUMERATOR_WITH_LEN(ary, 1, &num, INT2NUM(combi_len(len, n))); | ||
| if (n < 0 || len < n) { | ||
| /* yield nothing */ | ||
| } | ||
| enumerator.c (working copy) | ||
|---|---|---|
| return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv); | ||
| } | ||
| VALUE | ||
| rb_enumerator_set_length(VALUE self, VALUE length) | ||
| { | ||
| rb_ivar_set(self, rb_intern("length"), length); | ||
| return self; | ||
| } | ||
| static VALUE | ||
| enumerator_length(VALUE self) | ||
| { | ||
| VALUE len = rb_attr_get(self, rb_intern("length")); | ||
| switch (TYPE(len)) { | ||
| case T_ARRAY: | ||
| return INT2NUM(RARRAY_LEN(len)); | ||
| case T_STRING: | ||
| return INT2NUM(RSTRING_LEN(len)); | ||
| } | ||
| return len; | ||
| } | ||
| static VALUE | ||
| enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg) | ||
| { | ||
| ... | ... | |
| rb_define_method(rb_cEnumerator, "feed", enumerator_feed, 1); | ||
| rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0); | ||
| rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0); | ||
| rb_define_method(rb_cEnumerator, "length", enumerator_length, 0); | ||
| rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError); | ||
| rb_define_method(rb_eStopIteration, "result", stop_result, 0); | ||
| include/ruby/intern.h (working copy) | ||
|---|---|---|
| /* enum.c */ | ||
| /* enumerator.c */ | ||
| VALUE rb_enumeratorize(VALUE, VALUE, int, VALUE *); | ||
| VALUE rb_enumerator_set_length(VALUE, VALUE); | ||
| #define RETURN_ENUMERATOR(obj, argc, argv) do { \ | ||
| if (!rb_block_given_p()) \ | ||
| return rb_enumeratorize(obj, ID2SYM(rb_frame_this_func()), \ | ||
| argc, argv); \ | ||
| } while (0) | ||
| #define RETURN_ENUMERATOR_WITH_LEN(obj, argc, argv, len) do { \ | ||
| if (!rb_block_given_p()) { \ | ||
| VALUE _e = rb_enumeratorize(obj, ID2SYM(rb_frame_this_func()), \ | ||
| argc, argv); \ | ||
| return rb_enumerator_set_length(_e, len); \ | ||
| } \ | ||
| } while (0) | ||
| /* error.c */ | ||
| VALUE rb_exc_new(VALUE, const char*, long); | ||
| VALUE rb_exc_new2(VALUE, const char*); | ||
| test/ruby/test_array.rb (working copy) | ||
|---|---|---|
| assert_equal(@cls[], @cls[1,2,3,4].combination(5).to_a) | ||
| end | ||
| def test_combination_length | ||
| assert_equal(6, @cls[1,2,3,4].combination(2).length) | ||
| assert_equal(4, @cls[1,2,3,4].combination(3).length) | ||
| end | ||
| def test_product | ||
| assert_equal(@cls[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]], | ||
| @cls[1,2,3].product([4,5])) | ||
| ... | ... | |
| assert_equal(@cls[1, 2, 3, 4].permutation.to_a, b) | ||
| end | ||
| def test_permutation_length | ||
| assert_equal(6, @cls[1, 2, 3].permutation.length) | ||
| assert_equal(1, @cls[1, 2, 3].permutation(0).length) | ||
| assert_equal(3, @cls[1, 2, 3].permutation(1).length) | ||
| assert_equal(6, @cls[1, 2, 3].permutation(3).length) | ||
| assert_equal(0, @cls[1, 2, 3].permutation(4).length) | ||
| assert_equal(24, @cls[1, 2, 3, 4].permutation(3).length) | ||
| end | ||
| def test_take | ||
| assert_equal([1,2,3], [1,2,3,4,5,0].take(3)) | ||
| assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) } | ||
- « Previous
- 1
- 2
- Next »