#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; }