Karim Belabas on Fri, 08 Jun 2018 08:30:13 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Counting real roots of integer polynomials


* Gordon Royle [2018-06-08 07:48]:
> However, I could not find a way to use polsturm effectively - the
> polsturm  in  Pari 2.9.5  needs a squarefree polynomial, and while the
> one in Pari  2.10.0 version will accept a non-square-free polynomial,
> it only returns distinct roots.
> 
> So to get the actual multiplicities, I could see no better way than
> using “factor” to first factorise the polynomial, and then deal with
> each factor separately.
> 
> This proved to be a bad idea, because for polynomials of the size that
> I am dealing with, “factor” takes about 5 times as long as just
> running “polrootsreal”. 

Yes, in pure GP you can't easily do better. Here's another way using
libpari's "squarefree factorization", which writes P in Z[X] as
\prod F[i]^E[i] with F[i] squarefree and pairwise coprime.

  install(ZX_squff,"G&");
  val(P) = 
  { my (x = variable(P), v = 0, v2);
    P /= x-1;
    v2 = valuation(P, x-2); if (v2, P /= (x-2)^v2);
    F = ZX_squff(P, E);
    for (i = 1, #F, v += E[i] * polsturm(F[i], [1,2]));
    [v, v2];
  }

  ? P = (x-1) * (2*x - 3)^3 * (x^2 - 2)^2 * (x-3)^3 * (x-2)^2;
  ? ZX_squff(P,E)
  %2 = [x - 1, x^3 - 2*x^2 - 2*x + 4, 2*x^2 - 9*x + 9]~
  ? E
  %3 = Vecsmall([1, 2, 3])
  ? val(P)
  %4 = [5, 2]

It should be faster than polrootsreal (and much faster than factor):

  ? for(i=1,10^4,polrootsreal(P))
  time = 2,903 ms.
  ? for(i=1,10^4,val(P))
  time = 1,071 ms.

Cheers,

    K.B.
--
Karim Belabas, IMB (UMR 5251)  Tel: (+33) (0)5 40 00 26 17
Universite de Bordeaux         Fax: (+33) (0)5 40 00 21 23
351, cours de la Liberation    http://www.math.u-bordeaux.fr/~kbelabas/
F-33405 Talence (France)       http://pari.math.u-bordeaux.fr/  [PARI/GP]
`