-
Notifications
You must be signed in to change notification settings - Fork 27
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
Structure code into submodules #15
Comments
So, in #61 I did the absolute minimum to start exploring how we can start factoring this repository into submodules. The work so far has taken the base classes For the remaining code, my thought was to do something like:
For each of the main types, then a user would do
The same would naturally extend to whatever functions we have. |
However, if we're going through the work of refactoring and building up sensible class structures, then I think we might want something like cdef flint_elem:
cdef flint_scalar(flint_elem):
cdef generic_ring(flint_scalar):
cdef fmpz(generic_ring):
cdef fmpq(generic_ring):
... and so maybe a good first step would be to include the generic ring bindings into submodules in a clean and well documented way, and then we can refactor the existing code to sit on top of all these generics? |
This still makes it impossible to import fmpz without loading fmpz_poly etc. I think that it is better to just have precisely two ways of importing things: Either use fully qualified imports so from flint.fmpz.fmpz_poly import fmpz_poly or we provide a convenience layer: from flint.interactive import * The codebase should only ever use fully qualified imports internally and each module should only import the things that it needs so that one import does not recursively import everything else. I suggested having levels here: Probably all "level 1" things like these should be under a particular submodule like Some Python tooling (Sphinx, mypy etc) struggles with the idea that a module has the same name as something inside the module like: from flint.fmpz.fmpz import fmpz It is especially problematic if the from flint.types.fmpz_type import fmpz It is a bit redundant but that is not a problem for the internals of the codebase as long as the import statements are systematic and predictable. It is also fine to have long import statements like this for downstream codebases as long as module names are stable over time so it is better to make sure that you would never regret putting something at top-level in future. For interactive use it is not nice to have to fully qualify the imports, hence |
OK -- this looks sensible to me. I personally will be offline for a few weeks, so will be delayed in any work on this but my rough plan would be:
Then, after this has been done, the PR can be modified so that the imports throughout the module work nicely at the python level? |
Would this create packages i.e with Also would it mean that there is an
Perhaps simpler would just be
Then each
I'm not especially tied to any particular names here like
|
I think your suggestion is better and agree with your bullet points. After the refactor, I think what we can do in
and then the
Or
in the python world (or something similar) but this will be solved as we go? |
That would be my suggestion. Again I'm not tied to "interactive" as a name. Some people would certainly want to use it in a non-interactive context. Ideally it would be from flint.all import * However "all" is a builtin in Python so that name is best avoided.
It would have to be from flint.types.fmpz_type import fmpz because if the Even if we don't want to make a change to |
In the context of #59 I'm back from my holiday and so can assist with the refactoring of the current code if this would be helpful. Once we have all come to a solid idea of a plan we should be able to all work together to make quicker work of the refactoring |
If you could look at my fork and make any suggestions, they would be appreciated. I know the structure is all wrong and will spend some time today to rectify that by moving everything under a |
Now that I have caffinated, there are two simple questions that I basically punted.
|
I don't have good answers for these:
I had a look at your branch, as well as the movement of
and instead move the type specific imports from As an example, I was imagining moving cdef extern from "flint/nmod_mat.h":
ctypedef struct nmod_mat_struct:
mp_limb_t * entries
long r
long c
mp_limb_t ** rows
nmod_t mod
ctypedef nmod_mat_struct nmod_mat_t[1]
mp_limb_t nmod_mat_entry(nmod_mat_t mat, long i, long j)
long nmod_mat_nrows(nmod_mat_t mat)
long nmod_mat_ncols(nmod_mat_t mat)
void _nmod_mat_set_mod(nmod_mat_t mat, mp_limb_t n)
void nmod_mat_init(nmod_mat_t mat, long rows, long cols, mp_limb_t n)
void nmod_mat_init_set(nmod_mat_t mat, nmod_mat_t src)
void nmod_mat_clear(nmod_mat_t mat)
void nmod_mat_randtest(nmod_mat_t mat, flint_rand_t state)
void nmod_mat_randfull(nmod_mat_t mat, flint_rand_t state)
void nmod_mat_randrank(nmod_mat_t, flint_rand_t state, long rank)
void nmod_mat_randops(nmod_mat_t mat, long count, flint_rand_t state)
void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit)
void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit)
void nmod_mat_print_pretty(nmod_mat_t mat)
int nmod_mat_equal(nmod_mat_t mat1, nmod_mat_t mat2)
int nmod_mat_is_zero(nmod_mat_t mat)
int nmod_mat_is_empty(nmod_mat_t mat)
int nmod_mat_is_square(nmod_mat_t mat)
void nmod_mat_zero(nmod_mat_t mat)
void nmod_mat_set(nmod_mat_t B, nmod_mat_t A)
void nmod_mat_transpose(nmod_mat_t B, nmod_mat_t A)
void nmod_mat_add(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_sub(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_neg(nmod_mat_t B, nmod_mat_t A)
void nmod_mat_scalar_mul(nmod_mat_t B, nmod_mat_t A, mp_limb_t c)
void nmod_mat_mul(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_mul_classical(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_mul_strassen(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_addmul(nmod_mat_t D, nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
void nmod_mat_submul(nmod_mat_t D, nmod_mat_t C, nmod_mat_t A, nmod_mat_t B)
mp_limb_t nmod_mat_det(nmod_mat_t A)
long nmod_mat_rank(nmod_mat_t A)
int nmod_mat_inv(nmod_mat_t B, nmod_mat_t A)
void nmod_mat_solve_tril(nmod_mat_t X, nmod_mat_t L, nmod_mat_t B, int unit)
void nmod_mat_solve_triu(nmod_mat_t X, nmod_mat_t U, nmod_mat_t B, int unit)
long nmod_mat_lu(long * P, nmod_mat_t A, int rank_check)
int nmod_mat_solve(nmod_mat_t X, nmod_mat_t A, nmod_mat_t B)
int nmod_mat_solve_vec(mp_ptr x, nmod_mat_t A, mp_srcptr b)
long nmod_mat_rref(nmod_mat_t A)
long nmod_mat_nullspace(nmod_mat_t X, nmod_mat_t A) From |
One name only exists in C and the other is a runtime Python object: python-flint/src/flint/pyflint.pyx Line 31 in bf9d0d1
In [1]: import flint
In [2]: flint.ctx
Out[2]:
pretty = True # pretty-print repr() output
unicode = False # use unicode characters in output
prec = 53 # real/complex precision (in bits)
dps = 15 # real/complex precision (in digits)
cap = 10 # power series precision
threads = 1 # max number of threads used internally
In [3]: flint.thectx
---------------------------------------------------------------------------
AttributeError Maybe it is possible to do without
Currently these are defined as python-flint/src/flint/pyflint.pyx Lines 27 to 29 in bf9d0d1
That is deprecated but no alternative for cdef constants exists yet:cython/cython#4310 (comment) |
I'll leave the FMPZ constants as they are, but the endless warnings are annoying. It looks like the ultimate solution for Yes, I will soon split |
Seems like you have this next refactor covered but lmk if I can help |
I think this is fixed now. |
Currently pyflint.pyx includes all .pyx files textually. This is a headache for development: changing any one file and recompiling forces a recompile of all of python-flint, which takes forever. There should be separate submodules that can be compiled independently.
The text was updated successfully, but these errors were encountered: