#include #include #include #include "apl9.h" Rune primhybridnames[] = L"/\\⌿⍀"; fndyad hybridfunctiondefs[] = { fnReplicateLast, /* / */ 0, /* \ */ fnReplicateFirst, /* ⌿ */ 0, /* ⍀ */ }; opmonad hybridoperatordefs[] = { opReduceLast, /* / */ opScanLast, /* \ */ opReduceFirst, /* ⌿ */ opScanFirst, /* ⍀ */ }; /* function definitions */ Array * fnReplicateLast(Array *left, Array *right) { return rundfn(L"⍉⍺⌿⍉⍵", nil, nil, left, right); } Array * fnReplicateFirst(Array *left, Array *right) { Rune *code = L"(0=≢⍴⍵)∧⍺∧.=0: 0⍴⍵ ⋄" L"⍺∧.=0: (((1,¯1+≢⍴⍵)⌿¯1 1)⌿⍴⍵)⍴⍵ ⋄" L"1=×⌿⍴,⍵: ↑⍪⌿(+⌿⍺)⍴⊂⍵ ⋄" L"↑↑⍪⌿⍺ (⍵{e←⊂⍵⌷⍶ ⋄ ⍺>0: ⍺⍴e ⋄ (|⍺)⍴⎕PROTO e})¨⍳≢⍵"; return rundfn(code, nil, nil, left, right); } /* 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 * opScanLast(Datum *lefto, Array *left, Array *right) { if(left) throwerror(L"f\ doesn't take a left argument", ESyntax); right = fnTranspose(right); Array *tmp = opScanFirst(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 = globalIO(); 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; } Array * opScanFirst(Datum *lefto, Array *left, Array *right) { if(left) throwerror(L"f⍀ doesn't take a left argument", ESyntax); Array *result = allocarray(AtypeArray, right->rank, right->size); for(int i = 0; i < right->rank; i++) result->shape[i] = right->shape[i]; int n = result->shape[0]; int m = result->size / n; for(int i = 0; i < n; i++){ Array *len = mkscalarint(i + 1); Array *index = fnIndexGenerator(len); Array *ix = fnEnclose(index); Array *subarr = fnIndex(ix, right); Array *subres = opReduceFirst(lefto, left, subarr); for(int j = 0; j < m; j++) result->arraydata[i*m + j] = arrayitem(subres, j); freearray(len); freearray(index); freearray(ix); freearray(subarr); freearray(subres); } return result; }