Unitful.jl
Unitful.jl copied to clipboard
Equality between `Gain`s is not transitive, prevents correct hashing
When comparing a power gain Gain{L, :p} and a root-power gain Gain{L, :rp} with the same L, they get promoted to Gain{L, :?} without changing their numerical values. This breaks the transitivity of ==:
julia> a = Gain{Unitful.Decibel, :rp}(20) # 20 dB (root-power) == factor 10
20 dB
julia> b = Gain{Unitful.Decibel, :p}(20) # 20 dB (power) == factor 100
20 dB
julia> c = Gain{Unitful.Bel, :p}(2) # 2 B (power) == factor 100
2 B
julia> a == b == c
true
julia> a == c
false
Comparison involving numbers is intransitive as well:
julia> a = Gain{Unitful.Decibel, :rp}(20) # 20 dB (root-power) == factor 10
20 dB
julia> b = Gain{Unitful.Decibel, :p}(10) # 10 dB (power) == factor 10
10 dB
julia> c = Gain{Unitful.Decibel, :p}(20) # 20 dB (power) == factor 100
20 dB
julia> a == 10 == b
true
julia> a == b
false
julia> 10 == a == c
true
julia> 10 == c
false
To obtain a consistent behavior for ==, the promotion rules for Gain would have to be changed. It might be difficult to figure out a set of rules that is both practical and consistent, unless one gets rid of Gain{L, :?} altogether.
One consequence of the intransitive isequal is that a correct hash implementation for Gain is impossible: We have
isequal(Gain{Decibel, :p}(20), Gain{Decibel,:rp}(20)),isequal(Gain{Decibel, :p}(20), 100), andisequal(Gain{Decibel,:rp}(20), 10),
but hash(10) != hash(100).