Bug #15857 » complex-real-spaceship-v3.patch
NEWS | ||
---|---|---|
=== Core classes updates (outstanding ones only)
|
||
Complex::
|
||
New method::
|
||
* Added Complex#<=>. So 0 <=> 0i will not raise NoMethodError.
|
||
[Bug #15857]
|
||
Enumerable::
|
||
New method::
|
complex.c | ||
---|---|---|
return f_boolcast(f_eqeq_p(other, self));
|
||
}
|
||
static VALUE
|
||
nucomp_real_p(VALUE self)
|
||
{
|
||
get_dat1(self);
|
||
return(f_zero_p(dat->imag) ? Qtrue : Qfalse);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* cmp <=> object -> 0, 1, -1, or nil
|
||
*
|
||
* If +cmp+'s imaginary part is zero, and +object+ is also a
|
||
* real number (or a Complex number where the imaginary part is zero),
|
||
* compare the real part of +cmp+ to object. Otherwise, return nil.
|
||
*
|
||
* Complex(2, 3) <=> Complex(2, 3) #=> nil
|
||
* Complex(2, 3) <=> 1 #=> nil
|
||
* Complex(2) <=> 1 #=> 1
|
||
* Complex(2) <=> 2 #=> 0
|
||
* Complex(2) <=> 3 #=> -1
|
||
*/
|
||
static VALUE
|
||
nucomp_cmp(VALUE self, VALUE other)
|
||
{
|
||
if (nucomp_real_p(self) && k_numeric_p(other)) {
|
||
if (RB_TYPE_P(other, T_COMPLEX) && nucomp_real_p(other)) {
|
||
get_dat2(self, other);
|
||
return rb_funcall(adat->real, idCmp, 1, bdat->real);
|
||
} else if (f_real_p(other)) {
|
||
get_dat1(self);
|
||
return rb_funcall(dat->real, idCmp, 1, other);
|
||
}
|
||
}
|
||
return Qnil;
|
||
}
|
||
/* :nodoc: */
|
||
static VALUE
|
||
nucomp_coerce(VALUE self, VALUE other)
|
||
{
|
||
if (k_numeric_p(other) && f_real_p(other))
|
||
return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
|
||
if (RB_TYPE_P(other, T_COMPLEX))
|
||
return rb_assoc_new(other, self);
|
||
if (k_numeric_p(other) && f_real_p(other))
|
||
return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
|
||
rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
|
||
rb_obj_class(other), rb_obj_class(self));
|
||
... | ... | |
/*
|
||
* call-seq:
|
||
* cmp.real? -> false
|
||
* Complex(1).real? -> false
|
||
* Complex(1, 2).real? -> false
|
||
*
|
||
* Returns false.
|
||
* Returns false, even if the complex number has no imaginary part.
|
||
*/
|
||
static VALUE
|
||
nucomp_false(VALUE self)
|
||
... | ... | |
rb_undef_methods_from(rb_cComplex, rb_mComparable);
|
||
rb_undef_method(rb_cComplex, "%");
|
||
rb_undef_method(rb_cComplex, "<=>");
|
||
rb_undef_method(rb_cComplex, "div");
|
||
rb_undef_method(rb_cComplex, "divmod");
|
||
rb_undef_method(rb_cComplex, "floor");
|
||
... | ... | |
rb_define_method(rb_cComplex, "**", rb_complex_pow, 1);
|
||
rb_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
|
||
rb_define_method(rb_cComplex, "<=>", nucomp_cmp, 1);
|
||
rb_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
|
||
rb_define_method(rb_cComplex, "abs", rb_complex_abs, 0);
|
spec/ruby/core/complex/spaceship_spec.rb | ||
---|---|---|
require_relative '../../spec_helper'
|
||
describe "Complex#<=>" do
|
||
ruby_version_is '2.7' do
|
||
it "returns nil if either self or argument has imaginary part" do
|
||
(Complex(5, 1) <=> Complex(2)).should be_nil
|
||
(Complex(1) <=> Complex(2, 1)).should be_nil
|
||
(5 <=> Complex(2, 1)).should be_nil
|
||
end
|
||
it "returns nil if argument is not numeric" do
|
||
(Complex(5, 1) <=> "cmp").should be_nil
|
||
(Complex(1) <=> "cmp").should be_nil
|
||
(Complex(1) <=> Object.new).should be_nil
|
||
end
|
||
it "returns 0, 1, or -1 if self and argument do not have imaginary part" do
|
||
(Complex(5) <=> Complex(2)).should == 1
|
||
(Complex(2) <=> Complex(3)).should == -1
|
||
(Complex(2) <=> Complex(2)).should == 0
|
||
(Complex(5) <=> 2).should == 1
|
||
(Complex(2) <=> 3).should == -1
|
||
(Complex(2) <=> 2).should == 0
|
||
end
|
||
end
|
||
end
|
test/ruby/test_complex.rb | ||
---|---|---|
end
|
||
def test_cmp
|
||
assert_raise(NoMethodError){1 <=> Complex(1,1)}
|
||
assert_raise(NoMethodError){Complex(1,1) <=> 1}
|
||
assert_raise(NoMethodError){Complex(1,1) <=> Complex(1,1)}
|
||
assert_nil(Complex(5, 1) <=> Complex(2))
|
||
assert_nil(5 <=> Complex(2, 1))
|
||
assert_equal(1, Complex(5) <=> Complex(2))
|
||
assert_equal(-1, Complex(2) <=> Complex(3))
|
||
assert_equal(0, Complex(2) <=> Complex(2))
|
||
assert_equal(1, Complex(5) <=> 2)
|
||
assert_equal(-1, Complex(2) <=> 3)
|
||
assert_equal(0, Complex(2) <=> 2)
|
||
end
|
||
def test_eqeq
|
||
... | ... | |
def test_respond
|
||
c = Complex(1,1)
|
||
assert_not_respond_to(c, :%)
|
||
assert_not_respond_to(c, :<=>)
|
||
assert_not_respond_to(c, :div)
|
||
assert_not_respond_to(c, :divmod)
|
||
assert_not_respond_to(c, :floor)
|
test/ruby/test_complexrational.rb | ||
---|---|---|
assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), c * 2)
|
||
assert_equal(Complex(SimpleRat(1,3),SimpleRat(1,4)), c / 2)
|
||
assert_equal(Complex(SimpleRat(7,36),SimpleRat(2,3)), c ** 2)
|
||
assert_raise(NoMethodError){c <=> 2}
|
||
assert_nil(c <=> 2)
|
||
assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), 2 + c)
|
||
assert_equal(Complex(SimpleRat(4,3),SimpleRat(-1,2)), 2 - c)
|
||
... | ... | |
r = 2 ** c
|
||
assert_in_delta(1.4940, r.real, 0.001)
|
||
assert_in_delta(0.5392, r.imag, 0.001)
|
||
assert_raise(NoMethodError){2 <=> c}
|
||
assert_nil(2 <=> c)
|
||
assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), c + cc)
|
||
assert_equal(Complex(SimpleRat(-5,6),SimpleRat(-3,2)), c - cc)
|
||
... | ... | |
r = c ** cc
|
||
assert_in_delta(0.1732, r.real, 0.001)
|
||
assert_in_delta(0.1186, r.imag, 0.001)
|
||
assert_raise(NoMethodError){c <=> cc}
|
||
assert_nil(c <=> cc)
|
||
assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), cc + c)
|
||
assert_equal(Complex(SimpleRat(5,6),SimpleRat(3,2)), cc - c)
|
||
... | ... | |
r = cc ** c
|
||
assert_in_delta(0.5498, r.real, 0.001)
|
||
assert_in_delta(1.0198, r.imag, 0.001)
|
||
assert_raise(NoMethodError){cc <=> c}
|
||
assert_nil(cc <=> c)
|
||
assert_equal([SimpleRat,SimpleRat],
|
||
(+c).instance_eval{[real.class, imag.class]})
|
- « Previous
- 1
- 2
- 3
- Next »