Bill Allombert on Tue, 21 Sep 2004 14:29:24 +0200


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

Re: [GMP kernel] using mpn_sqrtrem for sqrtr


On Mon, Sep 20, 2004 at 10:52:02PM +0200, Bill Allombert wrote:
> Hello PARI-dev,
> 
> Here a patch that implement sqrtr using the GMP function
> mpn_sqrtrem() (when the GMP kernel is used).

Here a patch for the native kernel that implement the same
algorithm as sqrtr_with_gmp (in the function sqrtr_without_gmp)
With that patch sqrtr_with_gmp and sqrtr_without_gmp should
produce the exact same result.

The problem is that sqrtr_without_gmp is 2.5 times slower than
sqrtr_abs(), which probably means that isqrti is 2.5 times
slower than sqrtr_abs() with the native kernel, which is a bug.

Cheers,
Bill.

Index: src/kernel/none/mp.c
===================================================================
RCS file: /home/cvs/pari/src/kernel/none/mp.c,v
retrieving revision 1.138
diff -u -r1.138 mp.c
--- src/kernel/none/mp.c	14 Sep 2004 20:41:22 -0000	1.138
+++ src/kernel/none/mp.c	21 Sep 2004 10:42:37 -0000
@@ -1505,6 +1505,28 @@
 
 /* Return trunc(sqrt(a))). a must be an non-negative integer*/
 GEN isqrti(GEN a) {return racine_r(a,lgefint(a));}
+
+GEN sqrtr_without_gmp(GEN a)
+{
+  GEN res, b, c;
+  long pr=lg(a)-2;
+  long e=expo(a),er=e>>1;
+  int i;
+  if (!signe(a)) return realzero_bit(er);
+  res = cgetr(2 + pr);
+  b = new_chunk(pr + 2);
+  for (i=0; i<pr+2; i++) b[i]=0;
+  c = ishiftr_spec(a,pr+2,(e&1)?0:-1);
+  setsigne(c,1);
+  c = racine_r(c,(pr<<1)+4);
+  i=pr+2;
+  if (c[i]<0)
+    while( !++c[--i]);
+  for(i=2;i<pr+2;i++) res[i]=c[i];
+  res[1] = evalsigne(1) | evalexpo(er);
+  avma=(pari_sp)res;
+  return res;
+}
 
 /* Normalize a non-negative integer.  */
 GEN