diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-29 17:23:44 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-29 17:23:44 +0000 |
commit | 1ea2f6f8af7ef012005d46fd13acd082628f7295 (patch) | |
tree | ecd458e81035f6a1f2193d0efe4daf66fe6cfe55 | |
parent | a9cb9bb4ccc58a24ce2ab31193f179901f56cf5a (diff) |
Implement expand last (\) and expand first (⍀)
-rw-r--r-- | apl9.h | 2 | ||||
-rw-r--r-- | hybrids.c | 69 |
2 files changed, 69 insertions, 2 deletions
@@ -375,7 +375,9 @@ Array *opSelfReference2(Datum *, Datum *, Array *, Array *); /* Dyadic functions from hybrids.c */ Array *fnReplicateLast(Array *, Array *); +Array *fnExpandLast(Array *, Array *); Array *fnReplicateFirst(Array *, Array *); +Array *fnExpandFirst(Array *, Array *); /* Monadic operators from hybrids.c */ Array *opReduceLast(Datum *, Array *, Array *); @@ -8,9 +8,9 @@ Rune primhybridnames[] = L"/\\⌿⍀"; fndyad hybridfunctiondefs[] = { fnReplicateLast, /* / */ - 0, /* \ */ + fnExpandLast, /* \ */ fnReplicateFirst, /* ⌿ */ - 0, /* ⍀ */ + fnExpandFirst, /* ⍀ */ }; opmonad hybridoperatordefs[] = { @@ -28,6 +28,12 @@ fnReplicateLast(Array *left, Array *right) } Array * +fnExpandLast(Array *left, Array *right) +{ + return rundfn(L"⍉⍺⍀⍉⍵", nil, nil, left, right); +} + +Array * fnReplicateFirst(Array *left, Array *right) { Rune *code = @@ -38,6 +44,65 @@ fnReplicateFirst(Array *left, Array *right) return rundfn(code, nil, nil, left, right); } +Array * +fnExpandFirst(Array *left, Array *right) +{ + if(left->type != AtypeInt) + throwerror(nil, EType); + if(left->rank > 1) + throwerror(nil, ERank); + + right = right->rank == 0 ? fnRavel(right) : fnSame(right); + + int npos = 0; + int nsize = 0; + int i; + for(i = 0; i < left->size; i++){ + if(left->intdata[i] > 0) + npos++; + else if(left->intdata[i] == 0) + left->intdata[i] = -1; + + vlong n = left->intdata[i]; + nsize += n > 0 ? n : -n; + } + + if(right->shape[0] != 1 && right->shape[0] != npos) + throwerror(nil, ELength); + + vlong cellsize = right->shape[0] == 0 ? 1 : right->size / right->shape[0]; + Array *result = allocarray(right->type, right->rank, nsize * cellsize); + result->shape[0] = nsize; + for(i = 1; i < result->rank; i++) + result->shape[i] = right->shape[i]; + + Array *fill = fillelement(right); + int from, to; + for(from = 0, to = 0, i = 0; to < nsize; i++, to += npos){ + int neg = left->intdata[i] < 0; + npos = left->intdata[i]; + if(neg){ + npos = -npos; + for(int j = 0; j < npos*cellsize; j++) + memcpy(result->rawdata + (to*cellsize+j)*datasizes[result->type], + fill->rawdata, datasizes[result->type]); + }else{ + for(int j = 0; j < npos; j++) + memcpy(result->rawdata + (to+j)*cellsize*datasizes[result->type], + right->rawdata + from*cellsize*datasizes[result->type], + cellsize*datasizes[result->type]); + } + if(result->type == AtypeArray) + for(int j = 0; j < npos*cellsize; j++) + incref(result->arraydata[to*cellsize+j]); + if(right->shape[0] != 1 && !neg) + from++; + } + freearray(fill); + freearray(right); + return result; +} + /* operator definitions */ Array * opReduceLast(Datum *lefto, Array *left, Array *right) |