@@ -752,14 +752,11 @@ cdef class nmod_poly(flint_poly):
752752 nmod_poly_mullow(res.val, self .val, (< nmod_poly> other).val, n)
753753 return res
754754
755- def pow_trunc (self , slong e , slong n ):
755+ def pow_trunc (self , e , slong n ):
756756 r """
757757 Returns ``self`` raised to the power ``e`` modulo `x^ n`:
758758 :math:`f^ e \m od x^ n`/
759759
760- Note: For exponents larger that 2^ 63 ( which do not fit inside a slong) use the
761- method :meth:`~. pow_mod` with the explicit modulus `x^ n`.
762-
763760 >>> f = nmod_poly( [65, 44, 70, 33, 76, 104, 30 ], 163)
764761 >>> x = nmod_poly( [0, 1 ], 163)
765762 >>> f. pow_trunc( 2** 20, 30) == pow( f, 2** 20, x** 30)
@@ -772,7 +769,25 @@ cdef class nmod_poly(flint_poly):
772769 if e < 0 :
773770 raise ValueError (" Exponent must be non-negative" )
774771
775- cdef nmod_poly res = nmod_poly.__new__ (nmod_poly)
772+ cdef nmod_poly res, tmp
773+ cdef slong e_c
774+
775+ try :
776+ e_c = e
777+ except OverflowError :
778+ # Exponent does not fit slong
779+ res = nmod_poly.__new__ (nmod_poly)
780+ tmp = nmod_poly.__new__ (nmod_poly)
781+ nmod_poly_init_preinv(res.val, self .val.mod.n, self .val.mod.ninv)
782+ nmod_poly_init_preinv(tmp.val, self .val.mod.n, self .val.mod.ninv)
783+ ebytes = e.to_bytes((e.bit_length() + 15 ) // 16 * 2 , " big" )
784+ nmod_poly_pow_trunc(res.val, self .val, ebytes[0 ] * 256 + ebytes[1 ], n)
785+ for i in range (2 , len (ebytes), 2 ):
786+ nmod_poly_pow_trunc(res.val, res.val, 1 << 16 , n)
787+ nmod_poly_pow_trunc(tmp.val, self .val, ebytes[i] * 256 + ebytes[i+ 1 ], n)
788+ nmod_poly_mullow(res.val, res.val, tmp.val, n)
789+ return res
790+
776791 res = nmod_poly.__new__ (nmod_poly)
777792 nmod_poly_init_preinv(res.val, self .val.mod.n, self .val.mod.ninv)
778793 nmod_poly_pow_trunc(res.val, self .val, e, n)
0 commit comments