Bill Allombert on Wed, 31 Aug 2005 14:52:44 +0200

 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,

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