diff --git a/src/maths.c b/src/maths.c index 9f48ebe..dfed2a1 100755 --- a/src/maths.c +++ b/src/maths.c @@ -5,6 +5,7 @@ extern int128_t LIMIT; extern int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode); +extern int is_new_root(int128_t a, int128_t b, int128_t c); const int NUM_PRIMES = 3; const int primes[] = {2, 3, 5}; @@ -57,15 +58,21 @@ void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents, if ((n1 + n2) % 2 == 0) { int128_t val1 = values[1] + values[2] + ((n1 + n2) >> 1); int128_t val2 = values[1] + values[2] - ((n1 + n2) >> 1); - int128_t greater = values[2] >= val1 ? values[2] : val1; + int128_t gcd1 = gcd3(values[1], values[2], val1); int128_t gcd2 = gcd3(values[1], values[2], val2); - LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd1 * gcd1) : values[2] * val1 / (2 * gcd1 * gcd1); - run_bfs(sum, values[1] / gcd1, values[2] / gcd1, val1 / gcd1, print_mode); - if (val2 >= 0) { - greater = values[2] >= val2 ? values[2] : val2; - LIMIT =values[1] >= greater ? values[1] * greater / (2 * gcd2 * gcd2) : values[2] * val2 / (2 * gcd2 * gcd2); - run_bfs(sum, values[1] / gcd2, values[2] / gcd2, val2 / gcd2, print_mode); + int128_t r1a = values[1] / gcd1, r1b = values[2] / gcd1, r1c = val1 / gcd1; + int128_t r2a = values[1] / gcd2, r2b = values[2] / gcd2, r2c = val2 / gcd2; + + if (is_new_root(r1a, r1b, r1c)) { + int128_t greater = values[2] >= val1 ? values[2] : val1; + LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd1 * gcd1) : values[2] * val1 / (2 * gcd1 * gcd1); + run_bfs(sum, r1a, r1b, r1c, print_mode); + } + if (val2 >= 0 && is_new_root(r2a, r2b, r2c)) { + int128_t greater = values[2] >= val2 ? values[2] : val2; + LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd2 * gcd2) : values[2] * val2 / (2 * gcd2 * gcd2); + run_bfs(sum, r2a, r2b, r2c, print_mode); } } return; diff --git a/src/stergios.c b/src/stergios.c index 7136e4e..e4b90b3 100755 --- a/src/stergios.c +++ b/src/stergios.c @@ -7,6 +7,65 @@ #define HASH_SIZE 200003 int128_t LIMIT = 0; +typedef struct GlobalEntry { + int128_t a, b, c; + struct GlobalEntry* next; +} GlobalEntry; + +static GlobalEntry* global_root_table[HASH_SIZE] = {0}; + +// Helper to sort the triplet so order doesn't matter +static void sort_triplet(int128_t* a, int128_t* b, int128_t* c) { + int128_t tmp; + if (*a > *b) { tmp = *a; *a = *b; *b = tmp; } + if (*b > *c) { tmp = *b; *b = *c; *c = tmp; } + if (*a > *b) { tmp = *a; *a = *b; *b = tmp; } +} + +static inline uint128_t mix128(uint128_t a, uint128_t b, uint128_t c) { + uint128_t x = a + (uint128_t)0x9e3779b97f4a7c15ULL + ((uint128_t)0x9e3779b97f4a7c15ULL << 64); + x ^= b + ((uint128_t)0xbf58476d1ce4e5b9ULL + ((uint128_t)0xbf58476d1ce4e5b9ULL << 64)) + (x << 6) + (x >> 2); + x ^= c + ((uint128_t)0x94d049bb133111ebULL + ((uint128_t)0x94d049bb133111ebULL << 64)) + (x << 6) + (x >> 2); + return x; +} + +static unsigned int hash_three128(uint128_t a, uint128_t b, uint128_t c) { + uint128_t x = mix128(a, b, c); + return (unsigned int)(x % HASH_SIZE); +} + +// Returns 1 if this is a new root, 0 if we've already calculated it +int is_new_root(int128_t a, int128_t b, int128_t c) { + sort_triplet(&a, &b, &c); + unsigned int h = hash_three128((uint128_t)a, (uint128_t)b, (uint128_t)c); + + GlobalEntry* cur = global_root_table[h]; + while (cur) { + if (cur->a == a && cur->b == b && cur->c == c) return 0; + cur = cur->next; + } + + GlobalEntry* e = malloc(sizeof(GlobalEntry)); + if (!e) return 1; // Fallback to running BFS if malloc fails + e->a = a; e->b = b; e->c = c; + e->next = global_root_table[h]; + global_root_table[h] = e; + return 1; +} + +// Call this at the start of 'auto' mode +void clear_global_table() { + for (int i = 0; i < HASH_SIZE; i++) { + GlobalEntry* cur = global_root_table[i]; + while (cur) { + GlobalEntry* next = cur->next; + free(cur); + cur = next; + } + global_root_table[i] = NULL; + } +} + typedef struct Node { int128_t a, b, c; char move; @@ -36,17 +95,6 @@ void clear_hash_table() { int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode); -static inline uint128_t mix128(uint128_t a, uint128_t b, uint128_t c) { - uint128_t x = a + (uint128_t)0x9e3779b97f4a7c15ULL + ((uint128_t)0x9e3779b97f4a7c15ULL << 64); - x ^= b + ((uint128_t)0xbf58476d1ce4e5b9ULL + ((uint128_t)0xbf58476d1ce4e5b9ULL << 64)) + (x << 6) + (x >> 2); - x ^= c + ((uint128_t)0x94d049bb133111ebULL + ((uint128_t)0x94d049bb133111ebULL << 64)) + (x << 6) + (x >> 2); - return x; -} - -static unsigned int hash_three128(uint128_t a, uint128_t b, uint128_t c) { - uint128_t x = mix128(a, b, c); - return (unsigned int)(x % HASH_SIZE); -} static int visit_and_mark(int128_t a, int128_t b, int128_t c) { unsigned int h = hash_three128(a,b,c); @@ -202,6 +250,7 @@ int main() { run_bfs(&sum, a0 / gcd, b0 / gcd, c0 / gcd, print_mode); } else if (mode == 2) { + clear_global_table(); // Reset unique root tracker int p = 3; int exponents[3] = {2*p + 2, p, p}; int128_t values[3] = {4 * power(a0, p) * power(b0, p), power(a0, p), power(b0, p)};