-
Notifications
You must be signed in to change notification settings - Fork 58
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
Optimize mat_entry_ptr methods #1871
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1871 +/- ##
==========================================
- Coverage 87.33% 87.32% -0.01%
==========================================
Files 97 97
Lines 35858 35859 +1
==========================================
- Hits 31316 31314 -2
- Misses 4542 4545 +3 ☔ View full report in Codecov by Sentry. |
@@ -6204,10 +6204,10 @@ end | |||
const fqPolyRepMatrixSpace = AbstractAlgebra.Generic.MatSpace{fqPolyRepFieldElem} | |||
|
|||
mutable struct fqPolyRepMatrix <: MatElem{fqPolyRepFieldElem} | |||
entries::Ptr{Nothing} | |||
entries::Ptr{fqPolyRepFieldElem} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not 100% true, since otherwise I would expect the following to work (before this PR, with htis PR the Ptr conversion becomes unnecessary):
julia> F = Native.GF(2,2);
julia> a = matrix(F, 2, 2, [1,2,3,4]);
julia> unsafe_load(Ptr{fqPolyRepFieldElem}(a.entries))
[1054580] signal (11.1): Segmentation fault
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It definitely is a lie, just like with many other Ptr{ZZRingElem}
etc. etc. in our code base -- our Julia types are "supersets" of the FLINT types.
BTW you can get the same crash in master
via unsafe_load(Nemo.mat_entry_ptr(a, 1, 1))
. I simply chose the signatures here to make the implementation of mat_entry_ptr
as simple as possible for each type.
We could of course also resolve this by adding a separate struct fq_nmod_t
(and fmpz_t
etc. etc.) which faithfully replicate the FLINT structs, nothing more and nothing less. Then e.g. fqPolyRepFieldElem
could start with a member x:: fq_nmod_t
.
That way, we could resolve all the lies everywhere. But that would be a major piece of work for relatively limited gain (if I were to start Nemo today, that's more or less what I'd do anyway, but as it is now...).
Anyway: I am happy to discuss this further, but I think for the purpose of this PR, it doesn't really make anything worse, as nothing in Nemo.jl ever accesses .entries
fields, and the access to .rows
is limited to very, very few places. And to me at least it was helpful to get a better idea of what each entries
and rows
points to. But I am also ok with changing them back to Nothing
and adjust the mat_entry_ptr
to insert suitable reinterpret
calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. I am fine with merging this. Could you open an issue with basically what you explained here, so that we keep it somewhere? (even though that's nothing to be changed in the near future (unless someone has way too much time))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI is happy, I don't really understand all of the formulas, but trust you with this
@inline mat_entry_ptr(A::QQMatrix, i::Int, j::Int) = | ||
ccall((:fmpq_mat_entry, libflint), | ||
Ptr{QQFieldElem}, (Ref{QQMatrix}, Int, Int), A, i-1, j-1) | ||
mat_entry_ptr(A::QQMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*2*sizeof(Ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat_entry_ptr(A::QQMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*2*sizeof(Ptr) | |
mat_entry_ptr(A::QQMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(QQFieldElem) |
@@ -2107,4 +2107,4 @@ end | |||
# | |||
################################################################################ | |||
|
|||
@inline mat_entry_ptr(A::ZZMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(UInt) | |||
mat_entry_ptr(A::ZZMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat_entry_ptr(A::ZZMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) | |
mat_entry_ptr(A::ZZMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(ZZRingElem) |
@inline mat_entry_ptr(A::ZZModMatrix, i::Int, j::Int) = | ||
ccall((:fmpz_mod_mat_entry, libflint), Ptr{ZZRingElem}, | ||
(Ref{ZZModMatrix}, Int, Int), A, i - 1, j - 1) | ||
mat_entry_ptr(A::ZZModMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat_entry_ptr(A::ZZModMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) | |
mat_entry_ptr(A::ZZModMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(ZZRingElem) |
@inline mat_entry_ptr(A::FqPolyRepMatrix, i::Int, j::Int) = | ||
ccall((:fq_mat_entry, libflint), Ptr{FqPolyRepFieldElem}, | ||
(Ref{FqPolyRepMatrix}, Int, Int), A, i - 1, j - 1) | ||
mat_entry_ptr(A::FqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+2*sizeof(Int)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit confusing, perhaps I should add a comment
mat_entry_ptr(A::FqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+2*sizeof(Int)) | |
# each matrix entry consists of | |
# coeffs :: Ptr{Nothing} | |
# alloc :: Int | |
# length :: Int | |
# The `parent` member of struct FqPolyRepFieldElem is not replicated in each | |
# struct member, so we cannot use `sizeof(FqPolyRepFieldElem)`. | |
mat_entry_ptr(A::FqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+2*sizeof(Int)) |
@inline mat_entry_ptr(A::fqPolyRepMatrix, i::Int, j::Int) = | ||
ccall((:fq_nmod_mat_entry, libflint), Ptr{fqPolyRepFieldElem}, | ||
(Ref{fqPolyRepMatrix}, Int, Int), A, i - 1, j - 1) | ||
mat_entry_ptr(A::fqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+5*sizeof(Int)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat_entry_ptr(A::fqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+5*sizeof(Int)) | |
# each matrix entry consists of | |
# coeffs :: Ptr{Nothing} | |
# alloc :: Int | |
# length :: Int | |
# n :: Int | |
# ninv :: Int | |
# norm :: Int | |
# The `parent` member of struct fqPolyRepFieldElem is not replicated in each | |
# struct member, so we cannot simply use `sizeof(fqPolyRepFieldElem)`. | |
mat_entry_ptr(A::fqPolyRepMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*(sizeof(Ptr)+5*sizeof(Int)) |
@inline mat_entry_ptr(A::FpMatrix, i::Int, j::Int) = | ||
ccall((:fmpz_mod_mat_entry, libflint), Ptr{ZZRingElem}, | ||
(Ref{FpMatrix}, Int, Int), A, i - 1, j - 1) | ||
mat_entry_ptr(A::FpMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mat_entry_ptr(A::FpMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(Ptr) | |
mat_entry_ptr(A::FpMatrix, i::Int, j::Int) = unsafe_load(A.rows, i) + (j-1)*sizeof(ZZRingElem) |
These explanations really help! Thanks! |
No description provided.