•bit._cast prototype

This commit is contained in:
Marshall Lochbaum 2022-02-04 14:47:13 -05:00
parent d9c0e38c12
commit a21efec47e
2 changed files with 80 additions and 2 deletions

View File

@ -21,7 +21,8 @@
/*md1.c*/A(tbl,"") A(each,"¨") A(fold,"´") A(scan,"`") A(const,"˙") A(swap,"˜") A(cell,"˘") A(insert,"˝") \
/*inverse.c*/A(undo,"") \
/* everything before the definition of •_timed is defined to be pure, and everything after is not */ \
/*md1.c*/A(timed,"•_timed")
/*md1.c*/A(timed,"•_timed") \
/*bit.c*/M(bitcast,"•bit._cast")
#define FOR_PM2(A,M,D) \
/*md2.c*/A(val,"") A(repeat,"") A(rank,"") A(depth,"") A(fillBy,"•_fillBy_") A(catch,"") \
@ -84,4 +85,4 @@ FOR_PFN(F,F,F)
FOR_PM1(F,F,F)
FOR_PM2(F,F,F)
#undef F
rt_invFnReg, rt_invFnSwap;
rt_invFnReg, rt_invFnSwap;

View File

@ -856,6 +856,82 @@ B sh_c1(B t, B x) {
return sh_c2(t, bi_N, x);
}
typedef struct CastType { usz s; u8 t; } CastType;
CastType getCastType(B e) {
B s; u8 t;
if (isNum(e)) {
s = e;
t = '?';
} else {
if (!isArr(e) || rnk(e)!=1 || a(e)->ia!=2) thrM("•bit._cast: 𝕗 elements must be numbers or two-element lists");
SGetU(e);
s = GetU(e,0);
u32 c = o2c(GetU(e,1));
if (!(c=='i'||c=='u'||c=='f'||c=='c')) thrM("•bit._cast: type descriptor in 𝕗 must be one of \"iufc\"");
t = (u8)c;
}
return (CastType) { o2s(s), t };
}
TyArr* convert(CastType t, B x) {
switch (t.s) {
case 1: return toBitArr(x);
case 8: return t.t=='c' ? toC8Arr (x) : toI8Arr (x);
case 16: return t.t=='c' ? toC16Arr(x) : toI16Arr(x);
case 32: return t.t=='c' ? toC32Arr(x) : toI32Arr(x);
case 64: return toF64Arr(x);
default: thrM("•bit._cast: unsupported result width");
}
}
u8 typeOfCast(CastType t) {
switch (t.s) {
case 1: return t_bitarr;
case 8: return t.t=='c' ? t_c8arr : t_i8arr ;
case 16: return t.t=='c' ? t_c16arr : t_i16arr;
case 32: return t.t=='c' ? t_c32arr : t_i32arr;
case 64: return t_f64arr;
default: thrM("•bit._cast: unsupported result width");
}
}
B bitcast_c1(Md1D* d, B x) { B f = d->f;
if (!isArr(f) || rnk(f)!=1 || a(f)->ia!=2) thrM("•bit._cast: 𝕗 must be a 2-element list (from‿to)");
SGetU(f);
CastType xt = getCastType(GetU(f,0));
CastType zt = getCastType(GetU(f,1));
ur xr;
if (!isArr(x) || (xr=rnk(x))<1) thrM("•bit._cast: 𝕩 must have rank at least 1");
usz* sh = a(x)->sh;
usz s=xt.s*sh[xr-1], zl=s/zt.s;
if (zl*zt.s != s) thrM("•bit._cast: incompatible lengths");
// Convert to input type
B r = taga(convert(xt, x));
// Cast to output type
v(r)->type = typeOfCast(zt);
// Adjust shape
if (xr<=1) {
a(r)->sh[xr-1]=zl;
} else {
if (shObj(r)->refc>1) {
usz* zsh = arr_shAlloc(a(r), xr);
memcpy(zsh, sh, (xr-1)*sizeof(usz));
sh = zsh;
}
sh[xr-1]=zl;
usz ia=zl; for (usz i=0;i<xr-1;i++)ia*=sh[i]; a(r)->ia=ia;
}
return r;
}
static B bitNS;
B getBitNS() {
if (bitNS.u == 0) {
#define F(X) inc(bi_bit##X),
Body* d = m_nnsDesc("cast");
bitNS = m_nns(d, F(cast));
#undef F
gc_add(bitNS);
}
return inc(bitNS);
}
B getInternalNS(void);
B getMathNS(void);
@ -893,6 +969,7 @@ B sys_c1(B t, B x) {
}
else if (eqStr(c, U"internal")) cr = getInternalNS();
else if (eqStr(c, U"math")) cr = getMathNS();
else if (eqStr(c, U"bit")) cr = getBitNS();
else if (eqStr(c, U"type")) cr = incG(bi_type);
else if (eqStr(c, U"sh")) cr = incG(bi_sh);
else if (eqStr(c, U"decompose")) cr = incG(bi_decp);