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
|
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "apl9.h"
Rune primmonopnames[] = L"¨⍨⌸⌶&";
Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺";
opmonad monadoperatordefs[] = {
opEach, /* ¨ */
opSwitch, /* ⍨ */
0, /* ⌸ */
0, /* ⌶ */
0, /* & */
};
opdyad dyadoperatordefs[] = {
0, /* ⍣ */
0, /* . */
0, /* ∘ */
0, /* ⍤ */
opOver, /* ⍥ */
0, /* @ */
0, /* ⍠ */
0, /* ⌺ */
};
/* Monadic operators */
Array *
opEach(Datum *lefto, Array *left, Array *right)
{
int i;
if(lefto->tag != FunctionTag)
return nil;
Array *leftarr;
Array *rightarr;
if(left){
int rankok = scalarextend(left, right, &leftarr, &rightarr);
if(!rankok)
throwerror(nil, ERank);
}else{
leftarr = nil;
rightarr = fnSame(right);
}
Array *result = allocarray(AtypeArray, rightarr->rank, rightarr->size);
for(i = 0; i < rightarr->rank; i++)
result->shape[i] = rightarr->shape[i];
for(i = 0; i < rightarr->size; i++){
Array *elem1 = leftarr ? arrayitem(leftarr, i) : nil;
Array *elem2 = arrayitem(rightarr, i);
result->arraydata[i] = runfunc(lefto->func, elem1, elem2);
freearray(elem1);
freearray(elem2);
}
freearray(leftarr);
freearray(rightarr);
return result;
}
Array *
opSwitch(Datum *lefto, Array *left, Array *right)
{
if(lefto->tag == ArrayTag){
incref(lefto->array);
return lefto->array;
}else if(lefto->tag == FunctionTag){
if(left)
return runfunc(lefto->func, right, left);
else
return runfunc(lefto->func, right, right);
}else
return nil;
}
/* Dyadic operators */
Array *
opOver(Datum *lefto, Datum *righto, Array *left, Array *right)
{
if(lefto->tag != FunctionTag || righto->tag != FunctionTag)
return nil;
if(left){
Array *r = runfunc(righto->func, nil, right);
Array *l = runfunc(righto->func, nil, left);
Array *res = runfunc(lefto->func, l, r);
freearray(r);
freearray(l);
return res;
}else{
Array *tmp = runfunc(righto->func, nil, right);
Array *res = runfunc(lefto->func, nil, tmp);
freearray(tmp);
return res;
}
}
|