Feature #4787 ยป each_modulo.patch
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
|