All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.greenrobot.common.hash.FNVJ64 Maven / Gradle / Ivy

There is a newer version: 2.12.15
Show newest version
/*
 * Copyright (C) 2014 Markus Junginger, greenrobot (http://greenrobot.de)
 *
 * 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 de.greenrobot.common.hash;

import de.greenrobot.common.PrimitiveArrayUtils;

import java.util.zip.Checksum;

/**
 * Custom 64-bit hash function favoring speed over quality.
 *
 * Tests with random data showed pretty good collision behaviour, although quality measured by SMHasher is pretty bad
 * (much worse than FNV).
 * 

* If you do progressive updates, update with byte lengths that are a multiple of 8 for best performance. *

* Based on FNV, but xors 8 bytes at once after each multiplication. */ public class FNVJ64 implements Checksum { private static PrimitiveArrayUtils primitiveArrayUtils = PrimitiveArrayUtils.getInstance(); private final static long INITIAL_VALUE = 0xcbf29ce484222325L; private final static long MULTIPLIER = 0x100000001b3L; private final static int[] PARTIAL_SHIFTS = {56, 48, 40, 32, 24, 16, 8, 0}; private final long seed; private long hash; private int partialPos; private int length; public FNVJ64() { hash = seed = INITIAL_VALUE; } public FNVJ64(long seed) { hash = this.seed = INITIAL_VALUE ^ seed; } @Override public void update(int b) { if (partialPos == 0) { hash *= MULTIPLIER; } long xorValue = (0xff & b); if (partialPos != 7) { xorValue <<= PARTIAL_SHIFTS[partialPos]; } hash ^= xorValue; partialPos++; if (partialPos == 8) { partialPos = 0; } length++; } @Override public void update(byte[] b, int off, int len) { while (partialPos != 0 && len > 0) { update(b[off]); off++; len--; } int remainder = len & 7; int stop = off + len - remainder; for (int i = off; i < stop; i += 8) { hash *= MULTIPLIER; // Tests have shown big endian results in a better bit distribution quality hash ^= primitiveArrayUtils.getLongBE(b, i); } length += stop - off; for (int i = 0; i < remainder; i++) { update(b[stop + i]); } } @Override public long getValue() { long finished = hash * MULTIPLIER; finished ^= length; finished *= MULTIPLIER; return finished; } @Override public void reset() { hash = seed; partialPos = 0; length = 0; } public int getLength() { return length; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy