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

Make low-level ZZRingElem accessors more powerful #1942

Merged
merged 1 commit into from
Nov 12, 2024

Conversation

fingolfin
Copy link
Member

... and their code more readable (at least to me).

Also implement rem(::ZZRingElem, ::Type{UInt}) and use that to
speed up iseven, isodd, sign, signbit and is_squarefree
for ZZRingElem.

When tested in isolation using BenchmarkTools, the new methods
are usually a little bit faster, and never slower,
than the old ones. The main gain however is in code using them:
unlike opaque ccalls the compiler can inline these helper and
possibly perform further optimizations.

... and their code more readable (at least to me).

Also implement `rem(::ZZRingElem, ::Type{UInt})` and use that to
speed up `iseven`, `isodd`, `sign`, `signbit` and `is_squarefree`
for `ZZRingElem`.

When tested in isolation using BenchmarkTools, the new methods
are usually a little bit faster, and never slower,
than the old ones. The main gain however is in code using them:
unlike opaque `ccall`s the compiler can inline these helper and
possibly perform further optimizations.
Copy link

codecov bot commented Nov 10, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.89%. Comparing base (9b83a72) to head (bb128a7).
Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1942      +/-   ##
==========================================
- Coverage   87.90%   87.89%   -0.02%     
==========================================
  Files          99       99              
  Lines       36366    36361       -5     
==========================================
- Hits        31968    31958      -10     
- Misses       4398     4403       +5     

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

end

function hash_integer(a::ZZRingElem, h::UInt)
return _hash_integer(a.d, h)
return GC.@preserve a _hash_integer(data(a), h)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you need the preserve here for? a is not allowed to be a ptr by signature

Copy link
Member

Choose a reason for hiding this comment

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

The return value of data(a) is only useful if a is preserved. (Unless _fmpz_is_small(a) is `true, then it it does not need to be preserved.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed: data(a) returns an Int which however is a pointer in disguise. Julia could therefore decide to garbage collect a right after data(a) returned, but before _hash_integer starts. But then we may get garbage or a crash. Of course that only matters if the code calling hash_integer resp. hash does not access the value a anymore afterwards, which seems unlikely -- but not impossible.

p = unsafe_load(d)
__fmpz_is_small(a) && return Base.hash_integer(a, h)
# view it as a BigInt
z = unsafe_load(Ptr{BigInt}(unsigned(a) << 2))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Doesn't this line need a GC.preserve for a?

Copy link
Collaborator

Choose a reason for hiding this comment

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

And why not use the new _as_bigint function here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably all correct, but I don't like the convention that size(Int) = 1, but don't have string feelings about it. For fmpz's this is different and more nuanced due the possibility of beeing immediate....

Copy link
Member Author

Choose a reason for hiding this comment

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

This can't use _as_bigint (which BTW is not new, just moved around) because at this point we only have a which is a "pointer-disguised-as-Int.

Note that this code is essentially the same as it was before, I just reorganized it a bit for clarity.

Copy link
Collaborator

@lgoettgens lgoettgens left a comment

Choose a reason for hiding this comment

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

Apart from my random preserve comments, that I am really not sure about, this looks fine

@lgoettgens
Copy link
Collaborator

Thanks for the explanations. No further comments or objections from my side

@fingolfin fingolfin merged commit f4ac159 into master Nov 12, 2024
23 of 24 checks passed
@fingolfin fingolfin deleted the mh/low-level-fmpz branch November 12, 2024 19:12
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