diff --git a/makefile b/makefile index 34d354ab..d83de3b5 100644 --- a/makefile +++ b/makefile @@ -212,7 +212,7 @@ ${bd}/%.o: src/jit/%.c @echo $< | cut -c 5- @$(CC_INC) $@.d -o $@ -c $< -builtins: ${addprefix ${bd}/, arithm.o arithd.o cmp.o sfns.o squeeze.o select.o slash.o group.o sort.o search.o selfsearch.o md1.o md2.o fns.o sysfn.o internal.o inverse.o} +builtins: ${addprefix ${bd}/, arithm.o arithd.o cmp.o sfns.o squeeze.o select.o slash.o group.o sort.o search.o selfsearch.o scan.o md1.o md2.o fns.o sysfn.o internal.o inverse.o} ${bd}/%.o: src/builtins/%.c @echo $< | cut -c 5- @$(CC_INC) $@.d -o $@ -c $< diff --git a/src/builtins/md1.c b/src/builtins/md1.c index 4b3c4d9b..01cb30de 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -107,29 +107,6 @@ B each_c2(Md1D* d, B w, B x) { B f = d->f; return homFil2(f, eachd(f, w, x), wf, xf); } -#if SINGELI && __PCLMUL__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wunused-variable" - #include "../singeli/gen/neq.c" - #pragma GCC diagnostic pop -#endif -B scan_ne(u64 p, u64* xp, u64 ia) { - u64* rp; B r=m_bitarrv(&rp,ia); -#if SINGELI && __PCLMUL__ - clmul_scan_ne(p, xp, rp, BIT_N(ia)); -#else - for (usz i = 0; i < BIT_N(ia); i++) { - u64 c = xp[i]; - u64 r = c ^ (c<<1); - r^= r<< 2; r^= r<< 4; r^= r<<8; - r^= r<<16; r^= r<<32; r^= p; - rp[i] = r; - p = -(r>>63); // repeat sign bit - } -#endif - return r; -} - static bool fold_ne(u64* x, u64 am) { u64 r = 0; for (u64 i = 0; i < (am>>6); i++) r^= x[i]; @@ -143,204 +120,6 @@ static i64 bit_diff(u64* x, u64 am) { if (am&63) r+= POPC((x[am>>6]^a)<<(64-am & 63)); return r - (i64)(am/2); } - - -#if SINGELI - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wunused-variable" - #include "../singeli/gen/scan.c" - #pragma GCC diagnostic pop -#endif -B slash_c1(B f, B x); -B scan_bit_sum(B x, u64* xp, u64 ia, u64 xs) { // consumes x - u8 re = xs<=I8_MAX? el_i8 : xs<=I16_MAX? el_i16 : el_i32; - if (xs < ia/128) { - B ones = slash_c1(m_f64(0), x); - MAKE_MUT(r0, ia) mut_init(r0, re); MUTG_INIT(r0); - SGetU(ones) - usz ri = 0; - for (usz i = 0; i < xs; i++) { - usz e = o2s(GetU(ones, i)); - mut_fillG(r0, ri, m_i32(i), e-ri); - ri = e; - } - if (rif; - if (isAtm(x) || RNK(x)==0) thrM("`: Argument cannot have rank 0"); - ur xr = RNK(x); - usz ia = IA(x); - if (ia==0) return x; - B xf = getFillQ(x); - u8 xe = TI(x,elType); - if (xr==1 && xe<=el_f64 && isFun(f) && v(f)->flags) { - u8 rtid = v(f)->flags-1; - if (xe==el_bit) { - u64* xp=bitarr_ptr(x); - if (rtid==n_add) { - u64 xs = bit_sum(xp, ia); - if (xs>I32_MAX) goto base; - if (xs<=1) { if (xs==0) return x; goto bit_or; } - return FL_SET(scan_bit_sum(x, xp, ia, xs), fl_asc|fl_squoze); - } - if (rtid==n_or | rtid==n_ceil ) { bit_or:; u64* rp; B r=m_bitarrv(&rp,ia); usz n=BIT_N(ia); u64 xi; usz i=0; while(i>63); - rp[i] = p = x & (m10 ^ (x + c)); - } - decG(x); return r; - } - goto base; - } - if (rtid==n_add) { // + - if (xe==el_i8 ) { i8* xp=i8any_ptr (x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=0; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i16) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=I16_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i32) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=I32_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - #endif - } - if (rtid==n_ne) { // โ‰  - f64 x0 = IGetU(x,0).f; if (x0!=0 && x0!=1) goto base; - if (xe==el_i8 ) { i8* xp=i8any_ptr (x); u64* rp; B r=m_bitarrv(&rp,ia); bool c=x0; rp[0]=c; for (usz i=1; if; - if (isAtm(x) || RNK(x)==0) thrM("`: ๐•ฉ cannot have rank 0"); - ur xr = RNK(x); usz* xsh = SH(x); usz ia = IA(x); - B wf = getFillQ(w); - u8 xe = TI(x,elType); - if (xr==1 && q_i32(w) && elInt(xe) && isFun(f) && v(f)->flags) { - u8 rtid = v(f)->flags-1; - i32 wv = o2iG(w); - if (xe==el_bit) { - u64* xp=bitarr_ptr(x); - if (rtid==n_add) { i32* rp; B r=m_i32arrv(&rp, ia); i64 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i16 && wv==(i16)wv) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i32 && wv==(i32)wv) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - } - if (rtid==n_ne) { // โ‰  - if (!q_ibit(wv)) { goto base; } bool c=wv; - if (xe==el_i8 ) { i8* xp=i8any_ptr (x); u64* rp; B r=m_bitarrv(&rp, ia); for (usz i=0; if; if (isAtm(x) || RNK(x)!=1) thrF("ยด: Argument must be a list (%H โ‰ก โ‰ข๐•ฉ)", x); usz ia = IA(x); diff --git a/src/builtins/scan.c b/src/builtins/scan.c new file mode 100644 index 00000000..4db03f0f --- /dev/null +++ b/src/builtins/scan.c @@ -0,0 +1,224 @@ +#include "../core.h" +#include "../utils/mut.h" +#include "../builtins.h" + +#if !USE_VALGRIND +static u64 vg_rand(u64 x) { return x; } +#endif + +#if SINGELI + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-variable" + #include "../singeli/gen/scan.c" + #pragma GCC diagnostic pop +#endif + +#if SINGELI && __PCLMUL__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-variable" + #include "../singeli/gen/neq.c" + #pragma GCC diagnostic pop +#endif +B scan_ne(u64 p, u64* xp, u64 ia) { + u64* rp; B r=m_bitarrv(&rp,ia); +#if SINGELI && __PCLMUL__ + clmul_scan_ne(p, xp, rp, BIT_N(ia)); +#else + for (usz i = 0; i < BIT_N(ia); i++) { + u64 c = xp[i]; + u64 r = c ^ (c<<1); + r^= r<< 2; r^= r<< 4; r^= r<<8; + r^= r<<16; r^= r<<32; r^= p; + rp[i] = r; + p = -(r>>63); // repeat sign bit + } +#endif + return r; +} + +B slash_c1(B f, B x); +B scan_bit_sum(B x, u64* xp, u64 ia, u64 xs) { // consumes x + u8 re = xs<=I8_MAX? el_i8 : xs<=I16_MAX? el_i16 : el_i32; + if (xs < ia/128) { + B ones = slash_c1(m_f64(0), x); + MAKE_MUT(r0, ia) mut_init(r0, re); MUTG_INIT(r0); + SGetU(ones) + usz ri = 0; + for (usz i = 0; i < xs; i++) { + usz e = o2s(GetU(ones, i)); + mut_fillG(r0, ri, m_i32(i), e-ri); + ri = e; + } + if (rif; + if (isAtm(x) || RNK(x)==0) thrM("`: Argument cannot have rank 0"); + ur xr = RNK(x); + usz ia = IA(x); + if (ia==0) return x; + B xf = getFillQ(x); + u8 xe = TI(x,elType); + if (xr==1 && xe<=el_f64 && isFun(f) && v(f)->flags) { + u8 rtid = v(f)->flags-1; + if (xe==el_bit) { + u64* xp=bitarr_ptr(x); + if (rtid==n_add) { + u64 xs = bit_sum(xp, ia); + if (xs>I32_MAX) goto base; + if (xs<=1) { if (xs==0) return x; goto bit_or; } + return FL_SET(scan_bit_sum(x, xp, ia, xs), fl_asc|fl_squoze); + } + if (rtid==n_or | rtid==n_ceil ) { bit_or:; u64* rp; B r=m_bitarrv(&rp,ia); usz n=BIT_N(ia); u64 xi; usz i=0; while(i>63); + rp[i] = p = x & (m10 ^ (x + c)); + } + decG(x); return r; + } + goto base; + } + if (rtid==n_add) { // + + if (xe==el_i8 ) { i8* xp=i8any_ptr (x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=0; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i16) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=I16_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i32) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=I32_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + #endif + } + if (rtid==n_ne) { // โ‰  + f64 x0 = IGetU(x,0).f; if (x0!=0 && x0!=1) goto base; + if (xe==el_i8 ) { i8* xp=i8any_ptr (x); u64* rp; B r=m_bitarrv(&rp,ia); bool c=x0; rp[0]=c; for (usz i=1; if; + if (isAtm(x) || RNK(x)==0) thrM("`: ๐•ฉ cannot have rank 0"); + ur xr = RNK(x); usz* xsh = SH(x); usz ia = IA(x); + B wf = getFillQ(w); + u8 xe = TI(x,elType); + if (xr==1 && q_i32(w) && elInt(xe) && isFun(f) && v(f)->flags) { + u8 rtid = v(f)->flags-1; + i32 wv = o2iG(w); + if (xe==el_bit) { + u64* xp=bitarr_ptr(x); + if (rtid==n_add) { i32* rp; B r=m_i32arrv(&rp, ia); i64 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i16 && wv==(i16)wv) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i32 && wv==(i32)wv) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=wv; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + } + if (rtid==n_ne) { // โ‰  + if (!q_ibit(wv)) { goto base; } bool c=wv; + if (xe==el_i8 ) { i8* xp=i8any_ptr (x); u64* rp; B r=m_bitarrv(&rp, ia); for (usz i=0; i