Skip to content

Commit

Permalink
add __hash__ to complex, and fix the hash problem in long and str
Browse files Browse the repository at this point in the history
  • Loading branch information
Daetalus committed Aug 4, 2015
1 parent 03e4ab9 commit 5f1b69b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
28 changes: 28 additions & 0 deletions src/runtime/complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,33 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* com
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) {
assert(self->cls == complex_cls);
return boxString(complexFmt(self->real, self->imag, 12, 'g'));
Expand Down Expand Up @@ -336,6 +363,7 @@ void setupComplex() {
(void*)complexDiv);

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("__repr__", new BoxedFunction(boxRTFunction((void*)complexRepr, STR, 1)));
complex_cls->giveAttr("real",
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/long.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ BoxedLong* _longNew(Box* val, Box* _base) {
int r = mpz_init_set_str(rtn->n, s.data(), 10);
RELEASE_ASSERT(r == 0, "");
} 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 {
static BoxedString* long_str = internStringImmortal("__long__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/str.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
return self->hash;

Py_ssize_t len = PyUnicode_GET_SIZE(self);

if (len == 0)
return 0;

Py_UNICODE* p = PyUnicode_AS_UNICODE(self);
pyston::StringHash<Py_UNICODE> H;
return H(p, len);
Expand All @@ -1534,6 +1538,10 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
extern "C" Box* strHash(BoxedString* self) {
assert(PyString_Check(self));

// CPython set the hash empty string to 0 manually
if (self->size() == 0)
return boxInt(0);

StringHash<char> H;
return boxInt(H(self->data(), self->size()));
}
Expand Down

0 comments on commit 5f1b69b

Please sign in to comment.