Commit 52e385e0 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #797 from Daetalus/test_hash

Hash improvement for complex, str and long.
parents a8759628 5f1b69b3
...@@ -363,10 +363,19 @@ struct expr_dispatcher { ...@@ -363,10 +363,19 @@ struct expr_dispatcher {
} }
ResultPtr read(pypa::AstComplex& c) { ResultPtr read(pypa::AstComplex& c) {
AST_Num* ptr = new AST_Num(); AST_Num* imag = new AST_Num();
ptr->num_type = AST_Num::COMPLEX; location(imag, c);
pypa::string_to_double(c.imag, ptr->n_float); imag->num_type = AST_Num::COMPLEX;
return ptr; sscanf(c.imag.c_str(), "%lf", &imag->n_float);
if (!c.real)
return imag;
AST_BinOp* binop = new AST_BinOp();
location(binop, c);
binop->op_type = AST_TYPE::Add;
binop->right = readItem(c.real, interned_strings);
binop->left = imag;
return binop;
} }
ResultPtr read(pypa::AstComprehension& c) { ResultPtr read(pypa::AstComprehension& c) {
......
...@@ -228,6 +228,33 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* com ...@@ -228,6 +228,33 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* com
complex_cls->giveAttr(name, new BoxedFunction(cl)); complex_cls->giveAttr(name, new BoxedFunction(cl));
} }
Box* complexHash(BoxedComplex* self) {
if (!isSubclass(self->cls, complex_cls))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'complex' object but received a '%s'",
getTypeName(self));
long hashreal, hashimag, combined;
hashreal = _Py_HashDouble(self->real);
if (hashreal == -1) {
throwCAPIException();
}
hashimag = _Py_HashDouble(self->imag);
if (hashimag == -1) {
throwCAPIException();
}
/* Note: if the imaginary part is 0, hashimag is 0 now,
* so the following returns hashreal unchanged. This is
* important because numbers of different types that
* compare equal must have the same hash value, so that
* hash(x + 0*j) must equal hash(x).
*/
combined = hashreal + 1000003 * hashimag;
if (combined == -1)
combined = -2;
return boxInt(combined);
}
Box* complexStr(BoxedComplex* self) { Box* complexStr(BoxedComplex* self) {
assert(self->cls == complex_cls); assert(self->cls == complex_cls);
return boxString(complexFmt(self->real, self->imag, 12, 'g')); return boxString(complexFmt(self->real, self->imag, 12, 'g'));
...@@ -336,6 +363,7 @@ void setupComplex() { ...@@ -336,6 +363,7 @@ void setupComplex() {
(void*)complexDiv); (void*)complexDiv);
complex_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)complexPos, BOXED_COMPLEX, 1))); complex_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)complexPos, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)complexHash, BOXED_INT, 1)));
complex_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)complexStr, STR, 1))); complex_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)complexStr, STR, 1)));
complex_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)complexRepr, STR, 1))); complex_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)complexRepr, STR, 1)));
complex_cls->giveAttr("real", complex_cls->giveAttr("real",
......
...@@ -661,7 +661,7 @@ BoxedLong* _longNew(Box* val, Box* _base) { ...@@ -661,7 +661,7 @@ BoxedLong* _longNew(Box* val, Box* _base) {
int r = mpz_init_set_str(rtn->n, s.data(), 10); int r = mpz_init_set_str(rtn->n, s.data(), 10);
RELEASE_ASSERT(r == 0, ""); RELEASE_ASSERT(r == 0, "");
} else if (val->cls == float_cls) { } else if (val->cls == float_cls) {
mpz_init_set_si(rtn->n, static_cast<BoxedFloat*>(val)->d); mpz_init_set_d(rtn->n, static_cast<BoxedFloat*>(val)->d);
} else { } else {
static BoxedString* long_str = internStringImmortal("__long__"); static BoxedString* long_str = internStringImmortal("__long__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) }; CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
......
...@@ -1526,6 +1526,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) { ...@@ -1526,6 +1526,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
return self->hash; return self->hash;
Py_ssize_t len = PyUnicode_GET_SIZE(self); Py_ssize_t len = PyUnicode_GET_SIZE(self);
if (len == 0)
return 0;
Py_UNICODE* p = PyUnicode_AS_UNICODE(self); Py_UNICODE* p = PyUnicode_AS_UNICODE(self);
pyston::StringHash<Py_UNICODE> H; pyston::StringHash<Py_UNICODE> H;
return H(p, len); return H(p, len);
...@@ -1534,6 +1538,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) { ...@@ -1534,6 +1538,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
extern "C" Box* strHash(BoxedString* self) { extern "C" Box* strHash(BoxedString* self) {
assert(PyString_Check(self)); assert(PyString_Check(self));
// CPython set the hash empty string to 0 manually
if (self->size() == 0)
return boxInt(0);
StringHash<char> H; StringHash<char> H;
return boxInt(H(self->data(), self->size())); return boxInt(H(self->data(), self->size()));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment