Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2013 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"1617#define DEBUGLEVEL DEBUGLEVEL_fflog1819/* Let [ be the following order on Fp: 0 [ p-1 [ 1 [ p-2 [ 2 .. [ p\220and [[ the lexicographic extension of [ to Fp[T]. Compute the21isomorphism (Fp[X], [[) -> (N,<) on P */2223static long24Flx_cindex(GEN P, ulong p)25{26long d = degpol(P), i;27ulong s = 0, p2 = (p-1)>>1;28for (i = 0; i <= d; ++i)29{30ulong x = P[d-i+2];31if (x<=p2) x = 2*x; else x = 1+2*(p-1-x);32s = p*s+x;33}34return s;35}3637/* Compute the polynomial immediately after t for the [[ order */3839static void40Flx_cnext(GEN t, ulong p)41{42long i;43long p2 = p>>1;44for(i=2;;i++)45if (t[i]==p2)46t[i]=0;47else48{49t[i] = t[i]<p2 ? p-1-t[i]: p-t[i];50break;51}52}5354static int55has_deg1_auto(GEN T, ulong p)56{57long i, n = degpol(T);58GEN a = polx_Flx(get_Flx_var(T));59for (i=1; i<n; i++)60{61a = Flxq_powu(a, p, T, p);62if (degpol(a)==1) return 1;63}64return 0;65}6667static void68smallirred_Flx_next(GEN a, long p)69{70do71{72long i;73for(i=2;;i++)74if (++a[i]==p) a[i]=0;75else break;76} while (!Flx_is_irred(a, p) || has_deg1_auto(a,p) );77}7879/* Avoid automorphisms of degree 1 */80static GEN81smallirred_Flx(long p, ulong n, long sv)82{83GEN a = zero_zv(n+2);84a[1] = sv; a[3] = 1; a[n+2] = 1;85smallirred_Flx_next(a, p);86return a;87}8889struct Flxq_log_rel90{91long nbrel;92GEN rel;93long nb;94long r, off, nbmax, nbexp;95ulong nbtest;96};9798static GEN99cindex_Flx(long c, long d, ulong p, long v)100{101GEN P = cgetg(d+3, t_VECSMALL);102long i;103P[1] = v;104for (i = 0; i <= d; ++i)105{106ulong x = c%p;107P[i+2] = (x&1) ? p-1-(x>>1) : x>>1;108c/=p;109}110return Flx_renormalize(P, d+3);111}112113static GEN114factorel(GEN h, ulong p)115{116GEN F = Flx_factor(h, p);117GEN F1 = gel(F, 1), F2 = gel(F, 2);118long i, l1 = lg(F1)-1;119GEN p2 = cgetg(l1+1, t_VECSMALL);120GEN e2 = cgetg(l1+1, t_VECSMALL);121for (i = 1; i <= l1; ++i)122{123p2[i] = Flx_cindex(gel(F1, i), p);124e2[i] = F2[i];125}126return mkmat2(p2, e2);127}128129static long130Flx_addifsmooth3(pari_sp *av, struct Flxq_log_rel *r, GEN h, long u, long v, long w, ulong p)131{132long off = r->off;133r->nbtest++;134if (Flx_is_smooth(h, r->r, p))135{136GEN z = factorel(h, p);137if (v<0)138z = mkmat2(vecsmall_append(gel(z,1),off+u),vecsmall_append(gel(z,2),-1));139else140z = famatsmall_reduce(mkmat2(141vecsmall_concat(gel(z,1),mkvecsmall3(off+u,off+v,off+w)),142vecsmall_concat(gel(z,2),mkvecsmall3(-1,-1,-1))));143gel(r->rel,++r->nbrel) = gerepilecopy(*av,z);144if (DEBUGLEVEL && (r->nbrel&511UL)==0)145err_printf("%ld%% ",r->nbrel*100/r->nbexp);146*av = avma;147} else set_avma(*av);148return r->nbrel==r->nb || r->nbrel==r->nbmax;149}150151static void152Flx_renormalize_inplace(GEN x, long lx)153{154long i;155for (i = lx-1; i>1; i--)156if (x[i]) break;157setlg(x, i+1);158}159160/*161Let T*X^e=C^3-R162a+b+c = 0163(C+a)*(C+b)*(C+c) = C^3+ (a*b+a*c+b*c)*C+a*b*c164= R + (a*b+a*c+b*c)*C+a*b*c165= R + (a*b-c^2)*C+a*b*c166*/167static void168Flxq_log_cubic(struct Flxq_log_rel *r, GEN C, GEN R, ulong p)169{170long l = lg(C);171GEN a = zero_zv(l); /*We allocate one extra word to catch overflow*/172GEN b = zero_zv(l);173pari_sp av = avma;174long i,j,k;175for(i=0; ; i++, Flx_cnext(a, p))176{177Flx_renormalize_inplace(a, l+1);178r->nb++;179if (Flx_addifsmooth3(&av, r, Flx_add(a, C, p), i, -1, -1, p)) return;180for(j=2; j<=l; j++) b[j] = 0;181for(j=0; j<=i; j++, Flx_cnext(b, p))182{183GEN h,c;184GEN pab,pabc,pabc2;185Flx_renormalize_inplace(b, l+1);186c = Flx_neg(Flx_add(a,b,p),p);187k = Flx_cindex(c, p);188if (k > j) continue;189pab = Flx_mul(a, b, p);190pabc = Flx_mul(pab,c,p);191pabc2= Flx_sub(pab,Flx_sqr(c,p),p);192h = Flx_add(R,Flx_add(Flx_mul(C,pabc2,p),pabc,p), p);193h = Flx_normalize(h, p);194if (Flx_addifsmooth3(&av, r, h, i, j, k, p)) return;195}196}197}198199static GEN200Flxq_log_find_rel(GEN b, long r, GEN T, ulong p, GEN *g, long *e)201{202pari_sp av = avma;203while (1)204{205GEN M;206*g = Flxq_mul(*g, b, T, p); (*e)++;207M = Flx_halfgcd(*g,T,p);208if (Flx_is_smooth(gcoeff(M,1,1), r, p))209{210GEN z = Flx_add(Flx_mul(gcoeff(M,1,1),*g,p), Flx_mul(gcoeff(M,1,2),T,p),p);211if (Flx_is_smooth(z, r, p))212{213GEN F = factorel(z, p);214GEN G = factorel(gcoeff(M,1,1), p);215GEN rel = mkmat2(vecsmall_concat(gel(F, 1),gel(G, 1)),216vecsmall_concat(gel(F, 2),zv_neg(gel(G, 2))));217gerepileall(av,2,g,&rel); return rel;218}219}220if (gc_needed(av,2))221{222if (DEBUGMEM>1) pari_warn(warnmem,"Flxq_log_find_rel");223*g = gerepilecopy(av, *g);224}225}226}227228/* Generalised Odlyzko formulae ( EUROCRYPT '84, LNCS 209, pp. 224-314, 1985. ) */229/* Return the number of monic, k smooth, degree n polynomials for k=1..r */230static GEN231smoothness_vec(ulong p, long r, long n)232{233long i,j,k;234GEN R = cgetg(r+1, t_VEC), pp = utoipos(p);235GEN V = cgetg(n+1, t_VEC);236for (j = 1; j <= n; ++j)237gel(V, j) = binomialuu(p+j-1,j);238gel(R, 1) = gel(V, n);239for (k = 2; k <= r; ++k)240{241GEN W = cgetg(n+1, t_VEC);242GEN Ik = ffnbirred(pp, k);243for (j = 1; j <= n; ++j)244{245long l = j/k;246GEN s = gen_0;247pari_sp av2 = avma;248if (l*k == j)249{250s = binomial(addiu(Ik,l-1), l);251l--;252}253for (i = 0; i <= l; ++i)254s = addii(s, mulii(gel(V, j-k*i), binomial(addis(Ik,i-1), i)));255gel(W, j) = gerepileuptoint(av2, s);256}257V = W;258gel(R, k) = gel(V, n);259}260return R;261}262263/* Solve N^2*pr/6 + N*prC = N+fb264N^2*pr/6 + N*(prC-1) -fb = 0265*/266267static GEN268smooth_cost(GEN fb, GEN pr, GEN prC)269{270GEN a = gdivgs(pr,6);271GEN b = gsubgs(prC,1);272GEN c = gneg(fb);273GEN vD = gsqrt(gsub(gsqr(b),gmul2n(gmul(a,c),2)),BIGDEFAULTPREC);274return ceil_safe(gdiv(gsub(vD,b),gmul2n(a,1)));275}276277/* Return best choice of r.278We loop over d until there is sufficiently many triples (a,b,c) (a+b+c=0)279of degree <=d with respect to the probability of smoothness of (a*b-c^2)*C280*/281282static GEN283smooth_best(long p, long n, long *pt_r, long *pt_nb)284{285pari_sp av = avma, av2;286GEN bestc = NULL, pp = utoipos(p);287long bestr = 0, bestFB = 0;288long r,d, dC = (n+2)/3;289for (r = 1; r < dC; ++r)290{291GEN fb = ffsumnbirred(pp, r);292GEN smoothC = smoothness_vec(p,r,dC);293GEN prC = gdiv(gel(smoothC,r), powuu(p,dC));294ulong rels = 0;295av2 = avma;296for(d=0; d<dC && rels < ULONG_MAX; d++)297{298GEN c;299long dt = dC+2*d;300GEN smooth = smoothness_vec(p,r,dt);301GEN pr = gdiv(gel(smooth,r), powuu(p,dt));302GEN FB = addii(fb,powuu(p,d));303GEN N = smooth_cost(subiu(FB,rels),pr,prC);304GEN Nmax = powuu(p,d+1);305if (gcmp(N,Nmax) >= 0)306{307rels = itou_or_0(addui(rels, gceil(gmul(gdivgs(sqri(Nmax),6),pr))));308if (!rels) rels = ULONG_MAX;309set_avma(av2);310continue;311}312c = gdivgs(addii(powuu(p,2*d),sqri(N)),6);313FB = addii(FB,N);314if ((!bestc || gcmp(gmul2n(c,r), gmul2n(bestc,bestr)) < 0))315{316if (DEBUGLEVEL)317err_printf("r=%ld d=%ld fb=%Ps early rels=%lu P=%.5Pe -> C=%.5Pe \n",318r, dt, FB, rels, pr, c);319bestc = c;320bestr = r;321bestFB = itos_or_0(FB);322}323break;324}325}326*pt_r=bestr;327*pt_nb=bestFB;328return bestc ? gerepileupto(av, gceil(bestc)): NULL;329}330331static GEN332check_kernel(long r, GEN M, long nbi, long nbrow, GEN T, ulong p, GEN m)333{334pari_sp av = avma;335long N = 3*upowuu(p, r);336GEN K = FpMs_leftkernel_elt(M, nbrow, m);337long i, f=0, tbs;338long lm = lgefint(m), u=1;339GEN tab, g;340GEN q = powuu(p,degpol(T));341GEN idx = diviiexact(subiu(q,1),m);342pari_timer ti;343if (DEBUGLEVEL) timer_start(&ti);344while (signe(gel(K,u))==0)345u++;346K = FpC_Fp_mul(K, Fp_inv(gel(K, u), m), m);347g = Flxq_pow(cindex_Flx(u, r, p, T[1]), idx, T, p);348tbs = maxss(1, expu(nbi/expi(m)));349tab = Flxq_pow_init(g, q, tbs, T, p);350setlg(K, N);351for (i=1; i<N; i++)352{353GEN k = gel(K,i);354pari_sp av = avma;355long t = signe(k) && Flx_equal(Flxq_pow_table(tab, k, T, p),356Flxq_pow(cindex_Flx(i,r,p,T[1]), idx, T, p));357set_avma(av);358if (!t)359gel(K,i) = cgetineg(lm);360else361f++;362}363if (DEBUGLEVEL) timer_printf(&ti,"found %ld/%ld logs", f, nbi);364if (f < maxss(3,maxss(p/2,nbi/p))) return NULL; /* Not enough logs found */365return gerepilecopy(av, K);366}367368static GEN369Flxq_log_rec(GEN W, GEN a, long r, GEN T, ulong p, GEN m)370{371long AV = 0, u = 1;372GEN g = a, b;373pari_timer ti;374while (!equali1(gel(W,u)))375u++;376b = cindex_Flx(u, r, p, T[1]);377while(1)378{379long i, l;380GEN V, F, E, Ao;381timer_start(&ti);382V = Flxq_log_find_rel(b, r, T, p, &g, &AV);383if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r);384F = gel(V,1); E = gel(V,2);385l = lg(F);386Ao = gen_0;387for(i=1; i<l; i++)388{389GEN R = gel(W,F[i]);390if (signe(R)<=0)391break;392Ao = Fp_add(Ao, mulis(R, E[i]), m);393}394if (i==l) return subis(Ao,AV);395}396}397398static int399Flxq_log_use_index_cubic(GEN m, GEN T0, ulong p)400{401pari_sp av = avma;402long n = get_Flx_degree(T0), r, nb;403GEN cost = smooth_best(p, n, &r, &nb);404GEN cost_rho = sqrti(shifti(m,2));405int use = (cost && gcmp(cost,cost_rho)<0);406set_avma(av);407return use;408}409410static GEN411Flxq_log_index_cubic(GEN a0, GEN b0, GEN m, GEN T0, ulong p)412{413long n = get_Flx_degree(T0), r, nb;414pari_sp av = avma;415struct Flxq_log_rel rel;416long nbi;417GEN W, M, S, T, a, b, Ao, Bo, e, C, R;418pari_timer ti;419GEN cost = smooth_best(p, n, &r, &nb);420GEN cost_rho = sqrti(shifti(m,2));421if (!cost || gcmp(cost,cost_rho)>=0) return gc_NULL(av);422nbi = itos(ffsumnbirred(stoi(p), r));423if (DEBUGLEVEL)424{425err_printf("Size FB=%ld, looking for %ld relations, %Ps tests needed\n", nbi, nb,cost);426timer_start(&ti);427}428T = smallirred_Flx(p,n,get_Flx_var(T0));429for(;;)430{431S = Flx_ffisom(T0,T,p);432a = Flx_Flxq_eval(a0, S, T, p);433b = Flx_Flxq_eval(b0, S, T, p);434C = Flx_shift(pol1_Flx(get_Flx_var(T)), (n+2)/3);435R = Flxq_powu(C,3,T,p);436if (DEBUGLEVEL)437timer_printf(&ti," model change: %Ps",Flx_to_ZX(T));438rel.nbmax=2*nb;439M = cgetg(rel.nbmax+1, t_VEC);440rel.rel = M;441rel.nbrel = 0; rel.r = r; rel.off = 3*upowuu(p,r);442rel.nb = nbi; rel.nbexp = nb; rel.nbtest=0;443Flxq_log_cubic(&rel, C, R, p);444setlg(M,1+rel.nbrel);445if (DEBUGLEVEL)446{447err_printf("\n");448timer_printf(&ti," %ld relations, %ld generators (%ld tests)",rel.nbrel,rel.nb,rel.nbtest);449}450W = check_kernel(r, M, nbi, rel.off + rel.nb - nbi, T, p, m);451if (W) break;452if (DEBUGLEVEL) timer_start(&ti);453smallirred_Flx_next(T,p);454}455if (DEBUGLEVEL) timer_start(&ti);456Ao = Flxq_log_rec(W, a, r, T, p, m);457if (DEBUGLEVEL) timer_printf(&ti,"smooth element");458Bo = Flxq_log_rec(W, b, r, T, p, m);459if (DEBUGLEVEL) timer_printf(&ti,"smooth generator");460e = Fp_div(Ao, Bo, m);461if (!Flx_equal(Flxq_pow(b0, e, T0, p), a0)) pari_err_BUG("Flxq_log");462return gerepileupto(av, e);463}464465INLINE GEN Flx_frob(GEN u, ulong p) { return Flx_inflate(u, p); }466467static GEN468rel_Coppersmith(long r, GEN u, GEN v, long h, GEN R, long d, ulong p)469{470GEN a, b, F, G, M;471if (degpol(Flx_gcd(u,v,p))) return NULL;472a = Flx_add(Flx_shift(u, h), v, p);473if (lgpol(a)==0 || !Flx_is_smooth(a, r, p)) return NULL;474b = Flx_add(Flx_mul(R, Flx_frob(u, p), p), Flx_shift(Flx_frob(v, p),d), p);475if (!Flx_is_smooth(b, r, p)) return NULL;476F = factorel(a, p); G = factorel(b, p);477M = mkmat2(vecsmall_concat(gel(F, 1), vecsmall_append(gel(G, 1), 2*p)),478vecsmall_concat(zv_z_mul(gel(F, 2),p), vecsmall_append(zv_neg(gel(G, 2)),d)));479return famatsmall_reduce(M);480}481482GEN483Flxq_log_Coppersmith_worker(GEN u, long i, GEN V, GEN R)484{485long r = V[1], h = V[2], d = V[3], p = V[4], dT = V[5];486pari_sp ltop = avma;487GEN v = zero_zv(dT+2);488GEN L = cgetg(2*i+1, t_VEC);489pari_sp av = avma;490long j;491long nbtest=0, rel = 1;492ulong lu = Flx_lead(u), lv;493for (j=1; j<=i; j++)494{495GEN z;496Flx_cnext(v, p);497Flx_renormalize_inplace(v, dT+2);498lv = Flx_lead(v);499set_avma(av);500if (lu != 1 && lv != 1) continue;501if (degpol(Flx_gcd(u, v, p))!=0) continue;502if (lu==1)503{504z = rel_Coppersmith(r, u, v, h, R, d, p);505nbtest++;506if (z) { gel(L, rel++) = z; av = avma; }507}508if (i==j) continue;509if (lv==1)510{511z = rel_Coppersmith(r, v, u, h, R, d, p);512nbtest++;513if (z) { gel(L, rel++) = z; av = avma; }514}515}516setlg(L,rel);517return gerepilecopy(ltop, mkvec2(stoi(nbtest), L));518}519520static GEN521Flxq_log_Coppersmith(long nbrel, long r, GEN T, ulong p)522{523pari_sp av;524long dT = degpol(T);525long h = dT/p, d = dT-(h*p);526GEN R = Flx_sub(Flx_shift(pol1_Flx(T[1]), dT), T, p);527GEN u = zero_zv(dT+2);528GEN done;529long nbtest = 0, rel = 0;530GEN M = cgetg(nbrel+1, t_VEC);531long i = 1;532GEN worker = snm_closure(is_entry("_Flxq_log_Coppersmith_worker"),533mkvec2(mkvecsmall5(r,h,d,p,dT), R));534struct pari_mt pt;535long running, pending = 0, stop=0;536if (DEBUGLEVEL) err_printf("Coppersmith (R = %ld): ",degpol(R));537mt_queue_start(&pt, worker);538av = avma;539while ((running = !stop) || pending)540{541GEN L;542long l, j;543Flx_cnext(u, p);544Flx_renormalize_inplace(u, dT+2);545mt_queue_submit(&pt, 0, running ? mkvec2(u, stoi(i)): NULL);546done = mt_queue_get(&pt, NULL, &pending);547if (!done) continue;548L = gel(done, 2); nbtest += itos(gel(done,1));549l = lg(L);550if (l > 1)551{552for (j=1; j<l; j++)553{554if (rel>nbrel) break;555gel(M,++rel) = gel(L,j);556if (DEBUGLEVEL && (rel&511UL)==0)557err_printf("%ld%%[%ld] ",rel*100/nbrel,i);558}559av = avma;560}561else set_avma(av);562if (rel>nbrel) stop = 1;563i++;564}565mt_queue_end(&pt);566if (DEBUGLEVEL) err_printf(": %ld tests\n", nbtest);567return M;568}569570static GEN Flxq_log_Coppersmith_d(GEN W, GEN g, long r, GEN T, ulong p, GEN mo);571572static GEN573Flxq_log_from_rel(GEN W, GEN rel, long r, GEN T, ulong p, GEN m)574{575pari_sp av = avma;576GEN F = gel(rel,1), E = gel(rel,2), o = gen_0;577long i, l = lg(F);578for(i=1; i<l; i++)579{580GEN R = gel(W, F[i]);581if (signe(R)==0) /* Already failed */582return NULL;583else if (signe(R)<0) /* Not yet tested */584{585setsigne(gel(W,F[i]),0);586R = Flxq_log_Coppersmith_d(W, cindex_Flx(F[i],r,p,T[1]), r, T, p, m);587if (!R) return NULL;588}589o = Fp_add(o, mulis(R, E[i]), m);590}591return gerepileuptoint(av, o);592}593594static GEN595Flxq_log_Coppersmith_d(GEN W, GEN g, long r, GEN T, ulong p, GEN mo)596{597pari_sp av = avma, av2;598long dg = degpol(g), k = r-1, m = maxss((dg-k)/2,0);599long i, j, l = dg-m, N;600GEN v = cgetg(k+m+1,t_MAT);601long dT = degpol(T);602long h = dT/p, d = dT-h*p;603GEN R = Flx_rem(Flx_shift(pol1_Flx(T[1]), dT), T, p);604GEN z = Flx_rem(Flx_shift(pol1_Flx(T[1]), h), g, p);605for(i=1; i<=k+m; i++)606{607gel(v,i) = Flx_to_Flv(Flx_shift(z,-l),m);608z = Flx_rem(Flx_shift(z,1),g,p);609}610v = Flm_ker(v,p);611for(i=1; i<=k; i++)612gel(v,i) = Flv_to_Flx(gel(v,i),T[1]);613N = upowuu(p,k);614av2 = avma;615for (i=1; i<N; i++)616{617GEN p0,q,qh,a,b;618ulong el = i;619set_avma(av2);620q = pol0_Flx(T[1]);621for (j=1; j<=k; j++)622{623ulong r = el % p;624el /= p;625if (r) q = Flx_add(q, Flx_Fl_mul(gel(v,j), r, p), p);626}627qh = Flx_shift(q, h);628p0 = Flx_rem(qh, g, p);629b = Flx_sub(Flx_mul(R, Flx_frob(q, p), p), Flx_shift(Flx_frob(p0, p), d), p);630if (lgpol(b)==0 || !Flx_is_smooth(b, r, p)) continue;631a = Flx_div(Flx_sub(qh, p0, p), g, p);632if (degpol(Flx_gcd(a, q, p)) && degpol(Flx_gcd(a, p0 ,p)))633continue;634if (!(lgpol(a)==0 || !Flx_is_smooth(a, r, p)))635{636GEN F = factorel(b, p);637GEN G = factorel(a, p);638GEN FG = vecsmall_concat(vecsmall_append(gel(F, 1), 2*p), gel(G, 1));639GEN E = vecsmall_concat(vecsmall_append(gel(F, 2), -d),640zv_z_mul(gel(G, 2),-p));641GEN R = famatsmall_reduce(mkmat2(FG, E));642GEN l = Flxq_log_from_rel(W, R, r, T, p, mo);643if (!l) continue;644l = Fp_divu(l,p,mo);645if (dg <= r)646{647long idx = Flx_cindex(g, p);648affii(l, gel(W, idx));649if (DEBUGLEVEL>1) err_printf("Found %lu\n", idx);650}651return gerepileuptoint(av, l);652}653}654set_avma(av);655return NULL;656}657658static GEN659Flxq_log_Coppersmith_rec(GEN W, long r2, GEN a, long r, GEN T, ulong p, GEN m)660{661GEN b = polx_Flx(T[1]);662long AV = 0;663GEN g = a, bad = pol0_Flx(T[1]);664pari_timer ti;665while(1)666{667long i, l;668GEN V, F, E, Ao;669timer_start(&ti);670V = Flxq_log_find_rel(b, r2, T, p, &g, &AV);671if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r2);672F = gel(V,1); E = gel(V,2);673l = lg(F);674Ao = gen_0;675for(i=1; i<l; i++)676{677GEN Fi = cindex_Flx(F[i], r2, p, T[1]);678GEN R;679if (degpol(Fi) <= r)680{681if (signe(gel(W,F[i]))==0)682break;683else if (signe(gel(W,F[i]))<0)684{685setsigne(gel(W,F[i]),0);686R = Flxq_log_Coppersmith_d(W,Fi,r,T,p,m);687} else688R = gel(W,F[i]);689}690else691{692if (Flx_equal(Fi,bad)) break;693R = Flxq_log_Coppersmith_d(W,Fi,r,T,p,m);694if (!R) bad = Fi;695}696if (!R) break;697Ao = Fp_add(Ao, mulis(R, E[i]), m);698}699if (i==l) return subis(Ao,AV);700}701}702703static GEN704Flxq_log_index_Coppersmith(GEN a0, GEN b0, GEN m, GEN T0, ulong p)705{706pari_sp av = avma;707GEN M, S, a, b, Ao=NULL, Bo=NULL, W, e;708pari_timer ti;709double rf = p ==3 ? 1.2 : .9;710long n = degpol(T0), r = (long) sqrt(n*rf);711GEN T;712long r2 = 3*r/2;713long nbi = itos(ffsumnbirred(utoipos(p), r)), nbrel=nbi*5/4;714if (DEBUGLEVEL)715{716err_printf("Coppersmith: Parameters r=%ld r2=%ld\n", r,r2);717err_printf("Coppersmith: Size FB=%ld rel. needed=%ld\n", nbi, nbrel);718timer_start(&ti);719}720T = smallirred_Flx(p,n,get_Flx_var(T0));721S = Flx_ffisom(T0,T,p);722a = Flx_Flxq_eval(a0, S, T, p);723b = Flx_Flxq_eval(b0, S, T, p);724if (DEBUGLEVEL) timer_printf(&ti,"model change");725M = Flxq_log_Coppersmith(nbrel, r, T, p);726if (DEBUGLEVEL) timer_printf(&ti,"relations");727W = check_kernel(r, M, nbi, 3*upowuu(p,r), T, p, m);728timer_start(&ti);729Ao = Flxq_log_Coppersmith_rec(W, r2, a, r, T, p, m);730if (DEBUGLEVEL) timer_printf(&ti,"smooth element");731Bo = Flxq_log_Coppersmith_rec(W, r2, b, r, T, p, m);732if (DEBUGLEVEL) timer_printf(&ti,"smooth generator");733e = Fp_div(Ao, Bo, m);734if (!Flx_equal(Flxq_pow(b0,e,T0,p),a0)) pari_err_BUG("Flxq_log");735return gerepileupto(av, e);736}737738GEN739Flxq_log_index(GEN a, GEN b, GEN m, GEN T, ulong p)740{741long d = get_Flx_degree(T);742if (p==3 || (p==5 && d>41))743return Flxq_log_index_Coppersmith(a, b, m, T, p);744else return Flxq_log_index_cubic(a, b, m, T, p);745}746747int748Flxq_log_use_index(GEN m, GEN T, ulong p)749{750long d = get_Flx_degree(T);751if (p==3 || (p==5 && d>41))752return 1;753else if (d<=4 || d==6)754return 0;755else756return Flxq_log_use_index_cubic(m, T, p);757}758759760