Decimal not usable as Dict key: no hash method defined
Jasha10 opened this issue · 5 comments
Perhaps the hash could be defined in terms of the has of the underlying fields s
, c
and q
of the Decimal
struct. For reference, here is a stacktrace:
julia> d = Dict()
Dict{Any,Any} with 0 entries
julia> d[Decimal(123)] = 456
ERROR: MethodError: no method matching decompose(::Decimal)
Closest candidates are:
decompose(::BigFloat) at hashing2.jl:133
decompose(::Float64) at hashing2.jl:122
decompose(::Float32) at hashing2.jl:111
...
Stacktrace:
[1] hash(::Decimal, ::UInt64) at ./hashing2.jl:32
[2] hash(::Decimal) at ./hashing.jl:18
[3] hashindex(::Decimal, ::Int64) at ./dict.jl:169
[4] ht_keyindex2!(::Dict{Any,Any}, ::Decimal) at ./dict.jl:309
[5] setindex!(::Dict{Any,Any}, ::Int64, ::Decimal) at ./dict.jl:382
[6] top-level scope at none:0
Perhaps we could use something like this for the hash function.
using Decimals
function Base.hash(d::Decimal, h::UInt)
hash(d.s, hash(d.c, hash(d.q, hash(Decimal, h))))
end
d1 = Decimal(1.23)
d2 = Decimal(1.23)
d3 = Decimal(4.56)
@assert d1 == d2
@assert d1 != d3
@assert !(d1 === d2)
@assert !(d1 === d3)
@assert hash(d1) == hash(d2)
@assert hash(d1) != hash(d3)
If everyone agrees, I can create a pull request.
As far as I can tell, implementing hash
for Decimals.jl
presents similar problems as it does here: JuliaMath/DecFP.jl#97
I think that implementing decompose
for the Decimal
type would require using BigInt
, since Decimal
uses BigInt
internally.
This issue also makes it impossible to use the 'unique' function
DecFP (master) now supports hashing, though our solution involved BigInt
. It's possible that we may find a faster algorithm in the future, but for now at least it works.
Hashing could be supported by adding decompose()
similar to the DecFP implementation.
sigexp()
is a DecFP function that is documented here.