diff --git a/equi_miner.h b/equi_miner.h index dea1b2d..161ef61 100644 --- a/equi_miner.h +++ b/equi_miner.h @@ -82,24 +82,15 @@ typedef u32 au32; #endif #endif -// number of buckets -static const u32 NBUCKETS = 1< indices[size]) { @@ -397,6 +401,8 @@ struct equi { if (r == 0) { u32 idx = t.getindex(); if (dupes) { + // recognize most dupes by storing last seen index + // with same K least significant bits in array dupes u32 bin = idx & (PROOFSIZE-1); if (idx == dupes[bin]) return true; dupes[bin] = idx; @@ -411,6 +417,7 @@ struct equi { || listindices1(r, buck[t.slotid1()][tagi].tag, indices+size, dupes) || (!dupes && orderindices(indices, size)); } + // need separate instance for accessing (differently typed) heap1 bool listindices1(u32 r, const tree t, u32 *indices, u32 *dupes) { const slot0 *buck = hta.heap0[t.bucketid()]; const u32 size = 1 << --r; @@ -419,24 +426,31 @@ struct equi { || listindices0(r, buck[t.slotid1()][tagi].tag, indices+size, dupes) || (!dupes && orderindices(indices, size)); } + // check a candidate that resulted in 0 xor + // add as solution, with proper subtree ordering, if it has unique indices void candidate(const tree t) { proof prf, dupes; memset(dupes, 0xffff, sizeof(proof)); if (listindices1(WK, t, prf, dupes)) return; // assume WK odd + // it survived the probable dupe test, now check fully qsort(prf, PROOFSIZE, sizeof(u32), &compu32); for (u32 i=1; ihta), prevhtunits(0), dunits(0) { - u32 nexthashbytes = hashsize(r); - nexthtunits = hashwords(nexthashbytes); - prevbo = 0; - if (r) { + u32 nexthashbytes = hashsize(r); // number of bytes occupied by round r hash + nexthtunits = hashwords(nexthashbytes); // number of 32bit words taken up by those bytes + prevbo = 0; // byte offset for accessing hash form previous round + if (r) { // similar measure for previous round u32 prevhashbytes = hashsize(r-1); prevhtunits = hashwords(prevhashbytes); prevbo = prevhtunits * sizeof(htunit) - prevhashbytes; // 0-3 - dunits = prevhtunits - nexthtunits; + dunits = prevhtunits - nexthtunits; // number of words by which hash shrinks } } + // extract remaining bits in digit slots in same bucket still need to collide on u32 getxhash0(const htunit* slot) const { #if WN == 200 && RESTBITS == 4 return slot->bytes[prevbo] >> 4; @@ -491,6 +508,7 @@ struct equi { #error non implemented #endif } + // similar but accounting for possible change in hashsize modulo 4 bits u32 getxhash1(const htunit* slot) const { #if WN == 200 && RESTBITS == 4 return slot->bytes[prevbo] & 0xf; @@ -502,12 +520,19 @@ struct equi { #error non implemented #endif } + // test whether two hashes match in last 32 bits bool equal(const htunit *hash0, const htunit *hash1) const { return hash0[prevhtunits-1].word == hash1[prevhtunits-1].word; } }; + // this thread-local object performs in-bucket collissions + // by linking together slots that have identical rest bits + // (which is in essense a 2nd stage bucket sort) struct collisiondata { +// the bitmap is an early experiment in a bitmap encoding +// that works only for at most 64 slots +// it might as well be obsoleted as it performs worse even in that case #ifdef XBITMAP #if NSLOTS > 64 #error cant use XBITMAP with more than 64 slots @@ -515,6 +540,10 @@ struct equi { u64 xhashmap[NRESTS]; u64 xmap; #else +// This maintains NRESTS = 2^RESTBITS lists whose starting slot +// are in xhashslots[] and where subsequent slots in each list +// are found through nextxhashslot[] +// since 0 is already a valid slot number, use ~0 as nil value #if RESTBITS <= 6 typedef uchar xslot; #else