Add Numeric#ceildiv and Integer#ceildiv
This commit is contained in:
parent
cd1a0b3caa
commit
4165fd0e76
Notes:
git
2022-08-12 15:58:13 +09:00
@ -2335,6 +2335,7 @@ Init_Complex(void)
|
|||||||
rb_undef_method(rb_cComplex, "%");
|
rb_undef_method(rb_cComplex, "%");
|
||||||
rb_undef_method(rb_cComplex, "div");
|
rb_undef_method(rb_cComplex, "div");
|
||||||
rb_undef_method(rb_cComplex, "divmod");
|
rb_undef_method(rb_cComplex, "divmod");
|
||||||
|
rb_undef_method(rb_cComplex, "ceildiv");
|
||||||
rb_undef_method(rb_cComplex, "floor");
|
rb_undef_method(rb_cComplex, "floor");
|
||||||
rb_undef_method(rb_cComplex, "ceil");
|
rb_undef_method(rb_cComplex, "ceil");
|
||||||
rb_undef_method(rb_cComplex, "modulo");
|
rb_undef_method(rb_cComplex, "modulo");
|
||||||
|
49
numeric.c
49
numeric.c
@ -656,6 +656,31 @@ num_div(VALUE x, VALUE y)
|
|||||||
return rb_funcall(num_funcall1(x, '/', y), rb_intern("floor"), 0);
|
return rb_funcall(num_funcall1(x, '/', y), rb_intern("floor"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* ceildiv(other) -> integer
|
||||||
|
*
|
||||||
|
* Returns the quotient <tt>self/other</tt> as an integer, rounding up to the nearest integer.
|
||||||
|
* This method uses method +/+ in the derived class of +self+.
|
||||||
|
* (\Numeric itself does not define method +/+.)
|
||||||
|
*
|
||||||
|
* Of the Core and Standard Library classes,
|
||||||
|
* Float and Rational use this implementation.
|
||||||
|
*
|
||||||
|
* 3.0.ceildiv(3.0) # => 1
|
||||||
|
* 4.0.ceildiv(3.0) # => 2
|
||||||
|
*
|
||||||
|
* 4.0.ceildiv(-3.0) # => -1
|
||||||
|
* -4.0.ceildiv(3.0) # => -1
|
||||||
|
* -4.0.ceildiv(-3.0) # => 2
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
num_ceildiv(VALUE x, VALUE y)
|
||||||
|
{
|
||||||
|
VALUE tmp = num_div(x, num_uminus(y));
|
||||||
|
return num_uminus(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* self % other -> real_numeric
|
* self % other -> real_numeric
|
||||||
@ -4269,6 +4294,28 @@ rb_int_idiv(VALUE x, VALUE y)
|
|||||||
return num_div(x, y);
|
return num_div(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* ceildiv(other) -> integer
|
||||||
|
*
|
||||||
|
* Returns the result of division +self+ by +other+. The result is rounded up to the nearest integer.
|
||||||
|
*
|
||||||
|
* 3.ceildiv(3) # => 1
|
||||||
|
* 4.ceildiv(3) # => 2
|
||||||
|
*
|
||||||
|
* 4.ceildiv(-3) # => -1
|
||||||
|
* -4.ceildiv(3) # => -1
|
||||||
|
* -4.ceildiv(-3) # => 2
|
||||||
|
*
|
||||||
|
* 3.ceildiv(1.2) # => 3
|
||||||
|
*/
|
||||||
|
VALUE
|
||||||
|
rb_int_ceildiv(VALUE x, VALUE y)
|
||||||
|
{
|
||||||
|
VALUE tmp = rb_int_idiv(x, num_uminus(y));
|
||||||
|
return num_uminus(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
fix_mod(VALUE x, VALUE y)
|
fix_mod(VALUE x, VALUE y)
|
||||||
{
|
{
|
||||||
@ -6200,6 +6247,7 @@ Init_Numeric(void)
|
|||||||
rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
|
rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
|
||||||
rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
|
rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
|
||||||
rb_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
|
rb_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
|
||||||
|
rb_define_method(rb_cNumeric, "ceildiv", num_ceildiv, 1);
|
||||||
rb_define_method(rb_cNumeric, "div", num_div, 1);
|
rb_define_method(rb_cNumeric, "div", num_div, 1);
|
||||||
rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
|
rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
|
||||||
rb_define_method(rb_cNumeric, "%", num_modulo, 1);
|
rb_define_method(rb_cNumeric, "%", num_modulo, 1);
|
||||||
@ -6255,6 +6303,7 @@ Init_Numeric(void)
|
|||||||
rb_define_method(rb_cInteger, "remainder", int_remainder, 1);
|
rb_define_method(rb_cInteger, "remainder", int_remainder, 1);
|
||||||
rb_define_method(rb_cInteger, "divmod", rb_int_divmod, 1);
|
rb_define_method(rb_cInteger, "divmod", rb_int_divmod, 1);
|
||||||
rb_define_method(rb_cInteger, "fdiv", rb_int_fdiv, 1);
|
rb_define_method(rb_cInteger, "fdiv", rb_int_fdiv, 1);
|
||||||
|
rb_define_method(rb_cInteger, "ceildiv", rb_int_ceildiv, 1);
|
||||||
rb_define_method(rb_cInteger, "**", rb_int_pow, 1);
|
rb_define_method(rb_cInteger, "**", rb_int_pow, 1);
|
||||||
|
|
||||||
rb_define_method(rb_cInteger, "pow", rb_int_powm, -1); /* in bignum.c */
|
rb_define_method(rb_cInteger, "pow", rb_int_powm, -1); /* in bignum.c */
|
||||||
|
@ -915,6 +915,7 @@ class Complex_Test < Test::Unit::TestCase
|
|||||||
assert_not_respond_to(c, :%)
|
assert_not_respond_to(c, :%)
|
||||||
assert_not_respond_to(c, :div)
|
assert_not_respond_to(c, :div)
|
||||||
assert_not_respond_to(c, :divmod)
|
assert_not_respond_to(c, :divmod)
|
||||||
|
assert_not_respond_to(c, :ceildiv)
|
||||||
assert_not_respond_to(c, :floor)
|
assert_not_respond_to(c, :floor)
|
||||||
assert_not_respond_to(c, :ceil)
|
assert_not_respond_to(c, :ceil)
|
||||||
assert_not_respond_to(c, :modulo)
|
assert_not_respond_to(c, :modulo)
|
||||||
|
@ -704,4 +704,21 @@ class TestInteger < Test::Unit::TestCase
|
|||||||
def o.to_int; Object.new; end
|
def o.to_int; Object.new; end
|
||||||
assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
|
assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ceildiv
|
||||||
|
assert_equal(0, 0.ceildiv(3))
|
||||||
|
assert_equal(1, 1.ceildiv(3))
|
||||||
|
assert_equal(1, 3.ceildiv(3))
|
||||||
|
assert_equal(2, 4.ceildiv(3))
|
||||||
|
|
||||||
|
assert_equal(-1, 4.ceildiv(-3))
|
||||||
|
assert_equal(-1, -4.ceildiv(3))
|
||||||
|
assert_equal(2, -4.ceildiv(-3))
|
||||||
|
|
||||||
|
assert_equal(3, 3.ceildiv(1.2))
|
||||||
|
assert_equal(3, 3.ceildiv(6/5r))
|
||||||
|
|
||||||
|
assert_equal(10, (10**100-11).ceildiv(10**99-1))
|
||||||
|
assert_equal(11, (10**100-9).ceildiv(10**99-1))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -482,4 +482,18 @@ class TestNumeric < Test::Unit::TestCase
|
|||||||
assert_equal(0, -2.pow(3, 1))
|
assert_equal(0, -2.pow(3, 1))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ceildiv
|
||||||
|
assert_equal(0, 0.0.ceildiv(3.0))
|
||||||
|
assert_equal(1, 1.0.ceildiv(3.0))
|
||||||
|
assert_equal(1, 3.0.ceildiv(3.0))
|
||||||
|
assert_equal(2, 4.0.ceildiv(3.0))
|
||||||
|
|
||||||
|
assert_equal(-1, 4.0.ceildiv(-3.0))
|
||||||
|
assert_equal(-1, -4.0.ceildiv(3.0))
|
||||||
|
assert_equal(2, -4.0.ceildiv(-3.0))
|
||||||
|
|
||||||
|
assert_equal(3, 3.0.ceildiv(1.2))
|
||||||
|
assert_equal(3, 3.0.ceildiv(6/5r))
|
||||||
|
assert_equal(3, (7r/2).ceildiv(6/5r))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user