typedef struct TyArr { struct Arr; char a[]; } TyArr; typedef struct TySlice { struct Slice; void* a; } TySlice; #define TU I8 #define TP(W,X) W##i8##X #include "tyarrTemplate.h" #define TU I16 #define TP(W,X) W##i16##X #include "tyarrTemplate.h" #define TU I32 #define TP(W,X) W##i32##X #include "tyarrTemplate.h" #define TU F64 #define TP(W,X) W##f64##X #include "tyarrTemplate.h" typedef TyArr BitArr; // bit array stuff #define BIT_N(IA) (((IA)+63) >> 6) // u64 count needed to store IA bits static inline void bitp_set(u64* arr, u64 n, bool v) { u64 m = ((u64)1)<<(n&63); if (v) arr[n>>6]|= m; else arr[n>>6]&= ~m; // arr[n>>6] = (arr[n>>6]&(~m)) | (((u64)v)<<(n&63)); } static inline bool bitp_get(u64* arr, u64 n) { return (arr[n>>6] >> (n&63)) & 1; } static inline u64 bitp_l0(u64* arr, u64 ia) { // last u64 of the array, with the tail set to 0s return ia&63? arr[ia>>6]&((1ULL<<(ia&63))-1) : 0; } static inline u64 bitp_l1(u64* arr, u64 ia) { // last u64 of the array, with the tail set to 1s return ia&63? arr[ia>>6]|~((1ULL<<(ia&63))-1) : ~0ULL; } static inline u64 bitx(B x) { // repeats the boolean across all 64 bits return o2bu(x)? ~(u64)0 : 0; } // BitArr #define BITARR_SZ(IA) fsizeof(BitArr, a, u64, BIT_N(IA)) static B m_bitarrv(u64** p, usz ia) { BitArr* r = m_arr(BITARR_SZ(ia), t_bitarr, ia); arr_shVec((Arr*)r); *p = (u64*)r->a; return taga(r); } static B m_bitarrc(u64** p, B x) { assert(isArr(x)); BitArr* r = m_arr(BITARR_SZ(a(x)->ia), t_bitarr, a(x)->ia); *p = (u64*)r->a; arr_shCopy((Arr*)r, x); return taga(r); } static Arr* m_bitarrp(u64** p, usz ia) { BitArr* r = m_arr(BITARR_SZ(ia), t_bitarr, ia); *p = (u64*)r->a; return (Arr*)r; } static u64* bitarr_ptr(B x) { VTY(x, t_bitarr); return (u64*)c(BitArr,x)->a; } static u64* bitarrv_ptr(TyArr* x) { return (u64*)x->a; } I8Arr* cpyI8Arr (B x); // consumes I16Arr* cpyI16Arr(B x); // consumes I32Arr* cpyI32Arr(B x); // consumes F64Arr* cpyF64Arr(B x); // consumes BitArr* cpyBitArr(B x); // consumes // all consume x static I8Arr* toI8Arr (B x) { return v(x)->type==t_i8arr ? c(I8Arr, x) : cpyI8Arr (x); } static I16Arr* toI16Arr(B x) { return v(x)->type==t_i16arr? c(I16Arr,x) : cpyI16Arr(x); } static I32Arr* toI32Arr(B x) { return v(x)->type==t_i32arr? c(I32Arr,x) : cpyI32Arr(x); } static F64Arr* toF64Arr(B x) { return v(x)->type==t_f64arr? c(F64Arr,x) : cpyF64Arr(x); } static BitArr* toBitArr(B x) { return v(x)->type==t_bitarr? c(BitArr,x) : cpyBitArr(x); } static B toI8Any (B x) { u8 t=v(x)->type; return t==t_i8arr || t==t_i8slice ? x : taga(cpyI8Arr (x)); } static B toI16Any(B x) { u8 t=v(x)->type; return t==t_i16arr || t==t_i16slice? x : taga(cpyI16Arr(x)); } static B toI32Any(B x) { u8 t=v(x)->type; return t==t_i32arr || t==t_i32slice? x : taga(cpyI32Arr(x)); } static B toF64Any(B x) { u8 t=v(x)->type; return t==t_f64arr || t==t_f64slice? x : taga(cpyF64Arr(x)); } B m_cai32(usz ia, i32* a); B m_caf64(usz sz, f64* a); static i64 bit_sum(u64* x, u64 am) { i64 r = 0; for (u64 i = 0; i < (am>>6); i++) r+= POPC(x[i]); if (am&63) r+= POPC(x[am>>6]<<(64-am & 63)); return r; } static u64 usum(B x) { // doesn't consume; may error assert(isArr(x)); u64 r = 0; usz xia = a(x)->ia; u8 xe = TI(x,elType); if (xe==el_bit) return bit_sum(bitarr_ptr(x), xia); else if (xe==el_i8 ) { i8* p = i8any_ptr (x); for (usz i = 0; i < xia; i++) { if (RARE(p[i]<0)) goto neg; r+= p[i]; } } else if (xe==el_i16) { i16* p = i16any_ptr(x); for (usz i = 0; i < xia; i++) { if (RARE(p[i]<0)) goto neg; if (addOn(r,p[i])) goto overflow; } } else if (xe==el_i32) { i32* p = i32any_ptr(x); for (usz i = 0; i < xia; i++) { if (RARE(p[i]<0)) goto neg; if (addOn(r,p[i])) goto overflow; } } else if (xe==el_f64) { f64* p = f64any_ptr(x); for (usz i = 0; i < xia; i++) { f64 c = p[i]; u64 ci = (u64)c; if (c!=ci) thrM("Expected integer"); if (ci<0) goto neg; if (addOn(r,ci)) goto overflow; } } else { SGetU(x) for (usz i = 0; i < xia; i++) { u64 c = o2u64(GetU(x,i)); if (c<0) thrM("Didn't expect negative integer"); if (addOn(r,c)) goto overflow; } } return r; overflow: thrM("Sum too big"); neg: thrM("Didn't expect negative integer"); }