diff --git a/src/README.md b/src/README.md index b7314628..2295cc46 100644 --- a/src/README.md +++ b/src/README.md @@ -108,7 +108,9 @@ All heap-allocated objects have a type - `t_i32arr`, `t_f64slice`, `t_funBl`, `t An object can be allocated with `mm_alloc(sizeInBytes, t_something)`. The returned object starts with the structure of `Value`, so custom data must be after that. `mm_free` can be used to force-free an object regardless of its reference count. -A heap-allocated object from type `B` can be cast to a `Value*` with `v(x)`, to an `Arr*` with `a(x)`, or to a specific pointer type with `c(Type,x)`. `v(x)->type` stores the type of an object (one of `t_whatever`), which is used to dynamically determine how to interpret an object. Note that the type is separate from the tag used for NaN-boxing. +A heap-allocated object from type `B` can be cast to a `Value*` with `v(x)`, to an `Arr*` with `a(x)`, or to a specific pointer type with `c(Type,x)`. + +`TY(x)` / `PTY(x)` givs you the type of an object (one of `t_whatever`), which is used to dynamically determine how to interpret an object. Note that the type is separate from the tag used for NaN-boxing. The reference count of any `B` object can be incremented/decremented with `inc(x)`/`dec(x)`, and any subtype of `Value*` can use `ptr_inc(x)`/`ptr_dec(x)`. `inc(x)` and `ptr_inc(x)` will return the argument, so you can use it inline. `dec(x)` and `ptr_dec(x)` will return the object to the memory manager if the refcount as a result goes to zero. @@ -181,9 +183,17 @@ c(BMd2,bi_some2mod)->im = some2mod_im; // you get the idea ## Arrays -If you know that `x` is an array (e.g. by testing `isArr(x)` beforehand), `IA(x)` will give you the product of the shape (aka total element count), `rnk(x)` will give you the rank (use `prnk(x)` for an untagged pointer object), and `a(x)->sh` will give you a `usz*` to the full shape. +There exist various macros to view the main metadata of an array: -The shape pointer of a rank 0 or 1 array will point to the object's own `ia` field. Otherwise, it'll point inside a `t_shape` object. +| operation | `B x;` | `Value* x` / `Arr* x` / etc | result type | +|------------------------------------|-----------|-------------------------------|---------------| +| get shape | `SH(x)` | `PSH(x)` | `usz*` | +| get item amount (product of shape) | `IA(x)` | `PIA(x)` | `usz` | +| get rank | `RNK(x)` | `PRNK(x)` | `ur` | +| set rank | `SRNK(x)` | `SPRNK(x)` | `N/A` | + + +The shape pointer of a rank 0 or 1 array will point to the object's own `ia` field (the one read by `IA(x)`). Otherwise, it'll point inside a `t_shape` object (`ShArr*`'s `a` field). Allocating an array: ```C @@ -269,9 +279,9 @@ B c = IGetU(x,n); if (TI(x,elType)==el_i32) i32* xp = i32any_ptr(x); // for either t_i32arr or t_i32slice; for t_i32arr only, there's i32arr_ptr(x) if (TI(x,elType)==el_c32) u32* xp = c32any_ptr(x); // ↑ if (TI(x,elType)==el_f64) f64* xp = f64any_ptr(x); // ↑ -if (v(x)->type==t_harr) B* xp = harr_ptr(x); -if (v(x)->type==t_harr || v(x)->type==t_hslice) B* xp = hany_ptr(x); // note that elType==el_B doesn't imply hany_ptr is safe! -if (v(x)->type==t_fillarr) B* xp = fillarr_ptr(x); +if (TY(x)==t_harr) B* xp = harr_ptr(x); +if (TY(x)==t_harr || TY(x)==t_hslice) B* xp = hany_ptr(x); // note that elType==el_B doesn't imply hany_ptr is safe! +if (TY(x)==t_fillarr) B* xp = fillarr_ptr(x); B* xp = arr_bptr(x); // will return NULL if the array isn't backed by contiguous B*-s // functions to convert arrays to a specific type array: (all consume their argument) diff --git a/src/builtins/arithd.c b/src/builtins/arithd.c index d1e606bd..de808f15 100644 --- a/src/builtins/arithd.c +++ b/src/builtins/arithd.c @@ -23,7 +23,7 @@ if (isArr(w)|isArr(x)) { B ow=w; B ox=x; \ if (isArr(w)&isArr(x) && RNK(w)==RNK(x)) { \ if (!eqShPart(SH(w), SH(x), RNK(w))) thrF(SYMB ": Expected equal shape prefix (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); \ - usz ia = IA(x); \ + usz ia = IA(x); \ u8 we = TI(w,elType); \ u8 xe = TI(x,elType); \ if ((we==el_i32|we==el_f64)&(xe==el_i32|xe==el_f64)) { \ @@ -37,7 +37,7 @@ } \ decG(w); decG(x); return num_squeeze(r); \ } \ - } else if (isF64(w)&isArr(x)) { usz ia = IA(x); \ + } else if (isF64(w)&isArr(x)) { usz ia = IA(x); \ u8 xe = TI(x,elType); f64*rp; \ if (xe==el_i32) { B r=m_f64arrc(&rp, x); i32*xp=i32any_ptr(x); \ for (usz i = 0; i < ia; i++) {B x/*shadow*/;x.f=xp[i];rp[i]=EXPR;} \ @@ -47,7 +47,7 @@ for (usz i = 0; i < ia; i++) {B x/*shadow*/;x.f=xp[i];rp[i]=EXPR;} \ decG(x); return num_squeeze(r); \ } \ - } else if (isF64(x)&isArr(w)) { usz ia = IA(w); \ + } else if (isF64(x)&isArr(w)) { usz ia = IA(w); \ u8 we = TI(w,elType); f64*rp; \ if (we==el_i32) { B r=m_f64arrc(&rp, w); i32*wp=i32any_ptr(w); \ for (usz i = 0; i < ia; i++) {B w/*shadow*/;w.f=wp[i];rp[i]=EXPR;} \ @@ -160,7 +160,7 @@ if (isArr(w)|isArr(x)) { \ if (isArr(w)&isArr(x) && RNK(w)==RNK(x)) { \ if (!eqShPart(SH(w), SH(x), RNK(w))) thrF(SYMB ": Expected equal shape prefix (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); \ - usz ia = IA(x); \ + usz ia = IA(x); \ u8 we = TI(w,elType); \ u8 xe = TI(x,elType); \ if ((we==el_bit | xe==el_bit) && (we|xe)<=el_f64) { \ diff --git a/src/builtins/arithm.c b/src/builtins/arithm.c index 63da6363..80c38abd 100644 --- a/src/builtins/arithm.c +++ b/src/builtins/arithm.c @@ -24,7 +24,7 @@ B bit_negate(B x) { // consumes if (isF64(x)) { f64 v = x.f; return m_f64(FEXPR); } \ if (RARE(!isArr(x))) thrM(SYMB ": Expected argument to be a number"); \ u8 xe = TI(x,elType); \ - i64 sz = IA(x); BX \ + i64 sz = IA(x); BX \ if (xe==el_i8) { i8 MAX=I8_MAX; i8 MIN=I8_MIN; i8* xp=i8any_ptr(x); i8* rp; B r=m_i8arrc(&rp,x); \ for (i64 i = 0; i < sz; i++) { i8 v = xp[i]; if (RARE(IBAD)) { decG(r); goto base; } rp[i] = IEXPR; } \ decG(x); (void)MIN;(void)MAX; return r; \ diff --git a/src/utils/mut.c b/src/utils/mut.c index f987827c..faf6b887 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -237,7 +237,7 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x } \ static copy_fn copy##T##Fns[] = __VA_ARGS__; \ T##Arr* cpy##T##Arr(B x) { \ - usz ia = IA(x); \ + usz ia = IA(x); \ MAKE; arr_shCopy(r, x); \ if (ia>0) { \ copy##T##Fns[TI(x,elType)](tyany_ptr(x), (u8*)(XRP), ia, (u8*)a(x)); \ @@ -288,7 +288,7 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x } #else #define MAKE_ICPY(T,E) T##Arr* cpy##T##Arr(B x) { \ - usz ia = IA(x); \ + usz ia = IA(x); \ E* rp; Arr* r = m_##E##arrp(&rp, ia); \ arr_shCopy(r, x); \ u8 xe = TI(x,elType); \ @@ -308,7 +308,7 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x #define MAKE_CCPY(T,E) \ T##Arr* cpy##T##Arr(B x) { \ - usz ia = IA(x); \ + usz ia = IA(x); \ T##Atom* rp; Arr* r = m_##E##arrp(&rp, ia); \ arr_shCopy(r, x); \ u8 xe = TI(x,elType); \