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"16/*********************************************************************/17/** **/18/** BINARY DECOMPOSITION **/19/** **/20/*********************************************************************/2122INLINE GEN23inegate(GEN z) { return subsi(-1,z); }2425GEN26binary_zv(GEN x)27{28GEN xp, z;29long i, k, lx;30if (!signe(x)) return cgetg(1,t_VECSMALL);31xp = int_LSW(x);32lx = lgefint(x);33k = expi(x)+2;34z = cgetg(k, t_VECSMALL);35k--;36for(i = 2; i < lx; i++)37{38ulong u = *xp;39long j;40for (j=0; j<BITS_IN_LONG && k; j++) z[k--] = (u>>j)&1UL;41if (!k) break;42xp = int_nextW(xp);43}44return z;45}46static GEN47F2v_to_ZV_inplace(GEN v)48{49long i, l = lg(v);50v[0] = evaltyp(t_VEC) | _evallg(l);51for (i = 1; i < l; i++) gel(v,i) = v[i]? gen_1: gen_0;52return v;53}54/* "vector" of l bits (possibly no code word) to nonnegative t_INT */55GEN56bits_to_int(GEN x, long l)57{58long i, j, lz;59GEN z, zp;6061if (!l) return gen_0;62lz = nbits2lg(l);63z = cgetg(lz, t_INT);64z[1] = evalsigne(1) | evallgefint(lz);65zp = int_LSW(z); *zp = 0;66for(i=l,j=0; i; i--,j++)67{68if (j==BITS_IN_LONG) { j=0; zp = int_nextW(zp); *zp = 0; }69if (x[i]) *zp |= 1UL<<j;70}71return int_normalize(z, 0);72}73/* "vector" of l < BITS_IN_LONG bits (possibly no code word) to nonnegative74* ulong */75ulong76bits_to_u(GEN v, long l)77{78ulong u = 0;79long i;80for (i = 1; i <= l; i++) u = (u <<1) | v[i];81return u;82}8384/* set BITS_IN_LONG bits starting at word *w plus *r bits,85* clearing subsequent bits in the last word touched */86INLINE void87int_set_ulong(ulong a, GEN *w, long *r)88{89if (*r) {90**w |= (a << *r);91*w = int_nextW(*w);92**w = (a >> (BITS_IN_LONG - *r));93} else {94**w = a;95*w = int_nextW(*w);96}97}9899/* set k bits starting at word *w plus *r bits,100* clearing subsequent bits in the last word touched */101INLINE void102int_set_bits(ulong a, long k, GEN *w, long *r)103{104if (*r) {105**w |= a << *r;106a >>= BITS_IN_LONG - *r;107} else {108**w = a;109a = 0;110}111*r += k;112if (*r >= BITS_IN_LONG) {113*w = int_nextW(*w);114*r -= BITS_IN_LONG;115for (; *r >= BITS_IN_LONG; *r -= BITS_IN_LONG) {116**w = a;117a = 0;118*w = int_nextW(*w);119}120if (*r)121**w = a;122}123}124125/* set k bits from z (t_INT) starting at word *w plus *r bits,126* clearing subsequent bits in the last word touched */127INLINE void128int_set_int(GEN z, long k, GEN *w, long *r)129{130long l = lgefint(z) - 2;131GEN y;132if (!l) {133int_set_bits(0, k, w, r);134return;135}136y = int_LSW(z);137for (; l > 1; l--) {138int_set_ulong((ulong) *y, w, r);139y = int_nextW(y);140k -= BITS_IN_LONG;141}142if (k)143int_set_bits((ulong) *y, k, w, r);144}145146GEN147nv_fromdigits_2k(GEN x, long k)148{149long l = lg(x) - 1, r;150GEN w, z;151if (k == 1) return bits_to_int(x, l);152if (!l) return gen_0;153z = cgetipos(nbits2lg(k * l));154w = int_LSW(z);155r = 0;156for (; l; l--)157int_set_bits(uel(x, l), k, &w, &r);158return int_normalize(z, 0);159}160161GEN162fromdigits_2k(GEN x, long k)163{164long l, m;165GEN w, y, z;166for (l = lg(x) - 1; l && !signe(gel(x, 1)); x++, l--);167if (!l) return gen_0;168m = expi(gel(x, 1)) + 1;169z = cgetipos(nbits2lg(k * (l - 1) + m));170w = int_LSW(z);171if (!(k & (BITS_IN_LONG - 1)))172{173long i, j, t = k >> TWOPOTBITS_IN_LONG;174for (; l; l--)175{176j = lgefint(gel(x, l)) - 2;177y = int_LSW(gel(x, l));178for (i = 0; i < j; i++, y = int_nextW(y), w = int_nextW(w)) *w = *y;179if (l > 1) for (; i < t; i++, w = int_nextW(w)) *w = 0;180}181}182else183{184long r = 0;185for (; l > 1; l--) int_set_int(gel(x, l), k, &w, &r);186int_set_int(gel(x,1), m, &w, &r);187}188return int_normalize(z, 0);189}190191GEN192binaire(GEN x)193{194ulong m,u;195long i,lx,ex,ly,tx=typ(x);196GEN y,p1,p2;197198switch(tx)199{200case t_INT:201return F2v_to_ZV_inplace( binary_zv(x) );202case t_REAL:203ex = expo(x);204if (!signe(x)) return zerovec(maxss(-ex,0));205206lx=lg(x); y=cgetg(3,t_VEC);207if (ex > bit_prec(x)) pari_err_PREC("binary");208p1 = cgetg(maxss(ex,0)+2,t_VEC);209p2 = cgetg(bit_prec(x)-ex,t_VEC);210gel(y,1) = p1;211gel(y,2) = p2;212ly = -ex; ex++; m = HIGHBIT;213if (ex<=0)214{215gel(p1,1) = gen_0; for (i=1; i <= -ex; i++) gel(p2,i) = gen_0;216i=2;217}218else219{220ly=1;221for (i=2; i<lx && ly<=ex; i++)222{223m=HIGHBIT; u=x[i];224do225{ gel(p1,ly) = (m & u) ? gen_1 : gen_0; ly++; }226while ((m>>=1) && ly<=ex);227}228ly=1;229if (m) i--; else m=HIGHBIT;230}231for (; i<lx; i++)232{233u=x[i];234do { gel(p2,ly) = m & u ? gen_1 : gen_0; ly++; } while (m>>=1);235m=HIGHBIT;236}237break;238239case t_VEC: case t_COL: case t_MAT:240y = cgetg_copy(x, &lx);241for (i=1; i<lx; i++) gel(y,i) = binaire(gel(x,i));242break;243default: pari_err_TYPE("binary",x);244return NULL; /* LCOV_EXCL_LINE */245}246return y;247}248249/* extract k bits (as ulong) starting at word *w plus *r bits */250INLINE ulong251int_get_bits(long k, GEN *w, long *r)252{253ulong mask = (1UL << k) - 1;254ulong a = (((ulong) **w) >> *r) & mask;255*r += k;256if (*r >= BITS_IN_LONG) {257*r -= BITS_IN_LONG;258*w = int_nextW(*w);259if (*r)260a |= ((ulong)**w << (k - *r)) & mask;261}262return a;263}264265/* extract BITS_IN_LONG bits starting at word *w plus *r bits */266INLINE ulong267int_get_ulong(GEN *w, long *r)268{269ulong a = ((ulong) **w) >> *r;270*w = int_nextW(*w);271if (*r)272a |= ((ulong)**w << (BITS_IN_LONG - *r));273return a;274}275276/* extract k bits (as t_INT) starting at word *w plus *r bits */277INLINE GEN278int_get_int(long k, GEN *w, long *r)279{280GEN z = cgetipos(nbits2lg(k));281GEN y = int_LSW(z);282for (; k >= BITS_IN_LONG; k -= BITS_IN_LONG) {283*y = int_get_ulong(w, r);284y = int_nextW(y);285}286if (k)287*y = int_get_bits(k, w, r);288return int_normalize(z, 0);289}290291/* assume k < BITS_IN_LONG */292GEN293binary_2k_nv(GEN x, long k)294{295long l, n, r;296GEN v, w;297if (k == 1) return binary_zv(x);298if (!signe(x)) return cgetg(1, t_VECSMALL);299n = expi(x) + 1;300l = (n + k - 1) / k;301v = cgetg(l + 1, t_VECSMALL);302w = int_LSW(x);303r = 0;304for (; l > 1; l--) {305uel(v, l) = int_get_bits(k, &w, &r);306n -= k;307}308uel(v, 1) = int_get_bits(n, &w, &r);309return v;310}311312GEN313binary_2k(GEN x, long k)314{315long l, n;316GEN v, w, y, z;317if (k == 1) return binaire(x);318if (!signe(x)) return cgetg(1, t_VEC);319n = expi(x) + 1;320l = (n + k - 1) / k;321v = cgetg(l + 1, t_VEC);322w = int_LSW(x);323if (!(k & (BITS_IN_LONG - 1))) {324long m, t = k >> TWOPOTBITS_IN_LONG, u = lgefint(x) - 2;325for (; l; l--) {326m = minss(t, u);327z = cgetipos(m + 2);328y = int_LSW(z);329for (; m; m--) {330*y = *w;331y = int_nextW(y);332w = int_nextW(w);333}334gel(v, l) = int_normalize(z, 0);335u -= t;336}337} else {338long r = 0;339for (; l > 1; l--, n -= k)340gel(v, l) = int_get_int(k, &w, &r);341gel(v, 1) = int_get_int(n, &w, &r);342}343return v;344}345346/* return 1 if bit n of x is set, 0 otherwise */347long348bittest(GEN x, long n)349{350if (typ(x) != t_INT) pari_err_TYPE("bittest",x);351if (!signe(x) || n < 0) return 0;352if (signe(x) < 0)353{354pari_sp ltop=avma;355long b = !int_bit(inegate(x),n);356set_avma(ltop);357return b;358}359return int_bit(x, n);360}361362GEN363gbittest(GEN x, long n) { return map_proto_lGL(bittest,x,n); }364365/***********************************************************************/366/** **/367/** BITMAP OPS **/368/** x & y (and), x | y (or), x ^ y (xor), ~x (neg), x & ~y (negimply) **/369/** **/370/***********************************************************************/371/* Truncate a nonnegative integer to a number of bits. */372static GEN373ibittrunc(GEN x, long bits)374{375long lowbits, known_zero_words, xl = lgefint(x) - 2;376long len_out = nbits2nlong(bits);377378if (xl < len_out)379return x;380/* Check whether mask is trivial */381lowbits = bits & (BITS_IN_LONG-1);382if (!lowbits) {383if (xl == len_out)384return x;385} else if (len_out <= xl) {386GEN xi = int_W(x, len_out-1);387/* Non-trival mask is given by a formula, if x is not388normalized, this works even in the exceptional case */389*xi &= (1L << lowbits) - 1;390if (*xi && xl == len_out) return x;391}392/* Normalize */393known_zero_words = xl - len_out;394if (known_zero_words < 0) known_zero_words = 0;395return int_normalize(x, known_zero_words);396}397398GEN399gbitneg(GEN x, long bits)400{401const ulong uzero = 0;402long lowbits, xl, len_out, i;403404if (typ(x) != t_INT) pari_err_TYPE("bitwise negation",x);405if (bits < -1)406pari_err_DOMAIN("bitwise negation","exponent","<",gen_m1,stoi(bits));407if (bits == -1) return inegate(x);408if (bits == 0) return gen_0;409if (signe(x) < 0) { /* Consider as if mod big power of 2 */410pari_sp ltop = avma;411return gerepileuptoint(ltop, ibittrunc(inegate(x), bits));412}413xl = lgefint(x);414len_out = nbits2lg(bits);415lowbits = bits & (BITS_IN_LONG-1);416if (len_out > xl) /* Need to grow */417{418GEN out, outp, xp = int_MSW(x);419out = cgetipos(len_out);420outp = int_MSW(out);421if (!lowbits)422*outp = ~uzero;423else424*outp = (1L << lowbits) - 1;425for (i = 3; i < len_out - xl + 2; i++)426{427outp = int_precW(outp); *outp = ~uzero;428}429for ( ; i < len_out; i++)430{431outp = int_precW(outp); *outp = ~*xp;432xp = int_precW(xp);433}434return out;435}436x = icopy(x);437for (i = 2; i < xl; i++) x[i] = ~x[i];438return ibittrunc(int_normalize(x,0), bits);439}440441/* bitwise 'and' of two positive integers (any integers, but we ignore sign).442* Inputs are not necessary normalized. */443GEN444ibitand(GEN x, GEN y)445{446long lx, ly, lout;447long *xp, *yp, *outp;448GEN out;449long i;450451if (!signe(x) || !signe(y)) return gen_0;452lx=lgefint(x); ly=lgefint(y);453lout = minss(lx,ly); /* > 2 */454xp = int_LSW(x);455yp = int_LSW(y);456out = cgetipos(lout);457outp = int_LSW(out);458for (i=2; i<lout; i++)459{460*outp = (*xp) & (*yp);461outp = int_nextW(outp);462xp = int_nextW(xp);463yp = int_nextW(yp);464}465if ( !*int_MSW(out) ) out = int_normalize(out, 1);466return out;467}468469/* bitwise 'or' of absolute values of two integers */470GEN471ibitor(GEN x, GEN y)472{473long lx, ly;474long *xp, *yp, *outp;475GEN out;476long i;477if (!signe(x)) return absi(y);478if (!signe(y)) return absi(x);479480lx = lgefint(x); xp = int_LSW(x);481ly = lgefint(y); yp = int_LSW(y);482if (lx < ly) swapspec(xp,yp,lx,ly);483/* lx > 2 */484out = cgetipos(lx);485outp = int_LSW(out);486for (i=2;i<ly;i++)487{488*outp = (*xp) | (*yp);489outp = int_nextW(outp);490xp = int_nextW(xp);491yp = int_nextW(yp);492}493for ( ;i<lx;i++)494{495*outp = *xp;496outp = int_nextW(outp);497xp = int_nextW(xp);498}499/* If input is normalized, this is not needed */500if ( !*int_MSW(out) ) out = int_normalize(out, 1);501return out;502}503504/* bitwise 'xor' of absolute values of two integers */505GEN506ibitxor(GEN x, GEN y)507{508long lx, ly;509long *xp, *yp, *outp;510GEN out;511long i;512if (!signe(x)) return absi(y);513if (!signe(y)) return absi(x);514515lx = lgefint(x); xp = int_LSW(x);516ly = lgefint(y); yp = int_LSW(y);517if (lx < ly) swapspec(xp,yp,lx,ly);518/* lx > 2 */519out = cgetipos(lx);520outp = int_LSW(out);521for (i=2;i<ly;i++)522{523*outp = (*xp) ^ (*yp);524outp = int_nextW(outp);525xp = int_nextW(xp);526yp = int_nextW(yp);527}528for ( ;i<lx;i++)529{530*outp = *xp;531outp = int_nextW(outp);532xp = int_nextW(xp);533}534if ( !*int_MSW(out) ) out = int_normalize(out, 1);535return out;536}537538/* bitwise 'negimply' of absolute values of two integers */539/* "negimply(x,y)" is ~(x => y) == ~(~x | y) == x & ~y */540GEN541ibitnegimply(GEN x, GEN y)542{543long lx, ly, lin;544long *xp, *yp, *outp;545GEN out;546long i;547if (!signe(x)) return gen_0;548if (!signe(y)) return absi(x);549550lx = lgefint(x); xp = int_LSW(x);551ly = lgefint(y); yp = int_LSW(y);552lin = minss(lx,ly);553out = cgetipos(lx);554outp = int_LSW(out);555for (i=2; i<lin; i++)556{557*outp = (*xp) & ~(*yp);558outp = int_nextW(outp);559xp = int_nextW(xp);560yp = int_nextW(yp);561}562for ( ;i<lx;i++)563{564*outp = *xp;565outp = int_nextW(outp);566xp = int_nextW(xp);567}568if ( !*int_MSW(out) ) out = int_normalize(out, 1);569return out;570}571572static int573signs(GEN x, GEN y) { return (((signe(x) >= 0) << 1) | (signe(y) >= 0)); }574static void575checkint2(const char *f,GEN x, GEN y)576{ if (typ(x)!=t_INT || typ(y)!=t_INT) pari_err_TYPE2(f,x,y); }577578GEN579gbitor(GEN x, GEN y)580{581pari_sp ltop = avma;582GEN z;583584checkint2("bitwise or",x,y);585switch (signs(x, y))586{587case 3: /*1,1*/588return ibitor(x,y);589case 2: /*1,-1*/590z = ibitnegimply(inegate(y),x);591break;592case 1: /*-1,1*/593z = ibitnegimply(inegate(x),y);594break;595default: /*-1,-1*/596z = ibitand(inegate(x),inegate(y));597break;598}599return gerepileuptoint(ltop, inegate(z));600}601602GEN603gbitand(GEN x, GEN y)604{605pari_sp ltop = avma;606GEN z;607608checkint2("bitwise and",x,y);609switch (signs(x, y))610{611case 3: /*1,1*/612return ibitand(x,y);613case 2: /*1,-1*/614z = ibitnegimply(x,inegate(y));615break;616case 1: /*-1,1*/617z = ibitnegimply(y,inegate(x));618break;619default: /*-1,-1*/620z = inegate(ibitor(inegate(x),inegate(y)));621break;622}623return gerepileuptoint(ltop, z);624}625626GEN627gbitxor(GEN x, GEN y)628{629pari_sp ltop = avma;630GEN z;631632checkint2("bitwise xor",x,y);633switch (signs(x, y))634{635case 3: /*1,1*/636return ibitxor(x,y);637case 2: /*1,-1*/638z = inegate(ibitxor(x,inegate(y)));639break;640case 1: /*-1,1*/641z = inegate(ibitxor(inegate(x),y));642break;643default: /*-1,-1*/644z = ibitxor(inegate(x),inegate(y));645break;646}647return gerepileuptoint(ltop,z);648}649650/* x & ~y */651GEN652gbitnegimply(GEN x, GEN y)653{654pari_sp ltop = avma;655GEN z;656657checkint2("bitwise negated imply",x,y);658switch (signs(x, y))659{660case 3: /*1,1*/661return ibitnegimply(x,y);662case 2: /*1,-1*/663z = ibitand(x,inegate(y));664break;665case 1: /*-1,1*/666z = inegate(ibitor(y,inegate(x)));667break;668default: /*-1,-1*/669z = ibitnegimply(inegate(y),inegate(x));670break;671}672return gerepileuptoint(ltop,z);673}674675long676hammingl(ulong w)677{678#if 0679return __builtin_popcountl(w);680#endif681static long byte_weight[] = {6820,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,6831,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,6841,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,6852,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,6861,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,6872,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,6882,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,6893,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8690};691long sum = 0;692while (w) { sum += byte_weight[w & 255]; w >>= 8; }693return sum;694}695696/* number of nonzero entries among x[a], ..., x[b] */697static long698hamming_slice(GEN x, long a, long b)699{700long i, nb = 0;701for (i = a; i <= b; i++)702if (!gequal0(gel(x,i))) nb++;703return nb;704}705static long706hamming_mat(GEN x)707{708long i, lx = lg(x), nb = 0;709for (i = 1; i < lx; i++) nb += hammingweight(gel(x,i));710return nb;711}712static long713hamming_vecsmall(GEN x)714{715long i, lx = lg(x), nb = 0;716for (i = 1; i < lx; i++)717if (x[i]) nb++;718return nb;719}720static long721hamming_int(GEN n)722{723long lx = lgefint(n), i, sum;724if (lx == 2) return 0;725sum = hammingl(n[2]);726for (i = 3; i < lx; i++) sum += hammingl(n[i]);727return sum;728}729730long731hammingweight(GEN n)732{733switch(typ(n))734{735case t_INT: return hamming_int(n);736case t_VEC:737case t_COL: return hamming_slice(n, 1, lg(n)-1);738case t_POL: return hamming_slice(n, 2, lg(n)-1);739case t_VECSMALL: return hamming_vecsmall(n);740case t_MAT: return hamming_mat(n);741}742pari_err_TYPE("hammingweight", n);743return 0;/*LCOV_EXCL_LINE*/744}745746747