Skip to content
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

Add Base.hash(::Quaternion, ::UInt) #136

Merged
merged 4 commits into from
Feb 5, 2024

Conversation

hyrodium
Copy link
Collaborator

@hyrodium hyrodium commented Nov 9, 2023

This PR fixes #135.

Before this PR

julia> using Quaternions

julia> isequal(1, complex(1))
true

julia> 1 |> hash
0x5bca7c69b794f8ce

julia> complex(1) |> hash
0x5bca7c69b794f8ce

julia> isequal(1, quat(1))  # isequal(a,b) == true should imply `hash(a) == hash(b)`
true

julia> quat(1) |> hash
0x37cb992a8d339608

julia> unique(Complex[complex(2), complex(big"2")])
1-element Vector{Complex}:
 2 + 0im

julia> unique(Quaternion[quat(2), quat(big"2")])
2-element Vector{Quaternion}:
  Quaternion{Int64}(2, 0, 0, 0)
 Quaternion{BigInt}(2, 0, 0, 0)

After this PR

julia> using Quaternions

julia> isequal(1, complex(1))
true

julia> 1 |> hash
0x5bca7c69b794f8ce

julia> complex(1) |> hash
0x5bca7c69b794f8ce

julia> isequal(1, quat(1))  # isequal(a,b) == true should imply `hash(a) == hash(b)`
true

julia> quat(1) |> hash
0x5bca7c69b794f8ce

julia> unique(Complex[complex(2), complex(big"2")])
1-element Vector{Complex}:
 2 + 0im

julia> unique(Quaternion[quat(2), quat(big"2")])
1-element Vector{Quaternion}:
 Quaternion{Int64}(2, 0, 0, 0)

Copy link

codecov bot commented Nov 9, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (89232ef) 100.00% compared to head (eab2f56) 100.00%.
Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #136   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            2         2           
  Lines          162       175   +13     
=========================================
+ Hits           162       175   +13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@hyrodium hyrodium marked this pull request as ready for review November 9, 2023 16:06
@hyrodium
Copy link
Collaborator Author

hyrodium commented Nov 9, 2023

Hmm, not sure why the Invalidation test failed..

image

https://github.com/JuliaGeometry/Quaternions.jl/actions/runs/6814371318/job/18531083622?pr=136

@@ -236,6 +236,17 @@ function Base.isequal(q::Quaternion, w::Quaternion)
isequal(q.s, w.s) & isequal(q.v1, w.v1) & isequal(q.v2, w.v2) & isequal(q.v3, w.v3)
end

if UInt === UInt64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be better?

Suggested change
if UInt === UInt64
@static if UInt === UInt64

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @static macro brings better performance if it is used inside a function, but this case is not, so it seems there would not be better performance here.

julia> f() = @static Sys.iswindows() ? 1 : 2
f (generic function with 1 method)

julia> @code_lowered f()
CodeInfo(
1return 2
)

julia> g() = Sys.iswindows() ? 1 : 2
g (generic function with 1 method)

julia> @code_lowered g()
CodeInfo(
1%1 = Base.Sys.iswindows
│   %2 = (%1)()
└──      goto #3 if not %2
2return 1
3return 2
)

@hyrodium
Copy link
Collaborator Author

@ranocha Do you know why the Invalidation check failed?

@hyrodium
Copy link
Collaborator Author

The invalidation failure was because the number of uinvalidated(invalidations) has increased.

Before this PR

julia> using SnoopCompile, SnoopCompileCore

julia> invalidations = @snoopr begin using Quaternions end;

julia> uinvalidated(invalidations)
Set{Core.MethodInstance} with 1 element:
  MethodInstance for promote_rule(::Type, ::Type)

julia> inv_owned = length(filtermod(Quaternions, invalidation_trees(invalidations)))
0

After this PR

julia> using SnoopCompile, SnoopCompileCore

julia> invalidations = @snoopr begin using Quaternions end;

julia> uinvalidated(invalidations)
Set{Core.MethodInstance} with 2 elements:
  MethodInstance for hash(::Any, ::UInt64)
  MethodInstance for promote_rule(::Type, ::Type)

julia> inv_owned = length(filtermod(Quaternions, invalidation_trees(invalidations)))
0

But it seems this is not problematic because inv_owned is zero.

(The above code are from https://github.com/julia-actions/julia-invalidations/blob/main/action.yml.)

@ranocha
Copy link
Contributor

ranocha commented Nov 29, 2023

Based on your results above, it looks like there are some new invalidations caused by the new specialization. You don't invalidate your own functions but something that's using hash and is badly inferred. This may impact the latency when loading Quaternions.jl.
Of course, this doesn't mean that you cannot go ahead with this PR. It would be a nice contribution to the ecosystem to check where the invalidations are coming from and trying to fix them 🙂

@hyrodium
Copy link
Collaborator Author

I see. Thank you for the detailed explanation!

@hyrodium
Copy link
Collaborator Author

hyrodium commented Feb 1, 2024

I'll merge this PR in a few days if there are no objections.

@hyrodium hyrodium mentioned this pull request Feb 3, 2024
@hyrodium hyrodium merged commit 3f5c5c1 into JuliaGeometry:main Feb 5, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

hash(::Quaternion, ::UInt) should be defined
3 participants