From 4165fd0e763439421296fbc95d754ad53e6ae84f Mon Sep 17 00:00:00 2001 From: Kouhei Yanagita Date: Fri, 27 May 2022 15:46:46 +0900 Subject: Add Numeric#ceildiv and Integer#ceildiv --- numeric.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'numeric.c') diff --git a/numeric.c b/numeric.c index 4f927f00fb..df0c016b9e 100644 --- a/numeric.c +++ b/numeric.c @@ -656,6 +656,31 @@ num_div(VALUE x, VALUE y) return rb_funcall(num_funcall1(x, '/', y), rb_intern("floor"), 0); } +/* + * call-seq: + * ceildiv(other) -> integer + * + * Returns the quotient self/other 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: * self % other -> real_numeric @@ -4269,6 +4294,28 @@ rb_int_idiv(VALUE x, VALUE 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 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, "eql?", num_eql, 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, "divmod", num_divmod, 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, "divmod", rb_int_divmod, 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, "pow", rb_int_powm, -1); /* in bignum.c */ -- cgit v1.2.1