public final void add(byte[] data, int offset, int length) {
      if (length == 0) return;
      totalLen += length;
      if (tailLen + length < 4) {
        System.arraycopy(data, offset, tail, tailLen, length);
        tailLen += length;
        return;
      }
      int offset2 = 0;
      if (tailLen > 0) {
        offset2 = (4 - tailLen);
        int k = -1;
        switch (tailLen) {
        case 1:
          k = orBytes(tail[0], data[offset], data[offset + 1], data[offset + 2]);
          break;
        case 2:
          k = orBytes(tail[0], tail[1], data[offset], data[offset + 1]);
          break;
        case 3:
          k = orBytes(tail[0], tail[1], tail[2], data[offset]);
          break;
        default: throw new AssertionError(tailLen);
        }
        // mix functions
        k *= C1_32;
        k = Integer.rotateLeft(k, R1_32);
        k *= C2_32;
        hash ^= k;
        hash = Integer.rotateLeft(hash, R2_32) * M_32 + N_32;
      }
      int length2 = length - offset2;
      offset += offset2;
      final int nblocks = length2 >> 2;

      for (int i = 0; i < nblocks; i++) {
        int i_4 = (i << 2) + offset;
        int k = orBytes(data[i_4], data[i_4 + 1], data[i_4 + 2], data[i_4 + 3]);

        // mix functions
        k *= C1_32;
        k = Integer.rotateLeft(k, R1_32);
        k *= C2_32;
        hash ^= k;
        hash = Integer.rotateLeft(hash, R2_32) * M_32 + N_32;
      }

      int consumed = (nblocks << 2);
      tailLen = length2 - consumed;
      if (consumed == length2) return;
      System.arraycopy(data, offset + consumed, tail, 0, tailLen);
    }
Murmur3 128-bit variant.

@param data   - input byte array
@param offset - the first element of array
@param length - length of array
@param seed   - seed. (default is 0)
@return - hashcode (2 longs)
storage-api/src/java/org/apache/hive/common/util/Murmur3.java