-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invalid Hash implementation #142
Comments
Hmm. The We throw away the top few bits of the mantissa and exponent, which could be used in some custom implementations. This may increase collisions, but should not cause the Can you give an example of a correct
Or if necessary we could implement
Ouch, this is unfortunate. I wish we had specialization so we could easily fix this without a breaking change... |
Ah, I guess one possibility is that the mantissa is not normalized, so that the number 2 (for example) could be represented in multiple ways like |
I believe the generic implementation could be fixed by adding a normalization step, but this would make it even slower. In the absence of specialization, I am leaning toward your proposal of implementing I think the large majority of users only care about the primitive types, so performance in this common case is probably more important than support for very rare use cases. If there is demand for |
You are right, extra collisions technically don't make it incorrect. Although I do such consider systematic collisions problematic. So my initial statement was overstated.
That said, you are right, this once again does make it technically incorrect.
So do I... so do I...
My biggest concern with this is that it breaks generic code of users in a way that's more annoying to fix. At least with a |
My current plan is to adopt your suggested fix, starting with ordered-float 5.0.0. I’m waiting a bit to fix this in case there are other breaking changes we can bundle in the same release. |
Currently the
Hash
implementation just assumes that theFloatCore
type has a mantissa/exponent width likef64
. This is not necessarily true, one could have a valid customFloatCore
type that does not fit these constraints.Furthermore, the hash implementation is rather slow, because it reconstructs the type from
integer_decode
(https://rust.godbolt.org/z/hTTqnaso6). That's 10-15 cycles every float for what should be a no-op - this can be more expensive than the hash function itself!I propose we add a
StdFloat
sealed trait that is implemented forf32
andf64
only, and use that as the bound for theHash
implementation. Then the hash implementation can use.to_bits()
.Unfortunately, this is a breaking change. However I must reiterate that the current implementation is invalid for the
FloatCore
trait bound, it's possible to make a perfectly sane type implementingFloatCore
which would violate theEq
/Hash
parity when used inOrderedFloat
due to no fault of the original type.An alternative solution is to feed the sign, mantissa and exponent returned by
f.integer_decode()
separately into the hasher. However this would make the hash implementation slower still.The text was updated successfully, but these errors were encountered: