unified int & char cases for bitarr/x

This commit is contained in:
dzaima 2022-04-30 21:40:43 +03:00
parent f8408f0ca6
commit 1babdf247f
10 changed files with 126 additions and 33 deletions

View File

@ -357,8 +357,8 @@ B slash_c1(B t, B x) {
#if SINGELI && defined(__BMI2__)
if (xia<=32768 && xe==el_bit) {
u64* xp = bitarr_ptr(x);
if (xia<=128) { i8* rp; r = m_i8arrv (&rp, s+8); a(r)->ia-= 8; bmipopc_1slash8 (xp, rp, xia); }
else { i16* rp; r = m_i16arrv(&rp, s+16); a(r)->ia-= 16; bmipopc_1slash16(xp, rp, xia); }
if (xia<=128) { i8* rp = m_tyarrvO(&r, 1, s, t_i8arr , 8); bmipopc_1slash8 (xp, rp, xia); }
else { i16* rp = m_tyarrvO(&r, 2, s, t_i16arr, 16); bmipopc_1slash16(xp, rp, xia); }
} else
#endif
{
@ -445,8 +445,8 @@ B slash_c2(B t, B w, B x) {
goto bit_ret;
}
#if SINGELI
case el_i8: { i8* xp = i8any_ptr (x); i8* rp; r = m_i8arrv (&rp, wsum+8); a(r)->ia-= 8; bmipopc_2slash8 (wp, xp, rp, wia); goto bit_ret; }
case el_i16: { i16* xp = i16any_ptr(x); i16* rp; r = m_i16arrv(&rp, wsum+16); a(r)->ia-= 16; bmipopc_2slash16(wp, xp, rp, wia); goto bit_ret; }
case el_c8: case el_i8: { i8* xp=tyany_ptr(x); i8* rp=m_tyarrvO(&r,1,wsum,el2t(xe), 8); bmipopc_2slash8 (wp, xp, rp, wia); goto bit_ret; }
case el_c16:case el_i16: { i16* xp=tyany_ptr(x); i16* rp=m_tyarrvO(&r,2,wsum,el2t(xe), 16); bmipopc_2slash16(wp, xp, rp, wia); goto bit_ret; }
#endif
}
#endif
@ -459,18 +459,15 @@ B slash_c2(B t, B w, B x) {
switch(xe) { default: UD;
#if !SINGELI
case el_i8: { i8* xp = i8any_ptr (x); i8* rp; r = m_i8arrv (&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_i16: { i16* xp = i16any_ptr(x); i16* rp; r = m_i16arrv(&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_i8: case el_c8: { i8* xp=tyany_ptr(x); i8* rp=m_tyarrv(&r,1,wsum,el2t(xe)); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_i16:case el_c16: { i16* xp=tyany_ptr(x); i16* rp=m_tyarrv(&r,2,wsum,el2t(xe)); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
#ifndef __BMI2__
case el_bit: { u64* xp = bitarr_ptr(x); u64* rp; r = m_bitarrv(&rp,wsum); for (usz i=0; i<wia; i++) { bitp_set(rp,ri,bitp_get(xp,i)); ri+= bitp_get(wp,i); } break; }
#endif
#endif
case el_i32: { i32* xp = i32any_ptr(x); i32* rp; r = m_i32arrv(&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_i32:case el_c32: { i32* xp=tyany_ptr(x); i32* rp=m_tyarrv(&r,4,wsum,el2t(xe)); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_f64: { f64* xp = f64any_ptr(x); f64* rp; r = m_f64arrv(&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_c8: { u8* xp = c8any_ptr (x); u8* rp; r = m_c8arrv (&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_c16: { u16* xp = c16any_ptr(x); u16* rp; r = m_c16arrv(&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_c32: { u32* xp = c32any_ptr(x); u32* rp; r = m_c32arrv(&rp,wsum); for (usz i=0; i<wia; i++) { *rp = xp[i]; rp+= bitp_get(wp,i); } break; }
case el_B: {
B* xp = arr_bptr(x);
if (xp!=NULL) {

View File

@ -1,4 +1,5 @@
#pragma once
#include "h.h"
#include "core/stuff.h"
#include "core/heap.h"
@ -21,30 +22,12 @@
#include "core/fillarr.h"
#include "core/derv.h"
#include "core/arrFns.h"
#ifdef RT_VERIFY
extern B r1Objs[rtLen];
#endif
static B* arr_bptr(B x) { assert(isArr(x));
if (v(x)->type==t_harr) return harr_ptr(x);
if (v(x)->type==t_fillarr) return fillarr_ptr(a(x));
if (v(x)->type==t_hslice) return c(HSlice,x)->a;
if (v(x)->type==t_fillslice) return c(FillSlice,x)->a;
return NULL;
}
static B* arrV_bptr(Arr* x) {
if (x->type==t_harr) return ((HArr*)x)->a;
if (x->type==t_fillarr) return fillarr_ptr(x);
if (x->type==t_hslice) return ((HSlice*)x)->a;
if (x->type==t_fillslice) return ((FillSlice*)x)->a;
return NULL;
}
static void* tyany_ptr(B x) {
u8 t = v(x)->type;
return IS_SLICE(t)? c(TySlice,x)->a : c(TyArr,x)->a;
}
typedef struct BFn {
struct Fun;

35
src/core/arrFns.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
static B* arr_bptr(B x) { assert(isArr(x));
if (v(x)->type==t_harr) return harr_ptr(x);
if (v(x)->type==t_fillarr) return fillarr_ptr(a(x));
if (v(x)->type==t_hslice) return c(HSlice,x)->a;
if (v(x)->type==t_fillslice) return c(FillSlice,x)->a;
return NULL;
}
static B* arrV_bptr(Arr* x) {
if (x->type==t_harr) return ((HArr*)x)->a;
if (x->type==t_fillarr) return fillarr_ptr(x);
if (x->type==t_hslice) return ((HSlice*)x)->a;
if (x->type==t_fillslice) return ((FillSlice*)x)->a;
return NULL;
}
static void* tyany_ptr(B x) {
u8 t = v(x)->type;
return IS_SLICE(t)? c(TySlice,x)->a : c(TyArr,x)->a;
}
#define M_TYARR(OVER, MID) { \
Arr* r = m_arr(TYARR_SZW(w, ia) OVER, type, ia); \
MID \
*rp = taga(r); \
return ((TyArr*)r)->a; \
}
// width in bytes for m_tyarr*; overalloc is a byte count
static void* m_tyarrp (B* rp, usz w, usz ia, u8 type ) M_TYARR( , )
static void* m_tyarrpO(B* rp, usz w, usz ia, u8 type, usz over) M_TYARR(+over, )
static void* m_tyarrv (B* rp, usz w, usz ia, u8 type ) M_TYARR( , arr_shVec((Arr*)r);)
static void* m_tyarrvO(B* rp, usz w, usz ia, u8 type, usz over) M_TYARR(+over, arr_shVec((Arr*)r);)
extern u8 elType2type[];
#define el2t(X) elType2type[X] // TODO maybe reorganize array types such that this can just be addition?

View File

@ -32,6 +32,7 @@ static void decSh(Value* x) { if (RARE(prnk(x)>1)) tptr_dec(shObjP(x), mm_free);
#define TYARR_SZ(T,IA) fsizeof(TyArr, a, T##Atom, IA)
#define TYARR_SZ2(T,IA) TYARR_SZ(T,IA)
#define TYARR_SZW(W,IA) (offsetof(TyArr, a) + (W)*(IA))
#define WRAP(X,IA,MSG) ({ i64 wV=(i64)(X); u64 iaW=(IA); if(RARE((u64)wV >= iaW)) { if(wV<0) wV+= iaW; if((u64)wV >= iaW) {MSG;} }; (usz)wV; })

View File

@ -1,6 +1,14 @@
#include "../core.h"
#include "../utils/mut.h"
u8 elType2type[] = {
[el_bit] = t_bitarr,
[el_i8 ] = t_i8arr, [el_c8 ] = t_c8arr,
[el_i16] = t_i16arr,[el_c16] = t_c16arr,
[el_i32] = t_i32arr,[el_c32] = t_c32arr,
[el_f64] = t_f64arr
};
B m_i8(i8 x) { return m_i32(x); } B m_i16(i16 x) { return m_i32(x); }
B m_c8(u8 x) { return m_c32(x); } B m_c16(u16 x) { return m_c32(x); }
#define TU I8

View File

@ -31,7 +31,12 @@ static void* BN(allocL)(i64 bucket, u8 type) {
x->refc = 1;
x->type = type;
x->mmInfo = bucket;
#if defined(DEBUG) && !defined(DONT_FREE)
#if defined(SET_HEAP)
u8* p = (u8*)x;
u8* s = p + sizeof(Value);
u8* e = p + BSZ(bucket);
memset(s, SET_HEAP, e-s);
#elif defined(DEBUG) && !defined(DONT_FREE)
u64* p = (u64*)x;
u64* s = p + sizeof(Value)/8;
u64* e = p + BSZ(bucket)/8;

View File

@ -26,20 +26,21 @@ def comp16{w:*u64, X, r:*i16, l:u64} = {
r+= pc
}
step{w&15}
step{w>>4}
step{w>>4} # this runs even if the above step was all that's required, so it'll act on the invalid result of "r+= pc", so we need to overallocate even more to compensate
}
}
slash2{F, T}(w:*u64, x:*T, r:*T, l:u64) : void = {
xv:= reinterpret{*u64, x}
F{w, {} => {c:= *xv; xv+=1; c}, r, l}
F{w, {} => {c:= *xv; xv+= 1; c}, r, l}
}
slash1{F, T, iota, add}(w:*u64, r:*T, l:u64) : void = {
x:u64 = iota
F{w, {} => {c:=x; x+= add; c}, r, l}
F{w, {} => {c:= x; x+= add; c}, r, l}
}
# 8-bit writes ~8 bytes of garbage past end, 16-bit writes ~16 bytes
'bmipopc_2slash8' = slash2{comp8, i8}
'bmipopc_2slash16' = slash2{comp16, i16}
'bmipopc_1slash8' = slash1{comp8, i8, 0x0706050403020100, 0x0808080808080808}

View File

@ -43,6 +43,21 @@ def broadcast{T, v & w128i{T, 64}} = emit{T, '_mm_set1_epi64x',promote{eltype{T}
def broadcast{T, v & w128f{T, 64}} = emit{T, '_mm_set1_pd', v}
def broadcast{T, v & w128f{T, 32}} = emit{T, '_mm_set1_ps', v}
def make{T==[2]f64,a,b} = emit{T,'_mm_setr_pd',a,b}
def make{T==[4]f32,a,b,c,d} = emit{T,'_mm_setr_ps',a,b,c,d}
def makeGen{T,s,x} = apply{emit, merge{tup{T,s}, each{{c}=>promote{eltype{T},c}, x}}}
def make{T,a,b & w128i{T,64}} = makeGen{T, '_mm_set_epi64x', tup{b,a}} # yay no _mm_setr_epi64x
def make{T,a,b,c,d & w128i{T,32}} = makeGen{T, '_mm_setr_epi32', tup{a,b,c,d}}
def make{T,a,b,c,d,e,f,g,h & w128i{T,16}} = makeGen{T, '_mm_setr_epi16', tup{a,b,c,d,e,f,g,h}}
def make{T,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p & w128i{T,8}} = makeGen{T, '_mm_setr_epi8', tup{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}}
def make{T,x & w128{T} & istup{x}} = apply{make, merge{tup{T}, x}}
def iota{T & w128{T,64}} = make{T,0,1}
def iota{T & w128{T,32}} = make{T,0,1,2,3}
def iota{T & w128{T,16}} = make{T,0,1,2,3,4,5,6,7}
def iota{T & w128{T,8}} = make{T,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
# signed comparison
def __eq{a:T,b:T & T==[16]i8 } = emit{[16]u8, '_mm_cmpeq_epi8', a, b}
def __eq{a:T,b:T & T==[ 8]i16} = emit{[ 8]u16, '_mm_cmpeq_epi16', a, b}

View File

@ -11,4 +11,5 @@ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations
./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another
./BQN test/bitcpy.bqn // fuzz-test bit_cpy; requires a CBQN build with -DTEST_BITCPY
./BQN test/squeeze.bqn // fuzz-test squeezing; requires a CBQN build with -DEEQUAL_NEGZERO
./BQN test/random.bqn // various random tests
```

47
test/random.bqn Normal file
View File

@ -0,0 +1,47 @@
LVListVariations, VVariation, IInfo, TYType, RefcRefc •internal
u 100×(•UnixTime+1|100וMonoTime)@
rand •MakeRand •Show u
R rand.Range
RB "Ab" V R2 # uniformly random boolean array
RB2 {¬(R 2) "Ab" V 𝕩 R 1+R 2R 10} # random boolean array with random uniform probability
rByteVals "Ai8"V {𝕩-256×𝕩>127} {{2×+˜´ 8/ 𝕩 •rand.Subset 8}¨ 9}¨20
RByte (R (rByteVals)˙)(rByteVals)
RH R¨RByte # store to a variable to randomize heap by 𝕨 values, each up to 𝕩 bytes
CH { # do "var CH↩" to a variable assigned to a result of RH
"heap corruption" ! ´2=Refc¨ 𝕩
"heap corruption" ! 1 Refc 𝕩
0
}
rByteVals {! "i8arr" TY 𝕩𝕨} 10 # ⥊ is dumb for now, but when it realizes that n⥊0 is a bitarr this'll need changing
OrScanBitarr {𝕊:
n 1 + R 2R 13
! (` `) "Ab" V {𝕊: 1((R n))𝕩}2 0˜ n
}¨
PlusScanBitarr {𝕊:
a RB2 R 2R 13
! (+` +`) a
}¨
BitSlash {tydymax𝕊n:
f dy / {𝕩/ty V 𝕨 R 100}
{𝕊:
# 𝕩⊸{•Show 𝕨}⍟⊢ 0=10000|𝕩
t120 RH 100
nR max
xn F nRB2 128+n
t220 RH 100
x0 t1 CH t2 CH
}¨n
}
•Show "`bitarr" OrScanBitarr 100000
•Show "+`bitarr" PlusScanBitarr 100000
•Show "heap corruption of /bit" @0200 BitSlash 1000000
•Show "heap corruption of bit/i8" "Ai8"150 BitSlash 1000000
•Show "heap corruption of bit/i16" "Ai16"150 BitSlash 1000000
•Show "heap corruption of bit/i32" "Ai32"150 BitSlash 1000000