Files
stergios/src/node.c
T

123 lines
3.0 KiB
C

#include "node.h"
#include "hash.h"
#include "maths.h"
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
static Node* pool = NULL;
static VisitedEntry* visited_pool = NULL;
static VisitedEntry* hash_table[HASH_SIZE] = {0};
static int pool_ptr = 0;
static int pool_capacity = 0;
static int visited_ptr = 0;
void node_pool_init(int max_nodes) {
pool_capacity = max_nodes;
pool = malloc(pool_capacity * sizeof(Node));
visited_pool = malloc(pool_capacity * sizeof(VisitedEntry));
if (!pool || !visited_pool) {
fprintf(stderr, "Fatal: Could not allocate Node Pool for %d nodes.\n", max_nodes);
exit(1);
}
pool_ptr = 0;
visited_ptr = 0;
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
}
Node* node_pool_alloc() {
if (pool_ptr >= pool_capacity) {
fprintf(stderr, "\nNode Pool Overflow! Need more than %d nodes.\n", pool_capacity);
return NULL;
}
return &pool[pool_ptr++];
}
void node_pool_reset() {
pool_ptr = 0;
}
void node_pool_destroy() {
if (pool) free(pool);
}
int node_pool_usage() {
return pool_ptr;
}
static void make_move(char move, Node* curr) {
int128_t na = curr->a, nb = curr->b, nc = curr->c;
/* Calculate the new triplet based on the move type */
if (move == 'A') {
na = 2 * (curr->b + curr->c) - curr->a;
} else if (move == 'B') {
nb = 2 * (curr->a + curr->c) - curr->b;
} else if (move == 'C') {
nc = 2 * (curr->a + curr->b) - curr->c;
}
/* Validation and Enqueue */
if (safe_val(na) && safe_val(nb) && safe_val(nc)) {
if (visit_and_mark(na, nb, nc)) {
if (pool_ptr >= pool_capacity) return; /* Pool safety */
Node* n = &pool[pool_ptr++];
n->a = na; n->b = nb; n->c = nc;
n->move = move;
n->parent = curr;
n->next = NULL;
q_push(n);
}
}
}
void try_push_children(Node* curr) {
char last = curr->move;
if (last == '\0') {
make_move('A', curr);
make_move('B', curr);
make_move('C', curr);
return;
}
if (last == 'A') {
make_move('C', curr);
make_move('B', curr);
}
else if (last == 'B') {
make_move('C', curr);
make_move('A', curr);
}
else if (last == 'C') {
make_move('B', curr);
make_move('A', curr);
}
}
int visit_and_mark(int128_t a, int128_t b, int128_t c) {
sort_triplet(&a, &b, &c);
unsigned int h = hash_three128(a,b,c);
VisitedEntry* cur = hash_table[h];
while (cur) {
if (cur->a == a && cur->b == b && cur->c == c) return 0;
cur = cur->next;
}
if (visited_ptr >= pool_capacity) {
fprintf(stderr, "VisPool Overflow! Increase MAX_NODES.\n");
exit(1);
}
VisitedEntry* e = &visited_pool[visited_ptr++];
e->a = a; e->b = b; e->c = c;
e->next = hash_table[h];
hash_table[h] = e;
return 1;
}
void clear_hash_table() {
visited_ptr = 0;
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
}