PainterQubits / Unitful.jl

Physical quantities with arbitrary units
Other
612 stars 112 forks source link

Equality between `Gain`s is not transitive, prevents correct hashing #402

Open sostock opened 3 years ago

sostock commented 3 years ago

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.

sostock commented 3 years ago

One consequence of the intransitive isequal is that a correct hash implementation for Gain is impossible: We have

but hash(10) != hash(100).

kapple19 commented 1 month ago

Can someone explain why Unitful stores :p or :rp? Why is it we aren't just storing a logarithmic value along with linear units and logarithmic multiplier it was calculated with, and converting to power or root-power when requested?