/* * Copyright (C) 2012 tamtam180 * * 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 at.orz.hash; import at.orz.hash.EncodeUtils.EndianReader; /** * @author tamtam180 - kirscheless at gmail.com * */ public class XXHash { private static final int PRIME1 = (int) 2654435761L; private static final int PRIME2 = (int) 2246822519L; private static final int PRIME3 = (int) 3266489917L; private static final int PRIME4 = 668265263; private static final int PRIME5 = 0x165667b1; public static int digestSmall(byte[] data, int seed, boolean bigendian) { final EndianReader er = bigendian ? EncodeUtils.BEReader : EncodeUtils.LEReader; final int len = data.length; final int bEnd = len; final int limit = bEnd - 4; int idx = seed + PRIME1; int crc = PRIME5; int i = 0; while (i < limit) { crc += er.toInt(data, i) + (idx++); crc += Integer.rotateLeft(crc, 17) * PRIME4; crc *= PRIME1; i += 4; } while (i < bEnd) { crc += (data[i] & 0xFF) + (idx++); crc *= PRIME1; i++; } crc += len; crc ^= crc >>> 15; crc *= PRIME2; crc ^= crc >>> 13; crc *= PRIME3; crc ^= crc >>> 16; return crc; } public static int digestFast32(byte[] data, int seed, boolean bigendian) { final int len = data.length; if (len < 16) { return digestSmall(data, seed, bigendian); } final EndianReader er = bigendian ? EncodeUtils.BEReader : EncodeUtils.LEReader; final int bEnd = len; final int limit = bEnd - 16; int v1 = seed + PRIME1; int v2 = v1 * PRIME2 + len; int v3 = v2 * PRIME3; int v4 = v3 * PRIME4; int i = 0; int crc = 0; while (i < limit) { v1 = Integer.rotateLeft(v1, 13) + er.toInt(data, i); i += 4; v2 = Integer.rotateLeft(v2, 11) + er.toInt(data, i); i += 4; v3 = Integer.rotateLeft(v3, 17) + er.toInt(data, i); i += 4; v4 = Integer.rotateLeft(v4, 19) + er.toInt(data, i); i += 4; } i = bEnd - 16; v1 += Integer.rotateLeft(v1, 17); v2 += Integer.rotateLeft(v2, 19); v3 += Integer.rotateLeft(v3, 13); v4 += Integer.rotateLeft(v4, 11); v1 *= PRIME1; v2 *= PRIME1; v3 *= PRIME1; v4 *= PRIME1; v1 += er.toInt(data, i); i += 4; v2 += er.toInt(data, i); i += 4; v3 += er.toInt(data, i); i += 4; v4 += er.toInt(data, i); v1 *= PRIME2; v2 *= PRIME2; v3 *= PRIME2; v4 *= PRIME2; v1 += Integer.rotateLeft(v1, 11); v2 += Integer.rotateLeft(v2, 17); v3 += Integer.rotateLeft(v3, 19); v4 += Integer.rotateLeft(v4, 13); v1 *= PRIME3; v2 *= PRIME3; v3 *= PRIME3; v4 *= PRIME3; crc = v1 + Integer.rotateLeft(v2, 3) + Integer.rotateLeft(v3, 6) + Integer.rotateLeft(v4, 9); crc ^= crc >>> 11; crc += (PRIME4 + len) * PRIME1; crc ^= crc >>> 15; crc *= PRIME2; crc ^= crc >>> 13; return crc; } public static int digestStrong32(byte[] data, int seed, boolean bigendian) { final int len = data.length; if (len < 16) { return digestSmall(data, seed, bigendian); } final EndianReader er = bigendian ? EncodeUtils.BEReader : EncodeUtils.LEReader; final int bEnd = len; final int limit = bEnd - 16; int v1 = seed + PRIME1; int v2 = v1 * PRIME2 + len; int v3 = v2 * PRIME3; int v4 = v3 * PRIME4; int i = 0; int crc = 0; while (i < limit) { v1 += Integer.rotateLeft(v1, 13); v1 *= PRIME1; v1 += er.toInt(data, i); i += 4; v2 += Integer.rotateLeft(v2, 11); v2 *= PRIME1; v2 += er.toInt(data, i); i += 4; v3 += Integer.rotateLeft(v3, 17); v3 *= PRIME1; v3 += er.toInt(data, i); i += 4; v4 += Integer.rotateLeft(v4, 19); v4 *= PRIME1; v4 += er.toInt(data, i); i += 4; } i = bEnd - 16; v1 += Integer.rotateLeft(v1, 17); v2 += Integer.rotateLeft(v2, 19); v3 += Integer.rotateLeft(v3, 13); v4 += Integer.rotateLeft(v4, 11); v1 *= PRIME1; v2 *= PRIME1; v3 *= PRIME1; v4 *= PRIME1; v1 += er.toInt(data, i); i += 4; v2 += er.toInt(data, i); i += 4; v3 += er.toInt(data, i); i += 4; v4 += er.toInt(data, i); v1 *= PRIME2; v2 *= PRIME2; v3 *= PRIME2; v4 *= PRIME2; v1 += Integer.rotateLeft(v1, 11); v2 += Integer.rotateLeft(v2, 17); v3 += Integer.rotateLeft(v3, 19); v4 += Integer.rotateLeft(v4, 13); v1 *= PRIME3; v2 *= PRIME3; v3 *= PRIME3; v4 *= PRIME3; crc = v1 + Integer.rotateLeft(v2, 3) + Integer.rotateLeft(v3, 6) + Integer.rotateLeft(v4, 9); crc ^= crc >>> 11; crc += (PRIME4 + len) * PRIME1; crc ^= crc >>> 15; crc *= PRIME2; crc ^= crc >>> 13; return crc; } public static void main(String[] args) { System.out.println(PRIME1); } }