Bill Allombert on Wed, 31 Aug 2005 14:52:44 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
patch for a new divide_conquer_assoc function |
Hello PARI-dev, Here a patch that add a new function divide_conquer_assoc: divide_conquer_assoc(GEN x, GEN (*mul)(void*,GEN,GEN), void *data); This function is essentially the same than divide_conquer_prod but for the extra data parameter. This avoid the need of static variables, which are not thread-safe. A better name for this function would be much welcome. I elected to keep divide_conquer_prod() interface unchanged to preserve backward compatibility and because there are several direct use of it in libpari with arguments like gmul or mulii, though maybe they could be replaced by a dedicated function ZV_prod or RgV_prod. Cheers, Bill. Index: pari/src/basemath/Flx.c =================================================================== --- pari.orig/src/basemath/Flx.c 2005-08-30 16:18:31.000000000 +0200 +++ pari/src/basemath/Flx.c 2005-08-30 23:23:21.000000000 +0200 @@ -1211,11 +1211,10 @@ return p1; } -static ulong global_pp; static GEN -_Flx_mul(GEN a, GEN b) +_Flx_mul(void *p, GEN a, GEN b) { - return Flx_mul(a,b, global_pp); + return Flx_mul(a,b, (ulong)p); } /* compute prod (x - a[i]) */ @@ -1225,7 +1224,7 @@ long i,k,lx = lg(a); GEN p1,p2; if (lx == 1) return Fl_to_Flx(1,vs); - p1 = cgetg(lx, t_VEC); global_pp = p; + p1 = cgetg(lx, t_VEC); for (k=1,i=1; i<lx-1; i+=2) { p2 = cgetg(5,t_VECSMALL); gel(p1,k++) = p2; @@ -1243,7 +1242,7 @@ p2[2] = a[i]?p - a[i]:0; p2[3] = 1; } - setlg(p1, k); return divide_conquer_prod(p1, _Flx_mul); + setlg(p1, k); return divide_conquer_assoc(p1, _Flx_mul,(void *)p); } GEN @@ -2125,15 +2124,18 @@ return gerepileupto(av0, y); } -static GEN Tmodulo; -static ulong modulo; -static GEN _FlxqX_mul(GEN a,GEN b){return FlxqX_mul(a,b,Tmodulo,modulo);} +struct _FlxqX {ulong p; GEN T;}; +static GEN _FlxqX_mul(void *data,GEN a,GEN b) +{ + struct _FlxqX *d=(struct _FlxqX*)data; + return FlxqX_mul(a,b,d->T,d->p); +} GEN FlxqXV_prod(GEN V, GEN T, ulong p) { - modulo = p; Tmodulo = T; - return divide_conquer_prod(V, &_FlxqX_mul); + struct _FlxqX d; d.p=p; d.T=T; + return divide_conquer_assoc(V, &_FlxqX_mul, (void*)&d); } GEN Index: pari/src/basemath/polarit2.c =================================================================== --- pari.orig/src/basemath/polarit2.c 2005-08-30 16:18:31.000000000 +0200 +++ pari/src/basemath/polarit2.c 2005-08-30 23:23:21.000000000 +0200 @@ -2321,7 +2321,7 @@ } GEN -divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN)) +divide_conquer_assoc(GEN x, GEN (*mul)(void *,GEN,GEN),void *data) { pari_sp ltop, lim; long i,k,lx = lg(x); @@ -2336,7 +2336,7 @@ fprintferr("prod: remaining objects %ld\n",k-1); lx = k; k = 1; for (i=1; i<lx-1; i+=2) - gel(x,k++) = mul(gel(x,i),gel(x,i+1)); + gel(x,k++) = mul(data,gel(x,i),gel(x,i+1)); if (i < lx) x[k++] = x[i]; if (low_stack(lim,stack_lim(av,1))) gerepilecoeffs(ltop,x+1,k-1); @@ -2344,30 +2344,41 @@ return gel(x,1); } -static GEN static_OBJ; /* nf or ell */ +static GEN +_domul(void *data, GEN x, GEN y) +{ + GEN (*mul)(GEN,GEN)=(GEN (*)(GEN,GEN)) data; + return mul(x,y); +} + +GEN +divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN)) +{ + return divide_conquer_assoc(x, _domul, (void *)mul); +} static GEN -idmulred(GEN x, GEN y) { return idealmulred(static_OBJ, x, y, 0); } +idmulred(void *nf, GEN x, GEN y) { return idealmulred((GEN) nf, x, y, 0); } static GEN -idpowred(GEN x, GEN n) { return idealpowred(static_OBJ, x, n, 0); } +idpowred(void *nf, GEN x, GEN n) { return idealpowred((GEN) nf, x, n, 0); } static GEN -idmul(GEN x, GEN y) { return idealmul(static_OBJ, x, y); } +idmul(void *nf, GEN x, GEN y) { return idealmul((GEN) nf, x, y); } static GEN -idpow(GEN x, GEN n) { return idealpow(static_OBJ, x, n); } +idpow(void *nf, GEN x, GEN n) { return idealpow((GEN) nf, x, n); } static GEN -eltmul(GEN x, GEN y) { return element_mul(static_OBJ, x, y); } +eltmul(void *nf, GEN x, GEN y) { return element_mul((GEN) nf, x, y); } static GEN -eltpow(GEN x, GEN n) { return element_pow(static_OBJ, x, n); } +eltpow(void *nf, GEN x, GEN n) { return element_pow((GEN) nf, x, n); } #if 0 static GEN -ellmul(GEN x, GEN y) { return powell(static_OBJ, x, y); } +ellmul(void *ell, GEN x, GEN y) { return addell((GEN) ell, x, y); } static GEN -ellpow(GEN x, GEN n) { return idealpow(static_OBJ, x, n); } +ellpow(void *GEN x, GEN n) { return powell((GEN) ell, x, n); } #endif GEN -_factorback(GEN fa, GEN e, GEN (*_mul)(GEN,GEN), GEN (*_pow)(GEN,GEN)) +_factorback(GEN fa, GEN e, GEN (*_mul)(void*,GEN,GEN), GEN (*_pow)(void*,GEN,GEN), void *data) { pari_sp av = avma; long k,l,lx,t = typ(fa); @@ -2383,7 +2394,7 @@ if (l != 3) err(talker,"not a factorisation in factorback"); } else { if (!is_vec_t(t)) err(talker,"not a factorisation in factorback"); - return gerepileupto(av, divide_conquer_prod(fa, _mul)); + return gerepileupto(av, divide_conquer_assoc(fa, _mul,data)); } p = gel(fa,1); e = gel(fa,2); @@ -2402,11 +2413,14 @@ x = cgetg(lx,t_VEC); for (l=1,k=1; k<lx; k++) if (signe(e[k])) - gel(x,l++) = _pow(gel(p,k),gel(e,k)); + gel(x,l++) = _pow(data,gel(p,k),gel(e,k)); setlg(x,l); - return gerepileupto(av, divide_conquer_prod(x, _mul)); + return gerepileupto(av, divide_conquer_assoc(x, _mul,data)); } +static GEN _agmul(void *a, GEN x, GEN y) { return gmul(x,y);} +static GEN _apowgi(void *a, GEN x, GEN y) { return powgi(x,y);} + GEN factorback_i(GEN fa, GEN e, GEN OBJ, int red) { @@ -2415,11 +2429,10 @@ if (e) { OBJ = _checknf(e); if (OBJ) e = NULL; } - if (!OBJ) return _factorback(fa, e, &gmul, &powgi); + if (!OBJ) return _factorback(fa, e, &_agmul, &_apowgi, NULL); } - static_OBJ = OBJ; - if (red) return _factorback(fa, e, &idmulred, &idpowred); - else return _factorback(fa, e, &idmul, &idpow); + if (red) return _factorback(fa, e, &idmulred, &idpowred, OBJ); + else return _factorback(fa, e, &idmul, &idpow, OBJ); } GEN @@ -2428,8 +2441,8 @@ if (!nf && e && lg(e) > 1 && typ(e[1]) != t_INT) { nf = e; e = NULL; } if (!nf) err(talker, "missing nf in factorbackelt"); - static_OBJ = checknf(nf); - return _factorback(fa, e, &eltmul, &eltpow); + nf = checknf(nf); + return _factorback(fa, e, &eltmul, &eltpow, nf); } GEN Index: pari/src/basemath/polarit3.c =================================================================== --- pari.orig/src/basemath/polarit3.c 2005-08-30 16:18:31.000000000 +0200 +++ pari/src/basemath/polarit3.c 2005-08-30 23:23:21.000000000 +0200 @@ -669,13 +669,11 @@ return gerepileupto(av, y); } -static GEN modulo; -static GEN _FpX_mul(GEN a,GEN b){return FpX_mul(a,b,modulo);} +static GEN _FpX_mul(void *p,GEN a,GEN b){return FpX_mul(a,b,(GEN)p);} GEN FpXV_prod(GEN V, GEN p) { - modulo = p; - return divide_conquer_prod(V, &_FpX_mul); + return divide_conquer_assoc(V, &_FpX_mul,(void *)p); } GEN @@ -1121,8 +1119,12 @@ return T? FpXQX_divrem(x,y,T,p,z): FpX_divrem(x,y,p,z); } -static GEN Tmodulo; -static GEN _FpXQX_mul(GEN a,GEN b){return FpXQX_mul(a,b,Tmodulo,modulo);} +struct _FpXQX { GEN T,p; }; +static GEN _FpXQX_mul(void *data, GEN a,GEN b) +{ + struct _FpXQX *d=(struct _FpXQX*)data; + return FpXQX_mul(a,b,d->T,d->p); +} GEN FpXQXV_prod(GEN V, GEN T, GEN p) { @@ -1135,8 +1137,13 @@ Tl = FlxqXV_prod(Vl, Tl, pp); return gerepileupto(av, FlxX_to_ZXX(Tl)); } - modulo = p; Tmodulo = T; - return divide_conquer_prod(V, &_FpXQX_mul); + else + { + struct _FpXQX d; + d.p=p; + d.T=T; + return divide_conquer_assoc(V, &_FpXQX_mul,(void*)&d); + } } GEN Index: pari/src/headers/paridecl.h =================================================================== --- pari.orig/src/headers/paridecl.h 2005-08-30 19:52:03.000000000 +0200 +++ pari/src/headers/paridecl.h 2005-08-30 23:23:21.000000000 +0200 @@ -1491,6 +1491,7 @@ GEN deg1_from_roots(GEN L, long v); GEN discsr(GEN x); GEN divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN)); +GEN divide_conquer_assoc(GEN x, GEN (*mul)(void*,GEN,GEN), void *data); GEN factor(GEN x); GEN factor0(GEN x,long flag); GEN factorback(GEN fa,GEN nf);