Skip to content

Commit

Permalink
Make hash2 recursively incorporate metadata and symtype
Browse files Browse the repository at this point in the history
  • Loading branch information
bowenszhu committed Nov 25, 2024
1 parent e9e5b25 commit f2d7791
Showing 1 changed file with 26 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ Base.nameof(s::BasicSymbolic) = issym(s) ? s.name : error("None Sym BasicSymboli

## This is much faster than hash of an array of Any
hashvec(xs, z) = foldr(hash, xs, init=z)
hashvec2(xs, z) = foldr(hash2, xs, init=z)
const SYM_SALT = 0x4de7d7c66d41da43 % UInt
const ADD_SALT = 0xaddaddaddaddadda % UInt
const SUB_SALT = 0xaaaaaaaaaaaaaaaa % UInt
Expand Down Expand Up @@ -350,9 +351,33 @@ includes the metadata and symtype in the hash calculation. This can be beneficia
consing, allowing for more effective deduplication of symbolically equivalent expressions
with different metadata or symtypes.
"""
hash2(s, salt::UInt) = hash(s, salt)
hash2(s::BasicSymbolic) = hash2(s, zero(UInt))
function hash2(s::BasicSymbolic{T}, salt::UInt)::UInt where {T}
hash(metadata(s), hash(T, hash(s, salt)))
E = exprtype(s)
h::UInt = 0
if E === SYM
h = hash(nameof(s), salt SYM_SALT)
elseif E === ADD || E === MUL
hashoffset = isadd(s) ? ADD_SALT : SUB_SALT
hv = Base.hasha_seed
for (k, v) in s.dict
hv ⊻= hash2(k, hash(v))
end
h = hash(hv, salt)
h = hash(hashoffset, hash(s.coeff, h))
elseif E === DIV
h = hash2(s.num, hash2(s.den, salt DIV_SALT))
elseif E === POW
h = hash2(s.exp, hash2(s.base, salt POW_SALT))
elseif E === TERM
op = operation(s)
oph = op isa Function ? nameof(op) : op
h = hashvec2(arguments(s), hash(oph, salt))
else
error_on_type()
end
hash(metadata(s), hash(T, h))
end

###
Expand Down

0 comments on commit f2d7791

Please sign in to comment.