Karim BELABAS on Sun, 26 Aug 2001 19:46:10 +0200 (MEST)


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

Re: polrootspadic bug resolved


On Wed, 18 Jul 2001, Mark Dickinson wrote:
> The problem with polrootspadic that I reported earlier this week can be
> traced all the way back to a bug in resmod2n() in src/kernel/none/mp.c;
> this function computes x % 2^n for an integer x, but it turns out that it
> can sometimes fail to normalise the result properly (that is, the most
> significant word of the integer returned can sometimes be zero). The
> following patch seems to fix this for me; I hope it works for others as
> well  :)

Mark, I reworked your patch a little bit (in fact I had lost your patch and my net
access, so I had to start over from scratch :-) : I let l run in [0,BIL[ instead of
[1,BIL], used pointer arithmetic all the way through, and tried to help the
optimizer making the good choices.

I didn't run into discrepancies in any of the test suites or your original
examples; can you check that I didn't blunder ?

  Karim.

Index: src/kernel/none/mp.c
===================================================================
RCS file: /home/megrez/cvsroot/pari/src/kernel/none/mp.c,v
retrieving revision 1.44
diff -c -r1.44 mp.c
*** src/kernel/none/mp.c	2001/07/02 20:54:10	1.44
--- src/kernel/none/mp.c	2001/08/26 17:21:28
***************
*** 2134,2163 ****
    return gerepileuptoint(av, r); /* = resii(x, y) */
  }

! /* x % (2^n) */
  GEN
  resmod2n(GEN x, long n)
  {
!   long l,k,lx,ly;
!   GEN y, z, t;

!   if (!signe(x)) return gzero;

!   l = n % BITS_IN_LONG;
!   k = n / BITS_IN_LONG;
!   ly = l? k+3: k+2;
    lx = lgefint(x);
!   if (lx < ly) return icopy(x);
!   z = cgeti(ly);
!   z[1] = evalsigne(1)|evallgefint(ly);
!   y = z + ly;
!   t = x + lx;
!   for ( ;k; k--) *--y = *--t;
!   if (l) *--y = *--t & ((1<<l) - 1);
! #if 0
!   if (!egalii(z, resii(x, shifti(gun,n))))
!     err(talker,"bug in resmod2n: n = %ld, x = %Z\n",n,x);
! #endif
    return z;
  }

--- 2134,2170 ----
    return gerepileuptoint(av, r); /* = resii(x, y) */
  }

! /* x % (2^n), assuming x, n >= 0 */
  GEN
  resmod2n(GEN x, long n)
  {
!   long hi,l,k,lx,ly;
!   GEN z, xd, zd;

!   if (!signe(x) || !n) return gzero;

!   l = n & (BITS_IN_LONG-1);    /* n % BITS_IN_LONG */
!   k = n >> TWOPOTBITS_IN_LONG; /* n / BITS_IN_LONG */
    lx = lgefint(x);
!   if (lx < k+3) return icopy(x);
!
!   xd = x + (lx-k-1);
!   /* x = |_|...|#|1|...|k| : copy the last l bits of # and the last k words
!    *            ^--- initial xd  */
!   hi = *xd & ((1<<l) - 1); /* last l bits of # = top bits of result */
!   if (!hi)
!   { /* strip leading zeroes from result */
!     xd++; while (k && !*xd) { k--; xd++; }
!     if (!k) return gzero;
!     ly = k+2;
!   }
!   else
!     ly = k+3;
!
!   zd = z = cgeti(ly);
!   *++zd = evalsigne(1) | evallgefint(ly);
!   if (hi) *++zd = hi;
!   for ( ;k; k--) *++zd = *++xd;
    return z;
  }


-- 
Karim Belabas                    email: Karim.Belabas@math.u-psud.fr
Dep. de Mathematiques, Bat. 425
Universite Paris-Sud             Tel: (00 33) 1 69 15 57 48
F-91405 Orsay (France)           Fax: (00 33) 1 69 15 60 19
--
PARI/GP Home Page: http://www.parigp-home.de/