Project

General

Profile

Feature #4787 ยป each_modulo.patch

mrkn (Kenta Murata), 05/27/2011 01:18 PM

View differences:

numeric.c
/*
* call-seq:
* int.each_modulo(n) ->
*
* If a block given, enumerates with iterated modulo and returns self.
* Otherwise, returns an Enumerator.
*/
static VALUE
int_each_modulo(VALUE num, VALUE modulus)
{
VALUE big_q, qr;
long q, r, m;
switch (TYPE(modulus)) {
case T_BIGNUM:
if (rb_big_cmp(modulus, rb_int2big(1)) <= 0) {
goto arg_must_be_lt_1;
}
break;
case T_FIXNUM:
if (FIX2INT(modulus) <= 1) {
arg_must_be_lt_1:
rb_raise(rb_eArgError, "argument must be larger than 1");
}
break;
default:
rb_raise(rb_eArgError, "argument must be an Integer (%s)",
rb_obj_classname(modulus));
}
RETURN_ENUMERATOR(num, 1, &modulus);
big_q = num;
if (TYPE(big_q) == T_BIGNUM) {
while (TYPE(big_q) == T_BIGNUM) {
qr = rb_big_divmod(big_q, modulus);
rb_yield(RARRAY_PTR(qr)[1]);
big_q = RARRAY_PTR(qr)[0];
}
}
q = NUM2INT(big_q);
switch (TYPE(modulus)) {
case T_BIGNUM:
while (q > 0) {
qr = rb_big_divmod(rb_int2big(q), modulus);
rb_yield(RARRAY_PTR(qr)[1]);
q = NUM2INT(RARRAY_PTR(qr)[0]);
}
break;
case T_FIXNUM:
m = FIX2INT(modulus);
while (q > 0) {
fixdivmod(q, m, &q, &r);
rb_yield(INT2FIX(r));
}
break;
}
return num;
}
/*
* call-seq:
* fix.zero? -> true or false
*
* Returns <code>true</code> if <i>fix</i> is zero.
......
rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
rb_define_method(rb_cInteger, "round", int_round, -1);
rb_define_method(rb_cInteger, "each_modulo", int_each_modulo, 1);
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
test/ruby/test_integer.rb
assert_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).round(-1))
assert_equal(Bignum, (-1111_1111_1111_1111_1111_1111_1111_1111).round(-1).class)
end
def test_each_modulo_returns_Enumerator_unless_block_given
assert_instance_of(Enumerator, 1111.each_modulo(10))
assert_instance_of(Enumerator, 1111.each_modulo(2**100))
assert_instance_of(Enumerator, (2**100).each_modulo(10))
assert_instance_of(Enumerator, (2**100).each_modulo(2**100))
end
def test_each_modulo_calls_block_with_values_of_iterated_modulo
assert_equal([1, 2, 2, 1, 1], 133.each_modulo(3).to_a)
assert_equal([133], 133.each_modulo(2**100).to_a)
assert_equal([1, 2, 1], (2**200).each_modulo(2**100-1).to_a)
end
def test_each_modulo_raise_ArgumentError_when_arg_le_1
assert_raise(ArgumentError) { 111.each_modulo(1) }
assert_raise(ArgumentError) { 111.each_modulo(0) }
assert_raise(ArgumentError) { 111.each_modulo(-42) }
assert_raise(ArgumentError) { (2**100).each_modulo(1) }
assert_raise(ArgumentError) { (2**100).each_modulo(0) }
assert_raise(ArgumentError) { (2**100).each_modulo(-42) }
end
def test_each_modulo_raise_ArgumentError_when_arg_not_int
assert_raise(ArgumentError) { 111.each_modulo(Object.new) }
assert_raise(ArgumentError) { 111.each_modulo(1.0) }
assert_raise(ArgumentError) { 111.each_modulo(1.quo(3)) }
assert_raise(ArgumentError) { 111.each_modulo(Complex(1, 1)) }
assert_raise(ArgumentError) { (2**100).each_modulo(Object.new) }
assert_raise(ArgumentError) { (2**100).each_modulo(1.0) }
assert_raise(ArgumentError) { (2**100).each_modulo(1.quo(3)) }
assert_raise(ArgumentError) { (2**100).each_modulo(Complex(1, 1)) }
end
end
    (1-1/1)