@@ -252,6 +252,42 @@ cdef class nmod_poly(flint_poly):
252252 nmod_poly_reverse(res.val, self .val, length)
253253 return res
254254
255+ def truncate (self , slong n ):
256+ r """
257+ Notionally truncate the polynomial to have length ``n``. If
258+ ``n`` is larger than the length of the input, then a copy of ``self`` is
259+ returned. If ``n`` is not positive, then the zero polynomial
260+ is returned.
261+
262+ Effectively returns this polynomial :math:`\m od x^ n`.
263+
264+ >>> f = nmod_poly( [1,2,3 ], 65537)
265+ >>> f. truncate( 3) == f
266+ True
267+ >>> f. truncate( 2)
268+ 2* x + 1
269+ >>> f. truncate( 1)
270+ 1
271+ >>> f. truncate( 0)
272+ 0
273+ >>> f. truncate( -1)
274+ 0
275+
276+ """
277+ cdef nmod_poly res
278+ res = nmod_poly.__new__ (nmod_poly)
279+ nmod_poly_init_preinv(res.val, self .val.mod.n, self .val.mod.ninv)
280+
281+ length = nmod_poly_length(self .val)
282+ if n <= 0 : # return zero
283+ return res
284+ elif n > length: # do nothing
285+ nmod_poly_set(res.val, self .val)
286+ else :
287+ nmod_poly_set_trunc(res.val, self .val, n)
288+
289+ return res
290+
255291 def leading_coefficient (self ):
256292 """
257293 Return the leading coefficient of this polynomial.
@@ -521,6 +557,61 @@ cdef class nmod_poly(flint_poly):
521557 def __rmod__ (s , t ):
522558 return divmod (t, s)[1 ] # XXX
523559
560+ def left_shift (self , slong n ):
561+ """
562+ Returns ``self`` shifted left by ``n`` coefficients by inserting
563+ zero coefficients. This is equivalent to multiplying the polynomial
564+ by x^n
565+
566+ >>> f = nmod_poly([1,2,3], 99991)
567+ >>> f.left_shift(0)
568+ 3*x^2 + 2*x + 1
569+ >>> f.left_shift(1)
570+ 3*x^3 + 2*x^2 + x
571+ >>> f.left_shift(4)
572+ 3*x^6 + 2*x^5 + x^4
573+
574+ """
575+ cdef nmod_poly res
576+ res = nmod_poly.__new__ (nmod_poly)
577+ nmod_poly_init_preinv(res.val, self .val.mod.n, self .val.mod.ninv)
578+
579+ if n < 0 :
580+ raise ValueError (" Value must be shifted by a non-negative integer" )
581+ if n > 0 :
582+ nmod_poly_shift_left(res.val, self .val, n)
583+ else : # do nothing, just copy self
584+ nmod_poly_set(res.val, self .val)
585+
586+ return res
587+
588+ def right_shift (self , slong n ):
589+ """
590+ Returns ``self`` shifted right by ``n`` coefficients.
591+ This is equivalent to the floor division of the polynomial
592+ by x^n
593+
594+ >>> f = nmod_poly([1,2,3], 99991)
595+ >>> f.right_shift(0)
596+ 3*x^2 + 2*x + 1
597+ >>> f.right_shift(1)
598+ 3*x + 2
599+ >>> f.right_shift(4)
600+ 0
601+ """
602+ cdef nmod_poly res
603+ res = nmod_poly.__new__ (nmod_poly)
604+ nmod_poly_init_preinv(res.val, self .val.mod.n, self .val.mod.ninv)
605+
606+ if n < 0 :
607+ raise ValueError (" Value must be shifted by a non-negative integer" )
608+ if n > 0 :
609+ nmod_poly_shift_right(res.val, self .val, n)
610+ else : # do nothing, just copy self
611+ nmod_poly_set(res.val, self .val)
612+
613+ return res
614+
524615 def __pow__ (nmod_poly self , exp , mod = None ):
525616 cdef nmod_poly res
526617 if mod is not None :
0 commit comments