Skip to content
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 additional bindings from NTL to Polynomial_ZZ_pEX #36097

Merged
merged 6 commits into from
Aug 27, 2023

Conversation

GiacomoPope
Copy link
Contributor

@GiacomoPope GiacomoPope commented Aug 17, 2023

There are current cython bindings to NTL methods which are not made available to polynomial rings over extension fields.

For some of these bindings, their introduction does not offer much speed up, but there is a 50x improvement for using NTL reverse over that of the current implementation, and about a 20% speed up using the NTL ZZ_pEX_InvTrunc over what is currently implemented.

Method names and functionalities have been preserved, so this simply improves performance for the Polynomial_ZZ_pEX type without effecting other polynomial ring classes.

Before Patch

sage: p = next_prime(2**1024)
sage: F.<i> = GF(p^2)
sage: R.<x> = PolynomialRing(F, implementation="NTL")
sage:
sage: f = R([p for p in primes(10)])
sage: %timeit f.reverse()
125 µs ± 582 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sage: %timeit f.inverse_series_trunc(500)
4.96 ms ± 81.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage:
sage: f = R([p for p in primes(100)])
sage: %timeit f.reverse()
681 µs ± 4.21 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
sage: %timeit f.inverse_series_trunc(500)
7.1 ms ± 62.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage:
sage: f = R([p for p in primes(1000)])
sage: %timeit f.reverse()
4.57 ms ± 77 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
sage: %timeit f.inverse_series_trunc(500)
10.9 ms ± 82.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

After Patch

sage: p = next_prime(2**1024)
sage: F.<i> = GF(p^2)
sage: R.<x> = PolynomialRing(F, implementation="NTL")
sage: 
sage: f = R([p for p in primes(10)])
sage: %timeit f.reverse()
836 ns ± 9.91 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
sage: %timeit f.inverse_series_trunc(500)
1.84 ms ± 77.1 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
sage: 
sage: f = R([p for p in primes(100)])
sage: %timeit f.reverse()
3.63 µs ± 103 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
sage: %timeit f.inverse_series_trunc(500)
6.66 ms ± 441 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

sage: f = R([p for p in primes(1000)])
sage: %timeit f.reverse()
26.8 µs ± 1.48 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sage: %timeit f.inverse_series_trunc(500)
8.75 ms ± 432 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

📝 Checklist

  • The title is concise, informative, and self-explanatory.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation accordingly.

⌛ Dependencies

The only additional import is sig_on() and sig_off() into the Polynomial_ZZ_pEX.pyx

Warning!

This is my first attempt to contribute new functions to sagemath, and it's also my first few weeks of playing with cython. I have done my best to do what is needed, but maybe I have done something incorrect. Please let me know if there's more I can do.

In particular, I know an alternative edit to the one I proposed is to modify the child Polynomial_template class instead of the Polynomial_ZZ_pEX class, but I know less about all the other parents of this class and I was concerned I may make breaking changes somewhere downstream.

Currently, this just adds the NTL methods when I know they are avaialble and they simply do what is done currently, but faster.

Add reverse and inverse_series methods to extension polynomial classes using bindings to NTL
@fchapoton
Copy link
Contributor

  • the linter is not happyabout whitespaces
  • the "raise" introduced need to be doctested

@GiacomoPope
Copy link
Contributor Author

Tried to fix all the pycodestyle problems, which meant editing more of the file than just my additions, hopefully this is OK, but please let me know.

I added doctests for the two functions I've included but noticed other functions in this file are missing doctests.

@fchapoton
Copy link
Contributor

Thanks. You are only responsible for the code that you want to add.

@fchapoton
Copy link
Contributor

cython files are not supposed to be fully compliant with pycodestyle. You should rather undo your pycodestyle changes, except the ones insise your new code.

@GiacomoPope
Copy link
Contributor Author

Thank you for your advice. I have reverted the changes against old code and tidied up my own to match (hopefully with linting remaining happy)

@fchapoton
Copy link
Contributor

Thanks. The first line of each traceback doctest result should rather be
Traceback (most recent call last):

@GiacomoPope
Copy link
Contributor Author

Before committing etc, I will check. For interactive sage I have:

ValueError                                Traceback (most recent call last)
Cell In [6], line 1
----> 1 f.reverse(degree=-Integer(1))

File ~/sage/sage/src/sage/rings/polynomial/polynomial_zz_pex.pyx:537, in sage.rings.polynomial.polynomial_zz_pex.Polynomial_ZZ_pEX.reverse()
    535 if degree is not None:
    536     if degree <= 0:
--> 537         raise ValueError("degree argument must be a non-negative integer, got %s" % (degree))
    538     try:
    539         d = degree

ValueError: degree argument must be a non-negative integer, got -1

I should have only:

Traceback (most recent call last):
...
ValueError: degree argument must be a non-negative integer, got -1

Do I need the ellipse, or can I do

Traceback (most recent call last):
ValueError: degree argument must be a non-negative integer, got -1

@fchapoton
Copy link
Contributor

you shoudl write with the ellipsis


Traceback (most recent call last):
...
ValueError: degree argument must be a non-negative integer, got -1

You can use "git grep -A2 Traceback src/sage" to compare with existing doctests of this shape.

@fchapoton
Copy link
Contributor

there is a failing doctest in

File "sage/rings/polynomial/polynomial_zz_pex.pyx", line 510, in sage.rings.polynomial.polynomial_zz_pex.Polynomial_ZZ_pEX.reverse
Failed example:
    f.reverse(degree=10)
Expected:
    2*x^10 + 3*x^9
Got:
    4*x^10 + 32*x^4 + 11

@fchapoton
Copy link
Contributor

ok, looks good. Still some little tweaks required in the doc :

In the first new method, degree should be written with two backticks before and after, not only one

In the second new method, separate the first line and the rest of the first paragraph by an empty line.

@fchapoton
Copy link
Contributor

The failing doctests are known and unrelated to the present changes

Copy link
Contributor

@fchapoton fchapoton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, good to go. Thanks

@github-actions
Copy link

Documentation preview for this PR (built with commit 1308baa; changes) is ready! 🎉

@GiacomoPope
Copy link
Contributor Author

Thanks for all your help in getting this ready. My next contribution should be much smoother as a result :)

@vbraun vbraun merged commit 48ef6df into sagemath:develop Aug 27, 2023
10 of 12 checks passed
@mkoeppe mkoeppe added this to the sage-10.2 milestone Aug 27, 2023
@GiacomoPope GiacomoPope deleted the NTL-pEX-reverse branch March 6, 2024 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants