Also `Numeric#remainder` should.
This commit is contained in:
parent
1ddeb7473d
commit
71ce7e1825
Notes:
git
2023-01-15 04:03:52 +00:00
Merged-By: mrkn <mrkn@ruby-lang.org>
21
numeric.c
21
numeric.c
@ -740,6 +740,9 @@ num_modulo(VALUE x, VALUE y)
|
|||||||
static VALUE
|
static VALUE
|
||||||
num_remainder(VALUE x, VALUE y)
|
num_remainder(VALUE x, VALUE y)
|
||||||
{
|
{
|
||||||
|
if (!rb_obj_is_kind_of(y, rb_cNumeric)) {
|
||||||
|
do_coerce(&x, &y, TRUE);
|
||||||
|
}
|
||||||
VALUE z = num_funcall1(x, '%', y);
|
VALUE z = num_funcall1(x, '%', y);
|
||||||
|
|
||||||
if ((!rb_equal(z, INT2FIX(0))) &&
|
if ((!rb_equal(z, INT2FIX(0))) &&
|
||||||
@ -4363,12 +4366,22 @@ static VALUE
|
|||||||
int_remainder(VALUE x, VALUE y)
|
int_remainder(VALUE x, VALUE y)
|
||||||
{
|
{
|
||||||
if (FIXNUM_P(x)) {
|
if (FIXNUM_P(x)) {
|
||||||
return num_remainder(x, y);
|
if (FIXNUM_P(y)) {
|
||||||
|
VALUE z = fix_mod(x, y);
|
||||||
|
assert(FIXNUM_P(z));
|
||||||
|
if (z != INT2FIX(0) && (SIGNED_VALUE)(x ^ y) < 0)
|
||||||
|
z = fix_minus(z, y);
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
else if (!RB_BIGNUM_TYPE_P(y)) {
|
||||||
|
return num_remainder(x, y);
|
||||||
|
}
|
||||||
|
x = rb_int2big(FIX2LONG(x));
|
||||||
}
|
}
|
||||||
else if (RB_BIGNUM_TYPE_P(x)) {
|
else if (!RB_BIGNUM_TYPE_P(x)) {
|
||||||
return rb_big_remainder(x, y);
|
return Qnil;
|
||||||
}
|
}
|
||||||
return Qnil;
|
return rb_big_remainder(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -6,6 +6,9 @@ describe "Numeric#remainder" do
|
|||||||
@obj = NumericSpecs::Subclass.new
|
@obj = NumericSpecs::Subclass.new
|
||||||
@result = mock("Numeric#% result")
|
@result = mock("Numeric#% result")
|
||||||
@other = mock("Passed Object")
|
@other = mock("Passed Object")
|
||||||
|
ruby_version_is "3.3" do
|
||||||
|
@other.should_receive(:coerce).with(@obj).and_return([@obj, @other])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the result of calling self#% with other if self is 0" do
|
it "returns the result of calling self#% with other if self is 0" do
|
||||||
|
@ -227,6 +227,12 @@ class TestFloat < Test::Unit::TestCase
|
|||||||
assert_equal(-3.5, (-11.5).remainder(-4))
|
assert_equal(-3.5, (-11.5).remainder(-4))
|
||||||
assert_predicate(Float::NAN.remainder(4), :nan?)
|
assert_predicate(Float::NAN.remainder(4), :nan?)
|
||||||
assert_predicate(4.remainder(Float::NAN), :nan?)
|
assert_predicate(4.remainder(Float::NAN), :nan?)
|
||||||
|
|
||||||
|
ten = Object.new
|
||||||
|
def ten.coerce(other)
|
||||||
|
[other, 10]
|
||||||
|
end
|
||||||
|
assert_equal(4, 14.0.remainder(ten))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_to_s
|
def test_to_s
|
||||||
|
@ -408,19 +408,32 @@ class TestIntegerComb < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_remainder
|
def test_remainder
|
||||||
|
coerce = EnvUtil.labeled_class("CoerceNum") do
|
||||||
|
def initialize(num)
|
||||||
|
@num = num
|
||||||
|
end
|
||||||
|
def coerce(other)
|
||||||
|
[other, @num]
|
||||||
|
end
|
||||||
|
def inspect
|
||||||
|
"#{self.class.name}(#@num)"
|
||||||
|
end
|
||||||
|
alias to_s inspect
|
||||||
|
end
|
||||||
|
|
||||||
VS.each {|a|
|
VS.each {|a|
|
||||||
VS.each {|b|
|
(VS + VS.map {|b| [coerce.new(b), b]}).each {|b, i = b|
|
||||||
if b == 0
|
if i == 0
|
||||||
assert_raise(ZeroDivisionError) { a.divmod(b) }
|
assert_raise(ZeroDivisionError) { a.divmod(b) }
|
||||||
else
|
else
|
||||||
r = a.remainder(b)
|
r = assert_nothing_raised(ArgumentError, "#{a}.remainder(#{b})") {a.remainder(b)}
|
||||||
assert_kind_of(Integer, r)
|
assert_kind_of(Integer, r)
|
||||||
if a < 0
|
if a < 0
|
||||||
assert_operator(-b.abs, :<, r, "#{a}.remainder(#{b})")
|
assert_operator(-i.abs, :<, r, "#{a}.remainder(#{b})")
|
||||||
assert_operator(0, :>=, r, "#{a}.remainder(#{b})")
|
assert_operator(0, :>=, r, "#{a}.remainder(#{b})")
|
||||||
elsif 0 < a
|
elsif 0 < a
|
||||||
assert_operator(0, :<=, r, "#{a}.remainder(#{b})")
|
assert_operator(0, :<=, r, "#{a}.remainder(#{b})")
|
||||||
assert_operator(b.abs, :>, r, "#{a}.remainder(#{b})")
|
assert_operator(i.abs, :>, r, "#{a}.remainder(#{b})")
|
||||||
else
|
else
|
||||||
assert_equal(0, r, "#{a}.remainder(#{b})")
|
assert_equal(0, r, "#{a}.remainder(#{b})")
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user