[前][次][番号順一覧][スレッド一覧]

ruby-changes:72914

From: Kouhei <ko1@a...>
Date: Fri, 12 Aug 2022 15:58:02 +0900 (JST)
Subject: [ruby-changes:72914] 4165fd0e76 (master): Add Numeric#ceildiv and Integer#ceildiv

https://git.ruby-lang.org/ruby.git/commit/?id=4165fd0e76

From 4165fd0e763439421296fbc95d754ad53e6ae84f Mon Sep 17 00:00:00 2001
From: Kouhei Yanagita <yanagi@s...>
Date: Fri, 27 May 2022 15:46:46 +0900
Subject: Add Numeric#ceildiv and Integer#ceildiv

---
 complex.c                 |  1 +
 numeric.c                 | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 test/ruby/test_complex.rb |  1 +
 test/ruby/test_integer.rb | 17 ++++++++++++++++
 test/ruby/test_numeric.rb | 14 ++++++++++++++
 5 files changed, 82 insertions(+)

diff --git a/complex.c b/complex.c
index d625ced7fa..865466c499 100644
--- a/complex.c
+++ b/complex.c
@@ -2335,6 +2335,7 @@ Init_Complex(void) https://github.com/ruby/ruby/blob/trunk/complex.c#L2335
     rb_undef_method(rb_cComplex, "%");
     rb_undef_method(rb_cComplex, "div");
     rb_undef_method(rb_cComplex, "divmod");
+    rb_undef_method(rb_cComplex, "ceildiv");
     rb_undef_method(rb_cComplex, "floor");
     rb_undef_method(rb_cComplex, "ceil");
     rb_undef_method(rb_cComplex, "modulo");
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) https://github.com/ruby/ruby/blob/trunk/numeric.c#L656
     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:
  *    self % other -> real_numeric
@@ -4269,6 +4294,28 @@ rb_int_idiv(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L4294
     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) https://github.com/ruby/ruby/blob/trunk/numeric.c#L6247
     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) https://github.com/ruby/ruby/blob/trunk/numeric.c#L6303
     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 */
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index a3a7546575..5cf52e812e 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -915,6 +915,7 @@ class Complex_Test < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L915
     assert_not_respond_to(c, :%)
     assert_not_respond_to(c, :div)
     assert_not_respond_to(c, :divmod)
+    assert_not_respond_to(c, :ceildiv)
     assert_not_respond_to(c, :floor)
     assert_not_respond_to(c, :ceil)
     assert_not_respond_to(c, :modulo)
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index a2b181c642..c3e11498be 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -704,4 +704,21 @@ class TestInteger < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_integer.rb#L704
     def o.to_int; Object.new; end
     assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
   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
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index 0593cb535d..068f9a56eb 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -482,4 +482,18 @@ class TestNumeric < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_numeric.rb#L482
     assert_equal(0, -2.pow(3, 1))
   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
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]