diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-21 21:52:50 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-21 21:52:50 +0000 |
commit | 02aa544f14d0b544663face5107ceba197ba5aed (patch) | |
tree | b0de08a251447bfbfbb807b48b611e3f775eb9a2 | |
parent | 80ebae7887e21f58ef09a18515e5521c5162053c (diff) |
Implement monadic f⌿ and f/. Identity elements and windowed reduce is not implemented yet
-rw-r--r-- | apl9.h | 6 | ||||
-rw-r--r-- | hybrids.c | 71 |
2 files changed, 73 insertions, 4 deletions
@@ -270,6 +270,12 @@ Array *opSwitch(Datum *, Array *, Array *); /* Dyadic operators from operators.c */ Array *opOver(Datum *, Datum *, Array *, Array *); +/* Dyadic functions from hybrids.c */ + +/* Monadic operators from hybrids.c */ +Array *opReduceLast(Datum *, Array *, Array *); +Array *opReduceFirst(Datum *, Array *, Array *); + /* Global variables */ extern int traceeval; /* eval.c */ extern int debugmem; /* memory.c */ @@ -4,7 +4,7 @@ #include "apl9.h" -Rune primhybridnames[] = L"/\⌿⍀"; +Rune primhybridnames[] = L"/\\⌿⍀"; fndyad hybridfunctiondefs[] = { 0, /* / */ @@ -14,8 +14,71 @@ fndyad hybridfunctiondefs[] = { }; opmonad hybridoperatordefs[] = { - 0, /* / */ + opReduceLast, /* / */ 0, /* \ */ - 0, /* ⌿ */ + opReduceFirst, /* ⌿ */ 0, /* ⍀ */ -};
\ No newline at end of file +}; + +/* function definitions */ + +/* operator definitions */ +Array * +opReduceLast(Datum *lefto, Array *left, Array *right) +{ + if(left) + throwerror(L"left argument to f/", ENotImplemented); + + right = fnTranspose(right); + Array *tmp = opReduceFirst(lefto, left, right); + Array *res = fnTranspose(tmp); + freearray(right); + freearray(tmp); + return res; +} + +Array * +opReduceFirst(Datum *lefto, Array *left, Array *right) +{ + if(left) + throwerror(L"left argument to f⌿", ENotImplemented); + + if(right->rank == 0) + return fnSame(right); + + int n = right->shape[0]; + int io = currentsymtab->io; + if(n == 0) + throwerror(L"Can't figure out identity element", ENotImplemented); + + Array *result = allocarray(AtypeArray, right->rank - 1, right->size / n); + for(int i = 0; i < right->rank-1; i++) + result->shape[i] = right->shape[i+1]; + + Array *index = allocarray(AtypeArray, 1, right->rank); + index->shape[0] = right->rank; + Array *tmp = mkscalarint(n); + index->arraydata[0] = fnIndexGenerator(tmp); + freearray(tmp); + for(int i = 1; i < index->size; i++) + index->arraydata[i] = mkscalarint(io); + + for(int i = 0; i < result->size; i++){ + for(int j = index->size - 1; index->arraydata[j]->intdata[0] == io + right->shape[j]; j--){ + index->arraydata[j]->intdata[0] = io; + index->arraydata[j-1]->intdata[0]++; + } + Array *vector = fnIndex(index, right); + result->arraydata[i] = arrayitem(vector, n-1); + for(int j = n-2; j >= 0; j--){ + Array *argL = arrayitem(vector, j); + Array *argR = result->arraydata[i]; + result->arraydata[i] = runfunc(lefto->func, argL, argR); + freearray(argL); + freearray(argR); + } + index->arraydata[index->size-1]->intdata[0]++; + } + freearray(index); + return result; +} |