code: public static int hashSearch(final Memory mem, final int lgArrLongs, final long hash,
        final int memOffsetBytes) {
      final int arrayMask = (1 << lgArrLongs) - 1;
      final int stride = getStride(hash, lgArrLongs);
      int curProbe = (int) (hash & arrayMask);
      final int loopIndex = curProbe;
      do {
        final int curProbeOffsetBytes = (curProbe << 3) + memOffsetBytes;
        final long curArrayHash = mem.getLong(curProbeOffsetBytes);
        if (curArrayHash == EMPTY) { return -1; }
        else if (curArrayHash == hash) { return curProbe; }
        curProbe = (curProbe + stride) & arrayMask;
      } while (curProbe != loopIndex);
      return -1;
    }
docs: This is a classical Knuth-style Open Addressing, Double Hash search scheme for off-heap.
  Returns the index if found, -1 if not found.
  
  @param mem The Memory hash table to search.
  @param lgArrLongs <a href="{@docRoot}/resources/dictionary.html#lgArrLongs">See lgArrLongs</a>.
  lgArrLongs &le; log2(hashTable.length).
  @param hash A hash value to search for. Must not be zero.
  @param memOffsetBytes offset in the memory where the hash array starts
  @return index if found, -1 if not found.