| 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/