summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.mk1
-rw-r--r--compile.c7
-rw-r--r--internal/rational.h1
-rw-r--r--rational.c13
-rw-r--r--test/ruby/test_rational.rb7
5 files changed, 26 insertions, 3 deletions
diff --git a/common.mk b/common.mk
index f3aa284fb5..5310173bb7 100644
--- a/common.mk
+++ b/common.mk
@@ -2807,6 +2807,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.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/serial.h
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
diff --git a/compile.c b/compile.c
index a3a828fb1d..9001fd14ff 100644
--- a/compile.c
+++ b/compile.c
@@ -28,6 +28,7 @@
#include "internal/hash.h"
#include "internal/numeric.h"
#include "internal/object.h"
+#include "internal/rational.h"
#include "internal/re.h"
#include "internal/symbol.h"
#include "internal/thread.h"
@@ -2004,6 +2005,10 @@ cdhash_cmp(VALUE val, VALUE lit)
else if (tlit == T_FLOAT) {
return rb_float_cmp(lit, val);
}
+ else if (tlit == T_RATIONAL) {
+ /* Rational literals don't have fractions. */
+ return cdhash_cmp(val, rb_rational_num(lit));
+ }
else {
UNREACHABLE_RETURN(-1);
}
@@ -2022,6 +2027,8 @@ cdhash_hash(VALUE a)
return FIX2LONG(rb_big_hash(a));
case T_FLOAT:
return rb_dbl_long_hash(RFLOAT_VALUE(a));
+ case T_RATIONAL:
+ return rb_rational_hash(a);
default:
UNREACHABLE_RETURN(0);
}
diff --git a/internal/rational.h b/internal/rational.h
index e53ee7b499..6bbd2a9810 100644
--- a/internal/rational.h
+++ b/internal/rational.h
@@ -33,6 +33,7 @@ VALUE rb_rational_div(VALUE self, VALUE other);
VALUE rb_lcm(VALUE x, VALUE y);
VALUE rb_rational_reciprocal(VALUE x);
VALUE rb_cstr_to_rat(const char *, int);
+VALUE rb_rational_hash(VALUE self);
VALUE rb_rational_abs(VALUE self);
VALUE rb_rational_cmp(VALUE self, VALUE other);
VALUE rb_rational_pow(VALUE self, VALUE other);
diff --git a/rational.c b/rational.c
index c7437df86f..846e8bd586 100644
--- a/rational.c
+++ b/rational.c
@@ -1742,8 +1742,8 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self)
}
/* :nodoc: */
-static VALUE
-nurat_hash(VALUE self)
+st_index_t
+rb_rational_hash(VALUE self)
{
st_index_t v, h[2];
VALUE n;
@@ -1754,9 +1754,16 @@ nurat_hash(VALUE self)
n = rb_hash(dat->den);
h[1] = NUM2LONG(n);
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
f_format(VALUE self, VALUE (*func)(VALUE))
{
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index fe9de64c4c..d7f4961214 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -830,6 +830,13 @@ class Rational_Test < Test::Unit::TestCase
assert_raise(ZeroDivisionError) {Rational("1/0")}
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
+ end
+
def test_Rational_with_invalid_exception
assert_raise(ArgumentError) {
Rational("1/1", exception: 1)