Bill Allombert on Wed, 03 Aug 2005 11:11:34 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
faster output with the GMP kernel |
Hello PARI-dev, Here a patch that add a function conv_with_gmp that can be used in place of convi for faster output of large integers and reals when the GMP kernel is in use. (You have to manually tweak convi to call convi_with_gmp). You have to use 'time' for timing it since the GP timer does not take into account the output time: (using the GMP kernel:) Without the patch: 16.83s %time echo "3^400000" | ./gp -q -f>/dev/null echo "3^400000" 0,00s user 0,01s system 27% cpu 0,036 total ./gp -q -f > /dev/null 16,83s user 0,03s system 100% cpu 16,828 total With the patch: 2.25s %time echo "3^400000" | ./gp -q -f>/dev/null echo "3^400000" 0,00s user 0,01s system 26% cpu 0,037 total ./gp -q -f > /dev/null 2,25s user 0,04s system 100% cpu 2,276 total This patch is messy since it has to convert between GMP and PARI packed decimals format. We should extend the kernel to cover binary to decimal conversion (and eventually others bases) but it would be better if it was independant on the choice of a decimal packing format. The hard part is to support formatted real output (which require fiddling with decimal digits). Cheers, Bill Index: pari/src/kernel/gmp/mp.c =================================================================== --- pari.orig/src/kernel/gmp/mp.c 2005-08-02 22:56:31.000000000 +0200 +++ pari/src/kernel/gmp/mp.c 2005-08-02 23:40:38.000000000 +0200 @@ -1239,3 +1239,39 @@ if (x[i]) { setlgefint(x, i+1); return x; } x[1] = evalsigne(0) | evallgefint(2); return x; } + +/******************************************************************* + * base conversion * + *******************************************************************/ + +ulong *convi_with_gmp(GEN x, long *l) +{ + long n = nchar2nlong(2 + (long)(NLIMBS(x) * (BITS_IN_LONG / L2SL10))); + GEN str = cgetg(n+1, t_VECSMALL); + unsigned char *t = GSTR(str); + long llz = mpn_get_str(t, 10, LIMBS(icopy(x)), NLIMBS(x)); + long lz = (8+llz)/9; + ulong *z = (ulong*)new_chunk(1+lz); + long i, j; + t+=llz+9; + for(i=0;i<llz-8;i+=9) + { + ulong s; + t-=18; + s=*t++; + for (j=1; j<9;j++) + s=10*s+*t++; + *z++=s; + } + if (i<llz) + { + ulong s; + t=GSTR(str); + s=*t++; + for (j=i+1; j<llz;j++) + s=10*s+*t++; + *z++=s; + } + *l = lz; + return z; +}