-
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
Add fmpz mod #83
Add fmpz mod #83
Conversation
Here three things are being printed. The first is In other words The second thing printed is The third thing being printed is The first two cases that you have picked are less than 64 bits ( The third case is larger then 128 bits so we go to the general case: If you choose a modulus in between 64 and 128 bits then you should see |
Thanks so much Oscar, so the "generic" thing I misunderstood was that to get nice printing for >>> from flint import *
>>>
>>> ctx = fmpz_mod_ctx(123)
>>> ctx
Context for fmpz_mod with modulus: 123
>>>
>>> n = 2**100 - 1
>>> n
1267650600228229401496703205375
>>> ctx.set_modulus(n)
>>> ctx
Context for fmpz_mod with modulus: 1267650600228229401496703205375
>>>
>>> n = 2**1024 - 1
>>> n
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215
>>> ctx.set_modulus(n)
>>> ctx
Context for fmpz_mod with modulus: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 I have weird things happening with the initialisation of the actual values but I'll figure this out I hope. >>> from flint import *
>>>
>>> mod_ctx = fmpz_mod_ctx(11)
>>> for i in range(11):
... fmpz_mod(i, mod_ctx)
...
fmpz_mod(0, 11)
fmpz_mod(1, 11)
fmpz_mod(2, 11)
fmpz_mod(3, 11)
fmpz_mod(4, 11)
fmpz_mod(0, 11)
fmpz_mod(1, 11)
fmpz_mod(2, 11)
fmpz_mod(3, 11)
fmpz_mod(4, 11)
fmpz_mod(0, 11) |
If Maybe the contexts should be immutable. |
Maybe also there should be a way to create and |
OK very basic initialisation works, feels like that's most of the battle! >>> from flint import *
>>> mod_ctx = fmpz_mod_ctx(163)
>>>
>>> fmpz_mod(-1, mod_ctx)
fmpz_mod(162, 163)
>>> fmpz_mod(165, mod_ctx)
fmpz_mod(2, 163) |
Hmm good point, this is worth thinking about. I only included it as I saw the function. I should also do the |
Also, rather than ctx.new(val) we could have it callable so we can do ctx(val), not sure what you think fits better for the library? Then we'd basically have ZmodN = fmpz_mod_ctx(N) and we can make elements from ZmodN(val) |
I think either is fine. You could use this like: F11 = fmpz_mod_ctx(11)
a = F11(2)
b = F11(7)
c = a / b |
I agree with the above, I made something which allows the following: >>> from flint import *
>>> ZmodN = fmpz_mod_ctx(163)
>>> x = ZmodN(123)
>>> type(x)
<class 'flint.types.fmpz_mod.fmpz_mod'>
>>> x
fmpz_mod(123, 163)
>>>
>>> y = fmpz(456)
>>> ZmodN(y)
fmpz_mod(130, 163)
>>>
>>> z = fmpz_mod(789, ZmodN)
fmpz_mod(137, 163) |
Currently we have In [3]: print(str(flint.nmod(2, 3)))
2
In [4]: print(repr(flint.nmod(2, 3)))
2 I'm not sure that I like that this does not display the modulus. It is at least inconsistent with what you show above though: >>> x
fmpz_mod(123, 163) This is how the SymPy equivalent looks: In [5]: from sympy import GF
In [6]: F3 = GF(3)
In [7]: print(str(F3(2)))
2 mod 3
In [8]: print(repr(F3(2)))
SymmetricModularIntegerMod3(2) I like the We also have: In [9]: flint.nmod_poly([1, 2, 3], 7)
Out[9]: 3*x^2 + 2*x + 1
In [10]: flint.nmod_mat([[1, 2], [3, 4]], 7)
Out[10]:
[1, 2]
[3, 4] So the modulus is not shown there. This is how those look with SymPy: In [12]: Matrix([[1, 2], [3, 4]]).to_DM(domain=F3).to_dense()
Out[12]: DomainMatrix([[1 mod 3, 2 mod 3], [0 mod 3, 1 mod 3]], (2, 2), GF(3))
In [13]: Poly([1, 2, 3, 4], x, domain=F3)
Out[13]: Poly(x**3 - x**2 + 1, x, modulus=3) I'm not sure what is best here. My natural inclination is that the modulus should not be invisible because nonzero characteristic is very different from zero characteristic. We also have: In [15]: print(str(gmpy2.mpz(3)))
3
In [16]: print(repr(gmpy2.mpz(3)))
mpz(3)
In [17]: print(str(flint.fmpz(3)))
3
In [18]: print(repr(flint.fmpz(3)))
3 |
I agree that For another point of reference, in SageMath we have: sage: F = GF(163)
sage: x = F.random_element()
sage: x
116
sage: str(x)
'116'
sage:
sage: K = Zmod(163)
sage: x = K.random_element()
sage: x
136
sage: str(x)
'136' |
Addition and negation and comparison are done, but not in a clean way. More to do, but will leave it for tomorrow. I have some Dad chores to do while everyone is sleeping!! >>> from flint import *
>>>
>>> F163 = fmpz_mod_ctx(163)
>>> assert F163.modulus() == 163
>>>
>>> assert F163(162) == F163(-1) == -F163(1)
>>> assert F163(123) + F163(456) == F163(123 + 456)
>>>
>>> assert F163(162) != F163(1) |
Allowed the addition of: assert F163(123) + F163(456) == F163(123 + 456)
assert F163(123) + F163(456) == F163(456) + F163(123)
assert F163(123) + 456 == F163(123 + 456)
assert F163(123) + fmpz(456) == F163(456) + F163(123) So anything which can be cast to |
I think this looks good. What is needed now is documentation. We need an |
Looks like |
Do you recommend one of the classes for docstring examples? Otherwise I'll just do what seems sensible. |
There aren't many non-inbuilt functions so the docstrings may be a bit sparse for this type. |
A reference is needed here: python-flint/doc/source/index.rst Lines 41 to 50 in 11bb708
|
Agreed but the class level docstring should show the basic idea of how to construct an |
**fmpz** -- integers mod n | ||
=============================================================================== | ||
|
||
.. autoclass :: flint.fmpz_mod |
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.
The fmpz_mod_ctx
class also needs to be documented here.
@@ -0,0 +1,8 @@ | |||
**fmpz** -- integers mod n | |||
=============================================================================== |
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 should say fmpz_mod
.
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.
Thank you!!
src/flint/types/fmpz_mod.pyx
Outdated
""" | ||
The *fmpz_mod* type represents integer modulo an | ||
arbitrary-size modulus. For wordsize modulus, see | ||
*nmod*. |
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.
A Sphinx reference like
:class:`flint.types.nmod.nmod`
creates a clickable link in the html docs which is better.
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.
Ahh thanks, I haven't ever used sphinx. I'll add this now.
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.
Actually this is a shorter version:
:class:`~.nmod`
src/flint/types/fmpz_mod.pyx
Outdated
|
||
def inverse(self, check=True): | ||
""" | ||
Computes a^-1 mod N |
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 should be possible to use LaTeX here but possibly the LaTeX Sphinx extension is needed but not enabled...
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.
Yeah I'm trying to do that but the naive
math:`a^{-1} \mod N`
isn't working at least...
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.
Oh, I got it.
Added the latex to the docstring which works (at least locally) and in the process spotted that |
I guess it should be. I'm not sure what the situation was before. Possibly the recent mega-refactoring affected this... In any case if they are there then they should be made available and documented. |
The functions are there and are fairly well docstring'd so, they're being tested in other ways. My commit above makes them available from |
I'm off for the evening now. Thanks so much for your help with this class. I'm hoping there's a magnitude less discussion for my next type as I now have a much better idea of what I should be doing and how :) ❤️ |
src/flint/types/fmpz_mod.pyx
Outdated
raise NotImplementedError | ||
fmpz_mod_set_fmpz(self.val, (<fmpz>val).val, self.ctx.val) | ||
|
||
def any_as_fmpz_mod(self, obj): |
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.
Can this be cdef
?
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.
Or otherwise a leading underscore like _any_as...
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.
currently it shows in the docs but it should not be there.
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.
Made it a cdef
Unless you have anything to add I think this looks good now. More improvements can be made to the documentation but I think that is an already general problem rather than something that must be fixed in this PR. |
I think this is good to go now, at least, it doesn't feel much worse than the existing types? I want to eventually add the discrete log functions, but there's no rush for this and I'm more interested in getting |
One thing that would be good to think about going forwards is how to share testing code a bit e.g. most of the tests for We should make new test functions that are like |
I think so too. It will be in once the tests have passed. |
Agree about the testing. I also think it would be good to have randomised testing in certain places (addition, subtraction etc are all good candidates for this) |
This is a draft pull request adding the type
fmpz_mod
Before continuing, I am a little confused about the
fmpz_mod_ctx
and it's behaving in a way which doesn't make much sense to me...The context struct is of the form:
and as
n
is anfmpz_t
type, I assumed this was the standard modulus. I thinkmod
is then the modulus used for small input?However, if I print out
ctx.n
andctx.mod
for various values I find:Is it obvious here what I'm doing wrong?? Looking at the data out (a list, a dict, and a list) it seems I don't understand the "python" version of the types in this struct at all :/