1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "apl9.h"
Rune primhybridnames[] = L"/\\⌿⍀";
fndyad hybridfunctiondefs[] = {
0, /* / */
0, /* \ */
0, /* ⌿ */
0, /* ⍀ */
};
opmonad hybridoperatordefs[] = {
opReduceLast, /* / */
opScanLast, /* \ */
opReduceFirst, /* ⌿ */
opScanFirst, /* ⍀ */
};
/* 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 *
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;
}
|