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/*********************************************************************/15/** **/16/** ARITHMETIC FUNCTIONS **/17/** (second part) **/18/** **/19/*********************************************************************/20#include "pari.h"21#include "paripriv.h"2223#define DEBUGLEVEL DEBUGLEVEL_arith2425GEN26boundfact(GEN n, ulong lim)27{28switch(typ(n))29{30case t_INT: return Z_factor_limit(n,lim);31case t_FRAC: {32pari_sp av = avma;33GEN a = Z_factor_limit(gel(n,1),lim);34GEN b = Z_factor_limit(gel(n,2),lim);35gel(b,2) = ZC_neg(gel(b,2));36return gerepilecopy(av, merge_factor(a,b,(void*)&cmpii,cmp_nodata));37}38}39pari_err_TYPE("boundfact",n);40return NULL; /* LCOV_EXCL_LINE */41}4243/* NOT memory clean */44GEN45Z_lsmoothen(GEN N, GEN L, GEN *pP, GEN *pE)46{47long i, j, l = lg(L);48GEN E = new_chunk(l), P = new_chunk(l);49for (i = j = 1; i < l; i++)50{51ulong p = uel(L,i);52long v = Z_lvalrem(N, p, &N);53if (v) { P[j] = p; E[j] = v; j++; if (is_pm1(N)) { N = NULL; break; } }54}55P[0] = evaltyp(t_VECSMALL) | evallg(j); if (pP) *pP = P;56E[0] = evaltyp(t_VECSMALL) | evallg(j); if (pE) *pE = E; return N;57}58GEN59Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pE)60{61long i, j, l = lg(L);62GEN E = new_chunk(l), P = new_chunk(l);63for (i = j = 1; i < l; i++)64{65GEN p = gel(L,i);66long v = Z_pvalrem(N, p, &N);67if (v)68{69gel(P,j) = p; gel(E,j) = utoipos(v); j++;70if (is_pm1(N)) { N = NULL; break; }71}72}73P[0] = evaltyp(t_COL) | evallg(j); if (pP) *pP = P;74E[0] = evaltyp(t_COL) | evallg(j); if (pE) *pE = E; return N;75}76/***********************************************************************/77/** **/78/** SIMPLE FACTORISATIONS **/79/** **/80/***********************************************************************/81/* Factor n and output [p,e,c] where82* p, e and c are vecsmall with n = prod{p[i]^e[i]} and c[i] = p[i]^e[i] */83GEN84factoru_pow(ulong n)85{86GEN f = cgetg(4,t_VEC);87pari_sp av = avma;88GEN F, P, E, p, e, c;89long i, l;90/* enough room to store <= 15 * [p,e,p^e] (OK if n < 2^64) */91(void)new_chunk((15 + 1)*3);92F = factoru(n);93P = gel(F,1);94E = gel(F,2); l = lg(P);95set_avma(av);96gel(f,1) = p = cgetg(l,t_VECSMALL);97gel(f,2) = e = cgetg(l,t_VECSMALL);98gel(f,3) = c = cgetg(l,t_VECSMALL);99for(i = 1; i < l; i++)100{101p[i] = P[i];102e[i] = E[i];103c[i] = upowuu(p[i], e[i]);104}105return f;106}107108static GEN109factorlim(GEN n, ulong lim)110{ return lim? Z_factor_limit(n, lim): Z_factor(n); }111/* factor p^n - 1, assuming p prime. If lim != 0, limit factorization to112* primes <= lim */113GEN114factor_pn_1_limit(GEN p, long n, ulong lim)115{116pari_sp av = avma;117GEN A = factorlim(subiu(p,1), lim), d = divisorsu(n);118long i, pp = itos_or_0(p);119for(i=2; i<lg(d); i++)120{121GEN B;122if (pp && d[i]%pp==0 && (123((pp&3)==1 && (d[i]&1)) ||124((pp&3)==3 && (d[i]&3)==2) ||125(pp==2 && (d[i]&7)==4)))126{127GEN f=factor_Aurifeuille_prime(p,d[i]);128B = factorlim(f, lim);129A = merge_factor(A, B, (void*)&cmpii, cmp_nodata);130B = factorlim(diviiexact(polcyclo_eval(d[i],p), f), lim);131}132else133B = factorlim(polcyclo_eval(d[i],p), lim);134A = merge_factor(A, B, (void*)&cmpii, cmp_nodata);135}136return gerepilecopy(av, A);137}138GEN139factor_pn_1(GEN p, ulong n)140{ return factor_pn_1_limit(p, n, 0); }141142#if 0143static GEN144to_mat(GEN p, long e) {145GEN B = cgetg(3, t_MAT);146gel(B,1) = mkcol(p);147gel(B,2) = mkcol(utoipos(e)); return B;148}149/* factor phi(n) */150GEN151factor_eulerphi(GEN n)152{153pari_sp av = avma;154GEN B = NULL, A, P, E, AP, AE;155long i, l, v = vali(n);156157l = lg(n);158/* result requires less than this: at most expi(n) primes */159(void)new_chunk(bit_accuracy(l) * (l /*p*/ + 3 /*e*/ + 2 /*vectors*/) + 3+2);160if (v) { n = shifti(n, -v); v--; }161A = Z_factor(n); P = gel(A,1); E = gel(A,2); l = lg(P);162for(i = 1; i < l; i++)163{164GEN p = gel(P,i), q = subiu(p,1), fa;165long e = itos(gel(E,i)), w;166167w = vali(q); v += w; q = shifti(q,-w);168if (! is_pm1(q))169{170fa = Z_factor(q);171B = B? merge_factor(B, fa, (void*)&cmpii, cmp_nodata): fa;172}173if (e > 1) {174if (B) {175gel(B,1) = vec_append(gel(B,1), p);176gel(B,2) = vec_append(gel(B,2), utoipos(e-1));177} else178B = to_mat(p, e-1);179}180}181set_avma(av);182if (!B) return v? to_mat(gen_2, v): trivial_fact();183A = cgetg(3, t_MAT);184P = gel(B,1); E = gel(B,2); l = lg(P);185AP = cgetg(l+1, t_COL); gel(A,1) = AP; AP++;186AE = cgetg(l+1, t_COL); gel(A,2) = AE; AE++;187/* prepend "2^v" */188gel(AP,0) = gen_2;189gel(AE,0) = utoipos(v);190for (i = 1; i < l; i++)191{192gel(AP,i) = icopy(gel(P,i));193gel(AE,i) = icopy(gel(E,i));194}195return A;196}197#endif198199/***********************************************************************/200/** **/201/** CHECK FACTORIZATION FOR ARITHMETIC FUNCTIONS **/202/** **/203/***********************************************************************/204int205RgV_is_ZVpos(GEN v)206{207long i, l = lg(v);208for (i = 1; i < l; i++)209{210GEN c = gel(v,i);211if (typ(c) != t_INT || signe(c) <= 0) return 0;212}213return 1;214}215/* check whether v is a ZV with nonzero entries */216int217RgV_is_ZVnon0(GEN v)218{219long i, l = lg(v);220for (i = 1; i < l; i++)221{222GEN c = gel(v,i);223if (typ(c) != t_INT || !signe(c)) return 0;224}225return 1;226}227/* check whether v is a ZV with nonzero entries OR exactly [0] */228static int229RgV_is_ZV0(GEN v)230{231long i, l = lg(v);232for (i = 1; i < l; i++)233{234GEN c = gel(v,i);235long s;236if (typ(c) != t_INT) return 0;237s = signe(c);238if (!s) return (l == 2);239}240return 1;241}242243static int244RgV_is_prV(GEN v)245{246long l = lg(v), i;247for (i = 1; i < l; i++)248if (!checkprid_i(gel(v,i))) return 0;249return 1;250}251int252is_nf_factor(GEN F)253{254return typ(F) == t_MAT && lg(F) == 3255&& RgV_is_prV(gel(F,1)) && RgV_is_ZVpos(gel(F,2));256}257int258is_nf_extfactor(GEN F)259{260return typ(F) == t_MAT && lg(F) == 3261&& RgV_is_prV(gel(F,1)) && RgV_is_ZV(gel(F,2));262}263264static int265is_Z_factor_i(GEN f)266{ return typ(f) == t_MAT && lg(f) == 3 && RgV_is_ZVpos(gel(f,2)); }267int268is_Z_factorpos(GEN f)269{ return is_Z_factor_i(f) && RgV_is_ZVpos(gel(f,1)); }270int271is_Z_factor(GEN f)272{ return is_Z_factor_i(f) && RgV_is_ZV0(gel(f,1)); }273/* as is_Z_factorpos, also allow factor(0) */274int275is_Z_factornon0(GEN f)276{ return is_Z_factor_i(f) && RgV_is_ZVnon0(gel(f,1)); }277GEN278clean_Z_factor(GEN f)279{280GEN P = gel(f,1);281long n = lg(P)-1;282if (n && equalim1(gel(P,1)))283return mkmat2(vecslice(P,2,n), vecslice(gel(f,2),2,n));284return f;285}286GEN287fuse_Z_factor(GEN f, GEN B)288{289GEN P = gel(f,1), E = gel(f,2), P2,E2;290long i, l = lg(P);291if (l == 1) return f;292for (i = 1; i < l; i++)293if (abscmpii(gel(P,i), B) > 0) break;294if (i == l) return f;295/* tail / initial segment */296P2 = vecslice(P, i, l-1); P = vecslice(P, 1, i-1);297E2 = vecslice(E, i, l-1); E = vecslice(E, 1, i-1);298P = vec_append(P, factorback2(P2,E2));299E = vec_append(E, gen_1);300return mkmat2(P, E);301}302303/* n attached to a factorization of a positive integer: either N (t_INT)304* a factorization matrix faN, or a t_VEC: [N, faN] */305GEN306check_arith_pos(GEN n, const char *f) {307switch(typ(n))308{309case t_INT:310if (signe(n) <= 0) pari_err_DOMAIN(f, "argument", "<=", gen_0, gen_0);311return NULL;312case t_VEC:313if (lg(n) != 3 || typ(gel(n,1)) != t_INT || signe(gel(n,1)) <= 0) break;314n = gel(n,2); /* fall through */315case t_MAT:316if (!is_Z_factorpos(n)) break;317return n;318}319pari_err_TYPE(f,n);320return NULL;/*LCOV_EXCL_LINE*/321}322/* n attached to a factorization of a nonzero integer */323GEN324check_arith_non0(GEN n, const char *f) {325switch(typ(n))326{327case t_INT:328if (!signe(n)) pari_err_DOMAIN(f, "argument", "=", gen_0, gen_0);329return NULL;330case t_VEC:331if (lg(n) != 3 || typ(gel(n,1)) != t_INT || !signe(gel(n,1))) break;332n = gel(n,2); /* fall through */333case t_MAT:334if (!is_Z_factornon0(n)) break;335return n;336}337pari_err_TYPE(f,n);338return NULL;/*LCOV_EXCL_LINE*/339}340/* n attached to a factorization of an integer */341GEN342check_arith_all(GEN n, const char *f) {343switch(typ(n))344{345case t_INT:346return NULL;347case t_VEC:348if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break;349n = gel(n,2); /* fall through */350case t_MAT:351if (!is_Z_factor(n)) break;352return n;353}354pari_err_TYPE(f,n);355return NULL;/*LCOV_EXCL_LINE*/356}357358/***********************************************************************/359/** **/360/** MISCELLANEOUS ARITHMETIC FUNCTIONS **/361/** (ultimately depend on Z_factor()) **/362/** **/363/***********************************************************************/364/* set P,E from F. Check whether F is an integer and kill "factor" -1 */365static void366set_fact_check(GEN F, GEN *pP, GEN *pE, int *isint)367{368GEN E, P;369if (lg(F) != 3) pari_err_TYPE("divisors",F);370P = gel(F,1);371E = gel(F,2);372RgV_check_ZV(E, "divisors");373*isint = RgV_is_ZV(P);374if (*isint)375{376long i, l = lg(P);377/* skip -1 */378if (l>1 && signe(gel(P,1)) < 0) { E++; P = vecslice(P,2,--l); }379/* test for 0 */380for (i = 1; i < l; i++)381if (!signe(gel(P,i)) && signe(gel(E,i)))382pari_err_DOMAIN("divisors", "argument", "=", gen_0, F);383}384*pP = P;385*pE = E;386}387static void388set_fact(GEN F, GEN *pP, GEN *pE) { *pP = gel(F,1); *pE = gel(F,2); }389390int391divisors_init(GEN n, GEN *pP, GEN *pE)392{393long i,l;394GEN E, P, e;395int isint;396397switch(typ(n))398{399case t_INT:400if (!signe(n)) pari_err_DOMAIN("divisors", "argument", "=", gen_0, gen_0);401set_fact(absZ_factor(n), &P,&E);402isint = 1; break;403case t_VEC:404if (lg(n) != 3 || typ(gel(n,2)) !=t_MAT) pari_err_TYPE("divisors",n);405set_fact_check(gel(n,2), &P,&E, &isint);406break;407case t_MAT:408set_fact_check(n, &P,&E, &isint);409break;410default:411set_fact(factor(n), &P,&E);412isint = 0; break;413}414l = lg(P);415e = cgetg(l, t_VECSMALL);416for (i=1; i<l; i++)417{418e[i] = itos(gel(E,i));419if (e[i] < 0) pari_err_TYPE("divisors [denominator]",n);420}421*pP = P; *pE = e; return isint;422}423424static long425ndiv(GEN E)426{427long i, l;428GEN e = cgetg_copy(E, &l); /* left on stack */429ulong n;430for (i=1; i<l; i++) e[i] = E[i]+1;431n = itou_or_0( zv_prod_Z(e) );432if (!n || n & ~LGBITS) pari_err_OVERFLOW("divisors");433return n;434}435static int436cmpi1(void *E, GEN a, GEN b) { (void)E; return cmpii(gel(a,1), gel(b,1)); }437/* P a t_COL of objects, E a t_VECSMALL of exponents, return cleaned-up438* factorization (removing 0 exponents) as a t_MAT with 2 cols. */439static GEN440fa_clean(GEN P, GEN E)441{442long i, j, l = lg(E);443GEN Q = cgetg(l, t_COL);444for (i = j = 1; i < l; i++)445if (E[i]) { gel(Q,j) = gel(P,i); E[j] = E[i]; j++; }446setlg(Q,j);447setlg(E,j); return mkmat2(Q,Flc_to_ZC(E));448}449GEN450divisors_factored(GEN N)451{452pari_sp av = avma;453GEN *d, *t1, *t2, *t3, D, P, E;454int isint = divisors_init(N, &P, &E);455GEN (*mul)(GEN,GEN) = isint? mulii: gmul;456long i, j, l, n = ndiv(E);457458D = cgetg(n+1,t_VEC); d = (GEN*)D;459l = lg(E);460*++d = mkvec2(gen_1, const_vecsmall(l-1,0));461for (i=1; i<l; i++)462for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)463for (t2=d, t3=t1; t3<t2; )464{465GEN a, b;466a = mul(gel(*++t3,1), gel(P,i));467b = leafcopy(gel(*t3,2)); b[i]++;468*++d = mkvec2(a,b);469}470if (isint) gen_sort_inplace(D,NULL,&cmpi1,NULL);471for (i = 1; i <= n; i++) gmael(D,i,2) = fa_clean(P, gmael(D,i,2));472return gerepilecopy(av, D);473}474static int475cmpu1(void *E, GEN va, GEN vb)476{ long a = va[1], b = vb[1]; (void)E; return a>b? 1: (a<b? -1: 0); }477static GEN478fa_clean_u(GEN P, GEN E)479{480long i, j, l = lg(E);481GEN Q = cgetg(l, t_VECSMALL);482for (i = j = 1; i < l; i++)483if (E[i]) { Q[j] = P[i]; E[j] = E[i]; j++; }484setlg(Q,j);485setlg(E,j); return mkmat2(Q,E);486}487GEN488divisorsu_fact_factored(GEN fa)489{490pari_sp av = avma;491GEN *d, *t1, *t2, *t3, vD, D, P = gel(fa,1), E = gel(fa,2);492long i, j, l, n = ndiv(E);493494D = cgetg(n+1,t_VEC); d = (GEN*)D;495l = lg(E);496*++d = mkvec2((GEN)1, const_vecsmall(l-1,0));497for (i=1; i<l; i++)498for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)499for (t2=d, t3=t1; t3<t2; )500{501ulong a;502GEN b;503a = (*++t3)[1] * P[i];504b = leafcopy(gel(*t3,2)); b[i]++;505*++d = mkvec2((GEN)a,b);506}507gen_sort_inplace(D,NULL,&cmpu1,NULL);508vD = cgetg(n+1, t_VECSMALL);509for (i = 1; i <= n; i++)510{511vD[i] = umael(D,i,1);512gel(D,i) = fa_clean_u(P, gmael(D,i,2));513}514return gerepilecopy(av, mkvec2(vD,D));515}516GEN517divisors(GEN N)518{519long i, j, l;520GEN *d, *t1, *t2, *t3, D, P, E;521int isint = divisors_init(N, &P, &E);522GEN (*mul)(GEN,GEN) = isint? mulii: gmul;523524D = cgetg(ndiv(E)+1,t_VEC); d = (GEN*)D;525l = lg(E);526*++d = gen_1;527for (i=1; i<l; i++)528for (t1=(GEN*)D,j=E[i]; j; j--,t1=t2)529for (t2=d, t3=t1; t3<t2; ) *++d = mul(*++t3, gel(P,i));530if (isint) ZV_sort_inplace(D);531return D;532}533GEN534divisors0(GEN N, long flag)535{536if (flag && flag != 1) pari_err_FLAG("divisors");537return flag? divisors_factored(N): divisors(N);538}539540GEN541divisorsu_moebius(GEN P)542{543GEN d, t, t2, t3;544long i, l = lg(P);545d = t = cgetg((1 << (l-1)) + 1, t_VECSMALL);546*++d = 1;547for (i=1; i<l; i++)548for (t2=d, t3=t; t3<t2; ) *(++d) = *(++t3) * -P[i];549return t;550}551GEN552divisorsu_fact(GEN fa)553{554GEN d, t, t1, t2, t3, P = gel(fa,1), E = gel(fa,2);555long i, j, l = lg(P);556d = t = cgetg(numdivu_fact(fa) + 1,t_VECSMALL);557*++d = 1;558for (i=1; i<l; i++)559for (t1=t,j=E[i]; j; j--,t1=t2)560for (t2=d, t3=t1; t3<t2; ) *(++d) = *(++t3) * P[i];561vecsmall_sort(t); return t;562}563GEN564divisorsu(ulong N)565{566pari_sp av = avma;567return gerepileupto(av, divisorsu_fact(factoru(N)));568}569570static GEN571corefa(GEN fa)572{573GEN P = gel(fa,1), E = gel(fa,2), c = gen_1;574long i;575for (i=1; i<lg(P); i++)576if (mod2(gel(E,i))) c = mulii(c,gel(P,i));577return c;578}579static GEN580core2fa(GEN fa)581{582GEN P = gel(fa,1), E = gel(fa,2), c = gen_1, f = gen_1;583long i;584for (i=1; i<lg(P); i++)585{586long e = itos(gel(E,i));587if (e & 1) c = mulii(c, gel(P,i));588if (e != 1) f = mulii(f, powiu(gel(P,i), e >> 1));589}590return mkvec2(c,f);591}592GEN593corepartial(GEN n, long all)594{595pari_sp av = avma;596if (typ(n) != t_INT) pari_err_TYPE("corepartial",n);597return gerepileuptoint(av, corefa(Z_factor_limit(n,all)));598}599GEN600core2partial(GEN n, long all)601{602pari_sp av = avma;603if (typ(n) != t_INT) pari_err_TYPE("core2partial",n);604return gerepilecopy(av, core2fa(Z_factor_limit(n,all)));605}606/* given an arithmetic function argument, return the underlying integer */607static GEN608arith_n(GEN A)609{610switch(typ(A))611{612case t_INT: return A;613case t_VEC: return gel(A,1);614default: return factorback(A);615}616}617static GEN618core2_i(GEN n)619{620GEN f = core(n);621if (!signe(f)) return mkvec2(gen_0, gen_1);622return mkvec2(f, sqrtint(diviiexact(arith_n(n), f)));623}624GEN625core2(GEN n) { pari_sp av = avma; return gerepilecopy(av, core2_i(n)); }626627GEN628core0(GEN n,long flag) { return flag? core2(n): core(n); }629630static long631_mod4(GEN c) {632long r, s = signe(c);633if (!s) return 0;634r = mod4(c); if (s < 0) r = 4-r;635return r;636}637638long639corediscs(long D, ulong *f)640{641/* D = f^2 dK */642long dK = D>=0 ? (long) coreu(D) : -(long) coreu(-(ulong) D);643ulong dKmod4 = ((ulong)dK)&3UL;644if (dKmod4 == 2 || dKmod4 == 3)645dK *= 4;646if (f) *f = usqrt((ulong)(D/dK));647return D;648}649650GEN651coredisc(GEN n)652{653pari_sp av = avma;654GEN c = core(n);655if (_mod4(c)<=1) return c; /* c = 0 or 1 mod 4 */656return gerepileuptoint(av, shifti(c,2));657}658659GEN660coredisc2(GEN n)661{662pari_sp av = avma;663GEN y = core2_i(n);664GEN c = gel(y,1), f = gel(y,2);665if (_mod4(c)<=1) return gerepilecopy(av, y);666y = cgetg(3,t_VEC);667gel(y,1) = shifti(c,2);668gel(y,2) = gmul2n(f,-1); return gerepileupto(av, y);669}670671GEN672coredisc0(GEN n,long flag) { return flag? coredisc2(n): coredisc(n); }673674long675omegau(ulong n)676{677pari_sp av;678if (n == 1UL) return 0;679av = avma; return gc_long(av, nbrows(factoru(n)));680}681long682omega(GEN n)683{684pari_sp av;685GEN F, P;686if ((F = check_arith_non0(n,"omega"))) {687long n;688P = gel(F,1); n = lg(P)-1;689if (n && equalim1(gel(P,1))) n--;690return n;691}692if (lgefint(n) == 3) return omegau(n[2]);693av = avma;694F = absZ_factor(n);695return gc_long(av, nbrows(F));696}697698long699bigomegau(ulong n)700{701pari_sp av;702if (n == 1) return 0;703av = avma; return gc_long(av, zv_sum(gel(factoru(n),2)));704}705long706bigomega(GEN n)707{708pari_sp av = avma;709GEN F, E;710if ((F = check_arith_non0(n,"bigomega")))711{712GEN P = gel(F,1);713long n = lg(P)-1;714E = gel(F,2);715if (n && equalim1(gel(P,1))) E = vecslice(E,2,n);716}717else if (lgefint(n) == 3)718return bigomegau(n[2]);719else720E = gel(absZ_factor(n), 2);721E = ZV_to_zv(E);722return gc_long(av, zv_sum(E));723}724725/* assume f = factoru(n), possibly with 0 exponents. Return phi(n) */726ulong727eulerphiu_fact(GEN f)728{729GEN P = gel(f,1), E = gel(f,2);730long i, m = 1, l = lg(P);731for (i = 1; i < l; i++)732{733ulong p = P[i], e = E[i];734if (!e) continue;735if (p == 2)736{ if (e > 1) m <<= e-1; }737else738{739m *= (p-1);740if (e > 1) m *= upowuu(p, e-1);741}742}743return m;744}745ulong746eulerphiu(ulong n)747{748pari_sp av;749if (!n) return 2;750av = avma; return gc_long(av, eulerphiu_fact(factoru(n)));751}752GEN753eulerphi(GEN n)754{755pari_sp av = avma;756GEN Q, F, P, E;757long i, l;758759if ((F = check_arith_all(n,"eulerphi")))760{761F = clean_Z_factor(F);762n = arith_n(n);763if (lgefint(n) == 3)764{765ulong e;766F = mkmat2(ZV_to_nv(gel(F,1)), ZV_to_nv(gel(F,2)));767e = eulerphiu_fact(F);768set_avma(av); return utoipos(e);769}770}771else if (lgefint(n) == 3) return utoipos(eulerphiu(uel(n,2)));772else773F = absZ_factor(n);774if (!signe(n)) return gen_2;775P = gel(F,1);776E = gel(F,2); l = lg(P);777Q = cgetg(l, t_VEC);778for (i = 1; i < l; i++)779{780GEN p = gel(P,i), q;781ulong v = itou(gel(E,i));782q = subiu(p,1);783if (v != 1) q = mulii(q, v == 2? p: powiu(p, v-1));784gel(Q,i) = q;785}786return gerepileuptoint(av, ZV_prod(Q));787}788789long790numdivu_fact(GEN fa)791{792GEN E = gel(fa,2);793long n = 1, i, l = lg(E);794for (i = 1; i < l; i++) n *= E[i]+1;795return n;796}797long798numdivu(long N)799{800pari_sp av;801if (N == 1) return 1;802av = avma; return gc_long(av, numdivu_fact(factoru(N)));803}804static GEN805numdiv_aux(GEN F)806{807GEN x, E = gel(F,2);808long i, l = lg(E);809x = cgetg(l, t_VECSMALL);810for (i=1; i<l; i++) x[i] = itou(gel(E,i))+1;811return x;812}813GEN814numdiv(GEN n)815{816pari_sp av = avma;817GEN F, E;818if ((F = check_arith_non0(n,"numdiv")))819{820F = clean_Z_factor(F);821E = numdiv_aux(F);822}823else if (lgefint(n) == 3)824return utoipos(numdivu(n[2]));825else826E = numdiv_aux(absZ_factor(n));827return gerepileuptoint(av, zv_prod_Z(E));828}829830/* 1 + p + ... + p^v, p != 2^BIL - 1 */831static GEN832u_euler_sumdiv(ulong p, long v)833{834GEN u = utoipos(1 + p); /* can't overflow */835for (; v > 1; v--) u = addui(1, mului(p, u));836return u;837}838/* 1 + q + ... + q^v */839static GEN840euler_sumdiv(GEN q, long v)841{842GEN u = addui(1, q);843for (; v > 1; v--) u = addui(1, mulii(q, u));844return u;845}846847static GEN848sumdiv_aux(GEN F)849{850GEN x, P = gel(F,1), E = gel(F,2);851long i, l = lg(P);852x = cgetg(l, t_VEC);853for (i=1; i<l; i++) gel(x,i) = euler_sumdiv(gel(P,i), itou(gel(E,i)));854return ZV_prod(x);855}856GEN857sumdiv(GEN n)858{859pari_sp av = avma;860GEN F, v;861862if ((F = check_arith_non0(n,"sumdiv")))863{864F = clean_Z_factor(F);865v = sumdiv_aux(F);866}867else if (lgefint(n) == 3)868{869if (n[2] == 1) return gen_1;870F = factoru(n[2]);871v = usumdiv_fact(F);872}873else874v = sumdiv_aux(absZ_factor(n));875return gerepileuptoint(av, v);876}877878static GEN879sumdivk_aux(GEN F, long k)880{881GEN x, P = gel(F,1), E = gel(F,2);882long i, l = lg(P);883x = cgetg(l, t_VEC);884for (i=1; i<l; i++) gel(x,i) = euler_sumdiv(powiu(gel(P,i),k), gel(E,i)[2]);885return ZV_prod(x);886}887GEN888sumdivk(GEN n, long k)889{890pari_sp av = avma;891GEN F, v;892long k1;893894if (!k) return numdiv(n);895if (k == 1) return sumdiv(n);896if ((F = check_arith_non0(n,"sumdivk"))) F = clean_Z_factor(F);897k1 = k; if (k < 0) k = -k;898if (k == 1)899v = sumdiv(F? F: n);900else901{902if (F)903v = sumdivk_aux(F,k);904else if (lgefint(n) == 3)905{906if (n[2] == 1) return gen_1;907F = factoru(n[2]);908v = usumdivk_fact(F,k);909}910else911v = sumdivk_aux(absZ_factor(n), k);912if (k1 > 0) return gerepileuptoint(av, v);913}914915if (F) n = arith_n(n);916if (k != 1) n = powiu(n,k);917return gerepileupto(av, gdiv(v, n));918}919920GEN921usumdiv_fact(GEN f)922{923GEN P = gel(f,1), E = gel(f,2);924long i, l = lg(P);925GEN v = cgetg(l, t_VEC);926for (i=1; i<l; i++) gel(v,i) = u_euler_sumdiv(P[i],E[i]);927return ZV_prod(v);928}929GEN930usumdivk_fact(GEN f, ulong k)931{932GEN P = gel(f,1), E = gel(f,2);933long i, l = lg(P);934GEN v = cgetg(l, t_VEC);935for (i=1; i<l; i++) gel(v,i) = euler_sumdiv(powuu(P[i],k),E[i]);936return ZV_prod(v);937}938939long940uissquarefree_fact(GEN f)941{942GEN E = gel(f,2);943long i, l = lg(E);944for (i = 1; i < l; i++)945if (E[i] > 1) return 0;946return 1;947}948long949uissquarefree(ulong n)950{951if (!n) return 0;952return moebiusu(n)? 1: 0;953}954long955Z_issquarefree(GEN n)956{957switch(lgefint(n))958{959case 2: return 0;960case 3: return uissquarefree(n[2]);961}962return moebius(n)? 1: 0;963}964965static int966fa_issquarefree(GEN F)967{968GEN P = gel(F,1), E = gel(F,2);969long i, s, l = lg(P);970if (l == 1) return 1;971s = signe(gel(P,1)); /* = signe(x) */972if (!s) return 0;973for(i = 1; i < l; i++)974if (!equali1(gel(E,i))) return 0;975return 1;976}977long978issquarefree(GEN x)979{980pari_sp av;981GEN d;982switch(typ(x))983{984case t_INT: return Z_issquarefree(x);985case t_POL:986if (!signe(x)) return 0;987av = avma; d = RgX_gcd(x, RgX_deriv(x));988return gc_long(av, lg(d)==3);989case t_VEC:990case t_MAT: return fa_issquarefree(check_arith_all(x,"issquarefree"));991default: pari_err_TYPE("issquarefree",x);992return 0; /* LCOV_EXCL_LINE */993}994}995996/*********************************************************************/997/** **/998/** DIGITS / SUM OF DIGITS **/999/** **/1000/*********************************************************************/10011002/* set v[i] = 1 iff B^i is needed in the digits_dac algorithm */1003static void1004set_vexp(GEN v, long l)1005{1006long m;1007if (v[l]) return;1008v[l] = 1; m = l>>1;1009set_vexp(v, m);1010set_vexp(v, l-m);1011}10121013/* return all needed B^i for DAC algorithm, for lz digits */1014static GEN1015get_vB(GEN T, long lz, void *E, struct bb_ring *r)1016{1017GEN vB, vexp = const_vecsmall(lz, 0);1018long i, l = (lz+1) >> 1;1019vexp[1] = 1;1020vexp[2] = 1;1021set_vexp(vexp, lz);1022vB = zerovec(lz); /* unneeded entries remain = 0 */1023gel(vB, 1) = T;1024for (i = 2; i <= l; i++)1025if (vexp[i])1026{1027long j = i >> 1;1028GEN B2j = r->sqr(E, gel(vB,j));1029gel(vB,i) = odd(i)? r->mul(E, B2j, T): B2j;1030}1031return vB;1032}10331034static void1035gen_digits_dac(GEN x, GEN vB, long l, GEN *z,1036void *E, GEN div(void *E, GEN a, GEN b, GEN *r))1037{1038GEN q, r;1039long m = l>>1;1040if (l==1) { *z=x; return; }1041q = div(E, x, gel(vB,m), &r);1042gen_digits_dac(r, vB, m, z, E, div);1043gen_digits_dac(q, vB, l-m, z+m, E, div);1044}10451046static GEN1047gen_fromdigits_dac(GEN x, GEN vB, long i, long l, void *E,1048GEN add(void *E, GEN a, GEN b),1049GEN mul(void *E, GEN a, GEN b))1050{1051GEN a, b;1052long m = l>>1;1053if (l==1) return gel(x,i);1054a = gen_fromdigits_dac(x, vB, i, m, E, add, mul);1055b = gen_fromdigits_dac(x, vB, i+m, l-m, E, add, mul);1056return add(E, a, mul(E, b, gel(vB, m)));1057}10581059static GEN1060gen_digits_i(GEN x, GEN B, long n, void *E, struct bb_ring *r,1061GEN (*div)(void *E, GEN x, GEN y, GEN *r))1062{1063GEN z, vB;1064if (n==1) retmkvec(gcopy(x));1065vB = get_vB(B, n, E, r);1066z = cgetg(n+1, t_VEC);1067gen_digits_dac(x, vB, n, (GEN*)(z+1), E, div);1068return z;1069}10701071GEN1072gen_digits(GEN x, GEN B, long n, void *E, struct bb_ring *r,1073GEN (*div)(void *E, GEN x, GEN y, GEN *r))1074{1075pari_sp av = avma;1076return gerepilecopy(av, gen_digits_i(x, B, n, E, r, div));1077}10781079GEN1080gen_fromdigits(GEN x, GEN B, void *E, struct bb_ring *r)1081{1082pari_sp av = avma;1083long n = lg(x)-1;1084GEN vB = get_vB(B, n, E, r);1085GEN z = gen_fromdigits_dac(x, vB, 1, n, E, r->add, r->mul);1086return gerepilecopy(av, z);1087}10881089static GEN1090_addii(void *data /* ignored */, GEN x, GEN y)1091{ (void)data; return addii(x,y); }1092static GEN1093_sqri(void *data /* ignored */, GEN x) { (void)data; return sqri(x); }1094static GEN1095_mulii(void *data /* ignored */, GEN x, GEN y)1096{ (void)data; return mulii(x,y); }1097static GEN1098_dvmdii(void *data /* ignored */, GEN x, GEN y, GEN *r)1099{ (void)data; return dvmdii(x,y,r); }11001101static struct bb_ring Z_ring = { _addii, _mulii, _sqri };11021103static GEN1104check_basis(GEN B)1105{1106if (!B) return utoipos(10);1107if (typ(B)!=t_INT) pari_err_TYPE("digits",B);1108if (abscmpiu(B,2)<0) pari_err_DOMAIN("digits","B","<",gen_2,B);1109return B;1110}11111112/* x has l digits in base B, write them to z[0..l-1], vB[i] = B^i */1113static void1114digits_dacsmall(GEN x, GEN vB, long l, ulong* z)1115{1116pari_sp av = avma;1117GEN q,r;1118long m;1119if (l==1) { *z=itou(x); return; }1120m=l>>1;1121q = dvmdii(x, gel(vB,m), &r);1122digits_dacsmall(q,vB,l-m,z);1123digits_dacsmall(r,vB,m,z+l-m);1124set_avma(av);1125}11261127GEN1128digits(GEN x, GEN B)1129{1130pari_sp av=avma;1131long lz;1132GEN z, vB;1133if (typ(x)!=t_INT) pari_err_TYPE("digits",x);1134B = check_basis(B);1135if (signe(B)<0) pari_err_DOMAIN("digits","B","<",gen_0,B);1136if (!signe(x)) {set_avma(av); return cgetg(1,t_VEC); }1137if (abscmpii(x,B)<0) {set_avma(av); retmkvec(absi(x)); }1138if (Z_ispow2(B))1139{1140long k = expi(B);1141if (k == 1) return binaire(x);1142if (k < BITS_IN_LONG)1143{1144(void)new_chunk(4*(expi(x) + 2)); /* HACK */1145z = binary_2k_nv(x, k);1146set_avma(av); return Flv_to_ZV(z);1147}1148else1149{1150set_avma(av); return binary_2k(x, k);1151}1152}1153x = absi_shallow(x);1154lz = logint(x,B) + 1;1155if (lgefint(B)>3)1156{1157z = gerepileupto(av, gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii));1158vecreverse_inplace(z); return z;1159}1160else1161{1162vB = get_vB(B, lz, NULL, &Z_ring);1163(void)new_chunk(3*lz); /* HACK */1164z = zero_zv(lz);1165digits_dacsmall(x,vB,lz,(ulong*)(z+1));1166set_avma(av); return Flv_to_ZV(z);1167}1168}11691170static GEN1171fromdigitsu_dac(GEN x, GEN vB, long i, long l)1172{1173GEN a, b;1174long m = l>>1;1175if (l==1) return utoi(uel(x,i));1176if (l==2) return addumului(uel(x,i), uel(x,i+1), gel(vB, m));1177a = fromdigitsu_dac(x, vB, i, m);1178b = fromdigitsu_dac(x, vB, i+m, l-m);1179return addii(a, mulii(b, gel(vB, m)));1180}11811182GEN1183fromdigitsu(GEN x, GEN B)1184{1185pari_sp av = avma;1186long n = lg(x)-1;1187GEN vB, z;1188if (n==0) return gen_0;1189vB = get_vB(B, n, NULL, &Z_ring);1190z = fromdigitsu_dac(x, vB, 1, n);1191return gerepileuptoint(av, z);1192}11931194static int1195ZV_in_range(GEN v, GEN B)1196{1197long i, l = lg(v);1198for(i=1; i < l; i++)1199{1200GEN vi = gel(v, i);1201if (signe(vi) < 0 || cmpii(vi, B) >= 0)1202return 0;1203}1204return 1;1205}12061207GEN1208fromdigits(GEN x, GEN B)1209{1210pari_sp av = avma;1211if (typ(x)!=t_VEC || !RgV_is_ZV(x)) pari_err_TYPE("fromdigits",x);1212if (lg(x)==1) return gen_0;1213B = check_basis(B);1214if (Z_ispow2(B) && ZV_in_range(x, B))1215return fromdigits_2k(x, expi(B));1216x = vecreverse(x);1217return gerepileuptoint(av, gen_fromdigits(x, B, NULL, &Z_ring));1218}12191220static const ulong digsum[] ={12210,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,12229,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11,122312,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,122412,13,14,15,16,17,18,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,12259,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11,122612,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,122712,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,2,3,4,5,6,7,8,9,10,11,3,12284,5,6,7,8,9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,12299,10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,12309,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,123116,17,18,19,20,3,4,5,6,7,8,9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,123211,12,13,14,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,123312,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,123419,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,4,5,6,7,8,9,123510,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,123612,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,123711,12,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,123818,19,20,21,13,14,15,16,17,18,19,20,21,22,5,6,7,8,9,10,11,12,13,14,6,7,8,9,123910,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,124010,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16,124117,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14,124215,16,17,18,19,20,21,22,23,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,12,13,14,124315,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13,124414,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,124521,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18,124619,20,21,22,23,24,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,124710,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16,124817,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14,124915,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17,18,19,20,21,125022,23,24,25,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,125112,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,125219,20,21,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,125317,18,19,20,21,22,23,24,16,17,18,19,20,21,22,23,24,25,17,18,19,20,21,22,23,125424,25,26,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,125513,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,125620,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17,125718,19,20,21,22,23,24,25,17,18,19,20,21,22,23,24,25,26,18,19,20,21,22,23,24,125825,26,271259};12601261ulong1262sumdigitsu(ulong n)1263{1264ulong s = 0;1265while (n) { s += digsum[n % 1000]; n /= 1000; }1266return s;1267}12681269/* res=array of 9-digits integers, return sum_{0 <= i < l} sumdigits(res[i]) */1270static ulong1271sumdigits_block(ulong *res, long l)1272{1273ulong s = sumdigitsu(*--res);1274while (--l > 0) s += sumdigitsu(*--res);1275return s;1276}12771278GEN1279sumdigits(GEN n)1280{1281const long L = (long)(ULONG_MAX / 81);1282pari_sp av = avma;1283ulong *res;1284long l;12851286if (typ(n) != t_INT) pari_err_TYPE("sumdigits", n);1287switch(lgefint(n))1288{1289case 2: return gen_0;1290case 3: return utoipos(sumdigitsu(n[2]));1291}1292res = convi(n, &l);1293if (l < L)1294{1295ulong s = sumdigits_block(res, l);1296set_avma(av); return utoipos(s);1297}1298else /* Huge. Overflows ulong */1299{1300GEN S = gen_0;1301while (l > L)1302{1303S = addiu(S, sumdigits_block(res, L));1304res += L; l -= L;1305}1306if (l)1307S = addiu(S, sumdigits_block(res, l));1308return gerepileuptoint(av, S);1309}1310}13111312GEN1313sumdigits0(GEN x, GEN B)1314{1315pari_sp av = avma;1316GEN z;1317long lz;13181319if (!B) return sumdigits(x);1320if (typ(x) != t_INT) pari_err_TYPE("sumdigits", x);1321B = check_basis(B);1322if (Z_ispow2(B))1323{1324long k = expi(B);1325if (k == 1) { set_avma(av); return utoi(hammingweight(x)); }1326if (k < BITS_IN_LONG)1327{1328GEN z = binary_2k_nv(x, k);1329if (lg(z)-1 > 1L<<(BITS_IN_LONG-k)) /* may overflow */1330return gerepileuptoint(av, ZV_sum(Flv_to_ZV(z)));1331set_avma(av); return utoi(zv_sum(z));1332}1333return gerepileuptoint(av, ZV_sum(binary_2k(x, k)));1334}1335if (!signe(x)) { set_avma(av); return gen_0; }1336if (abscmpii(x,B)<0) { set_avma(av); return absi(x); }1337if (absequaliu(B,10)) { set_avma(av); return sumdigits(x); }1338x = absi_shallow(x); lz = logint(x,B) + 1;1339z = gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii);1340return gerepileuptoint(av, ZV_sum(z));1341}134213431344