aboutsummaryrefslogtreecommitdiff
path: root/include/cnn1986_cache.c
blob: d9545ac3cb64ae09af445b58757e3055d59df894 (plain)
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
#include "cnn1986_cache.h"

#define DATA_STONE_SHIFT 6
#define DATA_COUNT_SHIFT (DATA_STONE_SHIFT+2)
#define COLOUR_MASK      0x3F // 0b00111111

uint32_t cnn1986_num_cached, cnn1986_max_num_cached;
node_t *head = NULL, *tail = NULL;

void cnn1986_cache_free(void) {
	node_t *c = head, *n;
	while (c) {
		n = c->next;
		free(c);
		c = n;
	}
	head = NULL;
	tail = NULL;
}

int cnn1986_cache_seek(float *out_result) {
	node_t *c = head;

	if (c == NULL) return EXIT_FAILURE;

	uint8_t comp_data[25], fail;
	for (int k=0; k<25; k++) {
		comp_data[k] = (colours[k] & COLOUR_MASK)
			| (STONE_AT(k) << DATA_STONE_SHIFT)
			| (COUNT_AT(k) << DATA_COUNT_SHIFT);
	}

	// We've checked c = head already, so uncoditionally test it
	do {
		// Compare
		fail = 0;
		if (c->black_count == black_count && c->white_count == white_count) {
			for (int k=0; k<25; k++) {
				if (comp_data[k] != c->data[k]) {
					fail = 1;
					break;
				}
			}
		} else { fail = 1; }

		// Either seek next or move to front and return
		if (fail) {
			c = c->next;
		} else {
			*out_result = c->result;

			// Move to front
			if (c != head) {
				if (tail == c) tail=c->prev;
				if (c->next) c->next->prev = c->prev;
				c->prev->next = c->next;
				c->prev = NULL;
				c->next = head;
				head->prev = c;
				head = c;
			}

			return EXIT_SUCCESS;
		}
	} while (c);

	// Failed to find it
	return EXIT_FAILURE;
}

int cnn1986_cache_insert(float in_result) {
	node_t *new = malloc(sizeof(node_t));
	if (new == NULL) return EXIT_FAILURE;
	// TODO: check errno
	new->prev = NULL;
	new->next = head;
	if (head) head->prev = new;
	head = new;
	new->result = in_result;
	new->white_count = white_count;
	new->black_count = black_count;
	for (int k=0; k<25; k++) {
		new->data[k] = (colours[k] & COLOUR_MASK)
			| (STONE_AT(k) << DATA_STONE_SHIFT)
			| (COUNT_AT(k) << DATA_COUNT_SHIFT);
	}
	if (cnn1986_num_cached == 0) tail = new;
	cnn1986_num_cached++;

	if (cnn1986_num_cached > cnn1986_max_num_cached) {
		tail = tail->prev;
		free(tail->next);
		tail->next = NULL;
		cnn1986_num_cached--;
	}

	return EXIT_SUCCESS;
}