Description
Right now we ccall
many FLINT functions from multiple places, e.g. fmpq_mpoly_add
is called in three places in Nemo; so is fmpz_add
but that one also has two callers in Hecke.
At the same time, we are not using a bunch of FLINT accessor at all, e.g. while we also wrap fmpq_mpoly_add_si
we don't wrap fmpq_mpoly_add_ui
(perhaps it didn't exist when these wrappers were originally written).
To address this, I suggest we make provide these low-level helpers in a more systematic way (see e.g. PR #1809), and also use them more systematically (see e.g. PR #1811). In the example above, each of these functions should ideally be ccall'ed from exactly one spot, namely an add!
method. Those add!
methods then can take care of dispatching to the right ccalls
. The result is code that is easier to read, and often it enables us to reduce code duplication. E.g. with suitable add!
methods in place, we can have this:
function +(x::QQMatrix, y::QQMatrix)
check_parent(x, y)
z = similar(x)
add!(z, x, y)
end
and this
function +(x::ZZMatrix, y::ZZMatrix)
check_parent(x, y)
z = similar(x)
add!(z, x, y)
end
So if we wanted to we could implement +
for all Nemo matrix types in a single place. Maybe a more plausible example is how in PR #1810 several constructors for fqPolyRepField
become essentially identical and could be merged.
Using macros to generate all sensible variants of some low-level wrappers as done in e.g. PR #1809 probably should be done in more place. I.e. we should do similar things for the other FLINT types we wrap. For starters let's focus on set/add/sub/mul/div; but on the long run many more could and should be added -- e.g. neg!
, zero!
, divexact!
etc. etc.
Basically any fmpz_mat_*
API in FLINT could be wrapped in such a low-level wrapper. Someone could perhaps even write a tool to generate the relevant helpers (or at least some of them) from FLINT headers? I think some language wrappers for FLINT are already handled that way; was it the Haskell one? Maybe more? Surely @albinahlback and @fredrik-johansson can clarify that.
A key for this is to have, say, add!
methods which don't just accept, say, a ZZRingElem
but also a Ptr{ZZRingElem}
or Ref{ZZRingElem}
-- this can be achieved with a union type, see also e.g. PR #1808. That way we can use these low-level helpers in many more places.