
io.airlift.slice.Murmur3Hash128 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of slice Show documentation
Show all versions of slice Show documentation
Library for efficiently working with heap and off-heap memory
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.airlift.slice;
public class Murmur3Hash128
{
private static final long C1 = 0x87c37b91114253d5L;
private static final long C2 = 0x4cf5ad432745937fL;
private final static long DEFAULT_SEED = 0;
public static Slice hash(Slice data)
{
return hash(data, 0, data.length());
}
public static Slice hash(Slice data, int offset, int length)
{
return hash(DEFAULT_SEED, data, offset, length);
}
public static Slice hash(long seed, Slice data, int offset, int length)
{
final int fastLimit = offset + length - (2 * SizeOf.SIZE_OF_LONG) + 1;
long h1 = seed;
long h2 = seed;
int current = offset;
while (current < fastLimit) {
long k1 = data.getLong(current);
current += SizeOf.SIZE_OF_LONG;
long k2 = data.getLong(current);
current += SizeOf.SIZE_OF_LONG;
k1 *= C1;
k1 = Long.rotateLeft(k1, 31);
k1 *= C2;
h1 ^= k1;
h1 = Long.rotateLeft(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729L;
k2 *= C2;
k2 = Long.rotateLeft(k2, 33);
k2 *= C1;
h2 ^= k2;
h2 = Long.rotateLeft(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5L;
}
long k1 = 0;
long k2 = 0;
switch (length & 15) {
case 15:
k2 ^= ((long) data.getUnsignedByte(current + 14)) << 48;
case 14:
k2 ^= ((long) data.getUnsignedByte(current + 13)) << 40;
case 13:
k2 ^= ((long) data.getUnsignedByte(current + 12)) << 32;
case 12:
k2 ^= ((long) data.getUnsignedByte(current + 11)) << 24;
case 11:
k2 ^= ((long) data.getUnsignedByte(current + 10)) << 16;
case 10:
k2 ^= ((long) data.getUnsignedByte(current + 9)) << 8;
case 9:
k2 ^= ((long) data.getUnsignedByte(current + 8)) << 0;
k2 *= C2;
k2 = Long.rotateLeft(k2, 33);
k2 *= C1;
h2 ^= k2;
case 8:
k1 ^= ((long) data.getUnsignedByte(current + 7)) << 56;
case 7:
k1 ^= ((long) data.getUnsignedByte(current + 6)) << 48;
case 6:
k1 ^= ((long) data.getUnsignedByte(current + 5)) << 40;
case 5:
k1 ^= ((long) data.getUnsignedByte(current + 4)) << 32;
case 4:
k1 ^= ((long) data.getUnsignedByte(current + 3)) << 24;
case 3:
k1 ^= ((long) data.getUnsignedByte(current + 2)) << 16;
case 2:
k1 ^= ((long) data.getUnsignedByte(current + 1)) << 8;
case 1:
k1 ^= ((long) data.getUnsignedByte(current + 0)) << 0;
k1 *= C1;
k1 = Long.rotateLeft(k1, 31);
k1 *= C2;
h1 ^= k1;
}
h1 ^= length;
h2 ^= length;
h1 += h2;
h2 += h1;
h1 = mix64(h1);
h2 = mix64(h2);
h1 += h2;
h2 += h1;
Slice result = Slices.allocate(16);
result.setLong(0, h1);
result.setLong(8, h2);
return result;
}
/**
* Returns the 64 most significant bits of the Murmur128 hash of the provided value
*/
public static long hash64(Slice data)
{
return hash64(data, 0, data.length());
}
public static long hash64(Slice data, int offset, int length)
{
return hash64(DEFAULT_SEED, data, offset, length);
}
public static long hash64(long seed, Slice data, int offset, int length)
{
final int fastLimit = offset + length - (2 * SizeOf.SIZE_OF_LONG) + 1;
long h1 = seed;
long h2 = seed;
int current = offset;
while (current < fastLimit) {
long k1 = data.getLong(current);
current += SizeOf.SIZE_OF_LONG;
long k2 = data.getLong(current);
current += SizeOf.SIZE_OF_LONG;
k1 *= C1;
k1 = Long.rotateLeft(k1, 31);
k1 *= C2;
h1 ^= k1;
h1 = Long.rotateLeft(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729L;
k2 *= C2;
k2 = Long.rotateLeft(k2, 33);
k2 *= C1;
h2 ^= k2;
h2 = Long.rotateLeft(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5L;
}
long k1 = 0;
long k2 = 0;
switch (length & 15) {
case 15:
k2 ^= ((long) data.getUnsignedByte(current + 14)) << 48;
case 14:
k2 ^= ((long) data.getUnsignedByte(current + 13)) << 40;
case 13:
k2 ^= ((long) data.getUnsignedByte(current + 12)) << 32;
case 12:
k2 ^= ((long) data.getUnsignedByte(current + 11)) << 24;
case 11:
k2 ^= ((long) data.getUnsignedByte(current + 10)) << 16;
case 10:
k2 ^= ((long) data.getUnsignedByte(current + 9)) << 8;
case 9:
k2 ^= ((long) data.getUnsignedByte(current + 8)) << 0;
k2 *= C2;
k2 = Long.rotateLeft(k2, 33);
k2 *= C1;
h2 ^= k2;
case 8:
k1 ^= ((long) data.getUnsignedByte(current + 7)) << 56;
case 7:
k1 ^= ((long) data.getUnsignedByte(current + 6)) << 48;
case 6:
k1 ^= ((long) data.getUnsignedByte(current + 5)) << 40;
case 5:
k1 ^= ((long) data.getUnsignedByte(current + 4)) << 32;
case 4:
k1 ^= ((long) data.getUnsignedByte(current + 3)) << 24;
case 3:
k1 ^= ((long) data.getUnsignedByte(current + 2)) << 16;
case 2:
k1 ^= ((long) data.getUnsignedByte(current + 1)) << 8;
case 1:
k1 ^= ((long) data.getUnsignedByte(current + 0)) << 0;
k1 *= C1;
k1 = Long.rotateLeft(k1, 31);
k1 *= C2;
h1 ^= k1;
}
h1 ^= length;
h2 ^= length;
h1 += h2;
h2 += h1;
h1 = mix64(h1);
h2 = mix64(h2);
return h1 + h2;
}
/**
* Special-purpose version for hashing a single long value. Value is treated as little-endian
*/
public static long hash64(long value)
{
long h2 = DEFAULT_SEED ^ SizeOf.SIZE_OF_LONG;
long h1 = h2 + (h2 ^ (Long.rotateLeft(value * C1, 31) * C2));
return mix64(h1) + mix64(h1 + h2);
}
private static long mix64(long k)
{
k ^= k >>> 33;
k *= 0xff51afd7ed558ccdL;
k ^= k >>> 33;
k *= 0xc4ceb9fe1a85ec53L;
k ^= k >>> 33;
return k;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy