1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

merge revision(s) 2bc293e899c9d32dcd794a73de8925c49ecf8f15,d0e6c6e682b9ba2b0309a5177933a0628e8ef316,cc0dc67bbbe1951ff90004bc987f78545625d772,e1eff837cf12a8e813de9d4ff2db50c9b68b86b5,0ab0b86c8491d639b9ff1335ddf35e341ecd867e,6911b4bc82889860ff7da4ecf975504cdc3e5314: [Backport #17854]

cdhash_cmp: can take rational literals

	Rational literals are those integers suffixed with `r`.  They tend to
	be a part of more complex expressions like `123/456r`, but in theory
	they can live alone.  When such "bare" rational literals are passed to
	case-when branch, we have to take care of them.  Fixes [Bug #17854]
	---
	 common.mk                  |  1 +
	 compile.c                  |  7 +++++++
	 internal/rational.h        |  1 +
	 rational.c                 | 13 ++++++++++---
	 test/ruby/test_rational.rb |  7 +++++++
	 5 files changed, 26 insertions(+), 3 deletions(-)

	cdhash_cmp: rational literals with fractions

	Nobu kindly pointed out that rational literals can have fractions.
	---
	 compile.c                  | 5 +++--
	 test/ruby/test_rational.rb | 4 ++++
	 2 files changed, 7 insertions(+), 2 deletions(-)

	cdhash_cmp: can also take complex

	There are complex literals `123i`, which can also be a case condition.
	---
	 compile.c                  | 15 +++++++++++----
	 complex.c                  | 12 +++++++++---
	 internal/complex.h         |  1 +
	 test/ruby/test_rational.rb |  4 ++++
	 4 files changed, 25 insertions(+), 7 deletions(-)

	cdhash_cmp: recursively apply

	For instance a rational's numerator can be a bignum.  Comparison using
	C's == can be insufficient.
	---
	 compile.c | 4 ++--
	 1 file changed, 2 insertions(+), 2 deletions(-)

	cdhash_cmp: should use ||

	cf: https://github.com/ruby/ruby/pull/4469#discussion_r628386707
	---
	 compile.c | 4 ++--
	 1 file changed, 2 insertions(+), 2 deletions(-)

	test_cdhash: refactor change class

	It is now strange to test Complex in a class named Rational_Test.
	---
	 test/ruby/test_rational.rb | 15 ---------------
	 test/ruby/test_syntax.rb   | 15 +++++++++++++++
	 2 files changed, 15 insertions(+), 15 deletions(-)
This commit is contained in:
nagachika 2021-05-22 17:09:16 +09:00
parent af9de56c6f
commit 31816356ee
8 changed files with 53 additions and 7 deletions

View file

@ -2803,6 +2803,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
compile.$(OBJEXT): $(top_srcdir)/internal/object.h compile.$(OBJEXT): $(top_srcdir)/internal/object.h
compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
compile.$(OBJEXT): $(top_srcdir)/internal/re.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h
compile.$(OBJEXT): $(top_srcdir)/internal/serial.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h

View file

@ -28,6 +28,7 @@
#include "internal/hash.h" #include "internal/hash.h"
#include "internal/numeric.h" #include "internal/numeric.h"
#include "internal/object.h" #include "internal/object.h"
#include "internal/rational.h"
#include "internal/re.h" #include "internal/re.h"
#include "internal/symbol.h" #include "internal/symbol.h"
#include "internal/thread.h" #include "internal/thread.h"
@ -1985,6 +1986,16 @@ cdhash_cmp(VALUE val, VALUE lit)
else if (tlit == T_FLOAT) { else if (tlit == T_FLOAT) {
return rb_float_cmp(lit, val); return rb_float_cmp(lit, val);
} }
else if (tlit == T_RATIONAL) {
const struct RRational *rat1 = RRATIONAL(val);
const struct RRational *rat2 = RRATIONAL(lit);
return cdhash_cmp(rat1->num, rat2->num) || cdhash_cmp(rat1->den, rat2->den);
}
else if (tlit == T_COMPLEX) {
const struct RComplex *comp1 = RCOMPLEX(val);
const struct RComplex *comp2 = RCOMPLEX(lit);
return cdhash_cmp(comp1->real, comp2->real) || cdhash_cmp(comp1->imag, comp2->imag);
}
else { else {
UNREACHABLE_RETURN(-1); UNREACHABLE_RETURN(-1);
} }
@ -2003,6 +2014,10 @@ cdhash_hash(VALUE a)
return FIX2LONG(rb_big_hash(a)); return FIX2LONG(rb_big_hash(a));
case T_FLOAT: case T_FLOAT:
return rb_dbl_long_hash(RFLOAT_VALUE(a)); return rb_dbl_long_hash(RFLOAT_VALUE(a));
case T_RATIONAL:
return rb_rational_hash(a);
case T_COMPLEX:
return rb_complex_hash(a);
default: default:
UNREACHABLE_RETURN(0); UNREACHABLE_RETURN(0);
} }

View file

@ -1328,8 +1328,8 @@ nucomp_numerator(VALUE self)
} }
/* :nodoc: */ /* :nodoc: */
static VALUE st_index_t
nucomp_hash(VALUE self) rb_complex_hash(VALUE self)
{ {
st_index_t v, h[2]; st_index_t v, h[2];
VALUE n; VALUE n;
@ -1340,7 +1340,13 @@ nucomp_hash(VALUE self)
n = rb_hash(dat->imag); n = rb_hash(dat->imag);
h[1] = NUM2LONG(n); h[1] = NUM2LONG(n);
v = rb_memhash(h, sizeof(h)); v = rb_memhash(h, sizeof(h));
return ST2FIX(v); return v;
}
static VALUE
nucomp_hash(VALUE self)
{
return ST2FIX(rb_complex_hash(self));
} }
/* :nodoc: */ /* :nodoc: */

View file

@ -25,5 +25,6 @@ struct RComplex {
/* complex.c */ /* complex.c */
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang); VALUE rb_dbl_complex_new_polar_pi(double abs, double ang);
st_index_t rb_complex_hash(VALUE comp);
#endif /* INTERNAL_COMPLEX_H */ #endif /* INTERNAL_COMPLEX_H */

View file

@ -33,6 +33,7 @@ VALUE rb_rational_div(VALUE self, VALUE other);
VALUE rb_lcm(VALUE x, VALUE y); VALUE rb_lcm(VALUE x, VALUE y);
VALUE rb_rational_reciprocal(VALUE x); VALUE rb_rational_reciprocal(VALUE x);
VALUE rb_cstr_to_rat(const char *, int); VALUE rb_cstr_to_rat(const char *, int);
VALUE rb_rational_hash(VALUE self);
VALUE rb_rational_abs(VALUE self); VALUE rb_rational_abs(VALUE self);
VALUE rb_rational_cmp(VALUE self, VALUE other); VALUE rb_rational_cmp(VALUE self, VALUE other);
VALUE rb_rational_pow(VALUE self, VALUE other); VALUE rb_rational_pow(VALUE self, VALUE other);

View file

@ -1744,8 +1744,8 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self)
} }
/* :nodoc: */ /* :nodoc: */
static VALUE st_index_t
nurat_hash(VALUE self) rb_rational_hash(VALUE self)
{ {
st_index_t v, h[2]; st_index_t v, h[2];
VALUE n; VALUE n;
@ -1756,9 +1756,16 @@ nurat_hash(VALUE self)
n = rb_hash(dat->den); n = rb_hash(dat->den);
h[1] = NUM2LONG(n); h[1] = NUM2LONG(n);
v = rb_memhash(h, sizeof(h)); v = rb_memhash(h, sizeof(h));
return ST2FIX(v); return v;
} }
static VALUE
nurat_hash(VALUE self)
{
return ST2FIX(rb_rational_hash(self));
}
static VALUE static VALUE
f_format(VALUE self, VALUE (*func)(VALUE)) f_format(VALUE self, VALUE (*func)(VALUE))
{ {

View file

@ -1730,6 +1730,21 @@ eom
assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
end end
def test_cdhash
assert_separately([], <<-RUBY)
n = case 1 when 2r then false else true end
assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
RUBY
assert_separately([], <<-RUBY)
n = case 3/2r when 1.5r then true else false end
assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
RUBY
assert_separately([], <<-RUBY)
n = case 1i when 1i then true else false end
assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
RUBY
end
private private
def not_label(x) @result = x; @not_label ||= nil end def not_label(x) @result = x; @not_label ||= nil end

View file

@ -12,7 +12,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 2 #define RUBY_VERSION_TEENY 2
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 81 #define RUBY_PATCHLEVEL 82
#define RUBY_RELEASE_YEAR 2021 #define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 5 #define RUBY_RELEASE_MONTH 5