summaryrefslogtreecommitdiff
path: root/hybrids.c
blob: 39f3f7a29b5a9b1a3f6d3147cbf252df16a5630d (plain) (blame)
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
#include <u.h>
#include <libc.h>
#include <bio.h>

#include "apl9.h"

Rune primhybridnames[] = L"/\\⌿⍀";

fndyad hybridfunctiondefs[] = {
	0, /* / */
	0, /* \ */
	0, /* ⌿ */
	0, /* ⍀ */
};

opmonad hybridoperatordefs[] = {
	opReduceLast, /* / */
	0, /* \ */
	opReduceFirst, /* ⌿ */
	0, /* ⍀ */
};

/* 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;
}