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

com.github.tommyettinger.digital.Hasher Maven / Gradle / Ivy

/*
 * Copyright (c) 2022-2023 See AUTHORS file.
 *
 * 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 com.github.tommyettinger.digital;

import java.util.Iterator;
import java.util.List;

import static com.github.tommyettinger.digital.BitConversion.doubleToRawLongBits;
import static com.github.tommyettinger.digital.BitConversion.floatToRawIntBits;

import static com.github.tommyettinger.digital.MathTools.EPSILON;
import static com.github.tommyettinger.digital.MathTools.EPSILON_D;

/**
 * 64-bit and 32-bit hashing functions that we can rely on staying the same cross-platform.
 * This uses a family of algorithms all based on Wang Yi's wyhash, but using at most 64-bit
 * math. Wyhash was designed foremost for speed and also general-purpose usability, but not
 * cryptographic security. The functions here pass the stringent SMHasher test battery,
 * including the "bad seeds" test that wyhash itself fails. This is based on an early version
 * of wyhash,
 * source here,
 * but has diverged significantly.
 * 
* This provides an object-based API and a static API, where a Hasher object is * instantiated with a seed, and the static methods take a seed as their first argument. * The hashes this returns are always 0 when given null to hash. Arrays with * identical elements of identical types will hash identically. Arrays with identical * numerical values but different types will sometimes hash differently. This class * always provides 64-bit hashes via hash64() and 32-bit hashes via hash(). * The hash64() and hash() methods use 64-bit math even when producing * 32-bit hashes, for GWT reasons. GWT doesn't have the same behavior as desktop and * Android applications when using ints because it treats ints mostly like doubles, * sometimes, due to it using JavaScript. If we use mainly longs, though, GWT emulates * the longs with a more complex technique behind-the-scenes, that behaves the same on * the web as it does on desktop or on a phone. Since Hasher is supposed to be stable * cross-platform, this is the way we need to go, despite it being slightly slower. *
* This class also provides static {@link #randomize1(long)}, {@link #randomize2(long)}, and * {@link #randomize3(long)} methods, which are unary hashes (hashes of one item, a number) with variants such as * {@link #randomize1Bounded(long, int)} and {@link #randomize2Float(long)}. The randomize1() * methods are faster but more sensitive to patterns in their input; they are meant to * work well on sequential inputs, like 1, 2, 3, etc. with relatively-short sequences * (ideally under a million, but if statistical quality isn't a concern, they can handle any * length). The randomize2() methods are more-involved, but should be able to handle most * kinds of input pattern across even rather-large sequences (billions) while returning * random results. The randomize3() methods are likely complete overkill for many cases, but * provide extremely strong randomization for any possible input pattern, using the MX3 unary * hash with an extra XOR at the beginning to prevent a fixed point at 0. *
* There are also 428 predefined instances of Hasher that you can either * select from the array {@link #predefined} or select by hand, such as {@link #omega}. * The predefined instances are named after the 24 greek letters, then the same letters * with a trailing underscore, then * 72 names of demons from the Ars Goetia, * then the names of those demons with trailing underscores, then the names of 118 chemical elements, then those names * with trailing underscores. The greek letters are traditional, the demons are perfectly fitting for video games, and * chemistry has been closely linked with computing for many years now. * * @author Tommy Ettinger */ public class Hasher { /** * The seed used by all non-static hash() and hash64() methods in this class (the methods that don't take a seed). * You can create many different Hasher objects, all with different seeds, and get very different hashes as a result * of any calls on them. Because making this field hidden in some way doesn't meaningfully contribute to security, * and only makes it harder to use this class, {@code seed} is public (and final, so it can't be accidentally * modified, but still can if needed via reflection). */ public final long seed; /** * Creates a new Hasher seeded, arbitrarily, with the constant 0xC4CEB9FE1A85EC53L, or -4265267296055464877L . */ public Hasher() { this.seed = 0xC4CEB9FE1A85EC53L; } /** * Initializes this Hasher with the given seed, verbatim; it is recommended to use {@link #randomize3(long)} on the * seed if you don't know if it is adequately-random. If the seed is the same for two different Hasher instances and * they are given the same inputs, they will produce the same results. If the seed is even slightly different, the * results of the two Hashers given the same input should be significantly different. * * @param seed a long that will be used to change the output of hash() and hash64() methods on the new Hasher */ public Hasher(long seed) { this.seed = seed; } /** * Fast static randomizing method that takes its state as a parameter; state is expected to change between calls to * this. It is recommended that you use {@code randomize1(++state)} or {@code randomize1(--state)} * to produce a sequence of different numbers, and you may have slightly worse quality with increments or decrements * other than 1. All longs are accepted by this method, and all longs can be produced. Passing 0 here does not * cause this to return 0. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @return any long */ public static long randomize1(long state) { return (state = ((state = (((state * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ state >>> 27) * 0xAEF17502108EF2D9L) ^ state >>> 25; } /** * Mid-quality static randomizing method that takes its state as a parameter; state is expected to change between * calls to this. It is suggested that you use {@code DiverRNG.randomize(++state)} or * {@code DiverRNG.randomize(--state)} to produce a sequence of different numbers, but any increments are allowed * (even-number increments won't be able to produce all outputs, but their quality will be fine for the numbers they * can produce). All longs are accepted by this method, and all longs can be produced. Passing 0 here does not * cause this to return 0. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @return any long */ public static long randomize2(long state) { state ^= 0xD1B54A32D192ED03L; return (state = ((state = (state ^ (state << 39 | state >>> 25) ^ (state << 17 | state >>> 47)) * 0x9E6C63D0676A9A99L) ^ state >>> 23 ^ state >>> 51) * 0x9E6D62D06F6A9A9BL) ^ state >>> 23 ^ state >>> 51; // older Pelican mixer // return (state = ((state = (state ^ (state << 41 | state >>> 23) ^ (state << 17 | state >>> 47) ^ 0xD1B54A32D192ED03L) * 0xAEF17502108EF2D9L) ^ state >>> 43 ^ state >>> 31 ^ state >>> 23) * 0xDB4F0B9175AE2165L) ^ state >>> 28; } /** * Very thorough static randomizing method that takes its state as a parameter; state is expected to change between * calls to this. It is suggested that you use {@code randomize3(++state)} or {@code randomize3(--state)} * to produce a sequence of different numbers, but any odd-number increment should work well, as could another * source of different longs, such as a flawed random number generator. All longs are accepted by this method, and * all longs can be produced. Passing 0 here does not cause this to return 0. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @return any long */ public static long randomize3(long state) { state ^= 0xABC98388FB8FAC03L; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; state ^= state >>> 29; state *= 0xBEA225F9EB34556DL; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; return state ^ state >>> 29; } /** * Fast static randomizing method that takes its state as a parameter and limits output to an int between 0 * (inclusive) and bound (exclusive); state is expected to change between calls to this. It is recommended that you * use {@code randomize1Bounded(++state, bound)} or {@code randomize1Bounded(--state, bound)} to * produce a sequence of different numbers. All longs are accepted * by this method, but not all ints between 0 and bound are guaranteed to be produced with equal likelihood (for any * odd-number values for bound, this isn't possible for most generators). The bound can be negative. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @param bound the outer exclusive bound, as an int * @return an int between 0 (inclusive) and bound (exclusive) */ public static int randomize1Bounded(long state, int bound) { return (bound = (int) ((bound * (((state = ((state = (((state * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ state >>> 27) * 0xAEF17502108EF2D9L) ^ state >>> 25) & 0xFFFFFFFFL)) >> 32)) + (bound >>> 31); } /** * Mid-quality static randomizing method that takes its state as a parameter and limits output to an int between 0 * (inclusive) and bound (exclusive); state is expected to change between calls to this. It is suggested that you * use {@code randomize2Bounded(++state)} or {@code randomize2Bounded(--state)} to produce a sequence of * different numbers, but any increments are allowed (even-number increments won't be able to produce all outputs, * but their quality will be fine for the numbers they can produce). All longs are accepted by this method, but not * all ints between 0 and bound are guaranteed to be produced with equal likelihood (for any odd-number values for * bound, this isn't possible for most generators). The bound can be negative. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @param bound the outer exclusive bound, as an int * @return an int between 0 (inclusive) and bound (exclusive) */ public static int randomize2Bounded(long state, int bound) { state ^= 0xD1B54A32D192ED03L; return (bound = (int) ((bound * (((state = ((state = (state ^ (state << 39 | state >>> 25) ^ (state << 17 | state >>> 47)) * 0x9E6C63D0676A9A99L) ^ state >>> 23 ^ state >>> 51) * 0x9E6D62D06F6A9A9BL) ^ state >>> 23 ^ state >>> 51) & 0xFFFFFFFFL)) >> 32)) + (bound >>> 31); } /** * Very thorough static randomizing method that takes its state as a parameter and limits output to an int between 0 * (inclusive) and bound (exclusive); state is expected to change between calls to this. It is suggested that you * use {@code randomize3Bounded(++state)} or {@code randomize3(--state)} to produce a sequence of * different numbers, but any increments are allowed (even-number increments won't be able to produce all outputs, * but their quality will be fine for the numbers they can produce). All longs are accepted by this method, but not * all ints between 0 and bound are guaranteed to be produced with equal likelihood (for any odd-number values for * bound, this isn't possible for most generators). The bound can be negative. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state any long; subsequent calls should change by an odd number, such as with {@code ++state} * @param bound the outer exclusive bound, as an int * @return an int between 0 (inclusive) and bound (exclusive) */ public static int randomize3Bounded(long state, int bound) { state ^= 0xABC98388FB8FAC03L; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; state ^= state >>> 29; state *= 0xBEA225F9EB34556DL; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; return (bound = (int) ((bound * ((state ^ state >>> 29) & 0xFFFFFFFFL)) >> 32)) + (bound >>> 31); } /** * Returns a random float that is deterministic based on state; if state is the same on two calls to this, this will * return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize1Float(++state)}, where the increment for state should generally be 1. The period is 2 to the 64 * if you increment or decrement by 1, but there are only 2 to the 30 possible floats between 0 and 1, and this can * only return 2 to the 24 of them (a requirement for the returned values to be uniform). *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomize1Float(++state)} is recommended to go forwards or * {@code randomize1Float(--state)} to generate numbers in reverse order * @return a pseudo-random float between 0f (inclusive) and 1f (exclusive), determined by {@code state} */ public static float randomize1Float(long state) { return ((((state = (((state * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ state >>> 27) * 0xAEF17502108EF2D9L) >>> 40) * EPSILON; } /** * Returns a random float that is deterministic based on state; if state is the same on two calls to this, this will * return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize2Float(++state)}, where the increment for state can be any value and should usually be odd * (even-number increments reduce the period). The period is 2 to the 64 if you increment or decrement by any odd * number, but there are only 2 to the 30 possible floats between 0 and 1, and this can only return 2 to the 24 of * them (a requirement for the returned values to be uniform). *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomize2Float(++state)} is recommended to go forwards or * {@code randomize2Float(--state)} to generate numbers in reverse order * @return a pseudo-random float between 0f (inclusive) and 1f (exclusive), determined by {@code state} */ public static float randomize2Float(long state) { state ^= 0xD1B54A32D192ED03L; return ((((state = (state ^ (state << 39 | state >>> 25) ^ (state << 17 | state >>> 47)) * 0x9E6C63D0676A9A99L) ^ state >>> 23 ^ state >>> 51) * 0x9E6D62D06F6A9A9BL) >>> 40) * EPSILON; } /** * Returns a random float that is deterministic based on state; if state is the same on two calls to this, this will * return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize3Float(++state)}, where the increment for state can be any value and should usually be odd * (even-number increments reduce the period). The period is 2 to the 64 if you increment or decrement by any odd * number, but there are only 2 to the 30 possible floats between 0 and 1, and this can only return 2 to the 24 of * them (a requirement for the returned values to be uniform). *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomize3Float(++state)} is recommended to go forwards or * {@code randomize3Float(--state)} to generate numbers in reverse order * @return a pseudo-random float between 0f (inclusive) and 1f (exclusive), determined by {@code state} */ public static float randomize3Float(long state) { state ^= 0xABC98388FB8FAC03L; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; state ^= state >>> 29; state *= 0xBEA225F9EB34556DL; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; return (state >>> 40) * EPSILON; } /** * Returns a random double that is deterministic based on state; if state is the same on two calls to this, this * will return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize1Double(++state)}, where the increment for state should generally be 1. The period is 2 to the 64 * if you increment or decrement by 1, but there are only 2 to the 62 possible doubles between 0 and 1. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomize1Double(++state)} is recommended to go forwards or * {@code randomize1Double(--state)} to generate numbers in reverse order * @return a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive), determined by {@code state} */ public static double randomize1Double(long state) { return (((state = ((state = (((state * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ state >>> 27) * 0xAEF17502108EF2D9L) ^ state >>> 25) & 0x1FFFFFFFFFFFFFL) * EPSILON_D; } /** * Returns a random double that is deterministic based on state; if state is the same on two calls to this, this * will return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize2Double(++state)}, where the increment for state can be any number but should usually be odd * (even-number increments reduce the period). The period is 2 to the 64 if you increment or decrement by 1, but * there are only 2 to the 62 possible doubles between 0 and 1. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomizeDouble(++state)} is recommended to go forwards or * {@code randomizeDouble(--state)} to generate numbers in reverse order * @return a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive), determined by {@code state} */ public static double randomize2Double(long state) { state ^= 0xD1B54A32D192ED03L; return (((state = ((state = (state ^ (state << 39 | state >>> 25) ^ (state << 17 | state >>> 47)) * 0x9E6C63D0676A9A99L) ^ state >>> 23 ^ state >>> 51) * 0x9E6D62D06F6A9A9BL) ^ state >>> 23) >>> 11) * EPSILON_D; } /** * Returns a random double that is deterministic based on state; if state is the same on two calls to this, this * will return the same float. This is expected to be called with a changing variable, e.g. * {@code randomize3Double(++state)}, where the increment for state can be any number but should usually be odd * (even-number increments reduce the period). The period is 2 to the 64 if you increment or decrement by 1, but * there are only 2 to the 62 possible doubles between 0 and 1. *
* You have a choice between different randomize strengths in this class. {@code randomize1()} is simpler, and will * behave well when the inputs are sequential, while {@code randomize2()} is a completely different algorithm, Pelle * Evensen's xNASAM; * it will have excellent quality for most patterns in input but will be about 30% slower than * {@code randomize1()}, though this is rarely detectable. {@code randomize3()} is the slowest and most robust; it * uses MX3 by Jon Maiga, which the aforementioned author of xNASAM now recommends for any unary hashing. All * randomizeN methods will produce all long outputs if given all possible longs as input. Technically-speaking, * {@code randomize1(long)}, {@code randomize2(long)}, and {@code randomize3(long)} are bijective functions, which * means they are reversible; it is, however, somewhat harder to reverse the xor-rotate-xor-rotate stage used in * randomize2() (reversing randomize3() is easy, but takes more steps), and the methods that produce any output * other than a full-range long are not reversible (such as {@link #randomize1Bounded(long, int)} and * {@link #randomize2Double(long)}). * * @param state a variable that should be different every time you want a different random result; * using {@code randomize3Double(++state)} is recommended to go forwards or * {@code randomize3Double(--state)} to generate numbers in reverse order * @return a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive), determined by {@code state} */ public static double randomize3Double(long state) { state ^= 0xABC98388FB8FAC03L; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; state ^= state >>> 29; state *= 0xBEA225F9EB34556DL; state ^= state >>> 32; state *= 0xBEA225F9EB34556DL; return (state >>> 11 ^ state >>> 40) * EPSILON_D; } /** * Constructs a Hasher by hashing {@code seed} with {@link #hash64(long, CharSequence)}, and then running the result * through {@link #randomize3(long)}. This is the same as calling the constructor {@link #Hasher(long)} and passing * it {@code randomize3(hash64(1L, seed))} . * * @param seed a CharSequence, such as a String, that will be used to seed the Hasher. */ public Hasher(final CharSequence seed) { this(randomize3(hash64(1L, seed))); } /** * Big constant 0. */ public static final long b0 = 0xA0761D6478BD642FL; /** * Big constant 1. */ public static final long b1 = 0xE7037ED1A0B428DBL; /** * Big constant 2. */ public static final long b2 = 0x8EBC6AF09C88C6E3L; /** * Big constant 3. */ public static final long b3 = 0x589965CC75374CC3L; /** * Big constant 4. */ public static final long b4 = 0x1D8E4E27C47D124FL; /** * Big constant 5. */ public static final long b5 = 0xEB44ACCAB455D165L; /** * Takes two arguments that are technically longs, and should be very different, and uses them to get a result * that is technically a long and mixes the bits of the inputs. The arguments and result are only technically * longs because their lower 32 bits matter much more than their upper 32, and giving just any long won't work. *
* This is very similar to wyhash's mum function, but doesn't use 128-bit math because it expects that its * arguments are only relevant in their lower 32 bits (allowing their product to fit in 64 bits). * * @param a a long that should probably only hold an int's worth of data * @param b a long that should probably only hold an int's worth of data * @return a sort-of randomized output dependent on both inputs */ public static long mum(final long a, final long b) { final long n = a * b; return n ^ (n >>> 30); } /** * A slower but higher-quality variant on {@link #mum(long, long)} that can take two arbitrary longs (with any * of their 64 bits containing relevant data) instead of mum's 32-bit sections of its inputs, and outputs a * 64-bit result that can have any of its bits used. *
* This was changed so that it distributes bits from both inputs a little better on July 6, 2019. * * @param a any long * @param b any long * @return a sort-of randomized output dependent on both inputs */ public static long wow(final long a, final long b) { final long n = (a ^ (b << 39 | b >>> 25)) * (b ^ (a << 39 | a >>> 25)); return n ^ (n >>> 32); } public static final Hasher alpha = new Hasher("alpha"), beta = new Hasher("beta"), gamma = new Hasher("gamma"), delta = new Hasher("delta"), epsilon = new Hasher("epsilon"), zeta = new Hasher("zeta"), eta = new Hasher("eta"), theta = new Hasher("theta"), iota = new Hasher("iota"), kappa = new Hasher("kappa"), lambda = new Hasher("lambda"), mu = new Hasher("mu"), nu = new Hasher("nu"), xi = new Hasher("xi"), omicron = new Hasher("omicron"), pi = new Hasher("pi"), rho = new Hasher("rho"), sigma = new Hasher("sigma"), tau = new Hasher("tau"), upsilon = new Hasher("upsilon"), phi = new Hasher("phi"), chi = new Hasher("chi"), psi = new Hasher("psi"), omega = new Hasher("omega"), alpha_ = new Hasher("ALPHA"), beta_ = new Hasher("BETA"), gamma_ = new Hasher("GAMMA"), delta_ = new Hasher("DELTA"), epsilon_ = new Hasher("EPSILON"), zeta_ = new Hasher("ZETA"), eta_ = new Hasher("ETA"), theta_ = new Hasher("THETA"), iota_ = new Hasher("IOTA"), kappa_ = new Hasher("KAPPA"), lambda_ = new Hasher("LAMBDA"), mu_ = new Hasher("MU"), nu_ = new Hasher("NU"), xi_ = new Hasher("XI"), omicron_ = new Hasher("OMICRON"), pi_ = new Hasher("PI"), rho_ = new Hasher("RHO"), sigma_ = new Hasher("SIGMA"), tau_ = new Hasher("TAU"), upsilon_ = new Hasher("UPSILON"), phi_ = new Hasher("PHI"), chi_ = new Hasher("CHI"), psi_ = new Hasher("PSI"), omega_ = new Hasher("OMEGA"), baal = new Hasher("baal"), agares = new Hasher("agares"), vassago = new Hasher("vassago"), samigina = new Hasher("samigina"), marbas = new Hasher("marbas"), valefor = new Hasher("valefor"), amon = new Hasher("amon"), barbatos = new Hasher("barbatos"), paimon = new Hasher("paimon"), buer = new Hasher("buer"), gusion = new Hasher("gusion"), sitri = new Hasher("sitri"), beleth = new Hasher("beleth"), leraje = new Hasher("leraje"), eligos = new Hasher("eligos"), zepar = new Hasher("zepar"), botis = new Hasher("botis"), bathin = new Hasher("bathin"), sallos = new Hasher("sallos"), purson = new Hasher("purson"), marax = new Hasher("marax"), ipos = new Hasher("ipos"), aim = new Hasher("aim"), naberius = new Hasher("naberius"), glasya_labolas = new Hasher("glasya_labolas"), bune = new Hasher("bune"), ronove = new Hasher("ronove"), berith = new Hasher("berith"), astaroth = new Hasher("astaroth"), forneus = new Hasher("forneus"), foras = new Hasher("foras"), asmoday = new Hasher("asmoday"), gaap = new Hasher("gaap"), furfur = new Hasher("furfur"), marchosias = new Hasher("marchosias"), stolas = new Hasher("stolas"), phenex = new Hasher("phenex"), halphas = new Hasher("halphas"), malphas = new Hasher("malphas"), raum = new Hasher("raum"), focalor = new Hasher("focalor"), vepar = new Hasher("vepar"), sabnock = new Hasher("sabnock"), shax = new Hasher("shax"), vine = new Hasher("vine"), bifrons = new Hasher("bifrons"), vual = new Hasher("vual"), haagenti = new Hasher("haagenti"), crocell = new Hasher("crocell"), furcas = new Hasher("furcas"), balam = new Hasher("balam"), alloces = new Hasher("alloces"), caim = new Hasher("caim"), murmur = new Hasher("murmur"), orobas = new Hasher("orobas"), gremory = new Hasher("gremory"), ose = new Hasher("ose"), amy = new Hasher("amy"), orias = new Hasher("orias"), vapula = new Hasher("vapula"), zagan = new Hasher("zagan"), valac = new Hasher("valac"), andras = new Hasher("andras"), flauros = new Hasher("flauros"), andrealphus = new Hasher("andrealphus"), kimaris = new Hasher("kimaris"), amdusias = new Hasher("amdusias"), belial = new Hasher("belial"), decarabia = new Hasher("decarabia"), seere = new Hasher("seere"), dantalion = new Hasher("dantalion"), andromalius = new Hasher("andromalius"), baal_ = new Hasher("BAAL"), agares_ = new Hasher("AGARES"), vassago_ = new Hasher("VASSAGO"), samigina_ = new Hasher("SAMIGINA"), marbas_ = new Hasher("MARBAS"), valefor_ = new Hasher("VALEFOR"), amon_ = new Hasher("AMON"), barbatos_ = new Hasher("BARBATOS"), paimon_ = new Hasher("PAIMON"), buer_ = new Hasher("BUER"), gusion_ = new Hasher("GUSION"), sitri_ = new Hasher("SITRI"), beleth_ = new Hasher("BELETH"), leraje_ = new Hasher("LERAJE"), eligos_ = new Hasher("ELIGOS"), zepar_ = new Hasher("ZEPAR"), botis_ = new Hasher("BOTIS"), bathin_ = new Hasher("BATHIN"), sallos_ = new Hasher("SALLOS"), purson_ = new Hasher("PURSON"), marax_ = new Hasher("MARAX"), ipos_ = new Hasher("IPOS"), aim_ = new Hasher("AIM"), naberius_ = new Hasher("NABERIUS"), glasya_labolas_ = new Hasher("GLASYA_LABOLAS"), bune_ = new Hasher("BUNE"), ronove_ = new Hasher("RONOVE"), berith_ = new Hasher("BERITH"), astaroth_ = new Hasher("ASTAROTH"), forneus_ = new Hasher("FORNEUS"), foras_ = new Hasher("FORAS"), asmoday_ = new Hasher("ASMODAY"), gaap_ = new Hasher("GAAP"), furfur_ = new Hasher("FURFUR"), marchosias_ = new Hasher("MARCHOSIAS"), stolas_ = new Hasher("STOLAS"), phenex_ = new Hasher("PHENEX"), halphas_ = new Hasher("HALPHAS"), malphas_ = new Hasher("MALPHAS"), raum_ = new Hasher("RAUM"), focalor_ = new Hasher("FOCALOR"), vepar_ = new Hasher("VEPAR"), sabnock_ = new Hasher("SABNOCK"), shax_ = new Hasher("SHAX"), vine_ = new Hasher("VINE"), bifrons_ = new Hasher("BIFRONS"), vual_ = new Hasher("VUAL"), haagenti_ = new Hasher("HAAGENTI"), crocell_ = new Hasher("CROCELL"), furcas_ = new Hasher("FURCAS"), balam_ = new Hasher("BALAM"), alloces_ = new Hasher("ALLOCES"), caim_ = new Hasher("CAIM"), murmur_ = new Hasher("MURMUR"), orobas_ = new Hasher("OROBAS"), gremory_ = new Hasher("GREMORY"), ose_ = new Hasher("OSE"), amy_ = new Hasher("AMY"), orias_ = new Hasher("ORIAS"), vapula_ = new Hasher("VAPULA"), zagan_ = new Hasher("ZAGAN"), valac_ = new Hasher("VALAC"), andras_ = new Hasher("ANDRAS"), flauros_ = new Hasher("FLAUROS"), andrealphus_ = new Hasher("ANDREALPHUS"), kimaris_ = new Hasher("KIMARIS"), amdusias_ = new Hasher("AMDUSIAS"), belial_ = new Hasher("BELIAL"), decarabia_ = new Hasher("DECARABIA"), seere_ = new Hasher("SEERE"), dantalion_ = new Hasher("DANTALION"), andromalius_ = new Hasher("ANDROMALIUS"), hydrogen = new Hasher("hydrogen"), helium = new Hasher("helium"), lithium = new Hasher("lithium"), beryllium = new Hasher("beryllium"), boron = new Hasher("boron"), carbon = new Hasher("carbon"), nitrogen = new Hasher("nitrogen"), oxygen = new Hasher("oxygen"), fluorine = new Hasher("fluorine"), neon = new Hasher("neon"), sodium = new Hasher("sodium"), magnesium = new Hasher("magnesium"), aluminium = new Hasher("aluminium"), silicon = new Hasher("silicon"), phosphorus = new Hasher("phosphorus"), sulfur = new Hasher("sulfur"), chlorine = new Hasher("chlorine"), argon = new Hasher("argon"), potassium = new Hasher("potassium"), calcium = new Hasher("calcium"), scandium = new Hasher("scandium"), titanium = new Hasher("titanium"), vanadium = new Hasher("vanadium"), chromium = new Hasher("chromium"), manganese = new Hasher("manganese"), iron = new Hasher("iron"), cobalt = new Hasher("cobalt"), nickel = new Hasher("nickel"), copper = new Hasher("copper"), zinc = new Hasher("zinc"), gallium = new Hasher("gallium"), germanium = new Hasher("germanium"), arsenic = new Hasher("arsenic"), selenium = new Hasher("selenium"), bromine = new Hasher("bromine"), krypton = new Hasher("krypton"), rubidium = new Hasher("rubidium"), strontium = new Hasher("strontium"), yttrium = new Hasher("yttrium"), zirconium = new Hasher("zirconium"), niobium = new Hasher("niobium"), molybdenum = new Hasher("molybdenum"), technetium = new Hasher("technetium"), ruthenium = new Hasher("ruthenium"), rhodium = new Hasher("rhodium"), palladium = new Hasher("palladium"), silver = new Hasher("silver"), cadmium = new Hasher("cadmium"), indium = new Hasher("indium"), tin = new Hasher("tin"), antimony = new Hasher("antimony"), tellurium = new Hasher("tellurium"), iodine = new Hasher("iodine"), xenon = new Hasher("xenon"), caesium = new Hasher("caesium"), barium = new Hasher("barium"), lanthanum = new Hasher("lanthanum"), cerium = new Hasher("cerium"), praseodymium = new Hasher("praseodymium"), neodymium = new Hasher("neodymium"), promethium = new Hasher("promethium"), samarium = new Hasher("samarium"), europium = new Hasher("europium"), gadolinium = new Hasher("gadolinium"), terbium = new Hasher("terbium"), dysprosium = new Hasher("dysprosium"), holmium = new Hasher("holmium"), erbium = new Hasher("erbium"), thulium = new Hasher("thulium"), ytterbium = new Hasher("ytterbium"), lutetium = new Hasher("lutetium"), hafnium = new Hasher("hafnium"), tantalum = new Hasher("tantalum"), tungsten = new Hasher("tungsten"), rhenium = new Hasher("rhenium"), osmium = new Hasher("osmium"), iridium = new Hasher("iridium"), platinum = new Hasher("platinum"), gold = new Hasher("gold"), mercury = new Hasher("mercury"), thallium = new Hasher("thallium"), lead = new Hasher("lead"), bismuth = new Hasher("bismuth"), polonium = new Hasher("polonium"), astatine = new Hasher("astatine"), radon = new Hasher("radon"), francium = new Hasher("francium"), radium = new Hasher("radium"), actinium = new Hasher("actinium"), thorium = new Hasher("thorium"), protactinium = new Hasher("protactinium"), uranium = new Hasher("uranium"), neptunium = new Hasher("neptunium"), plutonium = new Hasher("plutonium"), americium = new Hasher("americium"), curium = new Hasher("curium"), berkelium = new Hasher("berkelium"), californium = new Hasher("californium"), einsteinium = new Hasher("einsteinium"), fermium = new Hasher("fermium"), mendelevium = new Hasher("mendelevium"), nobelium = new Hasher("nobelium"), lawrencium = new Hasher("lawrencium"), rutherfordium = new Hasher("rutherfordium"), dubnium = new Hasher("dubnium"), seaborgium = new Hasher("seaborgium"), bohrium = new Hasher("bohrium"), hassium = new Hasher("hassium"), meitnerium = new Hasher("meitnerium"), darmstadtium = new Hasher("darmstadtium"), roentgenium = new Hasher("roentgenium"), copernicium = new Hasher("copernicium"), nihonium = new Hasher("nihonium"), flerovium = new Hasher("flerovium"), moscovium = new Hasher("moscovium"), livermorium = new Hasher("livermorium"), tennessine = new Hasher("tennessine"), oganesson = new Hasher("oganesson"), hydrogen_ = new Hasher("HYDROGEN"), helium_ = new Hasher("HELIUM"), lithium_ = new Hasher("LITHIUM"), beryllium_ = new Hasher("BERYLLIUM"), boron_ = new Hasher("BORON"), carbon_ = new Hasher("CARBON"), nitrogen_ = new Hasher("NITROGEN"), oxygen_ = new Hasher("OXYGEN"), fluorine_ = new Hasher("FLUORINE"), neon_ = new Hasher("NEON"), sodium_ = new Hasher("SODIUM"), magnesium_ = new Hasher("MAGNESIUM"), aluminium_ = new Hasher("ALUMINIUM"), silicon_ = new Hasher("SILICON"), phosphorus_ = new Hasher("PHOSPHORUS"), sulfur_ = new Hasher("SULFUR"), chlorine_ = new Hasher("CHLORINE"), argon_ = new Hasher("ARGON"), potassium_ = new Hasher("POTASSIUM"), calcium_ = new Hasher("CALCIUM"), scandium_ = new Hasher("SCANDIUM"), titanium_ = new Hasher("TITANIUM"), vanadium_ = new Hasher("VANADIUM"), chromium_ = new Hasher("CHROMIUM"), manganese_ = new Hasher("MANGANESE"), iron_ = new Hasher("IRON"), cobalt_ = new Hasher("COBALT"), nickel_ = new Hasher("NICKEL"), copper_ = new Hasher("COPPER"), zinc_ = new Hasher("ZINC"), gallium_ = new Hasher("GALLIUM"), germanium_ = new Hasher("GERMANIUM"), arsenic_ = new Hasher("ARSENIC"), selenium_ = new Hasher("SELENIUM"), bromine_ = new Hasher("BROMINE"), krypton_ = new Hasher("KRYPTON"), rubidium_ = new Hasher("RUBIDIUM"), strontium_ = new Hasher("STRONTIUM"), yttrium_ = new Hasher("YTTRIUM"), zirconium_ = new Hasher("ZIRCONIUM"), niobium_ = new Hasher("NIOBIUM"), molybdenum_ = new Hasher("MOLYBDENUM"), technetium_ = new Hasher("TECHNETIUM"), ruthenium_ = new Hasher("RUTHENIUM"), rhodium_ = new Hasher("RHODIUM"), palladium_ = new Hasher("PALLADIUM"), silver_ = new Hasher("SILVER"), cadmium_ = new Hasher("CADMIUM"), indium_ = new Hasher("INDIUM"), tin_ = new Hasher("TIN"), antimony_ = new Hasher("ANTIMONY"), tellurium_ = new Hasher("TELLURIUM"), iodine_ = new Hasher("IODINE"), xenon_ = new Hasher("XENON"), caesium_ = new Hasher("CAESIUM"), barium_ = new Hasher("BARIUM"), lanthanum_ = new Hasher("LANTHANUM"), cerium_ = new Hasher("CERIUM"), praseodymium_ = new Hasher("PRASEODYMIUM"), neodymium_ = new Hasher("NEODYMIUM"), promethium_ = new Hasher("PROMETHIUM"), samarium_ = new Hasher("SAMARIUM"), europium_ = new Hasher("EUROPIUM"), gadolinium_ = new Hasher("GADOLINIUM"), terbium_ = new Hasher("TERBIUM"), dysprosium_ = new Hasher("DYSPROSIUM"), holmium_ = new Hasher("HOLMIUM"), erbium_ = new Hasher("ERBIUM"), thulium_ = new Hasher("THULIUM"), ytterbium_ = new Hasher("YTTERBIUM"), lutetium_ = new Hasher("LUTETIUM"), hafnium_ = new Hasher("HAFNIUM"), tantalum_ = new Hasher("TANTALUM"), tungsten_ = new Hasher("TUNGSTEN"), rhenium_ = new Hasher("RHENIUM"), osmium_ = new Hasher("OSMIUM"), iridium_ = new Hasher("IRIDIUM"), platinum_ = new Hasher("PLATINUM"), gold_ = new Hasher("GOLD"), mercury_ = new Hasher("MERCURY"), thallium_ = new Hasher("THALLIUM"), lead_ = new Hasher("LEAD"), bismuth_ = new Hasher("BISMUTH"), polonium_ = new Hasher("POLONIUM"), astatine_ = new Hasher("ASTATINE"), radon_ = new Hasher("RADON"), francium_ = new Hasher("FRANCIUM"), radium_ = new Hasher("RADIUM"), actinium_ = new Hasher("ACTINIUM"), thorium_ = new Hasher("THORIUM"), protactinium_ = new Hasher("PROTACTINIUM"), uranium_ = new Hasher("URANIUM"), neptunium_ = new Hasher("NEPTUNIUM"), plutonium_ = new Hasher("PLUTONIUM"), americium_ = new Hasher("AMERICIUM"), curium_ = new Hasher("CURIUM"), berkelium_ = new Hasher("BERKELIUM"), californium_ = new Hasher("CALIFORNIUM"), einsteinium_ = new Hasher("EINSTEINIUM"), fermium_ = new Hasher("FERMIUM"), mendelevium_ = new Hasher("MENDELEVIUM"), nobelium_ = new Hasher("NOBELIUM"), lawrencium_ = new Hasher("LAWRENCIUM"), rutherfordium_ = new Hasher("RUTHERFORDIUM"), dubnium_ = new Hasher("DUBNIUM"), seaborgium_ = new Hasher("SEABORGIUM"), bohrium_ = new Hasher("BOHRIUM"), hassium_ = new Hasher("HASSIUM"), meitnerium_ = new Hasher("MEITNERIUM"), darmstadtium_ = new Hasher("DARMSTADTIUM"), roentgenium_ = new Hasher("ROENTGENIUM"), copernicium_ = new Hasher("COPERNICIUM"), nihonium_ = new Hasher("NIHONIUM"), flerovium_ = new Hasher("FLEROVIUM"), moscovium_ = new Hasher("MOSCOVIUM"), livermorium_ = new Hasher("LIVERMORIUM"), tennessine_ = new Hasher("TENNESSINE"), oganesson_ = new Hasher("OGANESSON"); /** * Has a length of 428, which may be relevant if automatically choosing a predefined hash functor. */ public static final Hasher[] predefined = new Hasher[]{alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota, kappa, lambda, mu, nu, xi, omicron, pi, rho, sigma, tau, upsilon, phi, chi, psi, omega, alpha_, beta_, gamma_, delta_, epsilon_, zeta_, eta_, theta_, iota_, kappa_, lambda_, mu_, nu_, xi_, omicron_, pi_, rho_, sigma_, tau_, upsilon_, phi_, chi_, psi_, omega_, baal, agares, vassago, samigina, marbas, valefor, amon, barbatos, paimon, buer, gusion, sitri, beleth, leraje, eligos, zepar, botis, bathin, sallos, purson, marax, ipos, aim, naberius, glasya_labolas, bune, ronove, berith, astaroth, forneus, foras, asmoday, gaap, furfur, marchosias, stolas, phenex, halphas, malphas, raum, focalor, vepar, sabnock, shax, vine, bifrons, vual, haagenti, crocell, furcas, balam, alloces, caim, murmur, orobas, gremory, ose, amy, orias, vapula, zagan, valac, andras, flauros, andrealphus, kimaris, amdusias, belial, decarabia, seere, dantalion, andromalius, baal_, agares_, vassago_, samigina_, marbas_, valefor_, amon_, barbatos_, paimon_, buer_, gusion_, sitri_, beleth_, leraje_, eligos_, zepar_, botis_, bathin_, sallos_, purson_, marax_, ipos_, aim_, naberius_, glasya_labolas_, bune_, ronove_, berith_, astaroth_, forneus_, foras_, asmoday_, gaap_, furfur_, marchosias_, stolas_, phenex_, halphas_, malphas_, raum_, focalor_, vepar_, sabnock_, shax_, vine_, bifrons_, vual_, haagenti_, crocell_, furcas_, balam_, alloces_, caim_, murmur_, orobas_, gremory_, ose_, amy_, orias_, vapula_, zagan_, valac_, andras_, flauros_, andrealphus_, kimaris_, amdusias_, belial_, decarabia_, seere_, dantalion_, andromalius_, hydrogen, helium, lithium, beryllium, boron, carbon, nitrogen, oxygen, fluorine, neon, sodium, magnesium, aluminium, silicon, phosphorus, sulfur, chlorine, argon, potassium, calcium, scandium, titanium, vanadium, chromium, manganese, iron, cobalt, nickel, copper, zinc, gallium, germanium, arsenic, selenium, bromine, krypton, rubidium, strontium, yttrium, zirconium, niobium, molybdenum, technetium, ruthenium, rhodium, palladium, silver, cadmium, indium, tin, antimony, tellurium, iodine, xenon, caesium, barium, lanthanum, cerium, praseodymium, neodymium, promethium, samarium, europium, gadolinium, terbium, dysprosium, holmium, erbium, thulium, ytterbium, lutetium, hafnium, tantalum, tungsten, rhenium, osmium, iridium, platinum, gold, mercury, thallium, lead, bismuth, polonium, astatine, radon, francium, radium, actinium, thorium, protactinium, uranium, neptunium, plutonium, americium, curium, berkelium, californium, einsteinium, fermium, mendelevium, nobelium, lawrencium, rutherfordium, dubnium, seaborgium, bohrium, hassium, meitnerium, darmstadtium, roentgenium, copernicium, nihonium, flerovium, moscovium, livermorium, tennessine, oganesson, hydrogen_, helium_, lithium_, beryllium_, boron_, carbon_, nitrogen_, oxygen_, fluorine_, neon_, sodium_, magnesium_, aluminium_, silicon_, phosphorus_, sulfur_, chlorine_, argon_, potassium_, calcium_, scandium_, titanium_, vanadium_, chromium_, manganese_, iron_, cobalt_, nickel_, copper_, zinc_, gallium_, germanium_, arsenic_, selenium_, bromine_, krypton_, rubidium_, strontium_, yttrium_, zirconium_, niobium_, molybdenum_, technetium_, ruthenium_, rhodium_, palladium_, silver_, cadmium_, indium_, tin_, antimony_, tellurium_, iodine_, xenon_, caesium_, barium_, lanthanum_, cerium_, praseodymium_, neodymium_, promethium_, samarium_, europium_, gadolinium_, terbium_, dysprosium_, holmium_, erbium_, thulium_, ytterbium_, lutetium_, hafnium_, tantalum_, tungsten_, rhenium_, osmium_, iridium_, platinum_, gold_, mercury_, thallium_, lead_, bismuth_, polonium_, astatine_, radon_, francium_, radium_, actinium_, thorium_, protactinium_, uranium_, neptunium_, plutonium_, americium_, curium_, berkelium_, californium_, einsteinium_, fermium_, mendelevium_, nobelium_, lawrencium_, rutherfordium_, dubnium_, seaborgium_, bohrium_, hassium_, meitnerium_, darmstadtium_, roentgenium_, copernicium_, nihonium_, flerovium_, moscovium_, livermorium_, tennessine_, oganesson_, }; public long hash64(final boolean[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final boolean[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum((data[i - 3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i - 2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) - seed, mum((data[i - 1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 2: seed = mum((data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b0 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 3: seed = mum((data[len - 3] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b2 ^ (data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L)) + mum(seed ^ b5, b4 ^ (data[len - 1] ? 0x9E3779B9 : 0x7F4A7C15)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final byte[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final byte[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final short[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final short[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final char[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param data a char array * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the array) * @return a 64-bit hash of data */ public long hash64(final char[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final CharSequence data) { if (data == null) return 0; return hash64(data, 0, data.length()); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param data the String or other CharSequence to hash * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the CharSequence) * @return a 64-bit hash of data */ public long hash64(final CharSequence data, final int start, final int length) { if (data == null || start < 0 || length < 0 || start >= length) return 0; long seed = this.seed; final int len = Math.min(length, data.length()); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data.charAt(i - 3) ^ b1, data.charAt(i - 2) ^ b2) - seed, mum(data.charAt(i - 1) ^ b3, data.charAt(i) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data.charAt(start + len - 1))); break; case 2: seed = mum(data.charAt(start + len - 2) - seed, b0 ^ data.charAt(start + len - 1)); break; case 3: seed = mum(data.charAt(start + len - 3) - seed, b2 ^ data.charAt(start + len - 2)) + mum(b5 ^ seed, b4 ^ (data.charAt(start + len - 1))); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final int[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final int[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum((data[start + len - 1] >>> 16) - seed, b3 ^ (data[start + len - 1] & 0xFFFFL)); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum((data[start + len - 1] >>> 16) ^ seed, b4 ^ (data[start + len - 1] & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final int[] data, final int length) { return hash64(data, 0, length); } public long hash64(final long[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final long[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= data[i - 3] * b1; a = (a << 23 | a >>> 41) * b3; b ^= data[i - 2] * b2; b = (b << 25 | b >>> 39) * b4; c ^= data[i - 1] * b3; c = (c << 29 | c >>> 35) * b5; d ^= data[i] * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ data[start + len - 1]); break; case 2: seed = wow(seed + data[start + len - 2], b2 ^ data[start + len - 1]); break; case 3: seed = wow(seed + data[start + len - 3], b2 + data[start + len - 2]) + wow(seed + data[start + len - 1], seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final float[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final float[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); int n; for (int i = start + 3; i < len; i += 4) { seed = mum( mum(floatToRawIntBits(data[i - 3]) ^ b1, floatToRawIntBits(data[i - 2]) ^ b2) - seed, mum(floatToRawIntBits(data[i - 1]) ^ b3, floatToRawIntBits(data[i]) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: n = floatToRawIntBits(data[start + len - 1]); seed = mum((n >>> 16) - seed, b3 ^ (n & 0xFFFFL)); break; case 2: seed = mum(floatToRawIntBits(data[start + len - 2]) - seed, b0 ^ floatToRawIntBits(data[start + len - 1])); break; case 3: n = floatToRawIntBits(data[start + len - 1]); seed = mum(floatToRawIntBits(data[start + len - 3]) - seed, b2 ^ floatToRawIntBits(data[start + len - 2])) + mum((n >>> 16) ^ seed, b4 ^ (n & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final double[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final double[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= doubleToRawLongBits(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= doubleToRawLongBits(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= doubleToRawLongBits(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= doubleToRawLongBits(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ doubleToRawLongBits(data[start + len - 1])); break; case 2: seed = wow(seed + doubleToRawLongBits(data[start + len - 2]), b2 ^ doubleToRawLongBits(data[start + len - 1])); break; case 3: seed = wow(seed + doubleToRawLongBits(data[start + len - 3]), b2 + doubleToRawLongBits(data[start + len - 2])) + wow(seed + doubleToRawLongBits(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final byte[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final byte[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final char[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final char[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final float[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final float[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final double[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final double[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final int[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final int[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final long[][] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final long[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final CharSequence[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final CharSequence[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final CharSequence[]... data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final CharSequence[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final Iterable data) { if (data == null) return 0; long seed = this.seed; final Iterator it = data.iterator(); int len = 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; while (it.hasNext()) { ++len; a ^= hash64(it.next()) * b1; a = (a << 23 | a >>> 41) * b3; if(it.hasNext()) { ++len; b ^= hash64(it.next()) * b2; b = (b << 25 | b >>> 39) * b4; } if(it.hasNext()) { ++len; c ^= hash64(it.next()) * b3; c = (c << 29 | c >>> 35) * b5; } if(it.hasNext()) { ++len; d ^= hash64(it.next()) * b4; d = (d << 31 | d >>> 33) * b1; } seed += a + b + c + d; } seed += b5; seed = wow(b1 - seed, b4 + seed); seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final List data) { if (data == null) return 0; return hash64(data, 0, data.size()); } public long hash64(final List data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.size()) return 0; long seed = this.seed; final int len = Math.min(length, data.size() - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data.get(i - 3)) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data.get(i - 2)) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data.get(i - 1)) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data.get(i)) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data.get(start + len - 1))); break; case 2: seed = wow(seed + hash64(data.get(start + len - 2)), b2 ^ hash64(data.get(start + len - 1))); break; case 3: seed = wow(seed + hash64(data.get(start + len - 3)), b2 + hash64(data.get(start + len - 2))) + wow(seed + hash64(data.get(start + len - 1)), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final Object[] data) { if (data == null) return 0; return hash64(data, 0, data.length); } public long hash64(final Object[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public long hash64(final Object data) { if (data == null) return 0; return wow(data.hashCode() ^ b4, b5 - seed) ^ seed; } public int hash(final boolean[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final boolean[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum((data[i - 3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i - 2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) - seed, mum((data[i - 1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 2: seed = mum((data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b0 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 3: seed = mum((data[len - 3] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b2 ^ (data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L)) + mum(seed ^ b5, b4 ^ (data[len - 1] ? 0x9E3779B9 : 0x7F4A7C15)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final byte[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final byte[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final short[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final short[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final char[] data) { if (data == null) return 0; return hash(data, 0, data.length); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param data a char array * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the array) * @return a 32-bit hash of data */ public int hash(final char[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final CharSequence data) { if (data == null) return 0; return hash(data, 0, data.length()); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param data the String or other CharSequence to hash * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the CharSequence) * @return a 32-bit hash of data */ public int hash(final CharSequence data, final int start, final int length) { if (data == null || start < 0 || length < 0 || start >= length) return 0; long seed = this.seed; final int len = Math.min(length, data.length()); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data.charAt(i - 3) ^ b1, data.charAt(i - 2) ^ b2) - seed, mum(data.charAt(i - 1) ^ b3, data.charAt(i) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data.charAt(start + len - 1))); break; case 2: seed = mum(data.charAt(start + len - 2) - seed, b0 ^ data.charAt(start + len - 1)); break; case 3: seed = mum(data.charAt(start + len - 3) - seed, b2 ^ data.charAt(start + len - 2)) + mum(b5 ^ seed, b4 ^ (data.charAt(start + len - 1))); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final int[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final int[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum((data[start + len - 1] >>> 16) - seed, b3 ^ (data[start + len - 1] & 0xFFFFL)); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum((data[start + len - 1] >>> 16) ^ seed, b4 ^ (data[start + len - 1] & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final int[] data, final int length) { return hash(data, 0, length); } public int hash(final long[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final long[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= data[i - 3] * b1; a = (a << 23 | a >>> 41) * b3; b ^= data[i - 2] * b2; b = (b << 25 | b >>> 39) * b4; c ^= data[i - 1] * b3; c = (c << 29 | c >>> 35) * b5; d ^= data[i] * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ data[start + len - 1]); break; case 2: seed = wow(seed + data[start + len - 2], b2 ^ data[start + len - 1]); break; case 3: seed = wow(seed + data[start + len - 3], b2 + data[start + len - 2]) + wow(seed + data[start + len - 1], seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final float[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final float[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); int n; for (int i = start + 3; i < len; i += 4) { seed = mum( mum(floatToRawIntBits(data[i - 3]) ^ b1, floatToRawIntBits(data[i - 2]) ^ b2) - seed, mum(floatToRawIntBits(data[i - 1]) ^ b3, floatToRawIntBits(data[i]) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: n = floatToRawIntBits(data[start + len - 1]); seed = mum((n >>> 16) - seed, b3 ^ (n & 0xFFFFL)); break; case 2: seed = mum(floatToRawIntBits(data[start + len - 2]) - seed, b0 ^ floatToRawIntBits(data[start + len - 1])); break; case 3: n = floatToRawIntBits(data[start + len - 1]); seed = mum(floatToRawIntBits(data[start + len - 3]) - seed, b2 ^ floatToRawIntBits(data[start + len - 2])) + mum((n >>> 16) ^ seed, b4 ^ (n & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final double[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final double[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= doubleToRawLongBits(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= doubleToRawLongBits(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= doubleToRawLongBits(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= doubleToRawLongBits(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ doubleToRawLongBits(data[start + len - 1])); break; case 2: seed = wow(seed + doubleToRawLongBits(data[start + len - 2]), b2 ^ doubleToRawLongBits(data[start + len - 1])); break; case 3: seed = wow(seed + doubleToRawLongBits(data[start + len - 3]), b2 + doubleToRawLongBits(data[start + len - 2])) + wow(seed + doubleToRawLongBits(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final byte[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final byte[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final char[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final char[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final float[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final float[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final double[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final double[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final int[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final int[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final long[][] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final long[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final CharSequence[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final CharSequence[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final CharSequence[]... data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final CharSequence[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final Iterable data) { if (data == null) return 0; long seed = this.seed; final Iterator it = data.iterator(); int len = 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; while (it.hasNext()) { ++len; a ^= hash64(it.next()) * b1; a = (a << 23 | a >>> 41) * b3; if(it.hasNext()) { ++len; b ^= hash64(it.next()) * b2; b = (b << 25 | b >>> 39) * b4; } if(it.hasNext()) { ++len; c ^= hash64(it.next()) * b3; c = (c << 29 | c >>> 35) * b5; } if(it.hasNext()) { ++len; d ^= hash64(it.next()) * b4; d = (d << 31 | d >>> 33) * b1; } seed += a + b + c + d; } seed += b5; seed = wow(b1 - seed, b4 + seed); seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final List data) { if (data == null) return 0; return hash(data, 0, data.size()); } public int hash(final List data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.size()) return 0; long seed = this.seed; final int len = Math.min(length, data.size() - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data.get(i - 3)) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data.get(i - 2)) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data.get(i - 1)) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data.get(i)) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data.get(start + len - 1))); break; case 2: seed = wow(seed + hash64(data.get(start + len - 2)), b2 ^ hash64(data.get(start + len - 1))); break; case 3: seed = wow(seed + hash64(data.get(start + len - 3)), b2 + hash64(data.get(start + len - 2))) + wow(seed + hash64(data.get(start + len - 1)), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final Object[] data) { if (data == null) return 0; return hash(data, 0, data.length); } public int hash(final Object[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long seed = this.seed; final int len = Math.min(length, data.length - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(data[start + len - 1])); break; case 2: seed = wow(seed + hash64(data[start + len - 2]), b2 ^ hash64(data[start + len - 1])); break; case 3: seed = wow(seed + hash64(data[start + len - 3]), b2 + hash64(data[start + len - 2])) + wow(seed + hash64(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public int hash(final Object data) { if (data == null) return 0; return (int)(mum(data.hashCode() ^ b2, b3 - seed) ^ seed); } public static long hash64(long seed, final boolean[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final boolean[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum((data[i - 3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i - 2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) - seed, mum((data[i - 1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 2: seed = mum((data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b0 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 3: seed = mum((data[len - 3] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b2 ^ (data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L)) + mum(seed ^ b5, b4 ^ (data[len - 1] ? 0x9E3779B9 : 0x7F4A7C15)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final byte[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final byte[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final short[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final short[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final char[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param seed the seed to use for this hash, as a long * @param data a char array * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the array) * @return a 64-bit hash of data */ public static long hash64(long seed, final char[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final CharSequence data) { if (data == null) return 0; return hash64(seed, data, 0, data.length()); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param seed the seed to use for this hash, as a long * @param data the String or other CharSequence to hash * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the array) * @return a 64-bit hash of data */ public static long hash64(long seed, final CharSequence data, final int start, final int length) { if (data == null || start < 0 || length < 0 || start >= length) return 0; final int len = Math.min(length, data.length()); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data.charAt(i - 3) ^ b1, data.charAt(i - 2) ^ b2) - seed, mum(data.charAt(i - 1) ^ b3, data.charAt(i) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data.charAt(start + len - 1))); break; case 2: seed = mum(data.charAt(start + len - 2) - seed, b0 ^ data.charAt(start + len - 1)); break; case 3: seed = mum(data.charAt(start + len - 3) - seed, b2 ^ data.charAt(start + len - 2)) + mum(b5 ^ seed, b4 ^ (data.charAt(start + len - 1))); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final int[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final int[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum((data[start + len - 1] >>> 16) - seed, b3 ^ (data[start + len - 1] & 0xFFFFL)); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum((data[start + len - 1] >>> 16) ^ seed, b4 ^ (data[start + len - 1] & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45); } public static long hash64(long seed, final int[] data, final int length) { return hash64(seed, data, 0, length); } public static long hash64(long seed, final long[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final long[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= data[i - 3] * b1; a = (a << 23 | a >>> 41) * b3; b ^= data[i - 2] * b2; b = (b << 25 | b >>> 39) * b4; c ^= data[i - 1] * b3; c = (c << 29 | c >>> 35) * b5; d ^= data[i] * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ data[start + len - 1]); break; case 2: seed = wow(seed + data[start + len - 2], b2 ^ data[start + len - 1]); break; case 3: seed = wow(seed + data[start + len - 3], b2 + data[start + len - 2]) + wow(seed + data[start + len - 1], seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final float[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final float[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); int n; for (int i = start + 3; i < len; i += 4) { seed = mum( mum(floatToRawIntBits(data[i - 3]) ^ b1, floatToRawIntBits(data[i - 2]) ^ b2) - seed, mum(floatToRawIntBits(data[i - 1]) ^ b3, floatToRawIntBits(data[i]) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: n = floatToRawIntBits(data[start + len - 1]); seed = mum((n >>> 16) - seed, b3 ^ (n & 0xFFFFL)); break; case 2: seed = mum(floatToRawIntBits(data[start + len - 2]) - seed, b0 ^ floatToRawIntBits(data[start + len - 1])); break; case 3: n = floatToRawIntBits(data[start + len - 1]); seed = mum(floatToRawIntBits(data[start + len - 3]) - seed, b2 ^ floatToRawIntBits(data[start + len - 2])) + mum((n >>> 16) ^ seed, b4 ^ (n & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final double[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final double[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= doubleToRawLongBits(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= doubleToRawLongBits(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= doubleToRawLongBits(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= doubleToRawLongBits(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ doubleToRawLongBits(data[start + len - 1])); break; case 2: seed = wow(seed + doubleToRawLongBits(data[start + len - 2]), b2 ^ doubleToRawLongBits(data[start + len - 1])); break; case 3: seed = wow(seed + doubleToRawLongBits(data[start + len - 3]), b2 + doubleToRawLongBits(data[start + len - 2])) + wow(seed + doubleToRawLongBits(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final byte[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final byte[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final char[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final char[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final float[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final float[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final double[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final double[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final int[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final int[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final long[][] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final long[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final CharSequence[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final CharSequence[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final CharSequence[]... data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final CharSequence[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final Iterable data) { if (data == null) return 0; final Iterator it = data.iterator(); int len = 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; while (it.hasNext()) { ++len; a ^= hash64(seed, it.next()) * b1; a = (a << 23 | a >>> 41) * b3; if(it.hasNext()) { ++len; b ^= hash64(seed, it.next()) * b2; b = (b << 25 | b >>> 39) * b4; } if(it.hasNext()) { ++len; c ^= hash64(seed, it.next()) * b3; c = (c << 29 | c >>> 35) * b5; } if(it.hasNext()) { ++len; d ^= hash64(seed, it.next()) * b4; d = (d << 31 | d >>> 33) * b1; } seed += a + b + c + d; } seed += b5; seed = wow(b1 - seed, b4 + seed); seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final List data) { if (data == null) return 0; return hash64(seed, data, 0, data.size()); } public static long hash64(long seed, final List data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.size()) return 0; final int len = Math.min(length, data.size() - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data.get(i - 3)) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data.get(i - 2)) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data.get(i - 1)) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data.get(i)) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data.get(start + len - 1))); break; case 2: seed = wow(seed + hash64(seed, data.get(start + len - 2)), b2 ^ hash64(seed, data.get(start + len - 1))); break; case 3: seed = wow(seed + hash64(seed, data.get(start + len - 3)), b2 + hash64(seed, data.get(start + len - 2))) + wow(seed + hash64(seed, data.get(start + len - 1)), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final Object[] data) { if (data == null) return 0; return hash64(seed, data, 0, data.length); } public static long hash64(long seed, final Object[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static long hash64(long seed, final Object data) { if (data == null) return 0; return wow(data.hashCode() ^ b4, b5 - seed) ^ seed; } public static int hash(long seed, final boolean[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final boolean[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum((data[i - 3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i - 2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) - seed, mum((data[i - 1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 2: seed = mum((data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b0 ^ (data[len - 1] ? 0x9E3779B9L : 0x7F4A7C15L)); break; case 3: seed = mum((data[len - 3] ? 0x9E3779B9L : 0x7F4A7C15L) - seed, b2 ^ (data[len - 2] ? 0x9E3779B9L : 0x7F4A7C15L)) + mum(seed ^ b5, b4 ^ (data[len - 1] ? 0x9E3779B9 : 0x7F4A7C15)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final byte[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final byte[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final short[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final short[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final char[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final char[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data[start + len - 1])); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum(b5 ^ seed, b4 ^ (data[start + len - 1])); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final CharSequence data) { if (data == null) return 0; return hash(seed, data, 0, data.length()); } /** * This method changed in 0.2.1, from taking a start index and end index, to taking a start index and length. * Taking the length matches the behavior of more methods in the JVM. * @param data the String or other CharSequence to hash * @param start the start index * @param length how many items to hash (this will hash fewer if there aren't enough items in the CharSequence) * @return a 32-bit hash of data */ public static int hash(long seed, final CharSequence data, final int start, final int length) { if (data == null || start < 0 || length < 0 || start >= length) return 0; final int len = Math.min(length, data.length()); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data.charAt(i - 3) ^ b1, data.charAt(i - 2) ^ b2) - seed, mum(data.charAt(i - 1) ^ b3, data.charAt(i) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum(b5 - seed, b3 ^ (data.charAt(start + len - 1))); break; case 2: seed = mum(data.charAt(start + len - 2) - seed, b0 ^ data.charAt(start + len - 1)); break; case 3: seed = mum(data.charAt(start + len - 3) - seed, b2 ^ data.charAt(start + len - 2)) + mum(b5 ^ seed, b4 ^ (data.charAt(start + len - 1))); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final int[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final int[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { seed = mum( mum(data[i - 3] ^ b1, data[i - 2] ^ b2) - seed, mum(data[i - 1] ^ b3, data[i] ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: seed = mum((data[start + len - 1] >>> 16) - seed, b3 ^ (data[start + len - 1] & 0xFFFFL)); break; case 2: seed = mum(data[start + len - 2] - seed, b0 ^ data[start + len - 1]); break; case 3: seed = mum(data[start + len - 3] - seed, b2 ^ data[start + len - 2]) + mum((data[start + len - 1] >>> 16) ^ seed, b4 ^ (data[start + len - 1] & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final int[] data, final int length) { return hash(seed, data, 0, length); } public static int hash(long seed, final long[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final long[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= data[i - 3] * b1; a = (a << 23 | a >>> 41) * b3; b ^= data[i - 2] * b2; b = (b << 25 | b >>> 39) * b4; c ^= data[i - 1] * b3; c = (c << 29 | c >>> 35) * b5; d ^= data[i] * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ data[start + len - 1]); break; case 2: seed = wow(seed + data[start + len - 2], b2 ^ data[start + len - 1]); break; case 3: seed = wow(seed + data[start + len - 3], b2 + data[start + len - 2]) + wow(seed + data[start + len - 1], seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final float[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final float[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; final int len = Math.min(length, data.length - start); int n; for (int i = start + 3; i < len; i += 4) { seed = mum( mum(floatToRawIntBits(data[i - 3]) ^ b1, floatToRawIntBits(data[i - 2]) ^ b2) - seed, mum(floatToRawIntBits(data[i - 1]) ^ b3, floatToRawIntBits(data[i]) ^ b4)); } switch (len & 3) { case 0: seed = mum(b1 - seed, b4 + seed); break; case 1: n = floatToRawIntBits(data[start + len - 1]); seed = mum((n >>> 16) - seed, b3 ^ (n & 0xFFFFL)); break; case 2: seed = mum(floatToRawIntBits(data[start + len - 2]) - seed, b0 ^ floatToRawIntBits(data[start + len - 1])); break; case 3: n = floatToRawIntBits(data[start + len - 1]); seed = mum(floatToRawIntBits(data[start + len - 3]) - seed, b2 ^ floatToRawIntBits(data[start + len - 2])) + mum((n >>> 16) ^ seed, b4 ^ (n & 0xFFFFL)); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final double[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final double[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= doubleToRawLongBits(data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= doubleToRawLongBits(data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= doubleToRawLongBits(data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= doubleToRawLongBits(data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ doubleToRawLongBits(data[start + len - 1])); break; case 2: seed = wow(seed + doubleToRawLongBits(data[start + len - 2]), b2 ^ doubleToRawLongBits(data[start + len - 1])); break; case 3: seed = wow(seed + doubleToRawLongBits(data[start + len - 3]), b2 + doubleToRawLongBits(data[start + len - 2])) + wow(seed + doubleToRawLongBits(data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final byte[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final byte[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final char[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final char[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final float[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final float[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final double[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final double[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final int[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final int[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final long[][] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final long[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final CharSequence[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final CharSequence[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final CharSequence[]... data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final CharSequence[][] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final Iterable data) { if (data == null) return 0; final Iterator it = data.iterator(); int len = 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; while (it.hasNext()) { ++len; a ^= hash64(seed, it.next()) * b1; a = (a << 23 | a >>> 41) * b3; if(it.hasNext()) { ++len; b ^= hash64(seed, it.next()) * b2; b = (b << 25 | b >>> 39) * b4; } if(it.hasNext()) { ++len; c ^= hash64(seed, it.next()) * b3; c = (c << 29 | c >>> 35) * b5; } if(it.hasNext()) { ++len; d ^= hash64(seed, it.next()) * b4; d = (d << 31 | d >>> 33) * b1; } seed += a + b + c + d; } seed += b5; seed = wow(b1 - seed, b4 + seed); seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final List data) { if (data == null) return 0; return hash(seed, data, 0, data.size()); } public static int hash(long seed, final List data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.size()) return 0; final int len = Math.min(length, data.size() - start); long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data.get(i - 3)) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data.get(i - 2)) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data.get(i - 1)) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data.get(i)) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data.get(start + len - 1))); break; case 2: seed = wow(seed + hash64(seed, data.get(start + len - 2)), b2 ^ hash64(seed, data.get(start + len - 1))); break; case 3: seed = wow(seed + hash64(seed, data.get(start + len - 3)), b2 + hash64(seed, data.get(start + len - 2))) + wow(seed + hash64(seed, data.get(start + len - 1)), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final Object[] data) { if (data == null) return 0; return hash(seed, data, 0, data.length); } public static int hash(long seed, final Object[] data, int start, int length) { if (data == null || start < 0 || length < 0 || start >= data.length) return 0; long a = seed + b4, b = a ^ b3, c = b - b2, d = c ^ b1; final int len = Math.min(length, data.length - start); for (int i = start + 3; i < len; i += 4) { a ^= hash64(seed, data[i - 3]) * b1; a = (a << 23 | a >>> 41) * b3; b ^= hash64(seed, data[i - 2]) * b2; b = (b << 25 | b >>> 39) * b4; c ^= hash64(seed, data[i - 1]) * b3; c = (c << 29 | c >>> 35) * b5; d ^= hash64(seed, data[i]) * b4; d = (d << 31 | d >>> 33) * b1; seed += a + b + c + d; } seed += b5; switch (len & 3) { case 0: seed = wow(b1 - seed, b4 + seed); break; case 1: seed = wow(seed, b1 ^ hash64(seed, data[start + len - 1])); break; case 2: seed = wow(seed + hash64(seed, data[start + len - 2]), b2 ^ hash64(seed, data[start + len - 1])); break; case 3: seed = wow(seed + hash64(seed, data[start + len - 3]), b2 + hash64(seed, data[start + len - 2])) + wow(seed + hash64(seed, data[start + len - 1]), seed ^ b3); break; } seed = (seed ^ len) * (seed << 16 ^ b0); return (int)(seed ^ (seed << 33 | seed >>> 31) ^ (seed << 19 | seed >>> 45)); } public static int hash(long seed, final Object data) { if (data == null) return 0; return (int)(mum(data.hashCode() ^ b2, b3 - seed) ^ seed); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Hasher hasher = (Hasher) o; return seed == hasher.seed; } @Override public int hashCode() { return (int) (seed ^ (seed >>> 32)); } @Override public String toString() { return "Hasher{" + "seed=" + seed + '}'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy