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

use generic to allow 32 and 64 uint keys #30

Closed
wants to merge 2 commits into from

Conversation

jtarchie
Copy link

#27

map.go Outdated Show resolved Hide resolved
@jtarchie
Copy link
Author

Feel free to squash commits.

Comment on lines 361 to +363
// lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
func fastModN(x, n uint32) uint32 {
return uint32((uint64(x) * uint64(n)) >> 32)
func fastModN[S constraints.Unsigned](x, n S) S {
return S((uint64(x) * uint64(n)) >> 32)
Copy link

Choose a reason for hiding this comment

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

This is the part that will not work with uint64: it will always return values in 32-bit range, so those buckets will be unused.

Copy link
Author

Choose a reason for hiding this comment

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

I see. Would returning unsafe.Sizeof(S) help here? Or is this a bit-op trick that can not be rescued?

Copy link

Choose a reason for hiding this comment

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

I don't think it can be rescued without having to do the usual modulo division. See the link above that explains how the trick works.

Copy link
Author

Choose a reason for hiding this comment

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

This writeup shows a possible version to support uint64 ranges.

Perhaps there's a method here for assigning the correct fastmodN for the map instantiation. It, however, wouldn't be inlined by the compiler.

Copy link

Choose a reason for hiding this comment

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

Thank you for the link! It's always great to learn something new.

Maybe it would make sense to just have a fork of this repo (swiss64?) with the 64-bit version? It should be quite easy to keep it up to date (I guess there shouldn't be many or frequent incoming changes), the API would be clean (swiss.Map vs swiss64.Map) and the code would be easier and faster to follow. WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure. That seems like a dolthub call.

Copy link

@db47h db47h Dec 2, 2024

Choose a reason for hiding this comment

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

the fast modulo with 64 bits support can be as simple as

func fastModN(x, n uint) uint {
    h, _ := bits.Mul(x, n)
    return h
}

but this requires the high bits of x to be set (which is not necessarily the case for H1, depending on implementation). So just call it with x=H1<<7

Edit: and the compiler inlines it.

@jtarchie
Copy link
Author

Um... go 1.24 is getting native support for swiss tables. I assume this will be resolved already. Closing in favor of that.

@jtarchie jtarchie closed this Jan 15, 2025
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.

4 participants