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 »