Improve performance of Integer#ceildiv

This patch is suggested by nobu.

Benchmark result:

```
require 'benchmark'

n = 10 ** 7

Benchmark.bm do |x|
  x.report("Fixnum/Fixnum") { a, b = 5, 2; n.times { a.ceildiv(b) } }
  x.report("Bignum/Bignum") { a, b = 10**100, 10**99 - 1; n.times { a.ceildiv(b) } }
  x.report("Bignum/Fixnum") { a, b = 10**100, 3; n.times { a.ceildiv(b) } }
end
```

Original:

```
       user     system      total        real
Fixnum/Fixnum  3.340009   0.043029   3.383038 (  3.384022)
Bignum/Bignum  8.229500   0.118543   8.348043 (  8.349574)
Bignum/Fixnum  8.328971   0.097842   8.426813 (  8.426952)
```

Improved:

```
       user     system      total        real
Fixnum/Fixnum  0.699140   0.000961   0.700101 (  0.700199)
Bignum/Bignum  5.076165   0.083160   5.159325 (  5.159360)
Bignum/Fixnum  5.548684   0.115372   5.664056 (  5.666735)
```
This commit is contained in:
Kouhei Yanagita 2022-07-22 12:05:16 +09:00 committed by Yusuke Endoh
parent 24e33b84b5
commit 803a072630
Notes: git 2022-08-12 15:58:13 +09:00
2 changed files with 17 additions and 23 deletions

View File

@ -4269,28 +4269,6 @@ 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)
{
@ -6277,7 +6255,6 @@ 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 */

View File

@ -227,6 +227,23 @@ class Integer
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_int_zero_p(self)'
end
# 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
def ceildiv(other)
-div(-other)
end
end
# call-seq: