| Bill Allombert on Mon, 20 Sep 2004 22:58:48 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| [GMP kernel] using mpn_sqrtrem for sqrtr |
Hello PARI-dev,
Here a patch that implement sqrtr using the GMP function
mpn_sqrtrem() (when the GMP kernel is used).
In fact it provide two different implementations.
sqrtr_with_gmp() add two extra words for rounding whereas
sqrtr_with_gmp2() only add one.
Somehow sqrtr_with_gmp() seems to be faster with a slightly
more accurate rounding.
Any comment/tuning welcome.
Cheers,
Bill
Index: src/kernel/gmp/mp.c
===================================================================
RCS file: /home/cvs/pari/src/kernel/gmp/mp.c,v
retrieving revision 1.53
diff -u -r1.53 mp.c
--- src/kernel/gmp/mp.c 18 Sep 2004 22:12:47 -0000 1.53
+++ src/kernel/gmp/mp.c 20 Sep 2004 19:30:45 -0000
@@ -1187,6 +1187,68 @@
res= cgeti(l);
res[1] = evalsigne(1) | evallgefint(l);
mpn_sqrtrem(LIMBS(res),NULL,LIMBS(a),NLIMBS(a));
+ return res;
+}
+
+GEN sqrtr_with_gmp(GEN a)
+{
+ GEN res, b, c;
+ long pr=RNLIMBS(a);
+ long e=expo(a),er=e>>1;
+ if (!signe(a)) return realzero_bit(er);
+ res = cgetr(2 + pr);
+ if (e&1)
+ {
+ b = new_chunk((pr << 1)+2);
+ xmpn_mirrorcopy(b+pr+2, RLIMBS(a), pr);
+ }
+ else
+ {
+ c = ishiftr_spec(a,pr+2,-1);
+ b = new_chunk(pr);
+ /*xmpn_zero below will overwrite the code word of c, Yay!*/
+ }
+ xmpn_zero(b,pr+2);
+ c = new_chunk(pr+1);
+ mpn_sqrtrem(c,NULL,b,(pr<<1)+2);
+ if (((ulong)(c[0]))&HIGHBIT)
+ if (mpn_add_1(c+1,c+1,pr,1))
+ err(bugparier,"sqrtr_with_gmp");
+ xmpn_mirrorcopy(RLIMBS(res),c+1,pr);
+ res[1] = evalsigne(1) | evalexpo(er);
+ avma=(pari_sp)res;
+ return res;
+}
+
+GEN sqrtr_with_gmp2(GEN a)
+{
+ GEN res, b, c;
+ long pr=RNLIMBS(a);
+ long e=expo(a),er=e>>1;
+ if (!signe(a)) return realzero_bit(er);
+ res = cgetr(2 + pr);
+ if (e&1)
+ {
+ b = new_chunk((pr << 1)+1);
+ xmpn_mirrorcopy(b+pr+1, RLIMBS(a), pr);
+ }
+ else
+ {
+ c = ishiftr_spec(a,pr+2,-1);
+ b = pr<=1?c+pr-1:new_chunk(pr-1);
+ /*xmpn_zero below will overwrite the code word of c, Yay!*/
+ }
+ xmpn_zero(b,pr+1);
+ c = new_chunk(pr+1);
+ mpn_sqrtrem(c,NULL,b,(pr<<1)+1);
+ if (mpn_lshift(c,c,pr+1,BITS_IN_HALFULONG))
+ err(talker,"sqrtr_with_gmp22(%Z)",a);
+ if (((ulong)(c[0]))&HIGHBIT)
+ if (mpn_add_1(c+1,c+1,pr,1))
+ err(bugparier,"sqrtr_with_gmp");
+ xmpn_mirrorcopy(RLIMBS(res),c+1,pr);
+ res[1] = evalsigne(1) | evalexpo(er);
+ avma=(pari_sp)res;
return res;
}