uint64 FingerprintInterleavedImplementation()

in src/kudu/gutil/hash/hash.cc [49:184]


uint64 FingerprintInterleavedImplementation(const char *s, uint32 len) {
  uint32 a, b, c = kFingerprintSeed0, d, e, f = kFingerprintSeed1;
  uint32 keylen;

  a = b = d = e = 0x9e3779b9UL;   // the golden ratio; an arbitrary value

  keylen = len;
  if (keylen >= 4 * sizeof(a)) {
    uint32 word32AtOffset0 = Google1At(s);
    do {
      a += word32AtOffset0;
      d += word32AtOffset0;
      b += Google1At(s + sizeof(a));
      e += Google1At(s + sizeof(a));
      c += Google1At(s + sizeof(a) * 2);
      f += Google1At(s + sizeof(a) * 2);
      s += 3 * sizeof(a);
      word32AtOffset0 = Google1At(s);
      mix(a, b, c);
      mix(d, e, f);
      keylen -= 3 * static_cast<uint32>(sizeof(a));
    } while (keylen >= 4 * sizeof(a));
    if (keylen >= 3 * sizeof(a)) {
      a += word32AtOffset0;
      d += word32AtOffset0;
      b += Google1At(s + sizeof(a));
      e += Google1At(s + sizeof(a));
      c += Google1At(s + sizeof(a) * 2);
      f += Google1At(s + sizeof(a) * 2);
      s += 3 * sizeof(a);
      mix(a, b, c);
      mix(d, e, f);
      keylen -= 3 * static_cast<uint32>(sizeof(a));
      DCHECK_LT(keylen, sizeof(a));
      c += len;
      f += len;
      switch ( keylen ) {           // deal with rest.  Cases fall through
        case 3 :
          a += char2unsigned(s[2]) << 16;
          d += char2unsigned(s[2]) << 16;
        case 2 :
          a += char2unsigned(s[1]) << 8;
          d += char2unsigned(s[1]) << 8;
        case 1 :
          a += char2unsigned(s[0]);
          d += char2unsigned(s[0]);
      }
    } else {
      DCHECK(sizeof(a) <= keylen && keylen < 3 * sizeof(a));
      c += len;
      f += len;
      switch ( keylen ) {           // deal with rest.  Cases fall through
        case 11:
          c += char2unsigned(s[10]) << 24;
          f += char2unsigned(s[10]) << 24;
        case 10:
          c += char2unsigned(s[9]) << 16;
          f += char2unsigned(s[9]) << 16;
        case 9 :
          c += char2unsigned(s[8]) << 8;
          f += char2unsigned(s[8]) << 8;
        case 8 :
          b += Google1At(s+4);  a += word32AtOffset0;
          e += Google1At(s+4);  d += word32AtOffset0;
          break;
        case 7 :
          b += char2unsigned(s[6]) << 16;
          e += char2unsigned(s[6]) << 16;
        case 6 :
          b += char2unsigned(s[5]) << 8;
          e += char2unsigned(s[5]) << 8;
        case 5 :
          b += char2unsigned(s[4]);
          e += char2unsigned(s[4]);
        case 4 :
          a += word32AtOffset0;
          d += word32AtOffset0;
      }
    }
  } else {
    if (keylen >= 3 * sizeof(a)) {
      a += Google1At(s);
      d += Google1At(s);
      b += Google1At(s + sizeof(a));
      e += Google1At(s + sizeof(a));
      c += Google1At(s + sizeof(a) * 2);
      f += Google1At(s + sizeof(a) * 2);
      s += 3 * sizeof(a);
      mix(a, b, c);
      mix(d, e, f);
      keylen -= 3 * static_cast<uint32>(sizeof(a));
    }
    c += len;
    f += len;
    switch ( keylen ) {           // deal with rest.  Cases fall through
      case 11:
        c += char2unsigned(s[10]) << 24;
        f += char2unsigned(s[10]) << 24;
      case 10:
        c += char2unsigned(s[9]) << 16;
        f += char2unsigned(s[9]) << 16;
      case 9 :
        c += char2unsigned(s[8]) << 8;
        f += char2unsigned(s[8]) << 8;
      case 8 :
        b += Google1At(s+4);  a += Google1At(s);
        e += Google1At(s+4);  d += Google1At(s);
        break;
      case 7 :
        b += char2unsigned(s[6]) << 16;
        e += char2unsigned(s[6]) << 16;
      case 6 :
        b += char2unsigned(s[5]) << 8;
        e += char2unsigned(s[5]) << 8;
      case 5 :
        b += char2unsigned(s[4]);
        e += char2unsigned(s[4]);
      case 4 :
        a += Google1At(s);
        d += Google1At(s);
        break;
      case 3 :
        a += char2unsigned(s[2]) << 16;
        d += char2unsigned(s[2]) << 16;
      case 2 :
        a += char2unsigned(s[1]) << 8;
        d += char2unsigned(s[1]) << 8;
      case 1 :
        a += char2unsigned(s[0]);
        d += char2unsigned(s[0]);
    }
  }
  mix(a, b, c);
  mix(d, e, f);
  return CombineFingerprintHalves(c, f);
}