Skip to content

Conversation

remyoudompheng
Copy link
Contributor

These methods already exist on fmpz_mod_poly and fq_default_poly.

Additionally, the existing docstrings and doctests are updated to assume the upper bound of slong is 2^63. Let me know if this is not fine (current all configured Github runners are 64-bit platforms). I am unsure whether 64-bit specific tests are fine.

@oscarbenjamin
Copy link
Collaborator

I am unsure whether 64-bit specific tests are fine.

We want the tests to still pass on 32 bit (gh-317).

all configured Github runners are 64-bit platforms

Since gh-318 there is the pyodide job which runs on wasm32 although it would still be good to have a proper i686 job to test things like this.

@oscarbenjamin
Copy link
Collaborator

Looks like arb_poly and acb_poly have mullow but not pow_trunc.

If at least all the exact poly types have these methods now then they can be added to this typing protocol:

class epoly_p(poly_p[_Tscalar], Protocol):
"""FLINT exact univariate polynomial Protocol."""
def sqrt(self) -> Self: ...
def gcd(self, other: Self | _Tscalar, /) -> Self: ...
def factor(self) -> tuple[_Tscalar, list[tuple[Self, int]]]: ...
def factor_squarefree(self) -> tuple[_Tscalar, list[tuple[Self, int]]]: ...
def deflation(self) -> tuple[Self, int]: ...

:math:`f^e \mod x^n`/

Note: For exponents larger that 2^63 (which do not fit inside a slong) use the
method :meth:`~.pow_mod` with the explicit modulus `x^n`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe the code here could test for overflow and call pow_mod.

@remyoudompheng
Copy link
Contributor Author

New proposal :

  • extend pow_trunc to big integers (I believe it feels better for a Python API to not depend on hardware architecture)
  • remove note from docstrings
  • add missing unit tests for pow_trunc
  • add methods to epoly_p

The proposal is to not use modular pow (which is not defined for fmpz/fmpq) and implement "manually" large exponents using a loop (it works even for fmpz/fmpq and it is 2x-3x faster than powmod). I hope it is not overkill (I'm not sure there is a lot of use for large powers of fmpz_poly, maybe for combinatorics?)

@oscarbenjamin
Copy link
Collaborator

I hope it is not overkill (I'm not sure there is a lot of use for large powers of fmpz_poly, maybe for combinatorics?)

I'm not sure either but it is good to have an implementation that does not have an arbitrary upper limit on the exponent as long as higher powers are computable.

It took me a while to parse the code used for this but it looks good:

def pow(x, e):
    ebytes = e.to_bytes((e.bit_length() + 15) // 16 * 2, "nig")
    p = x ** (ebytes[0] * 256 + ebytes[1])
    for i in range(2, len(ebytes), 2):
        p = p ** (1 << 16)
        p = p * x ** (ebytes[i] * 256 + ebytes[i + 1])
    return p

I guess that is going to reduce the overhead a little compared to working through e one bit at a time (which is ultimately what e.g. fmpz_poly_pow_trunc ends up doing after a bit of preprocessing).

The series types can also be used for this but they also have the overflow problem so I guess the same approach could be used there:

In [1]: import flint

In [2]: f = flint.fmpz_series([1, 2, 3], prec=3)

In [3]: f
Out[3]: 1 + 2*x + 3*x^2 + O(x^3)

In [4]: f ** (5 ** 25)
Out[4]: 1 + 596046447753906250*x + 177635683940025046765804290771484375*x^2 + O(x^3)

In [5]: f ** (5 ** 30)
---------------------------------------------------------------------------
OverflowError

@oscarbenjamin
Copy link
Collaborator

Looks good to me. Thanks

@oscarbenjamin oscarbenjamin merged commit 0a59f53 into flintlib:main Sep 7, 2025
81 checks passed
@remyoudompheng remyoudompheng deleted the mullow branch September 7, 2025 20:35
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.

2 participants