-
Notifications
You must be signed in to change notification settings - Fork 34
Add missing operations for fmpz and fmpq #44
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 missing operations for fmpz and fmpq #44
Conversation
| def __lshift__(self, other): | ||
| if typecheck(other, fmpz): | ||
| other = int(other) | ||
| if typecheck(other, int): | ||
| u = fmpz.__new__(fmpz) | ||
| fmpz_mul_2exp((<fmpz>u).val, self.val, other) | ||
| return u |
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.
Probably need to check if other is negative.
test/test.py
Outdated
| assert ltype(s) & rtype(t) == s & t | ||
| assert ~ltype(s) == ~s | ||
|
|
||
| # XXX: Some sort of bug here means that the following fails | ||
| # for values of s and t bigger than the word size. | ||
| if abs(s) < 2**62 and abs(t) < 2**62: | ||
| assert ltype(s) | rtype(t) == s | t | ||
| else: | ||
| # This still works so somehow the internal representation | ||
| # of the fmpz made by fmpz_or is such that fmpz_equal | ||
| # returns false even though the values look the same. | ||
| assert str(ltype(s) | rtype(t)) == str(s | t) | ||
|
|
||
| assert ltype(s) ^ rtype(t) == s ^ t |
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'm not sure what is happening here but I think that the __or__ method here is correct so maybe this is a Flint bug. The __and__ and __xor__ methods have the same code and tests and they work fine.
It seems that somehow fmpz_or creates an fmpz that fmpz_equal considers different even though its string representation is the same:
>>> flint.fmpz(2**62) | -1
-1
>>> flint.fmpz(2**62) | -1 == -1
False
>>> flint.fmpz(2**62-1) | -1
-1
>>> flint.fmpz(2**62-1) | -1 == -1
TrueI'm not sure how to debug this via python-flint.
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, this is a bug in fmpz_or. Fixed now in flintlib/flint@9809014.
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.
Speedy work!
|
Okay, this PR is complete now and represents all of the changes needed for python-flint to be usable by SymPy as the ground types plus a few more for completeness. It is basically just adding missing operators/methods that are usually supported by implementations of Z or Q so that fmpz and fmpq can work better as a drop-in replacement for int/Fraction or gmpy2's mpz/mpq. There are still some differences e.g.: In [1]: import gmpy2
In [2]: import flint
In [3]: flint.fmpz(3) / flint.fmpz(2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 1
----> 1 flint.fmpz(3) / flint.fmpz(2)
TypeError: unsupported operand type(s) for /: 'flint._flint.fmpz' and 'flint._flint.fmpz'
In [4]: gmpy2.mpz(3) / gmpy2.mpz(2)
Out[4]: mpfr('1.5')
In [5]: gmpy2.mpz(3.0)
Out[5]: mpz(3)
In [6]: flint.fmpz(3.0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 flint.fmpz(3.0)
File src/flint/fmpz.pyx:92, in flint._flint.fmpz.__init__()
TypeError: cannot create fmpz from type <class 'float'>These lead to a couple of doctest failures in SymPy but I think that it is something that can be handled on SymPy's side. The doctest for division is just a doctest saying not to use I will add a temporary fix for the |
|
Okay, this looks good. I'll merge this and open a new PR to prepare for release. |
This is a companion to the SymPy PR adding flint for ground types:
sympy/sympy#25474
Various things are added:
numerator/denominatorforfmpzandfmpq.__int__and__floor__methods.&etc forfmpzpow(a, b, c)forfmpz.fmpq ** fmpz.