-
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 __radd__
etc methods for Cython 3.x
#35
Conversation
src/flint/fmpz.pyx
Outdated
def __rpow__(s, t, m): | ||
cdef fmpz_struct tval[1] | ||
cdef int stype = FMPZ_UNKNOWN | ||
cdef ulong exp | ||
u = NotImplemented | ||
if m is not None: | ||
raise NotImplementedError("modular exponentiation") | ||
ttype = fmpz_set_any_ref(tval, t) | ||
if ttype != FMPZ_UNKNOWN: | ||
u = fmpz.__new__(fmpz) | ||
s_ulong = fmpz_get_ui(s.val) | ||
fmpz_pow_ui((<fmpz>u).val, tval, s_ulong) |
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 about this.
Actually I see that with current master and Cython 0.29 we have:
>>> import flint
>>> flint.fmpz(2) ** flint.fmpz(-2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "src/flint/fmpz.pyx", line 297, in flint._flint.fmpz.__pow__
fmpz_pow_ui((<fmpz>u).val, sval, c)
OverflowError: can't convert negative value to ulong
So I guess the existing __pow__
method should be changed. At least OverflowError
is not the right exception to raise.
Python itself gives:
>>> 2 ** -2
0.25
>>> 1 ** -1
1.0
>>> 2 ** 2
4
In principle an fmpq
could be returned but I'm not sure if that's better than an error.
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.
gmpy2 returns mpfr
:
In [3]: gmpy2.mpz(2) ** -2
Out[3]: mpfr('0.25')
In [4]: gmpy2.mpz(2) ** 2
Out[4]: mpz(4)
It's probably good to maintain compatibility with gmpy2.mpz
and int
itself if possible so that mpz
can be used interchangeably with those. I'm not sure what type that really means in the python-flint
context though.
3aa4a76
to
f759cc5
Compare
As a general principle, I dislike value-dependent return types. If a larger domain is needed to represent some results of an operation, then either the the return type should always be that of the larger domain, or there should be an exception. You could support automatic extensions with method options like |
So then in this case it should be an exception but probably not There are two particular cases that could conceivably be handled: >>> flint.fmpz(1) ** flint.fmpz(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "src/flint/fmpz.pyx", line 297, in flint._flint.fmpz.__pow__
fmpz_pow_ui((<fmpz>u).val, sval, c)
OverflowError: can't convert negative value to ulong
>>> flint.fmpz(-1) ** flint.fmpz(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "src/flint/fmpz.pyx", line 297, in flint._flint.fmpz.__pow__
fmpz_pow_ui((<fmpz>u).val, sval, c)
OverflowError: can't convert negative value to ulong Both >>> 1 ** -1
1.0
>>> (-1) ** -1
-1.0
>>> gmpy2.mpz(1) ** gmpy2.mpz(-1)
mpfr('1.0')
>>> gmpy2.mpz(-1) ** gmpy2.mpz(-1)
mpfr('-1.0') Maybe it's just not worth handling them for the simplicity of just saying that the exponent should always be nonnegative. |
Sure, there could be a more appropriate exception. Right now error handling is just implemented very lazily in many places by having a conversion from Python type -> C type and letting Cython catch the overflow. In generic-rings there is much more systematic approach to error handling with two types of exceptions: "domain error" vs "unable to compute". It would be nice to implement something similar in the present python-flint in anticipation of a future merger with that code. But it's also not worth overengineering. |
59b9f35
to
070b7e5
Compare
I've added the At this point the test suite passes but there are other types that need to be changed:
I guess they are not covered as well in the tests. |
Okay, I think that is all types updated now. |
This will now only work with Cython 3.x because I have changed many of the existing It also fails to compile with Cython 3.0.0a12 (because of Cython bugs) but compiles correctly with Cython 3.0.0b2. |
This is needed for Cython 3.x compatibility: https://cython.readthedocs.io/en/latest/src/userguide/special_methods.html#arithmetic-methods Similar methods should be added to all python-flint types that have arithmetic operations.
d9ca14e
to
a390bdc
Compare
GitHub Actions CI jobs are failing because downloading the source code for GMP fails. The same command works fine locally:
Also I cancelled and restarted it but on the first run the OSX job did successfully download it but the Linux and Windows jobs failed to. The Cirrus CI job (for OSX arm64) succeeded. I'm not sure why downloading (mostly) fails from GitHub Actions. Maybe it is just a temporary problem. |
The GMP server is blocking accesses from GitHub because it's effectively being DDoSed: see the notice on https://gmplib.org/ You will need to use a mirror. |
Ah, thanks. I've made a GitHub repo to store the GMP release code: https://github.com/oscarbenjamin/gmp_mirror The CI scripts should now download from there... Not sure if there is a better idea than that but it seems reasonable to have all the CI stuff download from GitHub. |
Okay, that worked and now all wheels are built and tests passed. I've bumped the cython version to 3.0.0 (released two weeks ago) rather than 3.0.0b1. I've also bumped GMP from 6.2.1 to 6.3.0 and removed the macos_arm64 patch (it shouldn't be needed any more). If that all passes fine then everything is up to date although open a separate PR to test with flint 3.0.0-alpha1. |
I don't seem to be able to build flint 3.0.0 locally on Ubuntu 22.04: $ ./configure --disable-static
configure: WARNING: unrecognized options: --disable-static
./configure: line 2853: LT_INIT: command not found
checking for a race-free mkdir -p... /usr/bin/mkdir -p
checking for gcc... gcc
checking whether the compiler supports GNU C... no
checking whether gcc accepts -g... no
checking for gcc option to enable C11 features... unsupported
checking for gcc option to enable C99 features... unsupported
checking for gcc option to enable C89 features... unsupported
checking for inline... no
checking for stdio.h... no
checking for stdlib.h... no
checking for string.h... no
checking for inttypes.h... no
checking for stdint.h... no
checking for strings.h... no
checking for sys/stat.h... no
checking for sys/types.h... no
checking for unistd.h... no
checking whether byte ordering is bigendian... no
checking for ldconfig... ldconfig
checking for stdarg.h... no
configure: error: Could not find a mandatory header! I do have $ cat t.c
#include <stdarg.h>
$ gcc -c t.c Seems to be a problem with the configure script detecting headers somehow. |
This
is weird, as Did you run |
Fresh from the tarball: $ tar xf flint-3.0.0-alpha1.tar.gz
$ cd flint-3.0.0-alpha1/
$ ./bootstrap.sh
autoreconf: export WARNINGS=all
autoreconf: Entering directory '.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force
autoreconf: configure.ac: tracing
autoreconf: configure.ac: creating directory config
autoreconf: configure.ac: not using Libtool
autoreconf: configure.ac: not using Intltool
autoreconf: configure.ac: not using Gtkdoc
autoreconf: running: /usr/bin/autoconf --force
autoreconf: running: /usr/bin/autoheader --force
autoreconf: configure.ac: not using Automake
autoreconf: linking config/install-sh to /usr/share/autoconf/build-aux/install-sh
autoreconf: Leaving directory '.'
$ ./configure
./configure: line 2853: LT_INIT: command not found
checking for a race-free mkdir -p... /usr/bin/mkdir -p
checking for gcc... gcc
checking whether the compiler supports GNU C... no
checking whether gcc accepts -g... no
checking for gcc option to enable C11 features... unsupported
checking for gcc option to enable C99 features... unsupported
checking for gcc option to enable C89 features... unsupported
checking for inline... no
checking for stdio.h... no
checking for stdlib.h... no
checking for string.h... no
checking for inttypes.h... no
checking for stdint.h... no
checking for strings.h... no
checking for sys/stat.h... no
checking for sys/types.h... no
checking for unistd.h... no
checking whether byte ordering is bigendian... no
checking for ldconfig... ldconfig
checking for stdarg.h... no
configure: error: Could not find a mandatory header! In config.log it seems to think that everything fails to compile regardless of the exit code (if I'm interpreting it correctly):
|
Judging from
perhaps |
Thanks, that fixed it:
Now:
|
Okay, looks like getting python_flint to work with flint 3.0.0-alpha1 is just a simple case of renaming the arb headers and removing To summarise the changes in this PR:
It could be possible to make this work with all Cython versions by using a configuration option instead of changing the code but I think that it is better to update the code to the latest default Cython mode and given that Cython is a build-time dependency that can be pinned there is no real reason to support multiple versions. Actually I can remove the version pin on Cython in CI here since the default current version works. I'll do that now. Do you want to check the PR at all or am I good to merge it? |
Oh, the other change is that CI no longer downloads from gmplib.org which currently causes CI to fail. |
Okay, let's get this one in. |
Fixes #34