Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000 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"1617GEN18iferrpari(GEN a, GEN b, GEN c)19{20GEN res;21struct pari_evalstate state;22evalstate_save(&state);23pari_CATCH(CATCH_ALL)24{25GEN E;26if (!b&&!c) return gnil;27E = evalstate_restore_err(&state);28if (c)29{30push_lex(E,c);31res = closure_evalnobrk(c);32pop_lex(1);33if (gequal0(res))34pari_err(0, E);35}36if (!b) return gnil;37push_lex(E,b);38res = closure_evalgen(b);39pop_lex(1);40return res;41} pari_TRY {42res = closure_evalgen(a);43} pari_ENDCATCH;44return res;45}4647/********************************************************************/48/** **/49/** ITERATIONS **/50/** **/51/********************************************************************/5253static void54forparii(GEN a, GEN b, GEN code)55{56pari_sp av, av0 = avma;57GEN aa;58if (gcmp(b,a) < 0) return;59if (typ(b) != t_INFINITY) b = gfloor(b);60aa = a = setloop(a);61av=avma;62push_lex(a,code);63while (gcmp(a,b) <= 0)64{65closure_evalvoid(code); if (loop_break()) break;66a = get_lex(-1);67if (a == aa)68{69a = incloop(a);70if (a != aa) { set_lex(-1,a); aa = a; }71}72else73{ /* 'code' modified a ! Be careful (and slow) from now on */74a = gaddgs(a,1);75if (gc_needed(av,1))76{77if (DEBUGMEM>1) pari_warn(warnmem,"forparii");78a = gerepileupto(av,a);79}80set_lex(-1,a);81}82}83pop_lex(1); set_avma(av0);84}8586void87forpari(GEN a, GEN b, GEN code)88{89pari_sp ltop=avma, av;90if (typ(a) == t_INT) { forparii(a,b,code); return; }91b = gcopy(b); /* Kludge to work-around the a+(a=2) bug */92av=avma;93push_lex(a,code);94while (gcmp(a,b) <= 0)95{96closure_evalvoid(code); if (loop_break()) break;97a = get_lex(-1); a = gaddgs(a,1);98if (gc_needed(av,1))99{100if (DEBUGMEM>1) pari_warn(warnmem,"forpari");101a = gerepileupto(av,a);102}103set_lex(-1, a);104}105pop_lex(1); set_avma(ltop);106}107108void109foreachpari(GEN x, GEN code)110{111long i, l;112switch(typ(x))113{114case t_LIST:115x = list_data(x); /* FALL THROUGH */116if (!x) return;117case t_MAT: case t_VEC: case t_COL:118break;119default:120pari_err_TYPE("foreach",x);121return; /*LCOV_EXCL_LINE*/122}123clone_lock(x); l = lg(x);124push_lex(gen_0,code);125for (i = 1; i < l; i++)126{127set_lex(-1, gel(x,i));128closure_evalvoid(code); if (loop_break()) break;129}130pop_lex(1); clone_unlock_deep(x);131}132133/* 0 < a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow134* cheap early abort */135static int136forfactoredpos(ulong a, ulong b, GEN code)137{138const ulong step = 1024;139pari_sp av = avma;140ulong x1;141for(x1 = a;; x1 += step, set_avma(av))142{ /* beware overflow, fuse last two bins (avoid a tiny remainder) */143ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b;144GEN v = vecfactoru_i(x1, x2);145lv = lg(v);146for (j = 1; j < lv; j++)147{148ulong n = x1-1 + j;149set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(gel(v,j))));150closure_evalvoid(code);151if (loop_break()) return 1;152}153if (x2 == b) break;154set_lex(-1, gen_0);155}156return 0;157}158159/* vector of primes to squarefree factorization */160static GEN161zv_to_ZM(GEN v)162{ return mkmat2(zc_to_ZC(v), const_col(lg(v)-1,gen_1)); }163/* vector of primes to negative squarefree factorization */164static GEN165zv_to_mZM(GEN v)166{167long i, l = lg(v);168GEN w = cgetg(l+1, t_COL);169gel(w,1) = gen_m1; for (i = 1; i < l; i++) gel(w,i+1) = utoipos(v[i]);170return mkmat2(w, const_col(l,gen_1));171}172/* 0 <= a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow173* cheap early abort */174static void175forsquarefreepos(ulong a, ulong b, GEN code)176{177const ulong step = 1024;178pari_sp av = avma;179ulong x1;180for(x1 = a;; x1 += step, set_avma(av))181{ /* beware overflow, fuse last two bins (avoid a tiny remainder) */182ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b;183GEN v = vecfactorsquarefreeu(x1, x2);184lv = lg(v);185for (j = 1; j < lv; j++) if (gel(v,j))186{187ulong n = x1-1 + j;188set_lex(-1, mkvec2(utoipos(n), zv_to_ZM(gel(v,j))));189closure_evalvoid(code); if (loop_break()) return;190}191if (x2 == b) break;192set_lex(-1, gen_0);193}194}195/* 0 <= a <= b. Loop from -b, ... -a through squarefree integers */196static void197forsquarefreeneg(ulong a, ulong b, GEN code)198{199const ulong step = 1024;200pari_sp av = avma;201ulong x2;202for(x2 = b;; x2 -= step, set_avma(av))203{ /* beware overflow, fuse last two bins (avoid a tiny remainder) */204ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a;205GEN v = vecfactorsquarefreeu(x1, x2);206for (j = lg(v)-1; j > 0; j--) if (gel(v,j))207{208ulong n = x1-1 + j;209set_lex(-1, mkvec2(utoineg(n), zv_to_mZM(gel(v,j))));210closure_evalvoid(code); if (loop_break()) return;211}212if (x1 == a) break;213set_lex(-1, gen_0);214}215}216void217forsquarefree(GEN a, GEN b, GEN code)218{219pari_sp av = avma;220long s;221if (typ(a) != t_INT) pari_err_TYPE("forsquarefree", a);222if (typ(b) != t_INT) pari_err_TYPE("forsquarefree", b);223if (cmpii(a,b) > 0) return;224s = signe(a); push_lex(NULL,code);225if (s < 0)226{227if (signe(b) <= 0)228forsquarefreeneg(itou(b), itou(a), code);229else230{231forsquarefreeneg(1, itou(a), code);232forsquarefreepos(1, itou(b), code);233}234}235else236forsquarefreepos(itou(a), itou(b), code);237pop_lex(1); set_avma(av);238}239240/* convert factoru(n) to factor(-n); M pre-allocated factorization matrix241* with (-1)^1 already set */242static void243Flm2negfact(GEN v, GEN M)244{245GEN p = gel(v,1), e = gel(v,2), P = gel(M,1), E = gel(M,2);246long i, l = lg(p);247for (i = 1; i < l; i++)248{249gel(P,i+1) = utoipos(p[i]);250gel(E,i+1) = utoipos(e[i]);251}252setlg(P,l+1);253setlg(E,l+1);254}255/* 0 < a <= b, from -b to -a */256static int257forfactoredneg(ulong a, ulong b, GEN code)258{259const ulong step = 1024;260GEN P, E, M;261pari_sp av;262ulong x2;263264P = cgetg(18, t_COL); gel(P,1) = gen_m1;265E = cgetg(18, t_COL); gel(E,1) = gen_1;266M = mkmat2(P,E);267av = avma;268for(x2 = b;; x2 -= step, set_avma(av))269{ /* beware overflow, fuse last two bins (avoid a tiny remainder) */270ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a;271GEN v = vecfactoru_i(x1, x2);272for (j = lg(v)-1; j; j--)273{ /* run backward: from factor(x1..x2) to factor(-x2..-x1) */274ulong n = x1-1 + j;275Flm2negfact(gel(v,j), M);276set_lex(-1, mkvec2(utoineg(n), M));277closure_evalvoid(code); if (loop_break()) return 1;278}279if (x1 == a) break;280set_lex(-1, gen_0);281}282return 0;283}284static int285eval0(GEN code)286{287pari_sp av = avma;288set_lex(-1, mkvec2(gen_0, mkmat2(mkcol(gen_0),mkcol(gen_1))));289closure_evalvoid(code); set_avma(av);290return loop_break();291}292void293forfactored(GEN a, GEN b, GEN code)294{295pari_sp av = avma;296long sa, sb, stop = 0;297if (typ(a) != t_INT) pari_err_TYPE("forfactored", a);298if (typ(b) != t_INT) pari_err_TYPE("forfactored", b);299if (cmpii(a,b) > 0) return;300push_lex(NULL,code);301sa = signe(a);302sb = signe(b);303if (sa < 0)304{305stop = forfactoredneg((sb < 0)? uel(b,2): 1UL, itou(a), code);306if (!stop && sb >= 0) stop = eval0(code);307if (!stop && sb > 0) forfactoredpos(1UL, b[2], code);308}309else310{311if (!sa) stop = eval0(code);312if (!stop && sb) forfactoredpos(sa? uel(a,2): 1UL, itou(b), code);313}314pop_lex(1); set_avma(av);315}316void317whilepari(GEN a, GEN b)318{319pari_sp av = avma;320for(;;)321{322GEN res = closure_evalnobrk(a);323if (gequal0(res)) break;324set_avma(av);325closure_evalvoid(b); if (loop_break()) break;326}327set_avma(av);328}329330void331untilpari(GEN a, GEN b)332{333pari_sp av = avma;334for(;;)335{336GEN res;337closure_evalvoid(b); if (loop_break()) break;338res = closure_evalnobrk(a);339if (!gequal0(res)) break;340set_avma(av);341}342set_avma(av);343}344345static int negcmp(GEN x, GEN y) { return gcmp(y,x); }346347void348forstep(GEN a, GEN b, GEN s, GEN code)349{350long ss, i;351pari_sp av, av0 = avma;352GEN v = NULL;353int (*cmp)(GEN,GEN);354355b = gcopy(b);356s = gcopy(s); av = avma;357switch(typ(s))358{359case t_VEC: case t_COL: ss = gsigne(vecsum(s)); v = s; break;360case t_INTMOD:361if (typ(a) != t_INT) a = gceil(a);362a = addii(a, modii(subii(gel(s,2),a), gel(s,1)));363s = gel(s,1);364default: ss = gsigne(s);365}366if (!ss) pari_err_DOMAIN("forstep","step","=",gen_0,s);367cmp = (ss > 0)? &gcmp: &negcmp;368i = 0;369push_lex(a,code);370while (cmp(a,b) <= 0)371{372closure_evalvoid(code); if (loop_break()) break;373if (v)374{375if (++i >= lg(v)) i = 1;376s = gel(v,i);377}378a = get_lex(-1); a = gadd(a,s);379380if (gc_needed(av,1))381{382if (DEBUGMEM>1) pari_warn(warnmem,"forstep");383a = gerepileupto(av,a);384}385set_lex(-1,a);386}387pop_lex(1); set_avma(av0);388}389390static void391_fordiv(GEN a, GEN code, GEN (*D)(GEN))392{393pari_sp av = avma;394long i, l;395GEN t = D(a);396push_lex(gen_0,code); l = lg(t);397for (i=1; i<l; i++)398{399set_lex(-1,gel(t,i));400closure_evalvoid(code); if (loop_break()) break;401}402pop_lex(1); set_avma(av);403}404void405fordiv(GEN a, GEN code) { return _fordiv(a, code, &divisors); }406void407fordivfactored(GEN a, GEN code) { return _fordiv(a, code, &divisors_factored); }408409/* Embedded for loops:410* fl = 0: execute ch (a), where a = (ai) runs through all n-uplets in411* [m1,M1] x ... x [mn,Mn]412* fl = 1: impose a1 <= ... <= an413* fl = 2: a1 < ... < an414*/415/* increment and return d->a [over integers]*/416static GEN417_next_i(forvec_t *d)418{419long i = d->n;420if (d->first) { d->first = 0; return (GEN)d->a; }421for (;;) {422if (cmpii(d->a[i], d->M[i]) < 0) {423d->a[i] = incloop(d->a[i]);424return (GEN)d->a;425}426d->a[i] = resetloop(d->a[i], d->m[i]);427if (--i <= 0) return NULL;428}429}430/* increment and return d->a [generic]*/431static GEN432_next(forvec_t *d)433{434long i = d->n;435if (d->first) { d->first = 0; return (GEN)d->a; }436for (;;) {437d->a[i] = gaddgs(d->a[i], 1);438if (gcmp(d->a[i], d->M[i]) <= 0) return (GEN)d->a;439d->a[i] = d->m[i];440if (--i <= 0) return NULL;441}442}443444/* nondecreasing order [over integers] */445static GEN446_next_le_i(forvec_t *d)447{448long i = d->n;449if (d->first) { d->first = 0; return (GEN)d->a; }450for (;;) {451if (cmpii(d->a[i], d->M[i]) < 0)452{453d->a[i] = incloop(d->a[i]);454/* m[i] < a[i] <= M[i] <= M[i+1] */455while (i < d->n)456{457GEN t;458i++;459if (cmpii(d->a[i-1], d->a[i]) <= 0) continue;460/* a[i] < a[i-1] <= M[i-1] <= M[i] */461t = d->a[i-1]; if (cmpii(t, d->m[i]) < 0) t = d->m[i];462d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1],m[i])*/463}464return (GEN)d->a;465}466d->a[i] = resetloop(d->a[i], d->m[i]);467if (--i <= 0) return NULL;468}469}470/* nondecreasing order [generic] */471static GEN472_next_le(forvec_t *d)473{474long i = d->n;475if (d->first) { d->first = 0; return (GEN)d->a; }476for (;;) {477d->a[i] = gaddgs(d->a[i], 1);478if (gcmp(d->a[i], d->M[i]) <= 0)479{480while (i < d->n)481{482GEN c;483i++;484if (gcmp(d->a[i-1], d->a[i]) <= 0) continue;485/* M[i] >= M[i-1] >= a[i-1] > a[i] */486c = gceil(gsub(d->a[i-1], d->a[i]));487d->a[i] = gadd(d->a[i], c);488/* a[i-1] <= a[i] < M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */489}490return (GEN)d->a;491}492d->a[i] = d->m[i];493if (--i <= 0) return NULL;494}495}496/* strictly increasing order [over integers] */497static GEN498_next_lt_i(forvec_t *d)499{500long i = d->n;501if (d->first) { d->first = 0; return (GEN)d->a; }502for (;;) {503if (cmpii(d->a[i], d->M[i]) < 0)504{505d->a[i] = incloop(d->a[i]);506/* m[i] < a[i] <= M[i] < M[i+1] */507while (i < d->n)508{509pari_sp av;510GEN t;511i++;512if (cmpii(d->a[i-1], d->a[i]) < 0) continue;513av = avma;514/* M[i] > M[i-1] >= a[i-1] */515t = addiu(d->a[i-1],1); if (cmpii(t, d->m[i]) < 0) t = d->m[i];516d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1]+1,m[i]) <= M[i]*/517set_avma(av);518}519return (GEN)d->a;520}521d->a[i] = resetloop(d->a[i], d->m[i]);522if (--i <= 0) return NULL;523}524}525/* strictly increasing order [generic] */526static GEN527_next_lt(forvec_t *d)528{529long i = d->n;530if (d->first) { d->first = 0; return (GEN)d->a; }531for (;;) {532d->a[i] = gaddgs(d->a[i], 1);533if (gcmp(d->a[i], d->M[i]) <= 0)534{535while (i < d->n)536{537GEN c;538i++;539if (gcmp(d->a[i-1], d->a[i]) < 0) continue;540/* M[i] > M[i-1] >= a[i-1] >= a[i] */541c = addiu(gfloor(gsub(d->a[i-1], d->a[i])), 1); /* > a[i-1] - a[i] */542d->a[i] = gadd(d->a[i], c);543/* a[i-1] < a[i] <= M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */544}545return (GEN)d->a;546}547d->a[i] = d->m[i];548if (--i <= 0) return NULL;549}550}551/* for forvec(v=[],) */552static GEN553_next_void(forvec_t *d)554{555if (d->first) { d->first = 0; return (GEN)d->a; }556return NULL;557}558559/* Initialize minima (m) and maxima (M); guarantee M[i] - m[i] integer and560* if flag = 1: m[i-1] <= m[i] <= M[i] <= M[i+1]561* if flag = 2: m[i-1] < m[i] <= M[i] < M[i+1],562* for all i */563int564forvec_init(forvec_t *d, GEN x, long flag)565{566long i, tx = typ(x), l = lg(x), t = t_INT;567if (!is_vec_t(tx)) pari_err_TYPE("forvec [not a vector]", x);568d->first = 1;569d->n = l - 1;570d->a = (GEN*)cgetg(l,tx);571d->m = (GEN*)cgetg(l,tx);572d->M = (GEN*)cgetg(l,tx);573if (l == 1) { d->next = &_next_void; return 1; }574for (i = 1; i < l; i++)575{576GEN a, e = gel(x,i), m = gel(e,1), M = gel(e,2);577tx = typ(e);578if (! is_vec_t(tx) || lg(e)!=3)579pari_err_TYPE("forvec [expected vector not of type [min,MAX]]",e);580if (typ(m) != t_INT) t = t_REAL;581if (i > 1) switch(flag)582{583case 1: /* a >= m[i-1] - m */584a = gceil(gsub(d->m[i-1], m));585if (typ(a) != t_INT) pari_err_TYPE("forvec",a);586if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m);587break;588case 2: /* a > m[i-1] - m */589a = gfloor(gsub(d->m[i-1], m));590if (typ(a) != t_INT) pari_err_TYPE("forvec",a);591a = addiu(a, 1);592if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m);593break;594default: m = gcopy(m);595break;596}597M = gadd(m, gfloor(gsub(M,m))); /* ensure M-m is an integer */598if (gcmp(m,M) > 0) { d->a = NULL; d->next = &_next; return 0; }599d->m[i] = m;600d->M[i] = M;601}602if (flag == 1) for (i = l-2; i >= 1; i--)603{604GEN M = d->M[i], a = gfloor(gsub(d->M[i+1], M));605if (typ(a) != t_INT) pari_err_TYPE("forvec",a);606/* M[i]+a <= M[i+1] */607if (signe(a) < 0) d->M[i] = gadd(M, a);608}609else if (flag == 2) for (i = l-2; i >= 1; i--)610{611GEN M = d->M[i], a = gceil(gsub(d->M[i+1], M));612if (typ(a) != t_INT) pari_err_TYPE("forvec",a);613a = subiu(a, 1);614/* M[i]+a < M[i+1] */615if (signe(a) < 0) d->M[i] = gadd(M, a);616}617if (t == t_INT) {618for (i = 1; i < l; i++) {619d->a[i] = setloop(d->m[i]);620if (typ(d->M[i]) != t_INT) d->M[i] = gfloor(d->M[i]);621}622} else {623for (i = 1; i < l; i++) d->a[i] = d->m[i];624}625switch(flag)626{627case 0: d->next = t==t_INT? &_next_i: &_next; break;628case 1: d->next = t==t_INT? &_next_le_i: &_next_le; break;629case 2: d->next = t==t_INT? &_next_lt_i: &_next_lt; break;630default: pari_err_FLAG("forvec");631}632return 1;633}634GEN635forvec_next(forvec_t *d) { return d->next(d); }636637void638forvec(GEN x, GEN code, long flag)639{640pari_sp av = avma;641forvec_t T;642GEN v;643if (!forvec_init(&T, x, flag)) { set_avma(av); return; }644push_lex((GEN)T.a, code);645while ((v = forvec_next(&T)))646{647closure_evalvoid(code);648if (loop_break()) break;649}650pop_lex(1); set_avma(av);651}652653/********************************************************************/654/** **/655/** SUMS **/656/** **/657/********************************************************************/658659GEN660somme(GEN a, GEN b, GEN code, GEN x)661{662pari_sp av, av0 = avma;663GEN p1;664665if (typ(a) != t_INT) pari_err_TYPE("sum",a);666if (!x) x = gen_0;667if (gcmp(b,a) < 0) return gcopy(x);668669b = gfloor(b);670a = setloop(a);671av=avma;672push_lex(a,code);673for(;;)674{675p1 = closure_evalnobrk(code);676x=gadd(x,p1); if (cmpii(a,b) >= 0) break;677a = incloop(a);678if (gc_needed(av,1))679{680if (DEBUGMEM>1) pari_warn(warnmem,"sum");681x = gerepileupto(av,x);682}683set_lex(-1,a);684}685pop_lex(1); return gerepileupto(av0,x);686}687688static GEN689sum_init(GEN x0, GEN t)690{691long tp = typ(t);692GEN x;693if (is_vec_t(tp))694{695x = const_vec(lg(t)-1, x0);696settyp(x, tp);697}698else699x = x0;700return x;701}702703GEN704suminf_bitprec(void *E, GEN (*eval)(void *, GEN), GEN a, long bit)705{706long fl = 0, G = bit + 1;707pari_sp av0 = avma, av;708GEN x = NULL, _1;709710if (typ(a) != t_INT) pari_err_TYPE("suminf",a);711a = setloop(a); av = avma;712for(;;)713{714GEN t = eval(E, a);715if (!x) _1 = x = sum_init(real_1_bit(bit), t);716717x = gadd(x,t);718if (!gequal0(t) && gexpo(t) > gexpo(x)-G)719fl = 0;720else if (++fl == 3)721break;722a = incloop(a);723if (gc_needed(av,1))724{725if (DEBUGMEM>1) pari_warn(warnmem,"suminf");726gerepileall(av,2, &x, &_1);727}728}729return gerepileupto(av0, gsub(x, _1));730}731GEN732suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)733{ return suminf_bitprec(E, eval, a, prec2nbits(prec)); }734GEN735suminf0_bitprec(GEN a, GEN code, long bit)736{ EXPR_WRAP(code, suminf_bitprec(EXPR_ARG, a, bit)); }737738GEN739sumdivexpr(GEN num, GEN code)740{741pari_sp av = avma;742GEN y = gen_0, t = divisors(num);743long i, l = lg(t);744745push_lex(gen_0, code);746for (i=1; i<l; i++)747{748set_lex(-1,gel(t,i));749y = gadd(y, closure_evalnobrk(code));750}751pop_lex(1); return gerepileupto(av,y);752}753754GEN755sumdivmultexpr(void *D, GEN (*fun)(void*, GEN), GEN num)756{757pari_sp av = avma;758GEN y = gen_1, P,E;759int isint = divisors_init(num, &P,&E);760long i, l = lg(P);761GEN (*mul)(GEN,GEN);762763if (l == 1) return gc_const(av, gen_1);764mul = isint? mulii: gmul;765for (i=1; i<l; i++)766{767GEN p = gel(P,i), q = p, z = gen_1;768long j, e = E[i];769for (j = 1; j <= e; j++, q = mul(q, p))770{771z = gadd(z, fun(D, q));772if (j == e) break;773}774y = gmul(y, z);775}776return gerepileupto(av,y);777}778779GEN780sumdivmultexpr0(GEN num, GEN code)781{ EXPR_WRAP(code, sumdivmultexpr(EXPR_ARG, num)) }782783/********************************************************************/784/** **/785/** PRODUCTS **/786/** **/787/********************************************************************/788789GEN790produit(GEN a, GEN b, GEN code, GEN x)791{792pari_sp av, av0 = avma;793GEN p1;794795if (typ(a) != t_INT) pari_err_TYPE("prod",a);796if (!x) x = gen_1;797if (gcmp(b,a) < 0) return gcopy(x);798799b = gfloor(b);800a = setloop(a);801av=avma;802push_lex(a,code);803for(;;)804{805p1 = closure_evalnobrk(code);806x = gmul(x,p1); if (cmpii(a,b) >= 0) break;807a = incloop(a);808if (gc_needed(av,1))809{810if (DEBUGMEM>1) pari_warn(warnmem,"prod");811x = gerepileupto(av,x);812}813set_lex(-1,a);814}815pop_lex(1); return gerepileupto(av0,x);816}817818GEN819prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)820{821pari_sp av0 = avma, av;822long fl,G;823GEN p1,x = real_1(prec);824825if (typ(a) != t_INT) pari_err_TYPE("prodinf",a);826a = setloop(a);827av = avma;828fl=0; G = -prec2nbits(prec)-5;829for(;;)830{831p1 = eval(E, a); if (gequal0(p1)) { x = p1; break; }832x = gmul(x,p1); a = incloop(a);833p1 = gsubgs(p1, 1);834if (gequal0(p1) || gexpo(p1) <= G) { if (++fl==3) break; } else fl=0;835if (gc_needed(av,1))836{837if (DEBUGMEM>1) pari_warn(warnmem,"prodinf");838x = gerepileupto(av,x);839}840}841return gerepilecopy(av0,x);842}843GEN844prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)845{846pari_sp av0 = avma, av;847long fl,G;848GEN p1,p2,x = real_1(prec);849850if (typ(a) != t_INT) pari_err_TYPE("prodinf1",a);851a = setloop(a);852av = avma;853fl=0; G = -prec2nbits(prec)-5;854for(;;)855{856p2 = eval(E, a); p1 = gaddgs(p2,1);857if (gequal0(p1)) { x = p1; break; }858x = gmul(x,p1); a = incloop(a);859if (gequal0(p2) || gexpo(p2) <= G) { if (++fl==3) break; } else fl=0;860if (gc_needed(av,1))861{862if (DEBUGMEM>1) pari_warn(warnmem,"prodinf1");863x = gerepileupto(av,x);864}865}866return gerepilecopy(av0,x);867}868GEN869prodinf0(GEN a, GEN code, long flag, long prec)870{871switch(flag)872{873case 0: EXPR_WRAP(code, prodinf (EXPR_ARG, a, prec));874case 1: EXPR_WRAP(code, prodinf1(EXPR_ARG, a, prec));875}876pari_err_FLAG("prodinf");877return NULL; /* LCOV_EXCL_LINE */878}879880GEN881prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)882{883pari_sp av, av0 = avma;884GEN x = real_1(prec), prime;885forprime_t T;886887av = avma;888if (!forprime_init(&T, a,b)) return gc_const(av, x);889890av = avma;891while ( (prime = forprime_next(&T)) )892{893x = gmul(x, eval(E, prime));894if (gc_needed(av,1))895{896if (DEBUGMEM>1) pari_warn(warnmem,"prodeuler");897x = gerepilecopy(av, x);898}899}900return gerepilecopy(av0,x);901}902GEN903prodeuler0(GEN a, GEN b, GEN code, long prec)904{ EXPR_WRAP(code, prodeuler(EXPR_ARG, a, b, prec)); }905GEN906direuler0(GEN a, GEN b, GEN code, GEN c)907{ EXPR_WRAP(code, direuler(EXPR_ARG, a, b, c)); }908909/********************************************************************/910/** **/911/** VECTORS & MATRICES **/912/** **/913/********************************************************************/914915INLINE GEN916copyupto(GEN z, GEN t)917{918if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))919return z;920else921return gcopy(z);922}923924GEN925vecexpr0(GEN vec, GEN code, GEN pred)926{927switch(typ(vec))928{929case t_LIST:930{931if (list_typ(vec)==t_LIST_MAP)932vec = mapdomain_shallow(vec);933else934vec = list_data(vec);935if (!vec) return cgetg(1, t_VEC);936break;937}938case t_VECSMALL:939vec = vecsmall_to_vec(vec);940break;941case t_VEC: case t_COL: case t_MAT: break;942default: pari_err_TYPE("[_|_<-_,_]",vec);943}944if (pred && code)945EXPR_WRAP(code,vecselapply((void*)pred,&gp_evalbool,EXPR_ARGUPTO,vec))946else if (code)947EXPR_WRAP(code,vecapply(EXPR_ARGUPTO,vec))948else949EXPR_WRAP(pred,vecselect(EXPR_ARGBOOL,vec))950}951952GEN953vecexpr1(GEN vec, GEN code, GEN pred)954{955GEN v = vecexpr0(vec, code, pred);956return lg(v) == 1? v: shallowconcat1(v);957}958959GEN960vecteur(GEN nmax, GEN code)961{962GEN y, c;963long i, m = gtos(nmax);964965if (m < 0) pari_err_DOMAIN("vector", "dimension", "<", gen_0, stoi(m));966if (!code) return zerovec(m);967c = cgetipos(3); /* left on stack */968y = cgetg(m+1,t_VEC); push_lex(c, code);969for (i=1; i<=m; i++)970{971c[2] = i;972gel(y,i) = copyupto(closure_evalnobrk(code), y);973set_lex(-1,c);974}975pop_lex(1); return y;976}977978GEN979vecteursmall(GEN nmax, GEN code)980{981pari_sp av;982GEN y, c;983long i, m = gtos(nmax);984985if (m < 0) pari_err_DOMAIN("vectorsmall", "dimension", "<", gen_0, stoi(m));986if (!code) return zero_zv(m);987c = cgetipos(3); /* left on stack */988y = cgetg(m+1,t_VECSMALL); push_lex(c,code);989av = avma;990for (i = 1; i <= m; i++)991{992c[2] = i;993y[i] = gtos(closure_evalnobrk(code));994set_avma(av);995set_lex(-1,c);996}997pop_lex(1); return y;998}9991000GEN1001vvecteur(GEN nmax, GEN n)1002{1003GEN y = vecteur(nmax,n);1004settyp(y,t_COL); return y;1005}10061007GEN1008matrice(GEN nlig, GEN ncol, GEN code)1009{1010GEN c1, c2, y;1011long i, m, n;10121013n = gtos(nlig);1014m = ncol? gtos(ncol): n;1015if (m < 0) pari_err_DOMAIN("matrix", "nbcols", "<", gen_0, stoi(m));1016if (n < 0) pari_err_DOMAIN("matrix", "nbrows", "<", gen_0, stoi(n));1017if (!m) return cgetg(1,t_MAT);1018if (!code || !n) return zeromatcopy(n, m);1019c1 = cgetipos(3); push_lex(c1,code);1020c2 = cgetipos(3); push_lex(c2,NULL); /* c1,c2 left on stack */1021y = cgetg(m+1,t_MAT);1022for (i = 1; i <= m; i++)1023{1024GEN z = cgetg(n+1,t_COL);1025long j;1026c2[2] = i; gel(y,i) = z;1027for (j = 1; j <= n; j++)1028{1029c1[2] = j;1030gel(z,j) = copyupto(closure_evalnobrk(code), y);1031set_lex(-2,c1);1032set_lex(-1,c2);1033}1034}1035pop_lex(2); return y;1036}10371038/********************************************************************/1039/** **/1040/** SUMMING SERIES **/1041/** **/1042/********************************************************************/1043/* h = (2+2x)g'- g; g has t_INT coeffs */1044static GEN1045delt(GEN g, long n)1046{1047GEN h = cgetg(n+3,t_POL);1048long k;1049h[1] = g[1];1050gel(h,2) = gel(g,2);1051for (k=1; k<n; k++)1052gel(h,k+2) = addii(mului(k+k+1,gel(g,k+2)), mului(k<<1,gel(g,k+1)));1053gel(h,n+2) = mului(n<<1, gel(g,n+1)); return h;1054}10551056#ifdef _MSC_VER /* Bill Daly: work around a MSVC bug */1057#pragma optimize("g",off)1058#endif1059/* P = polzagier(n,m)(-X), unnormalized (P(0) != 1) */1060static GEN1061polzag1(long n, long m)1062{1063long d = n - m, i, k, d2, r, D;1064pari_sp av = avma;1065GEN g, T;10661067if (d <= 0 || m < 0) return pol_0(0);1068d2 = d << 1; r = (m+1) >> 1, D = (d+1) >> 1;1069g = cgetg(d+2, t_POL);1070g[1] = evalsigne(1)|evalvarn(0);1071T = cgetg(d+1,t_VEC);1072/* T[k+1] = binomial(2d,2k+1), 0 <= k < d */1073gel(T,1) = utoipos(d2);1074for (k = 1; k < D; k++)1075{1076long k2 = k<<1;1077gel(T,k+1) = diviiexact(mulii(gel(T,k), muluu(d2-k2+1, d2-k2)),1078muluu(k2,k2+1));1079}1080for (; k < d; k++) gel(T,k+1) = gel(T,d-k);1081gel(g,2) = gel(T,d); /* binomial(2d, 2(d-1)+1) */1082for (i = 1; i < d; i++)1083{1084pari_sp av2 = avma;1085GEN s, t = gel(T,d-i); /* binomial(2d, 2(d-1-i)+1) */1086s = t;1087for (k = d-i; k < d; k++)1088{1089long k2 = k<<1;1090t = diviiexact(mulii(t, muluu(d2-k2+1, d-k)), muluu(k2+1,k-(d-i)+1));1091s = addii(s, t);1092}1093/* g_i = sum_{d-1-i <= k < d}, binomial(2*d, 2*k+1)*binomial(k,d-1-i) */1094gel(g,i+2) = gerepileuptoint(av2, s);1095}1096/* sum_{0 <= i < d} g_i x^i * (x+x^2)^r */1097g = RgX_mulXn(gmul(g, gpowgs(deg1pol(gen_1,gen_1,0),r)), r);1098if (!odd(m)) g = delt(g, n);1099for (i = 1; i <= r; i++)1100{1101g = delt(ZX_deriv(g), n);1102if (gc_needed(av,4))1103{1104if (DEBUGMEM>1) pari_warn(warnmem,"polzag, i = %ld/%ld", i,r);1105g = gerepilecopy(av, g);1106}1107}1108return g;1109}1110GEN1111polzag(long n, long m)1112{1113pari_sp av = avma;1114GEN g = polzag1(n,m);1115if (lg(g) == 2) return g;1116g = ZX_z_unscale(polzag1(n,m), -1);1117return gerepileupto(av, RgX_Rg_div(g,gel(g,2)));1118}11191120/*0.39322 > 1/log_2(3+sqrt(8))*/1121static ulong1122sumalt_N(long prec)1123{ return (ulong)(0.39322*(prec2nbits(prec) + 7)); }11241125GEN1126sumalt(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)1127{1128ulong k, N;1129pari_sp av = avma, av2;1130GEN s, az, c, d;11311132if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);1133N = sumalt_N(prec);1134d = powru(addsr(3, sqrtr(utor(8,prec))), N);1135d = shiftr(addrr(d, invr(d)),-1);1136a = setloop(a);1137az = gen_m1; c = d;1138s = gen_0;1139av2 = avma;1140for (k=0; ; k++) /* k < N */1141{1142c = addir(az,c); s = gadd(s, gmul(c, eval(E, a)));1143if (k==N-1) break;1144az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1);1145a = incloop(a); /* in place! */1146if (gc_needed(av,4))1147{1148if (DEBUGMEM>1) pari_warn(warnmem,"sumalt, k = %ld/%ld", k,N-1);1149gerepileall(av2, 3, &az,&c,&s);1150}1151}1152return gerepileupto(av, gdiv(s,d));1153}11541155GEN1156sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)1157{1158long k, N;1159pari_sp av = avma, av2;1160GEN s, dn, pol;11611162if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);1163N = (long)(0.307073*(prec2nbits(prec) + 5)); /*0.307073 > 1/log_2(\beta_B)*/1164pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);1165a = setloop(a);1166N = degpol(pol);1167s = gen_0;1168av2 = avma;1169for (k=0; k<=N; k++)1170{1171GEN t = itor(gel(pol,k+2), prec+EXTRAPRECWORD);1172s = gadd(s, gmul(t, eval(E, a)));1173if (k == N) break;1174a = incloop(a); /* in place! */1175if (gc_needed(av,4))1176{1177if (DEBUGMEM>1) pari_warn(warnmem,"sumalt2, k = %ld/%ld", k,N-1);1178s = gerepileupto(av2, s);1179}1180}1181return gerepileupto(av, gdiv(s,dn));1182}11831184GEN1185sumalt0(GEN a, GEN code, long flag, long prec)1186{1187switch(flag)1188{1189case 0: EXPR_WRAP(code, sumalt (EXPR_ARG,a,prec));1190case 1: EXPR_WRAP(code, sumalt2(EXPR_ARG,a,prec));1191default: pari_err_FLAG("sumalt");1192}1193return NULL; /* LCOV_EXCL_LINE */1194}11951196/* For k > 0, set S[k*2^i] <- g(k*2^i), k*2^i <= N = #S.1197* Only needed with k odd (but also works for g even). */1198static void1199binsum(GEN S, ulong k, void *E, GEN (*f)(void *, GEN), GEN a,1200long G, long prec)1201{1202long e, i, N = lg(S)-1, l = expu(N / k); /* k 2^l <= N < k 2^(l+1) */1203pari_sp av = avma;1204GEN t = real_0(prec); /* unused unless f(a + k <<l) = 0 */12051206G -= l;1207if (!signe(a)) a = NULL;1208for (e = 0;; e++)1209{ /* compute g(k 2^l) with absolute error ~ 2^(G-l) */1210GEN u, r = shifti(utoipos(k), l+e);1211if (a) r = addii(r, a);1212u = gtofp(f(E, r), prec);1213if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);1214if (!signe(u)) break;1215if (!e)1216t = u;1217else {1218shiftr_inplace(u, e);1219t = addrr(t,u); if (expo(u) < G) break;1220if ((e & 0x1ff) == 0) t = gerepileuptoleaf(av, t);1221}1222}1223gel(S, k << l) = t = gerepileuptoleaf(av, t);1224/* g(j) = 2g(2j) + f(a+j) for all j > 0 */1225for(i = l-1; i >= 0; i--)1226{ /* t ~ g(2 * k*2^i) with error ~ 2^(G-i-1) */1227GEN u;1228av = avma; u = gtofp(f(E, a? addiu(a, k << i): utoipos(k << i)), prec);1229if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);1230t = addrr(gtofp(u,prec), mpshift(t,1)); /* ~ g(k*2^i) */1231gel(S, k << i) = t = gerepileuptoleaf(av, t);1232}1233}1234/* For k > 0, let g(k) := \sum_{e >= 0} 2^e f(a + k*2^e).1235* Return [g(k), 1 <= k <= N] */1236static GEN1237sumpos_init(void *E, GEN (*f)(void *, GEN), GEN a, long N, long prec)1238{1239GEN S = cgetg(N+1,t_VEC);1240long k, G = -prec2nbits(prec) - 5;1241for (k=1; k<=N; k+=2) binsum(S,k, E,f, a,G,prec);1242return S;1243}12441245GEN1246sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)1247{1248ulong k, N;1249pari_sp av = avma;1250GEN s, az, c, d, S;12511252if (typ(a) != t_INT) pari_err_TYPE("sumpos",a);1253a = subiu(a,1);1254N = sumalt_N(prec);1255if (odd(N)) N++; /* extra precision for free */1256d = powru(addsr(3, sqrtr(utor(8,prec))), N);1257d = shiftr(addrr(d, invr(d)),-1);1258az = gen_m1; c = d;12591260S = sumpos_init(E, eval, a, N, prec);1261s = gen_0;1262for (k=0; k<N; k++)1263{1264GEN t;1265c = addir(az,c);1266t = mulrr(gel(S,k+1), c);1267s = odd(k)? mpsub(s, t): mpadd(s, t);1268if (k == N-1) break;1269az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1);1270}1271return gerepileupto(av, gdiv(s,d));1272}12731274GEN1275sumpos2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)1276{1277ulong k, N;1278pari_sp av = avma;1279GEN s, pol, dn, S;12801281if (typ(a) != t_INT) pari_err_TYPE("sumpos2",a);1282a = subiu(a,1);1283N = (ulong)(0.31*(prec2nbits(prec) + 5));12841285if (odd(N)) N++; /* extra precision for free */1286S = sumpos_init(E, eval, a, N, prec);1287pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);1288s = gen_0;1289for (k=0; k<N; k++)1290{1291GEN t = mulri(gel(S,k+1), gel(pol,k+2));1292s = odd(k)? mpsub(s,t): mpadd(s,t);1293}1294return gerepileupto(av, gdiv(s,dn));1295}12961297GEN1298sumpos0(GEN a, GEN code, long flag, long prec)1299{1300switch(flag)1301{1302case 0: EXPR_WRAP(code, sumpos (EXPR_ARG,a,prec));1303case 1: EXPR_WRAP(code, sumpos2(EXPR_ARG,a,prec));1304default: pari_err_FLAG("sumpos");1305}1306return NULL; /* LCOV_EXCL_LINE */1307}13081309/********************************************************************/1310/** **/1311/** SEARCH FOR REAL ZEROS of an expression **/1312/** **/1313/********************************************************************/1314/* Brent's method, [a,b] bracketing interval */1315GEN1316zbrent(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)1317{1318long sig, iter, itmax;1319pari_sp av = avma;1320GEN c, d, e, tol, fa, fb, fc;13211322if (typ(a) != t_REAL || realprec(a) < prec) a = gtofp(a, prec);1323if (typ(b) != t_REAL || realprec(b) < prec) b = gtofp(b, prec);1324sig = cmprr(b, a);1325if (!sig) return gerepileupto(av, a);1326if (sig < 0) {c = a; a = b; b = c;} else c = b;1327fa = eval(E, a);1328fb = eval(E, b);1329if (gsigne(fa)*gsigne(fb) > 0)1330pari_err_DOMAIN("solve", "f(a)f(b)", ">", gen_0, mkvec2(fa, fb));1331itmax = prec2nbits(prec) * 2 + 1;1332tol = real2n(5-prec2nbits(prec), LOWDEFAULTPREC);1333fc = fb;1334e = d = NULL; /* gcc -Wall */1335for (iter = 1; iter <= itmax; ++iter)1336{1337GEN xm, tol1;1338if (gsigne(fb)*gsigne(fc) > 0)1339{1340c = a; fc = fa; e = d = subrr(b, a);1341}1342if (gcmp(gabs(fc, 0), gabs(fb, 0)) < 0)1343{1344a = b; b = c; c = a; fa = fb; fb = fc; fc = fa;1345}1346tol1 = abscmprr(tol, b) > 0? sqrr(tol): mulrr(tol, absr(b));1347xm = shiftr(subrr(c, b), -1);1348if (abscmprr(xm, tol1) <= 0 || gequal0(fb)) break; /* SUCCESS */13491350if (abscmprr(e, tol1) >= 0 && gcmp(gabs(fa, 0), gabs(fb, 0)) > 0)1351{ /* attempt interpolation */1352GEN min1, min2, p, q, s = gdiv(fb, fa);1353if (cmprr(a, c) == 0)1354{1355p = gmul2n(gmul(xm, s), 1);1356q = gsubsg(1, s);1357}1358else1359{1360GEN r = gdiv(fb, fc);1361q = gdiv(fa, fc);1362p = gmul2n(gmul(gsub(q, r), gmul(xm, q)), 1);1363p = gmul(s, gsub(p, gmul(gsub(b, a), gsubgs(r, 1))));1364q = gmul(gmul(gsubgs(q, 1), gsubgs(r, 1)), gsubgs(s, 1));1365}1366if (gsigne(p) > 0) q = gneg_i(q); else p = gneg_i(p);1367min1 = gsub(gmulsg(3, gmul(xm,q)), gabs(gmul(q, tol1), 0));1368min2 = gabs(gmul(e, q), 0);1369if (gcmp(gmul2n(p, 1), gmin_shallow(min1, min2)) < 0)1370{ e = d; d = gdiv(p, q); } /* interpolation OK */1371else1372{ d = xm; e = d; } /* failed, use bisection */1373}1374else { d = xm; e = d; } /* bound decreasing too slowly, use bisection */1375a = b; fa = fb;1376if (gcmp(gabs(d, 0), tol1) > 0) b = gadd(b, d);1377else if (gsigne(xm) > 0) b = addrr(b, tol1);1378else b = subrr(b, tol1);1379if (realprec(b) < prec) b = rtor(b, prec);1380fb = eval(E, b);1381}1382if (iter > itmax) pari_err_IMPL("solve recovery [too many iterations]");1383return gerepileuptoleaf(av, rcopy(b));1384}13851386GEN1387zbrent0(GEN a, GEN b, GEN code, long prec)1388{ EXPR_WRAP(code, zbrent(EXPR_ARG, a, b, prec)); }13891390/* Find zeros of a function in the real interval [a,b] by interval splitting */1391GEN1392solvestep(void *E, GEN (*f)(void *,GEN), GEN a, GEN b, GEN step, long flag, long prec)1393{1394const long ITMAX = 10;1395pari_sp av = avma;1396GEN fa, a0, b0;1397long sa0, it, bit = prec2nbits(prec) / 2, ct = 0, s = gcmp(a,b);13981399if (!s) return gequal0(f(E, a)) ? gcopy(mkvec(a)): cgetg(1,t_VEC);1400if (s > 0) swap(a, b);1401if (flag&4)1402{1403if (gcmpgs(step,1)<=0) pari_err_DOMAIN("solvestep","step","<=",gen_1,step);1404if (gsigne(a) <= 0) pari_err_DOMAIN("solvestep","a","<=",gen_0,a);1405}1406else if (gsigne(step) <= 0)1407pari_err_DOMAIN("solvestep","step","<=",gen_0,step);1408a0 = a = gtofp(a, prec); fa = f(E, a);1409b0 = b = gtofp(b, prec); step = gtofp(step, prec);1410sa0 = gsigne(fa);1411if (gexpo(fa) < -bit) sa0 = 0;1412for (it = 0; it < ITMAX; it++)1413{1414pari_sp av2 = avma;1415GEN v = cgetg(1, t_VEC);1416long sa = sa0;1417a = a0; b = b0;1418while (gcmp(a,b) < 0)1419{1420GEN fc, c = (flag&4)? gmul(a, step): gadd(a, step);1421long sc;1422if (gcmp(c,b) > 0) c = b;1423fc = f(E, c); sc = gsigne(fc);1424if (gexpo(fc) < -bit) sc = 0;1425if (!sc || sa*sc < 0)1426{1427GEN z = sc? zbrent(E, f, a, c, prec): c;1428long e;1429(void)grndtoi(z, &e);1430if (e <= -bit) ct = 1;1431if ((flag&1) && ((!(flag&8)) || ct)) return gerepileupto(av, z);1432v = shallowconcat(v, z);1433}1434a = c; fa = fc; sa = sc;1435if (gc_needed(av2,1))1436{1437if (DEBUGMEM>1) pari_warn(warnmem,"solvestep");1438gerepileall(av2, 4, &a ,&fa, &v, &step);1439}1440}1441if ((!(flag&2) || lg(v) > 1) && (!(flag&8) || ct))1442return gerepilecopy(av, v);1443step = (flag&4)? sqrtnr(step,4): gmul2n(step, -2);1444gerepileall(av2, 2, &fa, &step);1445}1446pari_err_IMPL("solvestep recovery [too many iterations]");1447return NULL;/*LCOV_EXCL_LINE*/1448}14491450GEN1451solvestep0(GEN a, GEN b, GEN step, GEN code, long flag, long prec)1452{ EXPR_WRAP(code, solvestep(EXPR_ARG, a,b, step, flag, prec)); }14531454/********************************************************************/1455/** Numerical derivation **/1456/********************************************************************/14571458struct deriv_data1459{1460GEN code;1461GEN args;1462GEN def;1463};14641465static GEN deriv_eval(void *E, GEN x, long prec)1466{1467struct deriv_data *data=(struct deriv_data *)E;1468gel(data->args,1)=x;1469uel(data->def,1)=1;1470return closure_callgenvecdefprec(data->code, data->args, data->def, prec);1471}14721473/* Rationale: (f(2^-e) - f(-2^-e) + O(2^-b)) / (2 * 2^-e) = f'(0) + O(2^-2e)1474* since 2nd derivatives cancel.1475* prec(LHS) = b - e1476* prec(RHS) = 2e, equal when b = 3e = 3/2 b0 (b0 = required final bitprec)1477*1478* For f'(x), x far from 0: prec(LHS) = b - e - expo(x)1479* --> pr = 3/2 b0 + expo(x) */1480GEN1481derivnum(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec)1482{1483long newprec, e, ex = gexpo(x), p = precision(x);1484long b0 = prec2nbits(p? p: prec), b = (long)ceil(b0 * 1.5 + maxss(0,ex));1485GEN eps, u, v, y;1486pari_sp av = avma;1487newprec = nbits2prec(b + BITS_IN_LONG);1488switch(typ(x))1489{1490case t_REAL:1491case t_COMPLEX:1492x = gprec_w(x, newprec);1493}1494e = b0/2; /* 1/2 required prec (in sig. bits) */1495b -= e; /* >= b0 */1496eps = real2n(-e, ex < -e? newprec: nbits2prec(b));1497u = eval(E, gsub(x, eps), newprec);1498v = eval(E, gadd(x, eps), newprec);1499y = gmul2n(gsub(v,u), e-1);1500return gerepilecopy(av, gprec_wtrunc(y, nbits2prec(b0)));1501}15021503/* Fornberg interpolation algorithm for finite differences coefficients1504* using 2N+1 equidistant grid points around 0 [ assume 2N even >= M ].1505* Compute \delta[m]_{N,i} for all derivation orders m = 0..M such that1506* h^m * f^{(m)}(0) = \sum_{i = 0}^n delta[m]_{N,i} f(a_i) + O(h^{N-m+1}),1507* for step size h.1508* Return a = [0,-1,1...,-N,N] and vector of vectors d: d[m+1][i+1]1509* = w'(a_i) delta[m]_{2N,i}, i = 0..2N */1510static void1511FD(long M, long N2, GEN *pd, GEN *pa)1512{1513GEN d, a, b, W, F;1514long N = N2>>1, m, i;15151516F = cgetg(N2+2, t_VEC);1517a = cgetg(N2+2, t_VEC);1518b = cgetg(N+1, t_VEC);1519gel(a,1) = gen_0;1520for (i = 1; i <= N; i++)1521{1522gel(a,2*i) = utoineg(i);1523gel(a,2*i+1) = utoipos(i);1524gel(b,i) = sqru(i);1525}1526/* w = \prod (X - a[i]) = x W(x^2) */1527W = roots_to_pol(b, 0);1528gel(F,1) = RgX_inflate(W,2);1529for (i = 1; i <= N; i++)1530{1531pari_sp av = avma;1532GEN r, U, S;1533U = RgX_inflate(RgX_div_by_X_x(W, gel(b,i), &r), 2);1534U = RgXn_red_shallow(U, M); /* higher terms not needed */1535U = RgX_shift_shallow(U,1); /* w(X) / (X^2-a[i]^2) mod X^(M+1) */1536S = ZX_sub(RgX_shift_shallow(U,1),1537ZX_Z_mul(U, gel(a,2*i+1)));1538S = gerepileupto(av, S);1539gel(F,2*i) = S;1540gel(F,2*i+1) = ZX_z_unscale(S, -1);1541}1542/* F[i] = w(X) / (X-a[i]) + O(X^(M+1)) in Z[X] */1543d = cgetg(M+2, t_VEC);1544for (m = 0; m <= M; m++)1545{1546GEN v = cgetg(N2+2, t_VEC); /* coeff(F[i],X^m) */1547for (i = 0; i <= N2; i++) gel(v, i+1) = gmael(F, i+1, m+2);1548gel(d,m+1) = v;1549}1550*pd = d;1551*pa = a;1552}15531554static void1555chk_ord(long m)1556{1557if (m < 0)1558pari_err_DOMAIN("derivnumk", "derivation order", "<", gen_0, stoi(m));1559}1560/* m! / N! for m in ind; vecmax(ind) <= N */1561static GEN1562vfact(GEN ind, long N, long prec)1563{1564GEN v, iN;1565long i, l;1566ind = vecsmall_uniq(ind); chk_ord(ind[1]); l = lg(ind);1567iN = invr(itor(mulu_interval(ind[1] + 1, N), prec));1568v = const_vec(ind[l-1], NULL); gel(v, ind[1]) = iN;1569for (i = 2; i < l; i++)1570gel(v, ind[i]) = iN = mulri(iN, mulu_interval(ind[i-1] + 1, ind[i]));1571return v;1572}15731574static GEN1575chk_ind(GEN ind, long *M)1576{1577*M = 0;1578switch(typ(ind))1579{1580case t_INT: ind = mkvecsmall(itos(ind)); break;1581case t_VECSMALL:1582if (lg(ind) == 1) return NULL;1583break;1584case t_VEC: case t_COL:1585if (lg(ind) == 1) return NULL;1586if (RgV_is_ZV(ind)) { ind = ZV_to_zv(ind); break; }1587/* fall through */1588default:1589pari_err_TYPE("derivnum", ind);1590return NULL; /*LCOV_EXCL_LINE*/1591}1592*M = vecsmall_max(ind); chk_ord(*M); return ind;1593}1594GEN1595derivnumk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec)1596{1597GEN A, C, D, DM, T, X, F, v, ind, t;1598long M, N, N2, fpr, p, i, pr, l, lA, e, ex, emin, emax, newprec;1599pari_sp av = avma;1600int allodd = 1;16011602ind = chk_ind(ind0, &M); if (!ind) return cgetg(1, t_VEC);1603l = lg(ind); F = cgetg(l, t_VEC);1604if (!M) /* silly degenerate case */1605{1606X = eval(E, x, prec);1607for (i = 1; i < l; i++) { chk_ord(ind[i]); gel(F,i) = X; }1608if (typ(ind0) == t_INT) F = gel(F,1);1609return gerepilecopy(av, F);1610}1611N2 = 3*M - 1; if (odd(N2)) N2++;1612N = N2 >> 1;1613FD(M, N2, &D,&A); /* optimal if 'eval' uses quadratic time */1614C = vecbinomial(N2); DM = gel(D,M);1615T = cgetg(N2+2, t_VEC);1616/* (2N)! / w'(i) = (2N)! / w'(-i) = (-1)^(N-i) binom(2*N, N-i) */1617t = gel(C, N+1);1618gel(T,1) = odd(N)? negi(t): t;1619for (i = 1; i <= N; i++)1620{1621t = gel(C, N-i+1);1622gel(T,2*i) = gel(T,2*i+1) = odd(N-i)? negi(t): t;1623}1624N = N2 >> 1; emin = LONG_MAX; emax = 0;1625for (i = 1; i <= N; i++)1626{1627e = expi(gel(DM,i)) + expi(gel(T,i));1628if (e < 0) continue; /* 0 */1629if (e < emin) emin = e;1630else if (e > emax) emax = e;1631}16321633p = precision(x);1634fpr = p ? prec2nbits(p): prec2nbits(prec);1635e = (fpr + 3*M*log2((double)M)) / (2*M);1636ex = gexpo(x);1637if (ex < 0) ex = 0; /* near 0 */1638pr = (long)ceil(fpr + e * M); /* ~ 3fpr/2 */1639newprec = nbits2prec(pr + (emax - emin) + ex + BITS_IN_LONG);1640switch(typ(x))1641{1642case t_REAL:1643case t_COMPLEX:1644x = gprec_w(x, newprec);1645}1646lA = lg(A); X = cgetg(lA, t_VEC);1647for (i = 1; i < l; i++)1648if (!odd(ind[i])) { allodd = 0; break; }1649/* if only odd derivation orders, the value at 0 (A[1]) is not needed */1650gel(X, 1) = gen_0;1651for (i = allodd? 2: 1; i < lA; i++)1652{1653GEN t = eval(E, gadd(x, gmul2n(gel(A,i), -e)), newprec);1654t = gmul(t, gel(T,i));1655if (!gprecision(t))1656t = is_scalar_t(typ(t))? gtofp(t, newprec): gmul(t, real_1(newprec));1657gel(X,i) = t;1658}16591660v = vfact(ind, N2, nbits2prec(fpr + 32));1661for (i = 1; i < l; i++)1662{1663long m = ind[i];1664GEN t = RgV_dotproduct(gel(D,m+1), X);1665gel(F,i) = gmul(t, gmul2n(gel(v, m), e*m));1666}1667if (typ(ind0) == t_INT) F = gel(F,1);1668return gerepilecopy(av, F);1669}1670/* v(t') */1671static long1672rfrac_val_deriv(GEN t)1673{1674long v = varn(gel(t,2));1675return gvaluation(deriv(t, v), pol_x(v));1676}16771678GEN1679derivfunk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec)1680{1681pari_sp av;1682GEN ind, xp, ixp, F, G;1683long i, l, vx, M;1684if (!ind0) return derivfun(E, eval, x, prec);1685switch(typ(x))1686{1687case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX:1688return derivnumk(E,eval, x, ind0, prec);1689case t_POL:1690ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);1691xp = RgX_deriv(x);1692x = RgX_to_ser(x, precdl+2 + M * (1+RgX_val(xp)));1693break;1694case t_RFRAC:1695ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);1696x = rfrac_to_ser(x, precdl+2 + M * (1+rfrac_val_deriv(x)));1697xp = derivser(x);1698break;1699case t_SER:1700ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC);1701xp = derivser(x);1702break;1703default: pari_err_TYPE("numerical derivation",x);1704return NULL; /*LCOV_EXCL_LINE*/1705}1706av = avma; vx = varn(x);1707ixp = M? ginv(xp): NULL;1708F = cgetg(M+2, t_VEC);1709gel(F,1) = eval(E, x, prec);1710for (i = 1; i <= M; i++) gel(F,i+1) = gmul(deriv(gel(F,i),vx), ixp);1711l = lg(ind); G = cgetg(l, t_VEC);1712for (i = 1; i < l; i++)1713{1714long m = ind[i]; chk_ord(m);1715gel(G,i) = gel(F,m+1);1716}1717if (typ(ind0) == t_INT) G = gel(G,1);1718return gerepilecopy(av, G);1719}17201721GEN1722derivfun(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec)1723{1724pari_sp av = avma;1725GEN xp;1726long vx;1727switch(typ(x))1728{1729case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX:1730return derivnum(E,eval, x, prec);1731case t_POL:1732xp = RgX_deriv(x);1733x = RgX_to_ser(x, precdl+2+ (1 + RgX_val(xp)));1734break;1735case t_RFRAC:1736x = rfrac_to_ser(x, precdl+2+ (1 + rfrac_val_deriv(x)));1737/* fall through */1738case t_SER:1739xp = derivser(x);1740break;1741default: pari_err_TYPE("formal derivation",x);1742return NULL; /*LCOV_EXCL_LINE*/1743}1744vx = varn(x);1745return gerepileupto(av, gdiv(deriv(eval(E, x, prec),vx), xp));1746}17471748GEN1749laurentseries(void *E, GEN (*f)(void*,GEN x, long), long M, long v, long prec)1750{1751pari_sp av = avma;1752long d;17531754if (v < 0) v = 0;1755d = maxss(M+1,1);1756for (;;)1757{1758long i, dr, vr;1759GEN s;1760s = cgetg(d+2, t_SER); s[1] = evalsigne(1) | evalvalp(1) | evalvarn(v);1761gel(s, 2) = gen_1; for (i = 3; i <= d+1; i++) gel(s, i) = gen_0;1762s = f(E, s, prec);1763if (typ(s) != t_SER || varn(s) != v) pari_err_TYPE("laurentseries", s);1764vr = valp(s);1765if (M < vr) { set_avma(av); return zeroser(v, M); }1766dr = lg(s) + vr - 3 - M;1767if (dr >= 0) return gerepileupto(av, s);1768set_avma(av); d -= dr;1769}1770}1771static GEN1772_evalclosprec(void *E, GEN x, long prec)1773{1774GEN s;1775push_localprec(prec); s = closure_callgen1((GEN)E, x);1776pop_localprec(); return s;1777}1778#define CLOS_ARGPREC __E, &_evalclosprec1779GEN1780laurentseries0(GEN f, long M, long v, long prec)1781{1782if (typ(f) != t_CLOSURE || closure_arity(f) != 1 || closure_is_variadic(f))1783pari_err_TYPE("laurentseries",f);1784EXPR_WRAP(f, laurentseries(CLOS_ARGPREC,M,v,prec));1785}17861787GEN1788derivnum0(GEN a, GEN code, GEN ind, long prec)1789{ EXPR_WRAP(code, derivfunk(EXPR_ARGPREC,a,ind,prec)); }17901791GEN1792derivfun0(GEN args, GEN def, GEN code, long k, long prec)1793{1794pari_sp av = avma;1795struct deriv_data E;1796GEN z;1797E.code=code; E.args=args; E.def=def;1798z = gel(derivfunk((void*)&E, deriv_eval, gel(args,1), mkvecs(k), prec),1);1799return gerepilecopy(av, z);1800}18011802/********************************************************************/1803/** Numerical extrapolation **/1804/********************************************************************/1805/* [u(n), u <= N] */1806static GEN1807get_u(void *E, GEN (*f)(void *, GEN, long), long N, long prec)1808{1809long n;1810GEN u;1811if (f)1812{1813GEN v = f(E, utoipos(N), prec);1814u = cgetg(N+1, t_VEC);1815if (typ(v) != t_VEC || lg(v) != N+1) { gel(u,N) = v; v = NULL; }1816else1817{1818GEN w = f(E, gen_1, LOWDEFAULTPREC);1819if (typ(w) != t_VEC || lg(w) != 2) { gel(u,N) = v; v = NULL; }1820}1821if (v) u = v;1822else1823for (n = 1; n < N; n++) gel(u,n) = f(E, utoipos(n), prec);1824}1825else1826{1827GEN v = (GEN)E;1828long t = lg(v)-1;1829if (t < N) pari_err_COMPONENT("limitnum","<",stoi(N), stoi(t));1830u = vecslice(v, 1, N);1831}1832for (n = 1; n <= N; n++)1833{1834GEN un = gel(u,n);1835if (is_rational_t(typ(un))) gel(u,n) = gtofp(un, prec);1836}1837return u;1838}18391840struct limit1841{1842long prec; /* working accuracy */1843long N; /* number of terms */1844GEN na; /* [n^alpha, n <= N] */1845GEN coef; /* or NULL (alpha != 1) */1846};18471848static GEN1849_gi(void *E, GEN x)1850{1851GEN A = (GEN)E, y = gsubgs(x, 1);1852if (gequal0(y)) return A;1853return gdiv(gsubgs(gpow(x, A, LOWDEFAULTPREC), 1), y);1854}1855static GEN1856_g(void *E, GEN x)1857{1858GEN D = (GEN)E, A = gel(D,1), T = gel(D,2);1859const long prec = LOWDEFAULTPREC;1860return gadd(glog(x,prec), intnum((void*)A, _gi, gen_0, gaddgs(x,1), T, prec));1861}18621863/* solve log(b) + int_0^{b+1} (x^(1/a)-1) / (x-1) dx = 0, b in [0,1]1864* return -log_2(b), rounded up */1865static double1866get_accu(GEN a)1867{1868pari_sp av = avma;1869const long prec = LOWDEFAULTPREC;1870const double We2 = 1.844434455794; /* (W(1/e) + 1) / log(2) */1871GEN b, T;1872if (!a) return We2;1873if (typ(a) == t_INT) switch(itos_or_0(a))1874{1875case 1: return We2;1876case 2: return 1.186955309668;1877case 3: return 0.883182331990;1878}1879else if (typ(a) == t_FRAC && equali1(gel(a,1))) switch(itos_or_0(gel(a,2)))1880{1881case 2: return 2.644090500290;1882case 3: return 3.157759214459;1883case 4: return 3.536383237500;1884}1885T = intnuminit(gen_0, gen_1, 0, prec);1886b = zbrent((void*)mkvec2(ginv(a), T), &_g, dbltor(1E-5), gen_1, prec);1887return gc_double(av, -dbllog2r(b));1888}18891890static double1891get_c(GEN a)1892{1893double A = a? gtodouble(a): 1.0;1894if (A <= 0) pari_err_DOMAIN("limitnum","alpha","<=",gen_0, a);1895if (A >= 2) return 0.2270;1896if (A >= 1) return 0.3318;1897if (A >= 0.5) return 0.6212;1898if (A >= 0.3333) return 1.2;1899return 3; /* only tested for A >= 0.25 */1900}1901static void1902limit_Nprec(struct limit *L, GEN alpha, long prec)1903{1904long bit = prec2nbits(prec);1905L->N = ceil(get_c(alpha) * bit);1906L->prec = nbits2prec(bit + (long)ceil(get_accu(alpha) * L->N));1907}1908/* solve x - a log(x) = b; a, b >= 3 */1909static double1910solvedivlog(double a, double b) { return dbllemma526(a,1,1,b); }19111912/* #u > 1, prod_{j != i} u[i] - u[j] */1913static GEN1914proddiff(GEN u, long i)1915{1916pari_sp av = avma;1917long l = lg(u), j;1918GEN p = NULL;1919if (i == 1)1920{1921p = gsub(gel(u,1), gel(u,2));1922for (j = 3; j < l; j++)1923p = gmul(p, gsub(gel(u,i), gel(u,j)));1924}1925else1926{1927p = gsub(gel(u,i), gel(u,1));1928for (j = 2; j < l; j++)1929if (j != i) p = gmul(p, gsub(gel(u,i), gel(u,j)));1930}1931return gerepileupto(av, p);1932}1933static GEN1934vecpows(GEN u, long N)1935{1936long i, l;1937GEN v = cgetg_copy(u, &l);1938for (i = 1; i < l; i++) gel(v,i) = gpowgs(gel(u,i), N);1939return v;1940}19411942static void1943limit_init(struct limit *L, GEN alpha, int asymp)1944{1945long n, N = L->N, a = 0;1946GEN c, v, T = NULL;19471948if (!alpha) a = 1;1949else if (typ(alpha) == t_INT)1950{1951a = itos_or_0(alpha);1952if (a > 2) a = 0;1953}1954else if (typ(alpha) == t_FRAC)1955{1956long na = itos_or_0(gel(alpha,1)), da = itos_or_0(gel(alpha,2));1957if (da && na && da <= 4 && na <= 4)1958{ /* don't bother with other cases */1959long e = (N-1) % da, k = (N-1) / da;1960if (e) { N += da - e; k++; } /* N = 1 (mod d) => simpler ^ (n/d)(N-1) */1961L->N = N;1962T = vecpowuu(N, na * k);1963}1964}1965L->coef = v = cgetg(N+1, t_VEC);1966if (!a)1967{1968long prec2 = gprecision(alpha);1969GEN u;1970if (prec2 && prec2 < L->prec) alpha = gprec_w(alpha, L->prec);1971L->na = u = vecpowug(N, alpha, L->prec);1972if (!T) T = vecpows(u, N-1);1973for (n = 1; n <= N; n++) gel(v,n) = gdiv(gel(T,n), proddiff(u,n));1974return;1975}1976L->na = asymp? vecpowuu(N, a): NULL;1977c = mpfactr(N-1, L->prec);1978if (a == 1)1979{1980c = invr(c);1981gel(v,1) = c; if (!odd(N)) togglesign(c);1982for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), n);1983}1984else1985{ /* a = 2 */1986c = invr(mulru(sqrr(c), (N*(N+1)) >> 1));1987gel(v,1) = c; if (!odd(N)) togglesign(c);1988for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), N+n);1989}1990T = vecpowuu(N, a*N);1991for (n = 2; n <= N; n++) gel(v,n) = mulri(gel(v,n), gel(T,n));1992}19931994/* Zagier/Lagrange extrapolation */1995static GEN1996limitnum_i(struct limit *L, GEN u, long prec)1997{ return gprec_w(RgV_dotproduct(u,L->coef), prec); }1998GEN1999limitnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec)2000{2001pari_sp av = avma;2002struct limit L;2003GEN u;2004limit_Nprec(&L, alpha, prec);2005limit_init(&L, alpha, 0);2006u = get_u(E, f, L.N, L.prec);2007return gerepilecopy(av, limitnum_i(&L, u, prec));2008}2009typedef GEN (*LIMIT_FUN)(void*,GEN,long);2010static LIMIT_FUN get_fun(GEN u, const char *s)2011{2012switch(typ(u))2013{2014case t_COL: case t_VEC: break;2015case t_CLOSURE: return gp_callprec;2016default: pari_err_TYPE(s, u);2017}2018return NULL;2019}2020GEN2021limitnum0(GEN u, GEN alpha, long prec)2022{ return limitnum((void*)u,get_fun(u, "limitnum"), alpha, prec); }20232024GEN2025asympnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec)2026{2027const long MAX = 100;2028pari_sp av = avma;2029GEN u, A = cgetg(MAX+1, t_VEC);2030long i, B = prec2nbits(prec);2031double LB = 0.9*expu(B); /* 0.9 and 0.95 below are heuristic */2032struct limit L;2033limit_Nprec(&L, alpha, prec);2034if (alpha) LB *= gtodouble(alpha);2035limit_init(&L, alpha, 1);2036u = get_u(E, f, L.N, L.prec);2037for(i = 1; i <= MAX; i++)2038{2039GEN a, v, q, s = limitnum_i(&L, u, prec);2040long n;2041/* NOT bestappr: lindep properly ignores the lower bits */2042v = lindep_bit(mkvec2(gen_1, s), maxss((long)(0.95*floor(B - i*LB)), 32));2043if (lg(v) == 1) break;2044q = gel(v,2); if (!signe(q)) break;2045a = gdiv(negi(gel(v,1)), q);2046s = gsub(s, a);2047/* |s|q^2 > eps */2048if (!gequal0(s) && gexpo(s) + 2*expi(q) > -17) break;2049gel(A,i) = a;2050for (n = 1; n <= L.N; n++) gel(u,n) = gmul(gsub(gel(u,n), a), gel(L.na,n));2051}2052setlg(A,i); return gerepilecopy(av, A);2053}2054GEN2055asympnumraw(void *E, GEN (*f)(void *,GEN,long), long LIM, GEN alpha, long prec)2056{2057pari_sp av = avma;2058double c, d, al;2059long i, B;2060GEN u, A;2061struct limit L;20622063if (LIM < 0) return cgetg(1, t_VEC);2064c = get_c(alpha);2065d = get_accu(alpha);2066al = alpha? gtodouble(alpha): 1.0;2067B = prec2nbits(prec);2068L.N = ceil(solvedivlog(c * al * LIM / M_LN2, c * B));2069L.prec = nbits2prec(ceil(B + L.N / c + d * L.N));2070limit_init(&L, alpha, 1);2071u = get_u(E, f, L.N, L.prec);2072A = cgetg(LIM+2, t_VEC);2073for(i = 0; i <= LIM; i++)2074{2075GEN a = RgV_dotproduct(u,L.coef);2076long n;2077for (n = 1; n <= L.N; n++)2078gel(u,n) = gprec_wensure(gmul(gsub(gel(u,n), a), gel(L.na,n)), L.prec);2079gel(A,i+1) = gprec_wtrunc(a, prec);2080}2081return gerepilecopy(av, A);2082}2083GEN2084asympnum0(GEN u, GEN alpha, long prec)2085{ return asympnum((void*)u,get_fun(u, "asympnum"), alpha, prec); }2086GEN2087asympnumraw0(GEN u, long LIM, GEN alpha, long prec)2088{ return asympnumraw((void*)u,get_fun(u, "asympnumraw"), LIM, alpha, prec); }208920902091