void add_edge(word_t u, word_t v) { assert(u < MAXNODES); assert(v < MAXNODES); v += MAXNODES; // distinguish partitions if (adjlist[u] != NIL && adjlist[v] != NIL) { // possibly part of a cycle sols[nsols][0] = nlinks/2; assert(!visited.test(u)); cycles_with_link(1, u, v); } word_t ulink = nlinks++; word_t vlink = nlinks++; // the two halfedges of an edge differ only in last bit assert(vlink != NIL); // avoid confusing links with NIL; guaranteed if bits in word_t > EDGEBITS + 1 links[ulink].next = adjlist[u]; links[vlink].next = adjlist[v]; links[adjlist[u] = ulink].to = u; links[adjlist[v] = vlink].to = v; }
void cycles_with_link(u32 len, word_t u, word_t dest) { // printf("cycles_with_link(%d, %x, %x)\n", len, u, dest); if (visited.test(u)) return; if (u == dest) { print_log(" %d-cycle found\n", len); if (len == PROOFSIZE && nsols < MAXSOLS) { qsort(sols[nsols++], PROOFSIZE, sizeof(word_t), nonce_cmp); memcpy(sols[nsols], sols[nsols-1], sizeof(sols[0])); } return; } if (len == PROOFSIZE) return; word_t au1 = adjlist[u]; if (au1 != NIL) { visited.set(u); for (; au1 != NIL; au1 = links[au1].next) { sols[nsols][len] = au1/2; cycles_with_link(len+1, links[au1 ^ 1].to, dest); } visited.reset(u); } }