@@ -176,6 +176,24 @@ cdef class fmpq_poly(flint_poly):
176176 def is_one (self ):
177177 return < bint> fmpq_poly_is_one(self .val)
178178
179+ def leading_coefficient (self ):
180+ """
181+ Returns the leading coefficient of the polynomial.
182+
183+ >>> f = fmpq_poly([1, 2, 3])
184+ >>> f
185+ 3*x^2 + 2*x + 1
186+ >>> f.leading_coefficient()
187+ 3
188+ """
189+ cdef fmpq x
190+ cdef slong d
191+ d = fmpq_poly_degree(self .val)
192+ x = fmpq.__new__ (fmpq)
193+ if d >= 0 :
194+ fmpq_poly_get_coeff_fmpq(x.val, self .val, d)
195+ return x
196+
179197 def __call__ (self , other ):
180198 t = any_as_fmpz(other)
181199 if t is not NotImplemented :
@@ -393,28 +411,64 @@ cdef class fmpq_poly(flint_poly):
393411 fmpq_poly_xgcd(res1.val, res2.val, res3.val, self .val, (< fmpq_poly> other).val)
394412 return (res1, res2, res3)
395413
396- def factor (self ):
414+ def factor (self , *, monic = False ):
397415 """
398416 Factors *self* into irreducible polynomials. Returns (*c*, *factors*)
399417 where *c* is the leading coefficient and *factors* is a list of
400- (*poly*, *exp*) pairs with all *poly* monic .
418+ (*poly*, *exp*).
401419
402420 >>> fmpq_poly.legendre_p(5).factor()
403- (63 /8, [(x, 1), (x^4 + (-10/9 )*x^2 + 5/21 , 1)])
421+ (1 /8, [(x, 1), (63* x^4 + (-70 )*x^2 + 15 , 1)])
404422 >>> (fmpq_poly([1,-1],10) ** 5 * fmpq_poly([1,2,3],7)).factor()
423+ (-1/700000, [(3*x^2 + 2*x + 1, 1), (x + (-1), 5)])
424+
425+ Since python-flint 0.7.0 this returns primitive denominator-free
426+ factors consistent with ``fmpq_mpoly.factor()``. In previous versions
427+ of python-flint all factors were made monic. Pass ``monic=True`` to get
428+ monic factors instead.
429+
430+ >>> fmpq_poly.legendre_p(5).factor(monic=True)
431+ (63/8, [(x, 1), (x^4 + (-10/9)*x^2 + 5/21, 1)])
432+ >>> (fmpq_poly([1,-1],10) ** 5 * fmpq_poly([1,2,3],7)).factor(monic=True)
405433 (-3/700000, [(x^2 + 2/3*x + 1/3, 1), (x + (-1), 5)])
406434
407435 """
408436 c, fac = self .numer().factor()
409437 c = fmpq(c)
410- for i in range (len (fac)):
411- base, exp = fac[i]
412- lead = base[base.degree()]
413- base = fmpq_poly(base, lead)
414- c *= lead ** exp
415- fac[i] = (base, exp)
438+
439+ if monic:
440+ for i in range (len (fac)):
441+ base, exp = fac[i]
442+ lead = base[base.degree()]
443+ base = fmpq_poly(base, lead)
444+ c *= lead ** exp
445+ fac[i] = (base, exp)
446+ else :
447+ fac = [(fmpq_poly(f), m) for f, m in fac]
448+
416449 return c / self .denom(), fac
417450
451+ def factor_squarefree (self ):
452+ """
453+ Factors *self* into square-free polynomials. Returns (*c*, *factors*)
454+ where *c* is the leading coefficient and *factors* is a list of
455+ (*poly*, *exp*).
456+
457+ >>> x = fmpq_poly([0, 1])
458+ >>> p = x**2 * (x/2 - 1)**2 * (x + 1)**3
459+ >>> p
460+ 1/4*x^7 + (-1/4)*x^6 + (-5/4)*x^5 + 1/4*x^4 + 2*x^3 + x^2
461+ >>> p.factor_squarefree()
462+ (1/4, [(x^2 + (-2)*x, 2), (x + 1, 3)])
463+ >>> p.factor()
464+ (1/4, [(x, 2), (x + (-2), 2), (x + 1, 3)])
465+
466+ """
467+ c, fac = self .numer().factor_squarefree()
468+ c = fmpq(c) / self .denom()
469+ fac = [(fmpq_poly(f), m) for f, m in fac]
470+ return c, fac
471+
418472 def sqrt (self ):
419473 """
420474 Return the exact square root of this polynomial or ``None``.
0 commit comments