void DUPFFformal_deriv2(DUPFF fprime, const DUPFF f) /* fprime and f may be identical */ { int df, dans, j, p; p = CurrentFF.prime; df = DUPFFdeg(f); /* find degree of the answer */ for (dans=df; dans >= 1; dans--) if (f->coeffs[dans] != 0 && (dans%p != 0)) break; dans--; if (dans < 0) { fprime->deg = -1; return; } if (fprime->maxdeg < dans) { JERROR(JERROR_DEG_TOO_LOW); return; } fprime->deg = dans; for (j = 1; j <= dans+1; j++) fprime->coeffs[j-1] = FFmul(j%p, f->coeffs[j]); return; }
DUPFF DUPFFexgcd(DUPFF *fcofac, DUPFF *gcofac, const DUPFF f, const DUPFF g) { DUPFF u, v, uf, ug, vf, vg; FFelem q, lcu, lcvrecip, p; int df, dg, du, dv; if (DUPFFdeg(f) < DUPFFdeg(g)) return DUPFFexgcd(gcofac, fcofac, g, f); if (DUPFFdeg(f) != 2 || DUPFFdeg(g) != 1) abort(); if (f->coeffs[0] == 0) return f; p = 2; df = DUPFFdeg(f); if (df < 0) df = 0; /* both inputs are zero */ dg = DUPFFdeg(g); if (dg < 0) dg = 0; /* one input is zero */ u = DUPFFcopy(f); v = DUPFFcopy(g); uf = DUPFFnew(dg); uf->coeffs[0] = 1; uf->deg = 0; ug = DUPFFnew(df); vf = DUPFFnew(dg); vg = DUPFFnew(df); vg->coeffs[0] = 1; vg->deg = 0; while (DUPFFdeg(v) > 0) { dv = DUPFFdeg(v); lcvrecip = FFmul(1, v->coeffs[dv]); while (DUPFFdeg(u) >= dv) { du = DUPFFdeg(u); lcu = u->coeffs[du]; q = FFmul(lcu, lcvrecip); DUPFFshift_add(u, v, du-dv, p-q); DUPFFshift_add(uf, vf, du-dv, p-q); DUPFFshift_add(ug, vg, du-dv, p-q); } DUPFFswap(u, v); DUPFFswap(uf, vf); DUPFFswap(ug, vg); } if (DUPFFdeg(v) == 0) { DUPFFswap(u, v); DUPFFswap(uf, vf); DUPFFswap(ug, vg); } DUPFFfree(vf); DUPFFfree(vg); DUPFFfree(v); *fcofac = uf; *gcofac = ug; return u; }
DMPFF DMPFFgcd_aux(DMPFF f, DMPFF g) { int var, i, p, nvars; int *df, *dg, *dans, *substitution; FF Fp; DUPFF fx, gx; DMPFFdegs(df, f); nvars = 0; for (var = 0; var < NVARS; var++) if (df[var]) nvars++; if (nvars == 0) return one; if (nvars == 1) return DMPFFunivariate_gcd(f, g, var); /* We have at least two variables . */ DMPFFdegs(dg, g); /* Predict degrees of the result in each variable. We may guess too high. */ /* For each var map to univariate by random substitution and compute gcd */ p = CurrentFF.prime; for (var = 0; var < NVARS; var++) { if (df[var] == 0) continue; do { for (i=0; i < NVARS; i++) substitution[i] = rand()%p; /* only need values for SOME variables */ fx = DMPFF_to_DUPFF(f, var, substitution); gx = DMPFF_to_DUPFF(g, var, substitution); } while (DUPFFdeg(fx) < df[var] || DUPFFdeg(gx) < dg[var]); DUPFFgcd2(fx, gx); dans[var] = DUPFFdeg(fx); DUPFFdtor(fx); DUPFFdtor(gx); if (dans[var] > 0) continue; /* if var does not appear in the answer, remove it from f and g */ nvars--; if (nvars == 0) return one; f = DMPFFcontent(f, var); g = DMPFFcontent(g, var); if (nvars == 1) return DMPFFunivariate_gcd(f, g, var); } /* At this point the predicted degrees are probably correct. */ printf("Predicted degrees are: ");for(i=0;i<NVARS;i++)printf("%3d ",dans[vars]);printf("\n"); /* Pick the 'main' variable. */ for (var=0; dans[var] == 0; var++); fc = DMPFFcontent(f, var); gc = DMPFFcontent(g, var); f = DMPFFdivexact(f, fc); g = DMPFFdivexact(g, gc); hc = DMPFFgcd(fc, gc); fx = DMPFF_to_DUPFF(f, var, substitution); gx = DMPFF_to_DUPFF(g, var, substitution); hx = DUPFFgcd2(fx, gx); fcofac = DUPFFdiv(fx, hx); gcofac = DUPFFdiv(gx, hx); tmp = DUPFFgcd2(fcofac, hx); if (DUPFFdeg(tmp) == 0) { DMPFFlift(f, hx, fcofac, substitution, dans); } tmp = DUPFFgcd2(gcofac, hx); if (DUPFFdeg(tmp) == 0) { DMPFFlift(g, hx, gcofac, substitution, dans); } for (i=1; i < p; i++) { DUPFFadd3(fcofac, fcofac, gcofac); DUPFFadd3(fx, fx, gx); DMPFFadd3(f, f, g); tmp = DUPFFgcd(fcofac, hx); if (DUPFFdeg(tmp) == 0) break } DMPFFlift(f, hx, fcofac, substitution, dans); }