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

hash.c: same hash values with Float#hash

* hash.c (rb_any_hash): use same hash values with Float#hash so
  that -0.0 and +0.0 will be identical.
  [ruby-core:68541] [Bug #10979]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49999 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-03-18 03:01:58 +00:00
parent 1e98a25e9f
commit 3bcf9fb53e
5 changed files with 25 additions and 3 deletions

View file

@ -1,3 +1,9 @@
Wed Mar 18 12:01:53 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* hash.c (rb_any_hash): use same hash values with Float#hash so
that -0.0 and +0.0 will be identical.
[ruby-core:68541] [Bug #10979]
Wed Mar 18 05:34:32 2015 Koichi Sasada <ko1@atdot.net> Wed Mar 18 05:34:32 2015 Koichi Sasada <ko1@atdot.net>
* string.c: introduce STR_FAKESTR to show string is FAKESTR or not. * string.c: introduce STR_FAKESTR to show string is FAKESTR or not.

5
hash.c
View file

@ -142,13 +142,16 @@ rb_any_hash(VALUE a)
} }
else if (FLONUM_P(a)) { else if (FLONUM_P(a)) {
/* prevent pathological behavior: [Bug #10761] */ /* prevent pathological behavior: [Bug #10761] */
a = (st_index_t)rb_float_value(a); return rb_dbl_hash(rb_float_value(a));
} }
hnum = rb_objid_hash((st_index_t)a); hnum = rb_objid_hash((st_index_t)a);
} }
else if (BUILTIN_TYPE(a) == T_STRING) { else if (BUILTIN_TYPE(a) == T_STRING) {
hnum = rb_str_hash(a); hnum = rb_str_hash(a);
} }
else if (BUILTIN_TYPE(a) == T_FLOAT) {
return rb_dbl_hash(rb_float_value(a));
}
else { else {
hval = rb_hash(a); hval = rb_hash(a);
hnum = FIX2LONG(hval); hnum = FIX2LONG(hval);

View file

@ -885,6 +885,7 @@ double ruby_float_mod(double x, double y);
int rb_num_negative_p(VALUE); int rb_num_negative_p(VALUE);
VALUE rb_int_succ(VALUE num); VALUE rb_int_succ(VALUE num);
VALUE rb_int_pred(VALUE num); VALUE rb_int_pred(VALUE num);
VALUE rb_dbl_hash(double d);
#if USE_FLONUM #if USE_FLONUM
#define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) #define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n)))

View file

@ -1137,10 +1137,14 @@ flo_eq(VALUE x, VALUE y)
static VALUE static VALUE
flo_hash(VALUE num) flo_hash(VALUE num)
{ {
double d; return rb_dbl_hash(RFLOAT_VALUE(num));
}
VALUE
rb_dbl_hash(double d)
{
st_index_t hash; st_index_t hash;
d = RFLOAT_VALUE(num);
/* normalize -0.0 to 0.0 */ /* normalize -0.0 to 0.0 */
if (d == 0.0) d = 0.0; if (d == 0.0) d = 0.0;
hash = rb_memhash(&d, sizeof(d)); hash = rb_memhash(&d, sizeof(d));

View file

@ -672,4 +672,12 @@ class TestFloat < Test::Unit::TestCase
assert_equal(0.0, z) assert_equal(0.0, z)
assert_equal(-Float::INFINITY, 1.0/z) assert_equal(-Float::INFINITY, 1.0/z)
end end
def test_hash_0
bug10979 = '[ruby-core:68541] [Bug #10979]'
assert_equal(+0.0.hash, -0.0.hash)
assert_operator(+0.0, :eql?, -0.0)
h = {0.0 => bug10979}
assert_equal(bug10979, h[-0.0])
end
end end