uCBQN/src/core/numarr.h
2024-09-12 05:18:52 +03:00

122 lines
4.0 KiB
C

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) {
u8 m = ((u8)1) << (n&7);
if (v) ((u8*)arr)[n>>3]|= m;
else ((u8*)arr)[n>>3]&= ~m;
// arr[n>>6] = (arr[n>>6]&(~m)) | (((u64)v)<<(n&63));
}
static inline bool bitp_get(u64* arr, u64 n) {
return (((u8*)arr)[n>>3] >> (n&7)) & 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 o2bG(x)? ~(u64)0 : 0;
}
static inline bool bit_has(u64* arr, u64 ia, bool v) {
u64 w = ~-(u64)v;
u64 e = ia/64, q = ia%64;
for (usz i=0; i<e; i++) if (arr[i]^w) return 1;
return q && ((arr[e]^w) & ((1ULL<<q)-1));
}
static inline u64 bit_find(u64* arr, u64 ia, bool v) {
u64 w = ~-(u64)v;
u64 e = ia/64;
for (u64 i=0; i<e; i++) {
u64 f = w ^ arr[i];
if (f) return 64*i + CTZ(f);
}
u64 q = ia%64;
return (ia - q) | CTZ((w^arr[e]) | ~(u64)0<<q);
}
// BitArr
#if UNSAFE_SIZES
#define CHECK_BITARR_IA(IA)
#elif USZ_64
#define CHECK_BITARR_IA(IA) if ((IA) > USZ_MAX) thrOOM()
#else
#define CHECK_BITARR_IA(IA) if ((IA) > USZ_MAX-65) thrOOM() // make sure BIT_N doesn't overflow
#endif
#define BITARR_SZ(IA) fsizeof(BitArr, a, u64, BIT_N(IA))
static B m_bitarrv(u64** p, u64 ia) {
CHECK_BITARR_IA(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));
// no need for a CHECK_BITARR_IA, as bitarrs should have the least restrictive IA requirement
BitArr* r = m_arr(BITARR_SZ(IA(x)), t_bitarr, IA(x));
*p = (u64*)r->a;
arr_shCopy((Arr*)r, x);
return taga(r);
}
static Arr* m_bitarrp(u64** p, u64 ia) {
CHECK_BITARR_IA(ia);
BitArr* r = m_arr(BITARR_SZ(ia), t_bitarr, ia);
*p = (u64*)r->a;
return (Arr*)r;
}
static u64* bitarrv_ptr(TyArr* x) { VTY(taga(x), t_bitarr); return (u64*)((BitArr*)x)->a; }
static u64* bitanyv_ptr(Arr* x) { VTY(taga(x), t_bitarr); return (u64*)((BitArr*)x)->a; }
static u64* bitarr_ptr(B x) { return bitarrv_ptr(c(TyArr,x)); }
static u64* bitany_ptr(B x) { return bitanyv_ptr(a(x)); }
Arr* cpyI8Arr (B x); // consumes
Arr* cpyI16Arr(B x); // consumes
Arr* cpyI32Arr(B x); // consumes
Arr* cpyF64Arr(B x); // consumes
Arr* cpyBitArr(B x); // consumes
// all consume x
static I8Arr* toI8Arr (B x) { return TY(x)==t_i8arr ? c(I8Arr, x) : (I8Arr*) cpyI8Arr (x); }
static I16Arr* toI16Arr(B x) { return TY(x)==t_i16arr? c(I16Arr,x) : (I16Arr*) cpyI16Arr(x); }
static I32Arr* toI32Arr(B x) { return TY(x)==t_i32arr? c(I32Arr,x) : (I32Arr*) cpyI32Arr(x); }
static F64Arr* toF64Arr(B x) { return TY(x)==t_f64arr? c(F64Arr,x) : (F64Arr*) cpyF64Arr(x); }
static BitArr* toBitArr(B x) { return TY(x)==t_bitarr? c(BitArr,x) : (BitArr*) cpyBitArr(x); }
static B toI8Any (B x) { u8 t=TY(x); return t==t_i8arr || t==t_i8slice ? x : taga(cpyI8Arr (x)); }
static B toI16Any(B x) { u8 t=TY(x); return t==t_i16arr || t==t_i16slice? x : taga(cpyI16Arr(x)); }
static B toI32Any(B x) { u8 t=TY(x); return t==t_i32arr || t==t_i32slice? x : taga(cpyI32Arr(x)); }
static B toF64Any(B x) { u8 t=TY(x); return t==t_f64arr || t==t_f64slice? x : taga(cpyF64Arr(x)); }
static B toBitAny(B x) { return taga(toBitArr(x)); }
B m_cai32(usz ia, i32* a);
B m_caf64(usz sz, f64* a);
i64 bit_sum(u64* x, u64 am);
u64 usum(B x); // doesn't consume; error if not natural numbers or overflow