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:
parent
af9de56c6f
commit
31816356ee
8 changed files with 53 additions and 7 deletions
|
@ -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
|
||||||
|
|
15
compile.c
15
compile.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
12
complex.c
12
complex.c
|
@ -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: */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
13
rational.c
13
rational.c
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue