001package squidpony.squidmath;
002
003import java.io.Serializable;
004import java.util.Arrays;
005import java.util.Iterator;
006import java.util.List;
007import java.util.Objects;
008
009import static squidpony.squidmath.CrossHash.Water.*;
010import static squidpony.squidmath.NumberTools.doubleToMixedIntBits;
011import static squidpony.squidmath.NumberTools.floatToIntBits;
012
013/**
014 * 64-bit and 32-bit hashing functions that we can rely on staying the same cross-platform.
015 * Several algorithms are present here, each with some tradeoffs for performance, quality,
016 * and extra features. Each algorithm was designed for speed and general-purpose usability,
017 * but not cryptographic security.
018 * <br>
019 * The hashes this returns are always 0 when given null to hash. Arrays with
020 * identical elements of identical types will hash identically. Arrays with identical
021 * numerical values but different types will sometimes hash differently. This class
022 * always provides 64-bit hashes via hash64() and 32-bit hashes via hash(), and Wisp
023 * provides a hash32() method that matches older behavior and uses only 32-bit math.
024 * The hash64() and hash() methods, except in Hive, use 64-bit math even when producing
025 * 32-bit hashes, for GWT reasons. GWT doesn't have the same behavior as desktop and
026 * Android applications when using ints because it treats doubles mostly like ints,
027 * sometimes, due to it using JavaScript. If we use mainly longs, though, GWT emulates
028 * the longs with a more complex technique behind-the-scenes, that behaves the same on
029 * the web as it does on desktop or on a phone. Since CrossHash is supposed to be stable
030 * cross-platform, this is the way we need to go, despite it being slightly slower.
031 * <br>
032 * The static methods in CrossHash, like {@link #hash64(int[])}, delegate to the {@link Water}
033 * algorithm. This is a fairly fast and heavily-tested hash that developed from something like
034 * Wang Yi's wyhash algorithm, though only the constants and the general concept of a mum()
035 * function are shared with wyhash. There are several static inner classes in CrossHash
036 * {@link Water} (already mentioned), {@link Yolk} (which is very close to Water but allows a
037 * 64-bit salt or seed), {@link Curlup} (which is the fastest hash here for larger inputs, and
038 * also allows a 64-bit seed), {@link Mist} (which allows a 128-bit salt, but has mediocre
039 * quality), {@link Hive} (which is mostly here for compatibility, but has OK quality and good
040 * collision rates), and {@link Wisp} (which is fast for small inputs but has bad collision
041 * rates). There's also the inner IHasher interface, and the classes that implement it.
042 * Water, Yolk, and Curlup all pass the rigorous SMHasher test battery. The others don't pass
043 * it in full, or sometimes at all.
044 * <br>
045 * IHasher values are provided as static fields, and use Water to hash a specific type or fall
046 * back to Object.hashCode if given an object with the wrong type. IHasher values are optional
047 * parts of OrderedMap, OrderedSet, Arrangement, and the various classes that use Arrangement
048 * like K2 and K2V1, and allow arrays to be used as keys in those collections while keeping
049 * hashing by value instead of the normal hashing by reference for arrays. You probably won't
050 * ever need to make a class that implements IHasher yourself; for some cases you may want to
051 * look at the {@link Hashers} class for additional functions.
052 * <br>
053 * Note: This class was formerly called StableHash, but since that refers to a specific
054 * category of hashing algorithm that this is not, and since the goal is to be cross-
055 * platform, the name was changed to CrossHash.
056 * Note 2: FNV-1a was removed from SquidLib on July 25, 2017, and replaced as default with Wisp; Wisp
057 * was later replaced as default by Hive, and in June 2019 Hive was replaced by Water. Wisp was used
058 * because at the time SquidLib preferred 64-bit math when math needed to be the same across platforms;
059 * math on longs behaves the same on GWT as on desktop, despite being slower. Hive passed an older version
060 * of SMHasher, a testing suite for hashes, where Wisp does not (it fails just like Arrays.hashCode()
061 * does). Hive uses a cross-platform subset of the possible 32-bit math operations when producing 32-bit 
062 * hashes of data that doesn't involve longs or doubles, and this should speed up the CrossHash.Hive.hash()
063 * methods a lot on GWT, but it slows down 32-bit output on desktop-class JVMs. Water became the default
064 * when newer versions of SMHasher showed that Hive wasn't as high-quality as it had appeared, and the
065 * recently-debuted wyhash by Wang Yi, a variation on a hash called MUM, opened some possibilities for
066 * structures that are simple but also very fast. Water is modeled after wyhash and uses the same constants
067 * in its hash64() methods, but avoids the 128-bit multiplication that wyhash uses. Because both wyhash and
068 * Water operate on 4 items at a time, they tend to be very fast on desktop platforms, but Water probably
069 * won't be amazing at GWT performance. Similarly, the recently-added Curlup performs very well due to SIMD
070 * optimizations that HotSpot performs, and probably won't do as well on GWT or Android.
071 * <br>
072 * Created by Tommy Ettinger on 1/16/2016.
073 * @author Tommy Ettinger
074 */
075public class CrossHash {
076    public static long hash64(final CharSequence data) {
077        return Water.hash64(data);
078    }
079
080    public static long hash64(final boolean[] data) {
081        return Water.hash64(data);
082    }
083
084    public static long hash64(final byte[] data) {
085        return Water.hash64(data);
086    }
087
088    public static long hash64(final short[] data) {
089        return Water.hash64(data);
090    }
091
092    public static long hash64(final int[] data) {
093        return Water.hash64(data);
094    }
095
096    public static long hash64(final long[] data) {
097        return Water.hash64(data);
098    }
099
100    public static long hash64(final char[] data) {
101        return Water.hash64(data);
102    }
103
104    public static long hash64(final float[] data) {
105        return Water.hash64(data);
106    }
107
108    public static long hash64(final double[] data) {
109        return Water.hash64(data);
110    }
111
112    /**
113     * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
114     *
115     * @param data  the char array to hash
116     * @param start the start of the section to hash (inclusive)
117     * @param end   the end of the section to hash (exclusive)
118     * @return a 64-bit hash code for the requested section of data
119     */
120    public static long hash64(final char[] data, final int start, final int end) {
121        return Water.hash64(data, start, end);
122    }
123
124    /**
125     * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
126     *
127     * @param data  the String or other CharSequence to hash
128     * @param start the start of the section to hash (inclusive)
129     * @param end   the end of the section to hash (exclusive)
130     * @return a 64-bit hash code for the requested section of data
131     */
132    public static long hash64(final CharSequence data, final int start, final int end) {
133        return Water.hash64(data, start, end);
134    }
135
136    public static long hash64(final char[][] data) {
137        return Water.hash64(data);
138    }
139
140    public static long hash64(final int[][] data) {
141        return Water.hash64(data);
142    }
143
144    public static long hash64(final long[][] data) {
145        return Water.hash64(data);
146    }
147
148    public static long hash64(final CharSequence[] data) {
149        return Water.hash64(data);
150    }
151
152    public static long hash64(final CharSequence[]... data) {
153        return Water.hash64(data);
154    }
155
156    public static long hash64(final Iterable<? extends CharSequence> data) {
157        return Water.hash64(data);
158    }
159
160    public static long hash64(final List<? extends CharSequence> data) {
161        return Water.hash64(data);
162    }
163
164    public static long hash64(final Object[] data) {
165        return Water.hash64(data);
166    }
167
168    public static long hash64(final Object data) {
169        return Water.hash64(data);
170    }
171
172
173    public static int hash(final CharSequence data) {
174        return Water.hash(data);
175    }
176
177    public static int hash(final boolean[] data) {
178        return Water.hash(data);
179    }
180
181    public static int hash(final byte[] data) {
182        return Water.hash(data);
183    }
184
185    public static int hash(final short[] data) {
186        return Water.hash(data);
187    }
188
189    public static int hash(final int[] data) {
190        return Water.hash(data);
191    }
192
193    public static int hash(final long[] data) {
194        return Water.hash(data);
195    }
196
197    public static int hash(final char[] data) {
198        return Water.hash(data);
199    }
200
201    public static int hash(final float[] data) {
202        return Water.hash(data);
203    }
204
205    public static int hash(final double[] data) {
206        return Water.hash(data);
207    }
208
209    /**
210     * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
211     *
212     * @param data  the char array to hash
213     * @param start the start of the section to hash (inclusive)
214     * @param end   the end of the section to hash (exclusive)
215     * @return a 32-bit hash code for the requested section of data
216     */
217    public static int hash(final char[] data, final int start, final int end) {
218        return Water.hash(data, start, end);
219    }
220
221    /**
222     * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
223     *
224     * @param data  the String or other CharSequence to hash
225     * @param start the start of the section to hash (inclusive)
226     * @param end   the end of the section to hash (exclusive)
227     * @return a 32-bit hash code for the requested section of data
228     */
229    public static int hash(final CharSequence data, final int start, final int end) {
230        return Water.hash(data, start, end);
231    }
232
233
234    public static int hash(final char[][] data) { 
235        return Water.hash(data);
236    }
237
238    public static int hash(final int[][] data) {
239        return Water.hash(data);
240    }
241
242    public static int hash(final long[][] data) {
243        return Water.hash(data);
244    }
245
246    public static int hash(final CharSequence[] data) {
247        return Water.hash(data);
248    }
249
250    public static int hash(final CharSequence[]... data) {
251        return Water.hash(data);
252    }
253
254    public static int hash(final Iterable<? extends CharSequence> data) {
255        return Water.hash(data);
256    }
257
258    public static int hash(final List<? extends CharSequence> data) {
259        return Water.hash(data);
260    }
261
262    public static int hash(final Object[] data) {
263        return Water.hash(data);
264    }
265
266    public static int hash(final Object data) {
267        return Water.hash(data);
268    }
269
270    /**
271     * An interface that can be used to move the logic for the hashCode() and equals() methods from a class' methods to
272     * an implementation of IHasher that certain collections in SquidLib can use. Primarily useful when the key type is
273     * an array, which normally doesn't work as expected in Java hash-based collections, but can if the right collection
274     * and IHasher are used. See also {@link Hashers} for additional implementations, some of which need dependencies on
275     * things the rest of CrossHash doesn't, like a case-insensitive String hasher/equator that uses RegExodus to handle
276     * CharSequence comparison on GWT.
277     */
278    public interface IHasher extends Serializable {
279        /**
280         * If data is a type that this IHasher can specifically hash, this method should use that specific hash; in
281         * other situations, it should simply delegate to calling {@link Object#hashCode()} on data. The body of an
282         * implementation of this method can be very small; for an IHasher that is meant for byte arrays, the body could
283         * be: {@code return (data instanceof byte[]) ? CrossHash.Lightning.hash((byte[]) data) : data.hashCode();}
284         *
285         * @param data the Object to hash; this method should take any type but often has special behavior for one type
286         * @return a 32-bit int hash code of data
287         */
288        int hash(final Object data);
289
290        /**
291         * Not all types you might want to use an IHasher on meaningfully implement .equals(), such as array types; in
292         * these situations the areEqual method helps quickly check for equality by potentially having special logic for
293         * the type this is meant to check. The body of implementations for this method can be fairly small; for byte
294         * arrays, it looks like: {@code return left == right
295         * || ((left instanceof byte[] && right instanceof byte[])
296         * ? Arrays.equals((byte[]) left, (byte[]) right)
297         * : Objects.equals(left, right));} , but for multidimensional arrays you should use the
298         * {@link #equalityHelper(Object[], Object[], IHasher)} method with an IHasher for the inner arrays that are 1D
299         * or otherwise already-hash-able, as can be seen in the body of the implementation for 2D char arrays, where
300         * charHasher is an existing IHasher that handles 1D arrays:
301         * {@code return left == right
302         * || ((left instanceof char[][] && right instanceof char[][])
303         * ? equalityHelper((char[][]) left, (char[][]) right, charHasher)
304         * : Objects.equals(left, right));}
305         *
306         * @param left  allowed to be null; most implementations will have special behavior for one type
307         * @param right allowed to be null; most implementations will have special behavior for one type
308         * @return true if left is equal to right (preferably by value, but reference equality may sometimes be needed)
309         */
310        boolean areEqual(final Object left, final Object right);
311    }
312
313    /**
314     * Not a general-purpose method; meant to ease implementation of {@link IHasher#areEqual(Object, Object)}
315     * methods when the type being compared is a multi-dimensional array (which normally requires the heavyweight method
316     * {@link Arrays#deepEquals(Object[], Object[])} or doing more work yourself; this reduces the work needed to
317     * implement fixed-depth equality). As mentioned in the docs for {@link IHasher#areEqual(Object, Object)}, example
318     * code that hashes 2D char arrays can be done using an IHasher for 1D char arrays called charHasher:
319     * {@code return left == right
320     * || ((left instanceof char[][] && right instanceof char[][])
321     * ? equalityHelper((char[][]) left, (char[][]) right, charHasher)
322     * : Objects.equals(left, right));}
323     *
324     * @param left an array of some kind of Object, usually an array, that the given IHasher can compare
325     * @param right an array of some kind of Object, usually an array, that the given IHasher can compare
326     * @param inner an IHasher to compare items in left with items in right
327     * @return true if the contents of left and right are equal by the given IHasher, otherwise false
328     */
329    public static boolean equalityHelper(Object[] left, Object[] right, IHasher inner) {
330        if (left == right)
331            return true;
332        if (left == null || right == null || left.length != right.length)
333            return false;
334        for (int i = 0; i < left.length; i++) {
335            if (!inner.areEqual(left[i], right[i]))
336                return false;
337        }
338        return true;
339    }
340
341    private static class BooleanHasher implements IHasher, Serializable {
342        private static final long serialVersionUID = 3L;
343
344        BooleanHasher() {
345        }
346
347        @Override
348        public int hash(final Object data) {
349            return (data instanceof boolean[]) ? CrossHash.hash((boolean[]) data) : data.hashCode();
350        }
351
352        @Override
353        public boolean areEqual(Object left, Object right) {
354            return left == right || ((left instanceof boolean[] && right instanceof boolean[]) ? Arrays.equals((boolean[]) left, (boolean[]) right) : Objects.equals(left, right));
355        }
356    }
357
358    public static final IHasher booleanHasher = new BooleanHasher();
359
360    private static class ByteHasher implements IHasher, Serializable {
361        private static final long serialVersionUID = 3L;
362
363        ByteHasher() {
364        }
365
366        @Override
367        public int hash(final Object data) {
368            return (data instanceof byte[]) ? CrossHash.hash((byte[]) data) : data.hashCode();
369        }
370
371        @Override
372        public boolean areEqual(Object left, Object right) {
373            return left == right
374                    || ((left instanceof byte[] && right instanceof byte[])
375                    ? Arrays.equals((byte[]) left, (byte[]) right)
376                    : Objects.equals(left, right));
377        }
378    }
379
380    public static final IHasher byteHasher = new ByteHasher();
381
382    private static class ShortHasher implements IHasher, Serializable {
383        private static final long serialVersionUID = 3L;
384
385        ShortHasher() {
386        }
387
388        @Override
389        public int hash(final Object data) {
390            return (data instanceof short[]) ? CrossHash.hash((short[]) data) : data.hashCode();
391        }
392
393        @Override
394        public boolean areEqual(Object left, Object right) {
395            return left == right || ((left instanceof short[] && right instanceof short[]) ? Arrays.equals((short[]) left, (short[]) right) : Objects.equals(left, right));
396        }
397    }
398
399    public static final IHasher shortHasher = new ShortHasher();
400
401    private static class CharHasher implements IHasher, Serializable {
402        private static final long serialVersionUID = 3L;
403
404        CharHasher() {
405        }
406
407        @Override
408        public int hash(final Object data) {
409            return (data instanceof char[]) ? CrossHash.hash((char[]) data) : data.hashCode();
410        }
411
412        @Override
413        public boolean areEqual(Object left, Object right) {
414            return left == right || ((left instanceof char[] && right instanceof char[]) ? Arrays.equals((char[]) left, (char[]) right) : Objects.equals(left, right));
415        }
416    }
417
418    public static final IHasher charHasher = new CharHasher();
419
420    private static class IntHasher implements IHasher, Serializable {
421        private static final long serialVersionUID = 3L;
422
423        IntHasher() {
424        }
425
426        @Override
427        public int hash(final Object data) {
428            return (data instanceof int[]) ? CrossHash.hash((int[]) data) : data.hashCode();
429        }
430
431        @Override
432        public boolean areEqual(Object left, Object right) {
433            return (left instanceof int[] && right instanceof int[]) ? Arrays.equals((int[]) left, (int[]) right) : Objects.equals(left, right);
434        }
435    }
436
437    public static final IHasher intHasher = new IntHasher();
438
439    private static class LongHasher implements IHasher, Serializable {
440        private static final long serialVersionUID = 3L;
441
442        LongHasher() {
443        }
444
445        @Override
446        public int hash(final Object data) {
447            return (data instanceof long[]) ? CrossHash.hash((long[]) data) : data.hashCode();
448        }
449
450        @Override
451        public boolean areEqual(Object left, Object right) {
452            return (left instanceof long[] && right instanceof long[]) ? Arrays.equals((long[]) left, (long[]) right) : Objects.equals(left, right);
453        }
454    }
455
456    public static final IHasher longHasher = new LongHasher();
457
458    private static class FloatHasher implements IHasher, Serializable {
459        private static final long serialVersionUID = 3L;
460
461        FloatHasher() {
462        }
463
464        @Override
465        public int hash(final Object data) {
466            return (data instanceof float[]) ? CrossHash.hash((float[]) data) : data.hashCode();
467        }
468
469        @Override
470        public boolean areEqual(Object left, Object right) {
471            return left == right || ((left instanceof float[] && right instanceof float[]) ? Arrays.equals((float[]) left, (float[]) right) : Objects.equals(left, right));
472        }
473    }
474
475    public static final IHasher floatHasher = new FloatHasher();
476
477    private static class DoubleHasher implements IHasher, Serializable {
478        private static final long serialVersionUID = 3L;
479
480        DoubleHasher() {
481        }
482
483        @Override
484        public int hash(final Object data) {
485            return (data instanceof double[]) ? CrossHash.hash((double[]) data) : data.hashCode();
486        }
487
488        @Override
489        public boolean areEqual(Object left, Object right) {
490            return left == right || ((left instanceof double[] && right instanceof double[]) ? Arrays.equals((double[]) left, (double[]) right) : Objects.equals(left, right));
491        }
492    }
493
494    public static final IHasher doubleHasher = new DoubleHasher();
495
496    private static class Char2DHasher implements IHasher, Serializable {
497        private static final long serialVersionUID = 3L;
498
499        Char2DHasher() {
500        }
501
502        @Override
503        public int hash(final Object data) {
504            return (data instanceof char[][]) ? CrossHash.hash((char[][]) data) : data.hashCode();
505        }
506
507        @Override
508        public boolean areEqual(Object left, Object right) {
509            return left == right
510                    || ((left instanceof char[][] && right instanceof char[][])
511                    ? equalityHelper((char[][]) left, (char[][]) right, charHasher)
512                    : Objects.equals(left, right));
513        }
514    }
515
516    public static final IHasher char2DHasher = new Char2DHasher();
517
518    private static class Int2DHasher implements IHasher, Serializable {
519        private static final long serialVersionUID = 3L;
520
521        Int2DHasher() {
522        }
523
524        @Override
525        public int hash(final Object data) {
526            return (data instanceof int[][]) ? CrossHash.hash((int[][]) data) : data.hashCode();
527        }
528
529        @Override
530        public boolean areEqual(Object left, Object right) {
531            return left == right
532                    || ((left instanceof int[][] && right instanceof int[][])
533                    ? equalityHelper((int[][]) left, (int[][]) right, intHasher)
534                    : Objects.equals(left, right));
535        }
536    }
537
538    public static final IHasher int2DHasher = new Int2DHasher();
539
540    private static class Long2DHasher implements IHasher, Serializable {
541        private static final long serialVersionUID = 3L;
542
543        Long2DHasher() {
544        }
545
546        @Override
547        public int hash(final Object data) {
548            return (data instanceof long[][]) ? CrossHash.hash((long[][]) data) : data.hashCode();
549        }
550
551        @Override
552        public boolean areEqual(Object left, Object right) {
553            return left == right
554                    || ((left instanceof long[][] && right instanceof long[][])
555                    ? equalityHelper((long[][]) left, (long[][]) right, longHasher)
556                    : Objects.equals(left, right));
557        }
558    }
559
560    public static final IHasher long2DHasher = new Long2DHasher();
561
562    private static class StringHasher implements IHasher, Serializable {
563        private static final long serialVersionUID = 3L;
564
565        StringHasher() {
566        }
567
568        @Override
569        public int hash(final Object data) {
570            return (data instanceof CharSequence) ? CrossHash.hash((CharSequence) data) : data.hashCode();
571        }
572
573        @Override
574        public boolean areEqual(Object left, Object right) {
575            return Objects.equals(left, right);
576        }
577    }
578
579    public static final IHasher stringHasher = new StringHasher();
580
581    private static class StringArrayHasher implements IHasher, Serializable {
582        private static final long serialVersionUID = 3L;
583
584        StringArrayHasher() {
585        }
586
587        @Override
588        public int hash(final Object data) {
589            return (data instanceof CharSequence[]) ? CrossHash.hash((CharSequence[]) data) : data.hashCode();
590        }
591
592        @Override
593        public boolean areEqual(Object left, Object right) {
594            return left == right || ((left instanceof CharSequence[] && right instanceof CharSequence[]) ? equalityHelper((CharSequence[]) left, (CharSequence[]) right, stringHasher) : Objects.equals(left, right));
595        }
596    }
597
598    /**
599     * Though the name suggests this only hashes String arrays, it can actually hash any CharSequence array as well.
600     */
601    public static final IHasher stringArrayHasher = new StringArrayHasher();
602
603    private static class ObjectArrayHasher implements IHasher, Serializable {
604        private static final long serialVersionUID = 3L;
605
606        ObjectArrayHasher() {
607        }
608
609        @Override
610        public int hash(final Object data) {
611            return (data instanceof Object[]) ? CrossHash.hash((Object[]) data) : data.hashCode();
612        }
613
614        @Override
615        public boolean areEqual(Object left, Object right) {
616            return left == right || ((left instanceof Object[] && right instanceof Object[]) && Arrays.equals((Object[]) left, (Object[]) right) || Objects.equals(left, right));
617        }
618    }
619    public static final IHasher objectArrayHasher = new ObjectArrayHasher();
620
621    private static class DefaultHasher implements IHasher, Serializable {
622        private static final long serialVersionUID = 5L;
623
624        DefaultHasher() {
625        }
626
627        @Override
628        public int hash(final Object data) {
629            if(data == null) return 0;
630            final int x = data.hashCode() * 0x9E375;
631            return x ^ x >>> 16;
632        }
633
634        @Override
635        public boolean areEqual(final Object left, final Object right) {
636            return (left == right) || (left != null && left.equals(right));
637        }
638    }
639
640    public static final IHasher defaultHasher = new DefaultHasher();
641
642    private static class MildHasher implements IHasher, Serializable {
643        private static final long serialVersionUID = 4L;
644
645        MildHasher() {
646        }
647
648        @Override
649        public int hash(final Object data) {
650            return data != null ? data.hashCode() : 0;
651        }
652
653        @Override
654        public boolean areEqual(final Object left, final Object right) {
655            return (left == right) || (left != null && left.equals(right));
656        }
657    }
658
659    /**
660     * The most basic IHasher type; effectively delegates to {@link Objects#hashCode(Object)} and
661     * {@link Objects#equals(Object, Object)}. Might not scramble the bits of a hash well enough to have good
662     * performance in a hash table lke {@link OrderedMap} or {@link UnorderedSet}, unless the objects being hashed have
663     * good hashCode() implementations already.
664     */
665    public static final IHasher mildHasher = new MildHasher();
666
667    private static class IdentityHasher implements IHasher, Serializable
668    {
669        private static final long serialVersionUID = 4L;
670        IdentityHasher() { }
671
672        @Override
673        public int hash(Object data) {
674            return System.identityHashCode(data);
675        }
676
677        @Override
678        public boolean areEqual(Object left, Object right) {
679            return left == right;
680        }
681    }
682    public static final IHasher identityHasher = new IdentityHasher();
683
684    private static class GeneralHasher implements IHasher, Serializable {
685        private static final long serialVersionUID = 3L;
686
687        GeneralHasher() {
688        }
689
690        @Override
691        public int hash(final Object data) {
692            return CrossHash.hash(data);
693        }
694
695        @Override
696        public boolean areEqual(Object left, Object right) {
697            if(left == right) return true;
698            Class<?> l = left.getClass(), r = right.getClass();
699            if(l == r)
700            {
701                if(l.isArray())
702                {
703                    if(left instanceof int[]) return Arrays.equals((int[]) left, (int[]) right);
704                    else if(left instanceof long[]) return Arrays.equals((long[]) left, (long[]) right);
705                    else if(left instanceof char[]) return Arrays.equals((char[]) left, (char[]) right);
706                    else if(left instanceof double[]) return Arrays.equals((double[]) left, (double[]) right);
707                    else if(left instanceof boolean[]) return Arrays.equals((boolean[]) left, (boolean[]) right);
708                    else if(left instanceof byte[]) return Arrays.equals((byte[]) left, (byte[]) right);
709                    else if(left instanceof float[]) return Arrays.equals((float[]) left, (float[]) right);
710                    else if(left instanceof short[]) return Arrays.equals((short[]) left, (short[]) right);
711                    else if(left instanceof char[][]) return equalityHelper((char[][]) left, (char[][]) right, charHasher);
712                    else if(left instanceof int[][]) return equalityHelper((int[][]) left, (int[][]) right, intHasher);
713                    else if(left instanceof long[][]) return equalityHelper((long[][]) left, (long[][]) right, longHasher);
714                    else if(left instanceof CharSequence[]) return equalityHelper((CharSequence[]) left, (CharSequence[]) right, stringHasher);
715                    else if(left instanceof Object[]) return Arrays.equals((Object[]) left, (Object[]) right);
716                }
717                return Objects.equals(left, right);
718            }
719            return false;
720        }
721    }
722
723    /**
724     * This IHasher is the one you should use if you aren't totally certain what types will go in an OrderedMap's keys
725     * or an OrderedSet's items, since it can handle mixes of elements.
726     */
727    public static final IHasher generalHasher = new GeneralHasher();
728
729    /**
730     * A quick, simple hashing function that seems to have good results. Like LightRNG, it stores a state that
731     * it updates independently of the output, and this starts at a large prime. At each step, it takes the
732     * current item in the array being hashed, adds a large non-prime used in LightRNG's generation function
733     * (it's 2 to the 64, times the golden ratio phi, and truncated to a signed long), multiplies by a prime
734     * called the "state multiplier", adds the result to the state and stores it, multiplies the value of the
735     * state by another prime called the "output multiplier", then XORs the current result with that value
736     * before moving onto the next item in the array. A finalization step XORs the result with a complex value
737     * made by adding the state (left over from the previous step) to what was the output multiplier, adding
738     * the last known value for result to the phi-related constant from LightRNG, multiplying that pair, adding
739     * the initial state (which turns out to be unusually good for this, despite no particularly special numeric
740     * qualities other than being a probable prime) and then bitwise-rotating it left by a seemingly-random
741     * number drawn from the highest 6 bits of the state.
742     * <br>
743     * This all can be done very quickly; a million hashes of a million different 16-element long arrays can be
744     * computed in under 18-20 ms (in the benchmark, some amount of that is overhead from generating a new
745     * array with LongPeriodRNG, since the benchmark uses that RNG's state for data, and the default
746     * Arrays.hashCode implementation is only somewhat faster at under 16 ms). After several tries and tweaks
747     * to the constants this uses, it also gets remarkably few hash collisions. On the same 0x100000, or
748     * 1048576, RNG states for data, Lightning gets 110 collisions, the JDK Arrays.hashCode method gets 129
749     * collisions, Sip (implementing SipHash) gets 145 collisions, and CrossHash (using the FNV-1a algorithm)
750     * gets 135 collisions. Dispersion is not perfect, but
751     * at many bit sizes Lightning continues to have less collisions (it disperses better than the other hashes
752     * with several quantities of bits, at least on this test data). Lightning also does relatively well, though
753     * it isn't clearly ahead of the rest all the time, when hashing Strings, especially ones that use a larger
754     * set of letters, it seems (FakeLanguageGen was used to make test data, and languages that used more
755     * characters in their alphabet seemed to hash better with this than competing hashes for some reason).
756     * <br>
757     * There is certainly room for improvement with the specific numbers chosen; earlier versions used the
758     * state multiplier "Neely's number", which is a probable prime made by taking the radix-29 number
759     * "HARGNALLINSCLOPIOPEEPIO" (a reference to a very unusual TV show), truncating to 64 bits, and rotating
760     * right by 42 bits. This version uses "Neely's number" for an initial state and during finalization, and
761     * uses a different probable prime as the state multiplier, made with a similar process; it starts with the
762     * radix-36 number "EDSGERWDIJKSTRA", then does the same process but rotates right by 37 bits to obtain a
763     * different prime. This tweak seems to help with hash collisions. Extensive trial and error was used to
764     * find the current output multiplier, which has no real relationship to anything else but has exactly 32 of
765     * 64 bits set to 1, has 1 in the least and most significant bit indices (meaning it is negative and odd),
766     * and other than that seems to have better results on most inputs for mystifying reasons. Earlier versions
767     * applied a Gray code step to alter the output instead of a multiplier that heavily overflows to obfuscate
768     * state, but that had a predictable pattern for most of the inputs tried, which seemed less-than-ideal for
769     * a hash. Vitally, Lightning avoids predictable collisions that Arrays.hashCode has, like
770     * {@code Arrays.hashCode(new long[]{0})==Arrays.hashCode(new long[]{-1})}.
771     * <br>
772     * The output multiplier is 0xC6BC279692B5CC83L, the state multiplier is 0xD0E89D2D311E289FL, the number
773     * added to the state (from LightRNG and code derived from FastUtil, but obtained from the golden ratio
774     * phi) is 0x9E3779B97F4A7C15L, and the starting state ("Neely's Number") is 0x632BE59BD9B4E019L.
775     * <br>
776     * To help find patterns in hash output in a visual way, you can hash an x,y point, take the bottom 24 bits,
777     * and use that as an RGB color for the pixel at that x,y point. On a 512x512 grid of points, the patterns
778     * in Arrays.hashCode and the default CrossHash algorithm (FNV-1a) are evident, and Sip (implementing
779     * SipHash) does approximately as well as Lightning, with no clear patterns visible (Sip has been removed
780     * from SquidLib because it needs a lot of code and is slower than Mist). The
781     * idea is from a technical report on visual uses for hashing,
782     * http://www.clockandflame.com/media/Goulburn06.pdf .
783     * <ul>
784     * <li>{@link java.util.Arrays#hashCode(int[])}: http://i.imgur.com/S4Gh1sX.png</li>
785     * <li>{@link CrossHash#hash(int[])}: http://i.imgur.com/x8SDqvL.png</li>
786     * <li>(Former) CrossHash.Sip.hash(int[]): http://i.imgur.com/keSpIwm.png</li>
787     * <li>{@link CrossHash.Lightning#hash(int[])}: http://i.imgur.com/afGJ9cA.png</li>
788     * </ul>
789     */
790    // tested output multipliers
791    // 0x DA1A459BD9B4C619L
792    // 0x DC1A459879B5C619L
793    // 0x DC1A479829B5E639L
794    // 0x DC1A479C29B5C639L
795    // 0x EA1C479692B5C639L
796    // 0x CA1C479692B5C635L // this gets 105 collisions, low
797    // 0x CABC479692B5C635L
798    // 0x DC1A479C29B5C647L
799    // 0x DC1A479C29B5C725L
800    // 0x CABC279692B5CB21L
801    // 0x C6BC279692B5CC83L // this gets 100 collisions, lowest
802    // 0x C6BC279692B4D8A5L
803    // 0x C6BC279692B4D345L
804    // 0x C6EC273692B4A4B9L
805    // 0x C6A3256B52D5B463L
806    // 0x C6A3256B52D5B463L
807    // 0x C6A3256D52D5B4C9L
808    // 0x D8A3256D52D5B619L
809    // 0x D96E6AC724658947L
810    // 0x D96E6AC724658C2DL
811    // 0x CCABF9E32FD684F9L
812    // 0x C314163FAF912A01L
813    // 0x C3246007A332C12AL
814    // 0x CA1C479692B5C6ABL
815    // 0x C6B5275692B5CC83 // untested so far
816    public static final class Lightning {
817
818        public static long hash64(final boolean[] data) {
819            if (data == null)
820                return 0;
821            long z = 0x632BE59BD9B4E019L, result = 1L;
822            for (int i = 0; i < data.length; i++) {
823                result ^= (z += (data[i] ? 0x9E3779B97F4A7C94L : 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
824            }
825            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
826        }
827
828        public static long hash64(final byte[] data) {
829            if (data == null)
830                return 0;
831            long z = 0x632BE59BD9B4E019L, result = 1L;
832            for (int i = 0; i < data.length; i++) {
833                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
834            }
835            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
836        }
837
838        public static long hash64(final short[] data) {
839            if (data == null)
840                return 0;
841            long z = 0x632BE59BD9B4E019L, result = 1L;
842            for (int i = 0; i < data.length; i++) {
843                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
844            }
845            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
846        }
847
848        public static long hash64(final char[] data) {
849            if (data == null)
850                return 0;
851            long z = 0x632BE59BD9B4E019L, result = 1L;
852            for (int i = 0; i < data.length; i++) {
853                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
854            }
855            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
856        }
857
858        public static long hash64(final int[] data) {
859            if (data == null)
860                return 0;
861            long z = 0x632BE59BD9B4E019L, result = 1L;
862            for (int i = 0; i < data.length; i++) {
863                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
864            }
865            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
866        }
867
868        public static long hash64(final long[] data) {
869            if (data == null)
870                return 0;
871            long z = 0x632BE59BD9B4E019L, result = 1L;
872            for (int i = 0; i < data.length; i++) {
873                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
874            }
875            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
876        }
877
878        public static long hash64(final float[] data) {
879            if (data == null)
880                return 0;
881            long z = 0x632BE59BD9B4E019L, result = 1L;
882            for (int i = 0; i < data.length; i++) {
883                result ^= (z += (floatToIntBits(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
884            }
885            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
886        }
887
888        public static long hash64(final double[] data) {
889            if (data == null)
890                return 0;
891            long z = 0x632BE59BD9B4E019L, result = 1L;
892            for (int i = 0; i < data.length; i++) {
893                result ^= (z += (NumberTools.doubleToMixedIntBits(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
894            }
895            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
896        }
897
898        /**
899         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
900         *
901         * @param data  the char array to hash
902         * @param start the start of the section to hash (inclusive)
903         * @param end   the end of the section to hash (exclusive)
904         * @return a 64-bit hash code for the requested section of data
905         */
906        public static long hash64(final char[] data, final int start, final int end) {
907            if (data == null || start >= end)
908                return 0;
909            long z = 0x632BE59BD9B4E019L, result = 1L;
910            for (int i = start; i < end && i < data.length; i++) {
911                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
912            }
913            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
914        }
915        /**
916         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
917         * moving between chars in increments of step (which is always greater than 0).
918         *
919         * @param data  the char array to hash
920         * @param start the start of the section to hash (inclusive)
921         * @param end   the end of the section to hash (exclusive)
922         * @param step  how many elements to advance after using one element from data; must be greater than 0
923         * @return a 64-bit hash code for the requested section of data
924         */
925        public static long hash64(final char[] data, final int start, final int end, final int step) {
926            if (data == null || start >= end || step <= 0)
927                return 0;
928            long z = 0x632BE59BD9B4E019L, result = 1L;
929            for (int i = start; i < end && i < data.length; i += step) {
930                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
931            }
932            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
933        }
934
935        public static long hash64(final CharSequence data) {
936            if (data == null)
937                return 0;
938            long z = 0x632BE59BD9B4E019L, result = 1L;
939            for (int i = 0; i < data.length(); i++) {
940                result ^= (z += (data.charAt(i) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
941            }
942            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
943        }
944
945        public static long hash64(final char[][] data) {
946            if (data == null)
947                return 0;
948            long z = 0x632BE59BD9B4E019L, result = 1L;
949            for (int i = 0; i < data.length; i++) {
950                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
951            }
952            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
953        }
954
955        public static long hash64(final long[][] data) {
956            if (data == null)
957                return 0;
958            long z = 0x632BE59BD9B4E019L, result = 1L;
959            for (int i = 0; i < data.length; i++) {
960                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
961            }
962            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
963        }
964
965        public static long hash64(final CharSequence[] data) {
966            if (data == null)
967                return 0;
968            long z = 0x632BE59BD9B4E019L, result = 1L;
969            for (int i = 0; i < data.length; i++) {
970                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
971            }
972            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
973        }
974
975        public static long hash64(final Iterable<? extends CharSequence> data) {
976            if (data == null)
977                return 0;
978            long z = 0x632BE59BD9B4E019L, result = 1L;
979            for (CharSequence datum : data) {
980                result ^= (z += (hash64(datum) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
981            }
982            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
983        }
984
985        public static long hash64(final CharSequence[]... data) {
986            if (data == null)
987                return 0;
988            long z = 0x632BE59BD9B4E019L, result = 1L;
989            for (int i = 0; i < data.length; i++) {
990                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
991            }
992            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
993        }
994
995        public static long hash64(final Object[] data) {
996            if (data == null)
997                return 0;
998            long z = 0x632BE59BD9B4E019L, result = 1L;
999            Object o;
1000            for (int i = 0; i < data.length; i++) {
1001                o = data[i];
1002                result ^= (z += ((o == null ? 0 : o.hashCode()) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1003            }
1004            return result ^ Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58));
1005        }
1006
1007        public static int hash(final boolean[] data) {
1008            if (data == null)
1009                return 0;
1010            long z = 0x632BE59BD9B4E019L, result = 1L;
1011            for (int i = 0; i < data.length; i++) {
1012                result ^= (z += (data[i] ? 0x9E3779B97F4A7C94L : 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1013            }
1014            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1015        }
1016
1017        public static int hash(final byte[] data) {
1018            if (data == null)
1019                return 0;
1020            long z = 0x632BE59BD9B4E019L, result = 1L;
1021            for (int i = 0; i < data.length; i++) {
1022                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1023            }
1024            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1025        }
1026
1027        public static int hash(final short[] data) {
1028            if (data == null)
1029                return 0;
1030            long z = 0x632BE59BD9B4E019L, result = 1L;
1031            for (int i = 0; i < data.length; i++) {
1032                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1033            }
1034            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1035        }
1036
1037        public static int hash(final char[] data) {
1038            if (data == null)
1039                return 0;
1040            long z = 0x632BE59BD9B4E019L, result = 1L;
1041            for (int i = 0; i < data.length; i++) {
1042                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1043            }
1044            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1045        }
1046
1047        public static int hash(final int[] data) {
1048            if (data == null)
1049                return 0;
1050            long z = 0x632BE59BD9B4E019L, result = 1L;
1051            for (int i = 0; i < data.length; i++) {
1052                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1053
1054            }
1055            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1056        }
1057
1058        public static int hash(final long[] data) {
1059            if (data == null)
1060                return 0;
1061            long z = 0x632BE59BD9B4E019L, result = 1L;
1062            for (int i = 0; i < data.length; i++) {
1063                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1064            }
1065            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1066        }
1067
1068        public static int hash(final float[] data) {
1069            if (data == null)
1070                return 0;
1071            long z = 0x632BE59BD9B4E019L, result = 1L;
1072            for (int i = 0; i < data.length; i++) {
1073                result ^= (z += (floatToIntBits(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1074            }
1075            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1076        }
1077
1078        public static int hash(final double[] data) {
1079            if (data == null)
1080                return 0;
1081            long z = 0x632BE59BD9B4E019L, result = 1L;
1082            for (int i = 0; i < data.length; i++) {
1083                result ^= (z += (NumberTools.doubleToMixedIntBits(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1084            }
1085            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1086        }
1087
1088        /**
1089         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
1090         *
1091         * @param data  the char array to hash
1092         * @param start the start of the section to hash (inclusive)
1093         * @param end   the end of the section to hash (exclusive)
1094         * @return a 32-bit hash code for the requested section of data
1095         */
1096        public static int hash(final char[] data, final int start, final int end) {
1097            if (data == null || start >= end)
1098                return 0;
1099
1100            long z = 0x632BE59BD9B4E019L, result = 1L;
1101            for (int i = start; i < end && i < data.length; i++) {
1102                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1103            }
1104            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1105        }
1106        /**
1107         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
1108         * moving between chars in increments of step (which is always greater than 0).
1109         *
1110         * @param data  the char array to hash
1111         * @param start the start of the section to hash (inclusive)
1112         * @param end   the end of the section to hash (exclusive)
1113         * @param step  how many elements to advance after using one element from data; must be greater than 0
1114         * @return a 32-bit hash code for the requested section of data
1115         */
1116        public static int hash(final char[] data, final int start, final int end, final int step) {
1117            if (data == null || start >= end || step <= 0)
1118                return 0;
1119
1120            long z = 0x632BE59BD9B4E019L, result = 1L;
1121            for (int i = start; i < end && i < data.length; i += step) {
1122                result ^= (z += (data[i] + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1123            }
1124            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1125        }
1126
1127        public static int hash(final CharSequence data) {
1128            if (data == null)
1129                return 0;
1130            long z = 0x632BE59BD9B4E019L, result = 1L;
1131            for (int i = 0; i < data.length(); i++) {
1132                result ^= (z += (data.charAt(i) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1133            }
1134            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1135        }
1136
1137        public static int hash(final char[][] data) {
1138            if (data == null)
1139                return 0;
1140            long z = 0x632BE59BD9B4E019L, result = 1L;
1141            for (int i = 0; i < data.length; i++) {
1142                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1143            }
1144            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1145        }
1146
1147        public static int hash(final long[][] data) {
1148            if (data == null)
1149                return 0;
1150            long z = 0x632BE59BD9B4E019L, result = 1L;
1151            for (int i = 0; i < data.length; i++) {
1152                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1153            }
1154            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1155        }
1156
1157        public static int hash(final CharSequence[] data) {
1158            if (data == null)
1159                return 0;
1160            long z = 0x632BE59BD9B4E019L, result = 1L;
1161            for (int i = 0; i < data.length; i++) {
1162                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1163            }
1164            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1165        }
1166
1167        public static int hash(final Iterable<? extends CharSequence> data) {
1168            if (data == null)
1169                return 0;
1170            long z = 0x632BE59BD9B4E019L, result = 1L;
1171            for (CharSequence datum : data) {
1172                result ^= (z += (hash64(datum) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1173            }
1174            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1175        }
1176
1177        public static int hash(final CharSequence[]... data) {
1178            if (data == null)
1179                return 0;
1180            long z = 0x632BE59BD9B4E019L, result = 1L;
1181            for (int i = 0; i < data.length; i++) {
1182                result ^= (z += (hash64(data[i]) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1183            }
1184            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1185        }
1186
1187        public static int hash(final Object[] data) {
1188            if (data == null)
1189                return 0;
1190            long z = 0x632BE59BD9B4E019L, result = 1L;
1191            Object o;
1192            for (int i = 0; i < data.length; i++) {
1193                o = data[i];
1194                result ^= (z += ((o == null ? 0 : o.hashCode()) + 0x9E3779B97F4A7C15L) * 0xD0E89D2D311E289FL) * 0xC6BC279692B5CC83L;
1195            }
1196            return (int) ((result ^= Long.rotateLeft((z * 0xC6BC279692B5CC83L ^ result * 0x9E3779B97F4A7C15L) + 0x632BE59BD9B4E019L, (int) (z >>> 58))) ^ (result >>> 32));
1197        }
1198    }
1199
1200    // Nice ints, all probable primes except the last one, for 32-bit hashing
1201    // 0x62E2AC0D 0x632BE5AB 0x85157AF5 0x9E3779B9
1202    /**
1203     * The fastest hash in CrossHash, with middling quality. Uses a finely-tuned mix of very few operations for each
1204     * element, plus a minimal and simple finalization step, and as such obtains superior speed on the standard
1205     * benchmark SquidLib uses for hashes (hashing one million 16-element long arrays, remaining the best in both 32-bit
1206     * and 64-bit versions). Specifically, Wisp takes 9.478 ms to generate a million 64-bit hashes on a recent laptop
1207     * with an i7-6700HQ processor (removing the time the control takes to generate the million arrays). For comparison,
1208     * the JDK's Arrays.hashCode method takes 13.642 ms on the same workload, though it produces 32-bit hashes. Wisp
1209     * performs almost exactly as well producing 32-bit hashes as it does 64-bit hashes, where Hive slows down
1210     * significantly on some input types. This also passes visual tests where an earlier version of Wisp did not.
1211     * Collision rates are slightly worse than other CrossHash classes, but are better than the JDK's
1212     * Arrays.hashCode method, that is, acceptably low when given varied-enough inputs. On certain kinds of similar
1213     * inputs, Wisp will struggle with a higher collision rate. For example, when hashing Strings that contain only
1214     * several spaces, then some combination of digits 0-5, then more spaces, Wisp does very badly, worse than
1215     * {@link String#hashCode()} (which also does badly, though not as badly), while other hashes here do fine (such as
1216     * Water, which is the default for {@link CrossHash#hash(CharSequence)}).
1217     * <br>
1218     * This version replaces an older version of Wisp that had serious quality issues and wasn't quite as fast. Since
1219     * the only reason one would use the older version was speed without regard for quality, and it was marked as Beta,
1220     * a faster version makes sense to replace the slower one, rather than add yet another nested class in CrossHash.
1221     * <br>
1222     * Wisp is no longer considered Beta-quality, but even though it is rather fast, it has some cases where categories
1223     * of input cause frequent collisions. {@link Water} is about 20% slower but doesn't have such categories of
1224     * pathologically bad inputs, and passes tests that Wisp fails badly on. Because the hash-based collections in
1225     * SquidLib need a pretty good hash function to work at their best (they use linear-probing with open addressing,
1226     * which struggles when hashes are bad), 20% loss of speed during hashing to avoid slower
1227     * lookups/insertions/deletions from {@link OrderedMap}, {@link OrderedSet}, {@link UnorderedMap},
1228     * {@link UnorderedSet}, {@link Arrangement}, and others is probably worth it; if you really need speed then you
1229     * should first consider {@link Curlup}, which is faster than Wisp on moderately-long input arrays (with 20 or more
1230     * items, usually), and only if you need a fast hash for small inputs, where collisions aren't a problem, should you
1231     * turn to Wisp.
1232     */
1233    public static final class Wisp {
1234        public static long hash64(final boolean[] data) {
1235            if (data == null)
1236                return 0;
1237            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1238            final int len = data.length;
1239            for (int i = 0; i < len; i++) {
1240                result += (a ^= 0x8329C6EB9E6AD3E3L * (data[i] ? 0xC6BC279692B5CC83L : 0xAEF17502108EF2D9L));
1241            }
1242            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1243        }
1244
1245        public static long hash64(final byte[] data) {
1246            if (data == null)
1247                return 0;
1248            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1249            final int len = data.length;
1250            for (int i = 0; i < len; i++) {
1251                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1252            }
1253            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1254        }
1255
1256        public static long hash64(final short[] data) {
1257            if (data == null)
1258                return 0;
1259            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1260            final int len = data.length;
1261            for (int i = 0; i < len; i++) {
1262                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1263            }
1264            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1265        }
1266
1267        public static long hash64(final char[] data) {
1268            if (data == null)
1269                return 0;
1270            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1271            final int len = data.length;
1272            for (int i = 0; i < len; i++) {
1273                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1274            }
1275            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1276        }
1277
1278        public static long hash64(final int[] data) {
1279            if (data == null)
1280                return 0;
1281            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1282            final int len = data.length;
1283            for (int i = 0; i < len; i++) {
1284                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1285            }
1286            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1287        }
1288
1289        public static long hash64(final long[] data) {
1290            if (data == null)
1291                return 0;
1292            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1293            final int len = data.length;
1294            for (int i = 0; i < len; i++) {
1295                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1296            }
1297            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1298        }
1299
1300        public static long hash64(final float[] data) {
1301            if (data == null)
1302                return 0;
1303            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1304            final int len = data.length;
1305            for (int i = 0; i < len; i++) {
1306                result += (a ^= 0x8329C6EB9E6AD3E3L * floatToIntBits(data[i]));
1307            }
1308            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1309        }
1310
1311        public static long hash64(final double[] data) {
1312            if (data == null)
1313                return 0;
1314            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1315            final int len = data.length;
1316            for (int i = 0; i < len; i++) {
1317                result += (a ^= 0x8329C6EB9E6AD3E3L * NumberTools.doubleToMixedIntBits(data[i]));
1318            }
1319            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1320        }
1321
1322        public static long hash64(final CharSequence data) {
1323            if (data == null)
1324                return 0;
1325            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1326            final int len = data.length();
1327            for (int i = 0; i < len; i++) {
1328                result += (a ^= 0x8329C6EB9E6AD3E3L * data.charAt(i));
1329            }
1330            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1331        }
1332
1333        /**
1334         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
1335         *
1336         * @param data  the char array to hash
1337         * @param start the start of the section to hash (inclusive)
1338         * @param end   the end of the section to hash (exclusive)
1339         * @return a 64-bit hash code for the requested section of data
1340         */
1341        public static long hash64(final char[] data, final int start, final int end) {
1342            if (data == null || start >= end)
1343                return 0;
1344            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1345            final int len = Math.min(end, data.length);
1346            for (int i = start; i < len; i++) {
1347                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1348            }
1349            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1350        }
1351
1352        /**
1353         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
1354         * moving between chars in increments of step (which is always greater than 0).
1355         *
1356         * @param data  the char array to hash
1357         * @param start the start of the section to hash (inclusive)
1358         * @param end   the end of the section to hash (exclusive)
1359         * @param step  how many elements to advance after using one element from data; must be greater than 0
1360         * @return a 64-bit hash code for the requested section of data
1361         */
1362        public static long hash64(final char[] data, final int start, final int end, final int step) {
1363            if (data == null || start >= end || step <= 0)
1364                return 0;
1365            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1366            final int len = Math.min(end, data.length);
1367            for (int i = start; i < len; i += step) {
1368                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1369            }
1370            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1371        }
1372
1373        public static long hash64(final char[][] data) {
1374            if (data == null)
1375                return 0;
1376            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1377            final int len = data.length;
1378            for (int i = 0; i < len; i++) {
1379                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1380            }
1381            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1382        }
1383
1384        public static long hash64(final int[][] data) {
1385            if (data == null)
1386                return 0;
1387            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1388            final int len = data.length;
1389            for (int i = 0; i < len; i++) {
1390                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1391            }
1392            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1393        }
1394
1395        public static long hash64(final long[][] data) {
1396            if (data == null)
1397                return 0;
1398            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1399            final int len = data.length;
1400            for (int i = 0; i < len; i++) {
1401                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1402            }
1403            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1404        }
1405
1406        public static long hash64(final CharSequence[] data) {
1407            if (data == null)
1408                return 0;
1409            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1410            final int len = data.length;
1411            for (int i = 0; i < len; i++) {
1412                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1413            }
1414            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1415        }
1416
1417        public static long hash64(final CharSequence[]... data) {
1418            if (data == null)
1419                return 0;
1420            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1421            final int len = data.length;
1422            for (int i = 0; i < len; i++) {
1423                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1424            }
1425            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1426        }
1427
1428        public static long hash64(final Iterable<? extends CharSequence> data) {
1429            if (data == null)
1430                return 0;
1431            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1432            for (CharSequence datum : data) {
1433                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(datum));
1434            }
1435            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1436        }
1437
1438        public static long hash64(final List<? extends CharSequence> data) {
1439            if (data == null)
1440                return 0;
1441            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1442            final int len = data.size();
1443            for (int i = 0; i < len; i++) {
1444                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data.get(i)));
1445            }
1446            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1447        }
1448
1449        public static long hash64(final Object[] data) {
1450            if (data == null)
1451                return 0;
1452            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1453            final int len = data.length;
1454            Object o;
1455            for (int i = 0; i < len; i++) {
1456                result += (a ^= 0x8329C6EB9E6AD3E3L * ((o = data[i]) == null ? -1L : o.hashCode()));
1457            }
1458            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1459        }
1460
1461        public static long hash64(final Object data) {
1462            if (data == null)
1463                return 0L;
1464            long a = 0x632BE59BD9B4E019L ^ 0x8329C6EB9E6AD3E3L * data.hashCode(), result = 0x9E3779B97F4A7C94L + a;
1465            return result * (a | 1L) ^ (result << 37 | result >>> 27);
1466        }
1467
1468        public static int hash32(final boolean[] data) {
1469            if (data == null)
1470                return 0;
1471            int result = 0x9E3779B9, a = 0x632BE5AB;
1472            final int len = data.length;
1473            for (int i = 0; i < len; i++) {
1474                result += (a ^= 0x85157AF5 * (data[i] ? 0x789ABCDE : 0x62E2AC0D));
1475            }
1476            return result * (a | 1) ^ (result >>> 11 | result << 21);
1477        }
1478
1479
1480        public static int hash32(final byte[] data) {
1481            if (data == null)
1482                return 0;
1483            int result = 0x9E3779B9, a = 0x632BE5AB;
1484            final int len = data.length;
1485            for (int i = 0; i < len; i++) {
1486                result += (a ^= 0x85157AF5 * data[i]);
1487            }
1488            return result * (a | 1) ^ (result >>> 11 | result << 21);
1489        }
1490
1491        public static int hash32(final short[] data) {
1492            if (data == null)
1493                return 0;
1494            int result = 0x9E3779B9, a = 0x632BE5AB;
1495            final int len = data.length;
1496            for (int i = 0; i < len; i++) {
1497                result += (a ^= 0x85157AF5 * data[i]);
1498            }
1499            return result * (a | 1) ^ (result >>> 11 | result << 21);
1500        }
1501
1502        public static int hash32(final char[] data) {
1503            if (data == null)
1504                return 0;
1505            int result = 0x9E3779B9, a = 0x632BE5AB;
1506            final int len = data.length;
1507            for (int i = 0; i < len; i++) {
1508                result += (a ^= 0x85157AF5 * data[i]);
1509            }
1510            return result * (a | 1) ^ (result >>> 11 | result << 21);
1511        }
1512        public static int hash32(final int[] data) {
1513            if (data == null)
1514                return 0;
1515            int result = 0x9E3779B9, a = 0x632BE5AB;
1516            final int len = data.length;
1517            for (int i = 0; i < len; i++) {
1518                result += (a ^= 0x85157AF5 * data[i]);
1519            }
1520            return result * (a | 1) ^ (result >>> 11 | result << 21);
1521        }
1522
1523        public static int hash32(final long[] data) {
1524            if (data == null)
1525                return 0;
1526            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1527            final int len = data.length;
1528            for (int i = 0; i < len; i++) {
1529                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1530            }
1531            return (int)((a += (result << 37 | result >>> 27)) ^ (a >>> 32));
1532        }
1533
1534        public static int hash32(final float[] data) {
1535            if (data == null)
1536                return 0;
1537            int result = 0x9E3779B9, a = 0x632BE5AB;
1538            final int len = data.length;
1539            for (int i = 0; i < len; i++) {
1540                result += (a ^= 0x85157AF5 * floatToIntBits(data[i]));
1541            }
1542            return result * (a | 1) ^ (result >>> 11 | result << 21);
1543        }
1544
1545        public static int hash32(final double[] data) {
1546            if (data == null)
1547                return 0;
1548            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1549            final int len = data.length;
1550            double t;
1551            for (int i = 0; i < len; i++) {
1552                result += (a ^= 0x8329C6EB9E6AD3E3L * ((long) (-0xD0E8.9D2D311E289Fp-25 * (t = data[i]) + t * -0x1.39b4dce80194cp9)));
1553            }
1554            return (int)((result = (result * (a | 1L) ^ (result << 37 | result >>> 27))) ^ (result >>> 32));
1555        }
1556
1557        public static int hash32(final CharSequence data) {
1558            if (data == null)
1559                return 0;
1560            int result = 0x9E3779B9, a = 0x632BE5AB;
1561            final int len = data.length();
1562            for (int i = 0; i < len; i++) {
1563                result += (a ^= 0x85157AF5 * data.charAt(i));
1564            }
1565            return result * (a | 1) ^ (result >>> 11 | result << 21);
1566        }
1567
1568        /**
1569         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
1570         * Uses 32-bit math on most platforms, but will give different results on GWT due to it using double values that
1571         * only somewhat act like int values.
1572         * @param data  the char array to hash
1573         * @param start the start of the section to hash (inclusive)
1574         * @param end   the end of the section to hash (exclusive)
1575         * @return a 32-bit hash code for the requested section of data
1576         */
1577        public static int hash32(final char[] data, final int start, final int end) {
1578            if (data == null || start >= end)
1579                return 0;
1580            int result = 0x9E3779B9, a = 0x632BE5AB;
1581            final int len = Math.min(end, data.length);
1582            for (int i = start; i < len; i++) {
1583                result += (a ^= 0x85157AF5 * data[i]);
1584            }
1585            return result * (a | 1) ^ (result >>> 11 | result << 21);
1586        }
1587
1588        public static int hash32(final char[][] data) {
1589            if (data == null)
1590                return 0;
1591            int result = 0x9E3779B9, a = 0x632BE5AB;
1592            final int len = data.length;
1593            for (int i = 0; i < len; i++) {
1594                result += (a ^= 0x85157AF5 * hash32(data[i]));
1595            }
1596            return result * (a | 1) ^ (result >>> 11 | result << 21);
1597        }
1598
1599        public static int hash32(final int[][] data) {
1600            if (data == null)
1601                return 0;
1602            int result = 0x9E3779B9, a = 0x632BE5AB;
1603            final int len = data.length;
1604            for (int i = 0; i < len; i++) {
1605                result += (a ^= 0x85157AF5 * hash32(data[i]));
1606            }
1607            return result * (a | 1) ^ (result >>> 11 | result << 21);
1608        }
1609
1610        public static int hash32(final long[][] data) {
1611            if (data == null)
1612                return 0;
1613            int result = 0x9E3779B9, a = 0x632BE5AB;
1614            final int len = data.length;
1615            for (int i = 0; i < len; i++) {
1616                result += (a ^= 0x85157AF5 * hash32(data[i]));
1617            }
1618            return result * (a | 1) ^ (result >>> 11 | result << 21);
1619        }
1620
1621        public static int hash32(final CharSequence[] data) {
1622            if (data == null)
1623                return 0;
1624            int result = 0x9E3779B9, a = 0x632BE5AB;
1625            final int len = data.length;
1626            for (int i = 0; i < len; i++) {
1627                result += (a ^= 0x85157AF5 * hash32(data[i]));
1628            }
1629            return result * (a | 1) ^ (result >>> 11 | result << 21);
1630        }
1631
1632        public static int hash32(final CharSequence[]... data) {
1633            if (data == null)
1634                return 0;
1635            int result = 0x9E3779B9, a = 0x632BE5AB;
1636            final int len = data.length;
1637            for (int i = 0; i < len; i++) {
1638                result += (a ^= 0x85157AF5 * hash32(data[i]));
1639            }
1640            return result * (a | 1) ^ (result >>> 11 | result << 21);
1641        }
1642
1643        public static int hash32(final Iterable<? extends CharSequence> data) {
1644            if (data == null)
1645                return 0;
1646            int result = 0x9E3779B9, a = 0x632BE5AB;
1647            for (CharSequence datum : data) {
1648                result += (a ^= 0x85157AF5 * hash32(datum));
1649            }
1650            return result * (a | 1) ^ (result >>> 11 | result << 21);
1651        }
1652
1653        public static int hash32(final List<? extends CharSequence> data) {
1654            if (data == null)
1655                return 0;
1656            int result = 0x9E3779B9, a = 0x632BE5AB;
1657            final int len = data.size();
1658            for (int i = 0; i < len; i++) {
1659                result += (a ^= 0x85157AF5 * hash32(data.get(i)));
1660            }
1661            return result * (a | 1) ^ (result >>> 11 | result << 21);
1662        }
1663
1664        public static int hash32(final Object[] data) {
1665            if (data == null)
1666                return 0;
1667            int result = 0x9E3779B9, a = 0x632BE5AB;
1668            final int len = data.length;
1669            Object o;
1670            for (int i = 0; i < len; i++) {
1671                result += (a ^= 0x85157AF5 * ((o = data[i]) == null ? -1 : o.hashCode()));
1672            }
1673            return result * (a | 1) ^ (result >>> 11 | result << 21);
1674        }
1675
1676        public static int hash32(final Object data) {
1677            if (data == null)
1678                return 0;
1679            int a = 0x632BE5AB ^ 0x85157AF5 * data.hashCode(), result = 0x9E3779B9 + a;
1680            return result * (a | 1) ^ (result >>> 11 | result << 21);
1681        }
1682        public static int hash(final boolean[] data) {
1683            if (data == null)
1684                return 0;
1685            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1686            final int len = data.length;
1687            for (int i = 0; i < len; i++) {
1688                result += (a ^= 0x8329C6EB9E6AD3E3L * (data[i] ? 0xC6BC279692B5CC83L : 0xAEF17502108EF2D9L));
1689            }
1690            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1691        }
1692
1693        public static int hash(final byte[] data) {
1694            if (data == null)
1695                return 0;
1696            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1697            final int len = data.length;
1698            for (int i = 0; i < len; i++) {
1699                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1700            }
1701            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1702        }
1703
1704        public static int hash(final short[] data) {
1705            if (data == null)
1706                return 0;
1707            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1708            final int len = data.length;
1709            for (int i = 0; i < len; i++) {
1710                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1711            }
1712            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1713        }
1714
1715        public static int hash(final char[] data) {
1716            if (data == null)
1717                return 0;
1718            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1719            final int len = data.length;
1720            for (int i = 0; i < len; i++) {
1721                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1722            }
1723            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1724        }
1725
1726        public static int hash(final int[] data) {
1727            if (data == null)
1728                return 0;
1729            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1730            final int len = data.length;
1731            for (int i = 0; i < len; i++) {
1732                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1733            }
1734            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1735        }
1736
1737        public static int hash(final long[] data) {
1738            if (data == null)
1739                return 0;
1740            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1741            final int len = data.length;
1742            for (int i = 0; i < len; i++) {
1743                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1744            }
1745            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1746        }
1747
1748        public static int hash(final float[] data) {
1749            if (data == null)
1750                return 0;
1751            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1752            final int len = data.length;
1753            for (int i = 0; i < len; i++) {
1754                result += (a ^= 0x8329C6EB9E6AD3E3L * floatToIntBits(data[i]));
1755            }
1756            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1757        }
1758
1759        public static int hash(final double[] data) {
1760            if (data == null)
1761                return 0;
1762            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1763            final int len = data.length;
1764            for (int i = 0; i < len; i++) {
1765                result += (a ^= 0x8329C6EB9E6AD3E3L * NumberTools.doubleToMixedIntBits(data[i]));
1766            }
1767            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1768        }
1769
1770        public static int hash(final CharSequence data) {
1771            if (data == null)
1772                return 0;
1773            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1774            final int len = data.length();
1775            for (int i = 0; i < len; i++) {
1776                result += (a ^= 0x8329C6EB9E6AD3E3L * data.charAt(i));
1777            }
1778            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1779        }
1780        /**
1781         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
1782         *
1783         * @param data  the char array to hash
1784         * @param start the start of the section to hash (inclusive)
1785         * @param end   the end of the section to hash (exclusive)
1786         * @return a 32-bit hash code for the requested section of data
1787         */
1788        public static int hash(final char[] data, final int start, final int end) {
1789            if (data == null || start >= end)
1790                return 0;
1791            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1792            final int len = Math.min(end, data.length);
1793            for (int i = start; i < len; i++) {
1794                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1795            }
1796            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1797        }
1798
1799        /**
1800         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
1801         * moving between chars in increments of step (which is always greater than 0).
1802         *
1803         * @param data  the char array to hash
1804         * @param start the start of the section to hash (inclusive)
1805         * @param end   the end of the section to hash (exclusive)
1806         * @param step  how many elements to advance after using one element from data; must be greater than 0
1807         * @return a 32-bit hash code for the requested section of data
1808         */
1809        public static int hash(final char[] data, final int start, final int end, final int step) {
1810            if (data == null || start >= end || step <= 0)
1811                return 0;
1812            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1813            final int len = Math.min(end, data.length);
1814            for (int i = start; i < len; i+= step) {
1815                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]);
1816            }
1817            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1818        }
1819
1820        public static int hash(final char[][] data) {
1821            if (data == null)
1822                return 0;
1823            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1824            final int len = data.length;
1825            for (int i = 0; i < len; i++) {
1826                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1827            }
1828            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1829        }
1830
1831        public static int hash(final int[][] data) {
1832            if (data == null)
1833                return 0;
1834            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1835            final int len = data.length;
1836            for (int i = 0; i < len; i++) {
1837                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1838            }
1839            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1840        }
1841
1842        public static int hash(final long[][] data) {
1843            if (data == null)
1844                return 0;
1845            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1846            final int len = data.length;
1847            for (int i = 0; i < len; i++) {
1848                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1849            }
1850            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1851        }
1852
1853        public static int hash(final CharSequence[] data) {
1854            if (data == null)
1855                return 0;
1856            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1857            final int len = data.length;
1858            for (int i = 0; i < len; i++) {
1859                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1860            }
1861            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1862        }
1863
1864        public static int hash(final CharSequence[]... data) {
1865            if (data == null)
1866                return 0;
1867            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1868            final int len = data.length;
1869            for (int i = 0; i < len; i++) {
1870                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i]));
1871            }
1872            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1873        }
1874
1875        public static int hash(final Iterable<? extends CharSequence> data) {
1876            if (data == null)
1877                return 0;
1878            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1879            for (CharSequence datum : data) {
1880                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(datum));
1881            }
1882            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1883        }
1884
1885        public static int hash(final List<? extends CharSequence> data) {
1886            if (data == null)
1887                return 0;
1888            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1889            final int len = data.size();
1890            for (int i = 0; i < len; i++) {
1891                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data.get(i)));
1892            }
1893            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1894        }
1895
1896        public static int hash(final Object[] data) {
1897            if (data == null)
1898                return 0;
1899            long result = 0x9E3779B97F4A7C94L, a = 0x632BE59BD9B4E019L;
1900            final int len = data.length;
1901            Object o;
1902            for (int i = 0; i < len; i++) {
1903                result += (a ^= 0x8329C6EB9E6AD3E3L * ((o = data[i]) == null ? -1 : o.hashCode()));
1904            }
1905            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1906        }
1907
1908        public static int hash(final Object data) {
1909            if (data == null)
1910                return 0;
1911            long a = 0x632BE59BD9B4E019L ^ 0x8329C6EB9E6AD3E3L * data.hashCode(), result = 0x9E3779B97F4A7C94L + a;
1912            return (int)(result * (a | 1L) ^ (result << 37 | result >>> 27));
1913        }
1914
1915    }
1916
1917    /**
1918     * A whole cluster of Wisp-like hash functions that sacrifice a small degree of speed, but can be built with up
1919     * to 128 bits of salt values that help to obscure what hashing function is actually being used. This class is
1920     * similar to the older Storm variety, but is somewhat faster and has many more possible salt "states" when using
1921     * the constructors that take two longs or a CharSequence. There isn't really any reason to use Storm, so Mist has
1922     * now replaced Storm entirely. Code that used Storm should be able to just change any usage of "Storm" to "Mist",
1923     * or can instead use {@link Yolk} or {@link Curlup} for higher quality and speed but smaller salt size.
1924     * <br>
1925     * The salt fields are not serialized, so it is important that the same salt will be given by the
1926     * program when the same hash results are wanted for some inputs.
1927     * <br>
1928     * A group of 48 static, final, pre-initialized Mist members are present in this class, 24 with the
1929     * name of a letter in the Greek alphabet (this uses the convention on Wikipedia,
1930     * https://en.wikipedia.org/wiki/Greek_alphabet#Letters , where lambda is spelled with a 'b') and 24 with the same
1931     * name followed by an underscore, such as {@link #alpha_}. The whole group of 48 pre-initialized members are also
1932     * present in a static array called {@code predefined}. These can be useful when, for example, you want to get
1933     * multiple hashes of a single array or String as part of cuckoo hashing or similar techniques that need multiple
1934     * hashes for the same inputs.
1935     */
1936    public static final class Mist implements Serializable {
1937        private static final long serialVersionUID = -1275284837479983271L;
1938
1939        private transient final long l1, l2;
1940
1941        public Mist() {
1942            this(0x1234567876543210L, 0xEDCBA98789ABCDEFL);
1943        }
1944
1945        public Mist(final CharSequence alteration) {
1946            this(CrossHash.hash64(alteration), Lightning.hash64(alteration));
1947        }
1948        private static int permute(final long state)
1949        {
1950            int s = (int)state ^ 0xD0E89D2D;
1951            s = (s >>> 19 | s << 13);
1952            s ^= state >>> (5 + (state >>> 59));
1953            return ((s *= 277803737) >>> 22) ^ s;
1954        }
1955
1956        @SuppressWarnings("NumericOverflow")
1957        public Mist(final long alteration) {
1958            long l1, l2;
1959            l1 = alteration + permute(alteration);
1960            l1 = (l1 ^ (l1 >>> 30)) * 0xBF58476D1CE4E5B9L;
1961            l1 = (l1 ^ (l1 >>> 27)) * 0x94D049BB133111EBL;
1962            this.l1 = l1 ^ l1 >>> 31;
1963
1964            l2 = alteration + 6 * 0x9E3779B97F4A7C15L;
1965            l2 = (l2 ^ (l2 >>> 30)) * 0xBF58476D1CE4E5B9L;
1966            l2 = (l2 ^ (l2 >>> 27)) * 0x94D049BB133111EBL;
1967            this.l2 = l2 ^ l2 >>> 31;
1968        }
1969
1970        public Mist(final long alteration1, long alteration2) {
1971            final int i1 = permute(alteration1);
1972            l1 = alteration1 + i1;
1973            l2 = alteration2 + permute(alteration2 + i1);
1974        }
1975
1976        /**
1977         * Makes a new Mist with all of the salt values altered based on the previous salt values.
1978         * This will make a different, incompatible Mist object that will give different results than the original.
1979         * Meant for use in Cuckoo Hashing, which can need the hash function to be updated or changed.
1980         * An alternative is to select a different Mist object from {@link #predefined}, or to simply
1981         * construct a new Mist with a different parameter or set of parameters.
1982         */
1983        @SuppressWarnings("NumericOverflow")
1984        public Mist randomize()
1985        {
1986            long l1, l2;
1987            l1 = this.l2 + permute(this.l2 + 3 * 0x9E3779B97F4A7C15L);
1988            l1 = (l1 ^ (l1 >>> 30)) * 0xBF58476D1CE4E5B9L;
1989            l1 = (l1 ^ (l1 >>> 27)) * 0x94D049BB133111EBL;
1990            l1 ^= l1 >>> 31;
1991
1992            l2 = permute(l1 + 5 * 0x9E3779B97F4A7C15L) + 6 * 0x9E3779B97F4A7C15L;
1993            l2 = (l2 ^ (l2 >>> 30)) * 0xBF58476D1CE4E5B9L;
1994            l2 = (l2 ^ (l2 >>> 27)) * 0x94D049BB133111EBL;
1995            l2 ^= l2 >>> 31;
1996
1997            return new Mist(l1, l2);
1998        }
1999
2000        public static final Mist alpha = new Mist("alpha"), beta = new Mist("beta"), gamma = new Mist("gamma"),
2001                delta = new Mist("delta"), epsilon = new Mist("epsilon"), zeta = new Mist("zeta"),
2002                eta = new Mist("eta"), theta = new Mist("theta"), iota = new Mist("iota"),
2003                kappa = new Mist("kappa"), lambda = new Mist("lambda"), mu = new Mist("mu"),
2004                nu = new Mist("nu"), xi = new Mist("xi"), omicron = new Mist("omicron"), pi = new Mist("pi"),
2005                rho = new Mist("rho"), sigma = new Mist("sigma"), tau = new Mist("tau"),
2006                upsilon = new Mist("upsilon"), phi = new Mist("phi"), chi = new Mist("chi"), psi = new Mist("psi"),
2007                omega = new Mist("omega"),
2008                alpha_ = new Mist("ALPHA"), beta_ = new Mist("BETA"), gamma_ = new Mist("GAMMA"),
2009                delta_ = new Mist("DELTA"), epsilon_ = new Mist("EPSILON"), zeta_ = new Mist("ZETA"),
2010                eta_ = new Mist("ETA"), theta_ = new Mist("THETA"), iota_ = new Mist("IOTA"),
2011                kappa_ = new Mist("KAPPA"), lambda_ = new Mist("LAMBDA"), mu_ = new Mist("MU"),
2012                nu_ = new Mist("NU"), xi_ = new Mist("XI"), omicron_ = new Mist("OMICRON"), pi_ = new Mist("PI"),
2013                rho_ = new Mist("RHO"), sigma_ = new Mist("SIGMA"), tau_ = new Mist("TAU"),
2014                upsilon_ = new Mist("UPSILON"), phi_ = new Mist("PHI"), chi_ = new Mist("CHI"), psi_ = new Mist("PSI"),
2015                omega_ = new Mist("OMEGA");
2016        /**
2017         * Has a length of 48, which may be relevant if automatically choosing a predefined hash functor.
2018         */
2019        public static final Mist[] predefined = new Mist[]{alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota,
2020                kappa, lambda, mu, nu, xi, omicron, pi, rho, sigma, tau, upsilon, phi, chi, psi, omega,
2021                alpha_, beta_, gamma_, delta_, epsilon_, zeta_, eta_, theta_, iota_,
2022                kappa_, lambda_, mu_, nu_, xi_, omicron_, pi_, rho_, sigma_, tau_, upsilon_, phi_, chi_, psi_, omega_};
2023
2024        public long hash64(final boolean[] data) {
2025            if (data == null)
2026                return 0;
2027            final int len = data.length;
2028            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2029            for (int i = 0; i < len; i++) {
2030                result += (a ^= 0x8329C6EB9E6AD3E3L * (data[i] ? 0x9E3779B97F4A7C15L : 0x789ABCDEFEDCBA98L)) ^ l2 * a + l1;
2031            }
2032            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2033        }
2034
2035
2036        public long hash64(final byte[] data) {
2037            if (data == null)
2038                return 0;
2039            final int len = data.length;
2040            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2041            for (int i = 0; i < len; i++) {
2042                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2043            }
2044            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2045        }
2046
2047        public long hash64(final short[] data) {
2048            if (data == null)
2049                return 0;
2050            final int len = data.length;
2051            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2052            for (int i = 0; i < len; i++) {
2053                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2054            }
2055            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2056        }
2057
2058        public long hash64(final char[] data) {
2059            if (data == null)
2060                return 0;
2061            final int len = data.length;
2062            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2063            for (int i = 0; i < len; i++) {
2064                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2065            }
2066            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2067        }
2068
2069        public long hash64(final int[] data) {
2070            if (data == null)
2071                return 0;
2072            final int len = data.length;
2073            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2074            for (int i = 0; i < len; i++) {
2075                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2076            }
2077            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2078        }
2079
2080        public long hash64(final long[] data) {
2081            if (data == null)
2082                return 0;
2083            final int len = data.length;
2084            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2085            for (int i = 0; i < len; i++) {
2086                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2087            }
2088            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2089        }
2090
2091
2092        public long hash64(final float[] data) {
2093            if (data == null)
2094                return 0;
2095            final int len = data.length;
2096            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2097            for (int i = 0; i < len; i++) {
2098                result += (a ^= 0x8329C6EB9E6AD3E3L * floatToIntBits(data[i])) ^ l2 * a + l1;
2099            }
2100            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2101        }
2102
2103        public long hash64(final double[] data) {
2104            if (data == null)
2105                return 0;
2106            final int len = data.length;
2107            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2108            for (int i = 0; i < len; i++) {
2109                result += (a ^= 0x8329C6EB9E6AD3E3L * NumberTools.doubleToMixedIntBits(data[i])) ^ l2 * a + l1;
2110            }
2111            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2112        }
2113
2114        /**
2115         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2116         *
2117         * @param data  the char array to hash
2118         * @param start the start of the section to hash (inclusive)
2119         * @param end   the end of the section to hash (exclusive)
2120         * @return a 64-bit hash code for the requested section of data
2121         */
2122        public long hash64(final char[] data, final int start, final int end) {
2123            if (data == null || start >= end)
2124                return 0;
2125            final int len = data.length;
2126            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2127            for (int i = start; i < end && i < len; i++) {
2128                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2129            }
2130            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2131        }
2132
2133        /**
2134         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
2135         * moving between chars in increments of step (which is always greater than 0).
2136         *
2137         * @param data  the char array to hash
2138         * @param start the start of the section to hash (inclusive)
2139         * @param end   the end of the section to hash (exclusive)
2140         * @param step  how many elements to advance after using one element from data; must be greater than 0
2141         * @return a 64-bit hash code for the requested section of data
2142         */
2143        public long hash64(final char[] data, final int start, final int end, final int step) {
2144            if (data == null || start >= end || step <= 0)
2145                return 0;
2146            final int len = data.length;
2147            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2148            for (int i = start; i < end && i < len; i += step) {
2149                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2150            }
2151            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2152        }
2153
2154        public long hash64(final CharSequence data) {
2155            if (data == null)
2156                return 0;
2157            final int len = data.length();
2158            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2159            for (int i = 0; i < len; i++) {
2160                result += (a ^= 0x8329C6EB9E6AD3E3L * data.charAt(i)) ^ l2 * a + l1;
2161            }
2162            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2163        }
2164
2165        public long hash64(final char[][] data) {
2166            if (data == null)
2167                return 0;
2168            final int len = data.length;
2169            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2170            for (int i = 0; i < len; i++) {
2171                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2172            }
2173            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2174        }
2175
2176        public long hash64(final long[][] data) {
2177            if (data == null)
2178                return 0;
2179            final int len = data.length;
2180            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2181            for (int i = 0; i < len; i++) {
2182                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2183            }
2184            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2185        }
2186
2187        public long hash64(final CharSequence[] data) {
2188            if (data == null)
2189                return 0;
2190            final int len = data.length;
2191            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2192            for (int i = 0; i < len; i++) {
2193                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2194            }
2195            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2196        }
2197
2198        public long hash64(final Iterable<? extends CharSequence> data) {
2199            if (data == null)
2200                return 0;
2201            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2202            for (CharSequence datum : data) {
2203                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(datum)) ^ l2 * a + l1;
2204            }
2205            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2206        }
2207
2208        public long hash64(final CharSequence[]... data) {
2209            if (data == null)
2210                return 0;
2211            final int len = data.length;
2212            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2213            for (int i = 0; i < len; i++) {
2214                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2215            }
2216            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2217        }
2218
2219        public long hash64(final Object[] data) {
2220            if (data == null)
2221                return 0;
2222            final int len = data.length;
2223            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2224            Object o;
2225            for (int i = 0; i < len; i++) {
2226                result += (a ^= 0x8329C6EB9E6AD3E3L * ((o = data[i]) == null ? -1 : o.hashCode())) ^ l2 * a + l1;
2227            }
2228            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2229        }
2230
2231        public long hash64(final Object data) {
2232            if (data == null)
2233                return 0;
2234            final long a = 0x632BE59BD9B4E019L ^ 0x8329C6EB9E6AD3E3L * data.hashCode(),
2235                    result = 0x9E3779B97F4A7C94L + l2 + (a ^ l2 * a + l1);
2236            return result * (a * l1 | 1L) ^ (result << 37 | result >>> 27);
2237        }
2238        public int hash(final boolean[] data) {
2239            if (data == null)
2240                return 0;
2241            final int len = data.length;
2242            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2243            for (int i = 0; i < len; i++) {
2244                result += (a ^= 0x8329C6EB9E6AD3E3L * (data[i] ? 0x9E3779B97F4A7C15L : 0x789ABCDEFEDCBA98L)) ^ l2 * a + l1;
2245            }
2246            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2247        }
2248
2249
2250        public int hash(final byte[] data) {
2251            if (data == null)
2252                return 0;
2253            final int len = data.length;
2254            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2255            for (int i = 0; i < len; i++) {
2256                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2257            }
2258            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2259        }
2260
2261        public int hash(final short[] data) {
2262            if (data == null)
2263                return 0;
2264            final int len = data.length;
2265            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2266            for (int i = 0; i < len; i++) {
2267                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2268            }
2269            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2270        }
2271
2272        public int hash(final char[] data) {
2273            if (data == null)
2274                return 0;
2275            final int len = data.length;
2276            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2277            for (int i = 0; i < len; i++) {
2278                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2279            }
2280            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2281        }
2282
2283        public int hash(final int[] data) {
2284            if (data == null)
2285                return 0;
2286            final int len = data.length;
2287            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2288            for (int i = 0; i < len; i++) {
2289                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2290            }
2291            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2292        }
2293
2294        public int hash(final long[] data) {
2295            if (data == null)
2296                return 0;
2297            final int len = data.length;
2298            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2299            for (int i = 0; i < len; i++) {
2300                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2301            }
2302            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2303        }
2304
2305
2306        public int hash(final float[] data) {
2307            if (data == null)
2308                return 0;
2309            final int len = data.length;
2310            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2311            for (int i = 0; i < len; i++) {
2312                result += (a ^= 0x8329C6EB9E6AD3E3L * floatToIntBits(data[i])) ^ l2 * a + l1;
2313            }
2314            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2315        }
2316
2317        public int hash(final double[] data) {
2318            if (data == null)
2319                return 0;
2320            final int len = data.length;
2321            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2322            for (int i = 0; i < len; i++) {
2323                result += (a ^= 0x8329C6EB9E6AD3E3L * NumberTools.doubleToMixedIntBits(data[i])) ^ l2 * a + l1;
2324            }
2325            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2326        }
2327
2328        /**
2329         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2330         *
2331         * @param data  the char array to hash
2332         * @param start the start of the section to hash (inclusive)
2333         * @param end   the end of the section to hash (exclusive)
2334         * @return a 32-bit hash code for the requested section of data
2335         */
2336        public int hash(final char[] data, final int start, final int end) {
2337            if (data == null || start >= end)
2338                return 0;
2339            final int len = data.length;
2340            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2341            for (int i = start; i < end && i < len; i++) {
2342                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2343            }
2344            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2345        }
2346        /**
2347         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
2348         * moving between chars in increments of step (which is always greater than 0).
2349         *
2350         * @param data  the char array to hash
2351         * @param start the start of the section to hash (inclusive)
2352         * @param end   the end of the section to hash (exclusive)
2353         * @param step  how many elements to advance after using one element from data; must be greater than 0
2354         * @return a 32-bit hash code for the requested section of data
2355         */
2356        public int hash(final char[] data, final int start, final int end, final int step) {
2357            if (data == null || start >= end || step <= 0)
2358                return 0;
2359            final int len = data.length;
2360            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2361            for (int i = start; i < end && i < len; i += step) {
2362                result += (a ^= 0x8329C6EB9E6AD3E3L * data[i]) ^ l2 * a + l1;
2363            }
2364            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2365        }
2366
2367        public int hash(final CharSequence data) {
2368            if (data == null)
2369                return 0;
2370            final int len = data.length();
2371            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2372            for (int i = 0; i < len; i++) {
2373                result += (a ^= 0x8329C6EB9E6AD3E3L * data.charAt(i)) ^ l2 * a + l1;
2374            }
2375            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2376        }
2377
2378        public int hash(final char[][] data) {
2379            if (data == null)
2380                return 0;
2381            final int len = data.length;
2382            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2383            for (int i = 0; i < len; i++) {
2384                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2385            }
2386            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2387        }
2388
2389        public int hash(final long[][] data) {
2390            if (data == null)
2391                return 0;
2392            final int len = data.length;
2393            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2394            for (int i = 0; i < len; i++) {
2395                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2396            }
2397            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2398        }
2399
2400        public int hash(final CharSequence[] data) {
2401            if (data == null)
2402                return 0;
2403            final int len = data.length;
2404            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2405            for (int i = 0; i < len; i++) {
2406                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2407            }
2408            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2409        }
2410
2411        public int hash(final Iterable<? extends CharSequence> data) {
2412            if (data == null)
2413                return 0;
2414            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2415            for (CharSequence datum : data) {
2416                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(datum)) ^ l2 * a + l1;
2417            }
2418            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2419        }
2420
2421        public int hash(final CharSequence[]... data) {
2422            if (data == null)
2423                return 0;
2424            final int len = data.length;
2425            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2426            for (int i = 0; i < len; i++) {
2427                result += (a ^= 0x8329C6EB9E6AD3E3L * hash64(data[i])) ^ l2 * a + l1;
2428            }
2429            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2430        }
2431
2432        public int hash(final Object[] data) {
2433            if (data == null)
2434                return 0;
2435            final int len = data.length;
2436            long result = 0x9E3779B97F4A7C94L + l2, a = 0x632BE59BD9B4E019L;
2437            Object o;
2438            for (int i = 0; i < len; i++) {
2439                result += (a ^= 0x8329C6EB9E6AD3E3L * ((o = data[i]) == null ? -1 : o.hashCode())) ^ l2 * a + l1;
2440            }
2441            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2442        }
2443
2444        public int hash(final Object data) {
2445            if (data == null)
2446                return 0;
2447            final long a = 0x632BE59BD9B4E019L ^ 0x8329C6EB9E6AD3E3L * data.hashCode(),
2448                    result = 0x9E3779B97F4A7C94L + l2 + (a ^ l2 * a + l1);
2449            return (int)(result * (a * l1 | 1L) ^ (result << 37 | result >>> 27));
2450        }
2451    }
2452
2453    /**
2454     * A reasonably-fast hashing function that passes some of SMHasher's quality tests, but neither critically fails nor
2455     * overwhelmingly succeeds the full SMHasher test battery. This was the default used by methods in the
2456     * outer class like {@link CrossHash#hash(int[])}, but it has been replaced there by {@link Water}; you should
2457     * prefer using the outer class since this inner class is only here for reference. The one advantage Hive has over
2458     * Water is potentially better optimization for GWT, but since the main usage of CrossHash is for 64-bit hashes, GWT
2459     * will be slow regardless for that usage.
2460     * <br>
2461     * This mixes three different algorithms: the main one is used whenever inputs or outputs are 64-bit (so, all
2462     * hash64() overloads and {@link Hive#hash(long[])} for long and double), a modification of the main one to perform
2463     * better on GWT (only used on hash() overloads, and only when inputs are individually 32-bit or less), and
2464     * a simpler algorithm (which was called Jolt) for hash64() on boolean and byte data.
2465     * <br>
2466     * Speed-wise, the main algorithm is about 20% slower than Wisp, but in hash tables it doesn't have clear failure 
2467     * cases like Wisp does on some inputs (such as fixed-length Strings with identical prefixes). If collisions are
2468     * expensive or profiling shows that Wisp's algorithm is colliding at a high rate, you should probably use the
2469     * normal IHasher and CrossHash.hash() methods, since those will use Hive. The modified algorithm for GWT is a
2470     * little slower than the main algorithm in the C++ implementation that was used to check SMHasher quality, but it
2471     * may perform similarly to the main algorithm in Java on desktop platforms. Since it avoids creating longs or doing
2472     * any math on them, it should be at least 3x faster than the main algorithm on GWT (a GWT long is internally
2473     * represented by 3 JS numbers, so barring special optimizations it takes at least 3x as many math operations to use
2474     * longs there).
2475     * <br>
2476     * Its design uses two states like {@link Lightning} or {@link Wisp}, updating them differently from each other, and
2477     * bitwise-rotates one at each step. It combines the states (xorshifting one state, multiplying it by a huge
2478     * constant, and adding that to the other state) and then runs that through MurmurHash3's finalization function (its
2479     * {@code fmix64()} function; the main algorithm elides one xorshift at the end that proved unnecessary). Parts of
2480     * the code here are inspired by the design of {@link DiverRNG}, particularly its determine() method since both
2481     * use an XLCG (XOR Linear Congruential Generator, as PractRand calls it) as a processing step.
2482     * <br>
2483     * The name comes from the song I was listening to when I finally got the tests to pass ("Slave The Hive" by High On
2484     * Fire) and from the wide assortment of code that I had to employ to achieve a SMHasher successful run (which
2485     * turned out to be not-so-successful).
2486     */
2487    public static final class Hive {
2488        public static long hash64(final CharSequence data) {
2489            if (data == null)
2490                return 0L;
2491            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2492            final int len = data.length();
2493            for (int i = 0; i < len; i++) {
2494                result ^= (z += (data.charAt(i) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2495                result = (result << 54 | result >>> 10);
2496            }
2497            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2498            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2499            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2500        }
2501
2502        public static long hash64(final boolean[] data) {
2503            if (data == null)
2504                return 0L;
2505            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2506            final int len = data.length;
2507            for (int i = 0; i < len; i++) {
2508                result ^= (z += (data[i] ? 0xFF51AFD7ED558CCDL : 0xC4CEB9FE1A85EC53L));
2509            }
2510            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2511            result ^= result >>> 25 ^ z ^ z >>> 29;
2512            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2513            result = (result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L;
2514            return (result ^ result >>> 33);
2515        }
2516
2517        public static long hash64(final byte[] data) {
2518            if (data == null)
2519                return 0L;
2520            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2521            final int len = data.length;
2522            for (int i = 0; i < len; i++) {
2523                result ^= (z += (data[i] ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L);
2524            }
2525            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2526            result ^= result >>> 25 ^ z ^ z >>> 29;
2527            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2528            result = (result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L;
2529            return (result ^ result >>> 33);
2530        }
2531
2532        public static long hash64(final short[] data) {
2533            if (data == null)
2534                return 0L;
2535            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2536            final int len = data.length;
2537            for (int i = 0; i < len; i++) {
2538                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2539                result = (result << 54 | result >>> 10);
2540            }
2541            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2542            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2543            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2544        }
2545
2546        public static long hash64(final int[] data) {
2547            if (data == null)
2548                return 0L;
2549            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2550            final int len = data.length;
2551            for (int i = 0; i < len; i++) {
2552                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2553                result = (result << 54 | result >>> 10);
2554            }
2555            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2556            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2557            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2558        }
2559
2560        public static long hash64(final long[] data) {
2561            if (data == null)
2562                return 0L;
2563            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2564            final int len = data.length;
2565            for (int i = 0; i < len; i++) {
2566                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2567                result = (result << 54 | result >>> 10);
2568            }
2569            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2570            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2571            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2572        }
2573
2574        public static long hash64(final char[] data) {
2575            if (data == null)
2576                return 0L;
2577            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2578            final int len = data.length;
2579            for (int i = 0; i < len; i++) {
2580                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2581                result = (result << 54 | result >>> 10);
2582            }
2583            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2584            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2585            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2586        }
2587
2588        public static long hash64(final float[] data) {
2589            if (data == null)
2590                return 0L;
2591            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2592            final int len = data.length;
2593            for (int i = 0; i < len; i++) {
2594                result ^= (z += (floatToIntBits(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2595                result = (result << 54 | result >>> 10);
2596            }
2597            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2598            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2599            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2600        }
2601
2602        public static long hash64(final double[] data) {
2603            if (data == null)
2604                return 0L;
2605            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2606            final int len = data.length;
2607            for (int i = 0; i < len; i++) {
2608                result ^= (z += (NumberTools.doubleToLongBits(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2609                result = (result << 54 | result >>> 10);
2610            }
2611            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2612            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2613            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2614        }
2615
2616        /**
2617         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2618         *
2619         * @param data  the char array to hash
2620         * @param start the start of the section to hash (inclusive)
2621         * @param end   the end of the section to hash (exclusive)
2622         * @return a 32-bit hash code for the requested section of data
2623         */
2624        public static long hash64(final char[] data, final int start, final int end) {
2625            if (data == null || start >= end)
2626                return 0L;
2627            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2628            final int len = Math.min(end, data.length);
2629            for (int i = start; i < len; i++) {
2630                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2631                result = (result << 54 | result >>> 10);
2632            }
2633            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2634            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2635            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2636        }
2637
2638        /**
2639         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2640         *
2641         * @param data  the String or other CharSequence to hash
2642         * @param start the start of the section to hash (inclusive)
2643         * @param end   the end of the section to hash (exclusive)
2644         * @return a 32-bit hash code for the requested section of data
2645         */
2646        public static long hash64(final CharSequence data, final int start, final int end) {
2647            if (data == null || start >= end)
2648                return 0L;
2649            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2650            final int len = Math.min(end, data.length());
2651            for (int i = start; i < len; i++) {
2652                result ^= (z += (data.charAt(i) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2653                result = (result << 54 | result >>> 10);
2654            }
2655            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2656            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2657            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2658        }
2659
2660        /**
2661         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
2662         * moving between chars in increments of step (which is always greater than 0).
2663         *
2664         * @param data  the char array to hash
2665         * @param start the start of the section to hash (inclusive)
2666         * @param end   the end of the section to hash (exclusive)
2667         * @param step  how many elements to advance after using one element from data; must be greater than 0
2668         * @return a 32-bit hash code for the requested section of data
2669         */
2670        public static long hash64(final char[] data, final int start, final int end, final int step) {
2671            if (data == null || start >= end || step <= 0)
2672                return 0L;
2673            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2674            final int len = Math.min(end, data.length);
2675            for (int i = start; i < len; i += step) {
2676                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2677                result = (result << 54 | result >>> 10);
2678            }
2679            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2680            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2681            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2682        }
2683
2684        /**
2685         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
2686         * moving between chars in increments of step (which is always greater than 0).
2687         *
2688         * @param data  the String or other CharSequence to hash
2689         * @param start the start of the section to hash (inclusive)
2690         * @param end   the end of the section to hash (exclusive)
2691         * @param step  how many elements to advance after using one element from data; must be greater than 0
2692         * @return a 32-bit hash code for the requested section of data
2693         */
2694        public static long hash64(final CharSequence data, final int start, final int end, final int step) {
2695            if (data == null || start >= end || step <= 0)
2696                return 0L;
2697            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2698            final int len = Math.min(end, data.length());
2699            for (int i = start; i < len; i += step) {
2700                result ^= (z += (data.charAt(i) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2701                result = (result << 54 | result >>> 10);
2702            }
2703            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2704            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2705            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2706        }
2707
2708        public static long hash64(final char[][] data) {
2709            if (data == null)
2710                return 0L;
2711            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2712            final int len = data.length;
2713            for (int i = 0; i < len; i++) {
2714                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2715                result = (result << 54 | result >>> 10);
2716            }
2717            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2718            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2719            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2720        }
2721
2722        public static long hash64(final int[][] data) {
2723            if (data == null)
2724                return 0L;
2725            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2726            final int len = data.length;
2727            for (int i = 0; i < len; i++) {
2728                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2729                result = (result << 54 | result >>> 10);
2730            }
2731            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2732            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2733            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2734        }
2735
2736        public static long hash64(final long[][] data) {
2737            if (data == null)
2738                return 0L;
2739            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2740            final int len = data.length;
2741            for (int i = 0; i < len; i++) {
2742                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2743                result = (result << 54 | result >>> 10);
2744            }
2745            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2746            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2747            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2748        }
2749
2750        public static long hash64(final CharSequence[] data) {
2751            if (data == null)
2752                return 0L;
2753            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2754            final int len = data.length;
2755            for (int i = 0; i < len; i++) {
2756                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2757                result = (result << 54 | result >>> 10);
2758            }
2759            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2760            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2761            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2762        }
2763
2764        public static long hash64(final CharSequence[]... data) {
2765            if (data == null)
2766                return 0L;
2767            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2768            final int len = data.length;
2769            for (int i = 0; i < len; i++) {
2770                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2771                result = (result << 54 | result >>> 10);
2772            }
2773            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2774            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2775            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2776        }
2777
2778        public static long hash64(final Iterable<? extends CharSequence> data) {
2779            if (data == null)
2780                return 0L;
2781            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2782            for (CharSequence datum : data) {
2783                result ^= (z += (hash64(datum) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2784                result = (result << 54 | result >>> 10);
2785            }
2786            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2787            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2788            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2789
2790        }
2791
2792        public static long hash64(final List<? extends CharSequence> data) {
2793            if (data == null)
2794                return 0L;
2795            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2796            final int len = data.size();
2797            for (int i = 0; i < len; i++) {
2798                result ^= (z += (hash64(data.get(i)) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2799                result = (result << 54 | result >>> 10);
2800            }
2801            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2802            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2803            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2804
2805        }
2806
2807        public static long hash64(final Object[] data) {
2808            if (data == null)
2809                return 0L;
2810            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2811            final int len = data.length;
2812            Object o;
2813            for (int i = 0; i < len; i++) {
2814                result ^= (z += (((o = data[i]) == null ? -1L : o.hashCode()) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2815                result = (result << 54 | result >>> 10);
2816            }
2817            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2818            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2819            return ((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2820        }
2821
2822        public static long hash64(final Object data) {
2823            if (data == null)
2824                return 0L;
2825            long result = data.hashCode() * 0xFF51AFD7ED558CCDL;
2826            result = (result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L;
2827            return (result ^ result >>> 33);
2828        }
2829
2830
2831        public static int hash(final CharSequence data) {
2832            if (data == null)
2833                return 0;
2834            int result = 0x1A976FDF, z = 0x60642E25;
2835            final int len = data.length();
2836            for (int i = 0; i < len; i++) {
2837                result ^= (z += (data.charAt(i) ^ 0xC3564E95) * 0x9E375);
2838                z ^= (result = (result << 20 | result >>> 12));
2839            }
2840            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2841            result = (result ^ result >>> 15) * 0xFF51D;
2842            result = (result ^ result >>> 15) * 0xC4CEB;
2843            return result ^ result >>> 15;
2844        }
2845
2846        public static int hash(final boolean[] data) {
2847            if (data == null)
2848                return 0;
2849            int result = 0x1A976FDF, z = 0x60642E25;
2850            final int len = data.length;
2851            for (int i = 0; i < len; i++) {
2852                result ^= (z += (data[i] ? 0x6F51AFDB : 0xC3564E95));
2853                z ^= (result = (result << 20 | result >>> 12));
2854            }
2855            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2856            result = (result ^ result >>> 15) * 0xFF51D;
2857            result = (result ^ result >>> 15) * 0xC4CEB;
2858            return result ^ result >>> 15;
2859        }
2860
2861        public static int hash(final byte[] data) {
2862            if (data == null)
2863                return 0;
2864            int result = 0x1A976FDF, z = 0x60642E25;
2865            final int len = data.length;
2866            for (int i = 0; i < len; i++) {
2867                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
2868                z ^= (result = (result << 20 | result >>> 12));
2869            }
2870            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2871            result = (result ^ result >>> 15) * 0xFF51D;
2872            result = (result ^ result >>> 15) * 0xC4CEB;
2873            return result ^ result >>> 15;
2874        }
2875
2876        public static int hash(final short[] data) {
2877            if (data == null)
2878                return 0;
2879            int result = 0x1A976FDF, z = 0x60642E25;
2880            final int len = data.length;
2881            for (int i = 0; i < len; i++) {
2882                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
2883                z ^= (result = (result << 20 | result >>> 12));
2884            }
2885            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2886            result = (result ^ result >>> 15) * 0xFF51D;
2887            result = (result ^ result >>> 15) * 0xC4CEB;
2888            return result ^ result >>> 15;
2889        }
2890
2891        public static int hash(final int[] data) {
2892            if (data == null)
2893                return 0;
2894            int result = 0x1A976FDF, z = 0x60642E25;
2895            final int len = data.length;
2896            for (int i = 0; i < len; i++) {
2897                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
2898                z ^= (result = (result << 20 | result >>> 12));
2899            }
2900            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2901            result = (result ^ result >>> 15) * 0xFF51D;
2902            result = (result ^ result >>> 15) * 0xC4CEB;
2903            return result ^ result >>> 15;
2904        }
2905
2906        public static int hash(final long[] data) {
2907            if (data == null)
2908                return 0;
2909            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2910            final int len = data.length;
2911            for (int i = 0; i < len; i++) {
2912                result ^= (z += (data[i] ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2913                result = (result << 54 | result >>> 10);
2914            }
2915            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2916            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2917            return (int)((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2918        }
2919
2920        public static int hash(final char[] data) {
2921            if (data == null)
2922                return 0;
2923            int result = 0x1A976FDF, z = 0x60642E25;
2924            final int len = data.length;
2925            for (int i = 0; i < len; i++) {
2926                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
2927                z ^= (result = (result << 20 | result >>> 12));
2928            }
2929            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2930            result = (result ^ result >>> 15) * 0xFF51D;
2931            result = (result ^ result >>> 15) * 0xC4CEB;
2932            return result ^ result >>> 15;
2933        }
2934
2935        public static int hash(final float[] data) {
2936            if (data == null)
2937                return 0;
2938            int result = 0x1A976FDF, z = 0x60642E25;
2939            final int len = data.length;
2940            for (int i = 0; i < len; i++) {
2941                result ^= (z += (floatToIntBits(data[i]) ^ 0xC3564E95) * 0x9E375);
2942                z ^= (result = (result << 20 | result >>> 12));
2943            }
2944            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2945            result = (result ^ result >>> 15) * 0xFF51D;
2946            result = (result ^ result >>> 15) * 0xC4CEB;
2947            return result ^ result >>> 15;
2948
2949        }
2950
2951        public static int hash(final double[] data) {
2952            if (data == null)
2953                return 0;
2954            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
2955            final int len = data.length;
2956            for (int i = 0; i < len; i++) {
2957                result ^= (z += (NumberTools.doubleToLongBits(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
2958                result = (result << 54 | result >>> 10);
2959            }
2960            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
2961            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
2962            return (int)((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
2963        }
2964
2965        /**
2966         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2967         *
2968         * @param data  the char array to hash
2969         * @param start the start of the section to hash (inclusive)
2970         * @param end   the end of the section to hash (exclusive)
2971         * @return a 32-bit hash code for the requested section of data
2972         */
2973        public static int hash(final char[] data, final int start, final int end) {
2974            if (data == null || start >= end)
2975                return 0;
2976            int result = 0x1A976FDF, z = 0x60642E25;
2977            final int len = Math.min(end, data.length);
2978            for (int i = start; i < len; i++) {
2979                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
2980                z ^= (result = (result << 20 | result >>> 12));
2981            }
2982            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
2983            result = (result ^ result >>> 15) * 0xFF51D;
2984            result = (result ^ result >>> 15) * 0xC4CEB;
2985            return result ^ result >>> 15;
2986        }
2987
2988        /**
2989         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
2990         *
2991         * @param data  the String or other CharSequence to hash
2992         * @param start the start of the section to hash (inclusive)
2993         * @param end   the end of the section to hash (exclusive)
2994         * @return a 32-bit hash code for the requested section of data
2995         */
2996        public static int hash(final CharSequence data, final int start, final int end) {
2997            if (data == null || start >= end)
2998                return 0;
2999            int result = 0x1A976FDF, z = 0x60642E25;
3000            final int len = Math.min(end, data.length());
3001            for (int i = start; i < len; i++) {
3002                result ^= (z += (data.charAt(i) ^ 0xC3564E95) * 0x9E375);
3003                z ^= (result = (result << 20 | result >>> 12));
3004            }
3005            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3006            result = (result ^ result >>> 15) * 0xFF51D;
3007            result = (result ^ result >>> 15) * 0xC4CEB;
3008            return result ^ result >>> 15;
3009        }
3010
3011        /**
3012         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
3013         * moving between chars in increments of step (which is always greater than 0).
3014         *
3015         * @param data  the char array to hash
3016         * @param start the start of the section to hash (inclusive)
3017         * @param end   the end of the section to hash (exclusive)
3018         * @param step  how many elements to advance after using one element from data; must be greater than 0
3019         * @return a 32-bit hash code for the requested section of data
3020         */
3021        public static int hash(final char[] data, final int start, final int end, final int step) {
3022            if (data == null || start >= end || step <= 0)
3023                return 0;
3024            int result = 0x1A976FDF, z = 0x60642E25;
3025            final int len = Math.min(end, data.length);
3026            for (int i = start; i < len; i += step) {
3027                result ^= (z += (data[i] ^ 0xC3564E95) * 0x9E375);
3028                z ^= (result = (result << 20 | result >>> 12));
3029            }
3030            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3031            result = (result ^ result >>> 15) * 0xFF51D;
3032            result = (result ^ result >>> 15) * 0xC4CEB;
3033            return result ^ result >>> 15;
3034        }
3035
3036        /**
3037         * Hashes only a subsection of the given data, starting at start (inclusive), ending before end (exclusive), and
3038         * moving between chars in increments of step (which is always greater than 0).
3039         *
3040         * @param data  the String or other CharSequence to hash
3041         * @param start the start of the section to hash (inclusive)
3042         * @param end   the end of the section to hash (exclusive)
3043         * @param step  how many elements to advance after using one element from data; must be greater than 0
3044         * @return a 32-bit hash code for the requested section of data
3045         */
3046        public static int hash(final CharSequence data, final int start, final int end, final int step) {
3047            if (data == null || start >= end || step <= 0)
3048                return 0;
3049            int result = 0x1A976FDF, z = 0x60642E25;
3050            final int len = Math.min(end, data.length());
3051            for (int i = start; i < len; i += step) {
3052                result ^= (z += (data.charAt(i) ^ 0xC3564E95) * 0x9E375);
3053                z ^= (result = (result << 20 | result >>> 12));
3054            }
3055            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3056            result = (result ^ result >>> 15) * 0xFF51D;
3057            result = (result ^ result >>> 15) * 0xC4CEB;
3058            return result ^ result >>> 15;
3059        }
3060
3061        public static int hash(final char[][] data) {
3062            if (data == null)
3063                return 0;
3064            int result = 0x1A976FDF, z = 0x60642E25;
3065            final int len = data.length;
3066            for (int i = 0; i < len; i++) {
3067                result ^= (z += (hash(data[i]) ^ 0xC3564E95) * 0x9E375);
3068                z ^= (result = (result << 20 | result >>> 12));
3069            }
3070            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3071            result = (result ^ result >>> 15) * 0xFF51D;
3072            result = (result ^ result >>> 15) * 0xC4CEB;
3073            return result ^ result >>> 15;
3074        }
3075
3076        public static int hash(final int[][] data) {
3077            if (data == null)
3078                return 0;
3079            int result = 0x1A976FDF, z = 0x60642E25;
3080            final int len = data.length;
3081            for (int i = 0; i < len; i++) {
3082                result ^= (z += (hash(data[i]) ^ 0xC3564E95) * 0x9E375);
3083                z ^= (result = (result << 20 | result >>> 12));
3084            }
3085            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3086            result = (result ^ result >>> 15) * 0xFF51D;
3087            result = (result ^ result >>> 15) * 0xC4CEB;
3088            return result ^ result >>> 15;
3089        }
3090
3091        public static int hash(final long[][] data) {
3092            if (data == null)
3093                return 0;
3094            long result = 0x1A976FDF6BF60B8EL, z = 0x60642E2A34326F15L;
3095            final int len = data.length;
3096            for (int i = 0; i < len; i++) {
3097                result ^= (z += (hash64(data[i]) ^ 0xC6BC279692B5CC85L) * 0x6C8E9CF570932BABL);
3098                result = (result << 54 | result >>> 10);
3099            }
3100            result += (z ^ z >>> 26) * 0x632BE59BD9B4E019L;
3101            result = (result ^ result >>> 33) * 0xFF51AFD7ED558CCDL;
3102            return (int)((result ^ result >>> 33) * 0xC4CEB9FE1A85EC53L);
3103        }
3104
3105        public static int hash(final CharSequence[] data) {
3106            if (data == null)
3107                return 0;
3108            int result = 0x1A976FDF, z = 0x60642E25;
3109            final int len = data.length;
3110            for (int i = 0; i < len; i++) {
3111                result ^= (z += (hash(data[i]) ^ 0xC3564E95) * 0x9E375);
3112                z ^= (result = (result << 20 | result >>> 12));
3113            }
3114            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3115            result = (result ^ result >>> 15) * 0xFF51D;
3116            result = (result ^ result >>> 15) * 0xC4CEB;
3117            return result ^ result >>> 15;
3118        }
3119
3120        public static int hash(final CharSequence[]... data) {
3121            if (data == null)
3122                return 0;
3123            int result = 0x1A976FDF, z = 0x60642E25;
3124            final int len = data.length;
3125            for (int i = 0; i < len; i++) {
3126                result ^= (z += (hash(data[i]) ^ 0xC3564E95) * 0x9E375);
3127                z ^= (result = (result << 20 | result >>> 12));
3128            }
3129            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3130            result = (result ^ result >>> 15) * 0xFF51D;
3131            result = (result ^ result >>> 15) * 0xC4CEB;
3132            return result ^ result >>> 15;
3133        }
3134
3135        public static int hash(final Iterable<? extends CharSequence> data) {
3136            if (data == null)
3137                return 0;
3138            int result = 0x1A976FDF, z = 0x60642E25;
3139            for (CharSequence datum : data) {
3140                result ^= (z += (hash(datum) ^ 0xC3564E95) * 0x9E375);
3141                z ^= (result = (result << 20 | result >>> 12));
3142            }
3143            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3144            result = (result ^ result >>> 15) * 0xFF51D;
3145            result = (result ^ result >>> 15) * 0xC4CEB;
3146            return result ^ result >>> 15;
3147
3148        }
3149
3150        public static int hash(final List<? extends CharSequence> data) {
3151            if (data == null)
3152                return 0;
3153            int result = 0x1A976FDF, z = 0x60642E25;
3154            final int len = data.size();
3155            for (int i = 0; i < len; i++) {
3156                result ^= (z += (hash(data.get(i)) ^ 0xC3564E95) * 0x9E375);
3157                z ^= (result = (result << 20 | result >>> 12));
3158            }
3159            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3160            result = (result ^ result >>> 15) * 0xFF51D;
3161            result = (result ^ result >>> 15) * 0xC4CEB;
3162            return result ^ result >>> 15;
3163
3164        }
3165
3166        public static int hash(final Object[] data) {
3167            if (data == null)
3168                return 0;
3169            int result = 0x1A976FDF, z = 0x60642E25;
3170            final int len = data.length;
3171            Object o;
3172            for (int i = 0; i < len; i++) {
3173                result ^= (z += (((o = data[i]) == null ? -1 : o.hashCode()) ^ 0xC3564E95) * 0x9E375);
3174                z ^= (result = (result << 20 | result >>> 12));
3175            }
3176            result += (z ^ z >>> 15 ^ 0xAE932BD5) * 0x632B9;
3177            result = (result ^ result >>> 15) * 0xFF51D;
3178            result = (result ^ result >>> 15) * 0xC4CEB;
3179            return result ^ result >>> 15;
3180        }
3181
3182        public static int hash(final Object data) {
3183            if (data == null)
3184                return 0;
3185            final int h = data.hashCode() * 0x9E375;
3186            return h ^ (h >>> 16);
3187        }
3188    }
3189
3190
3191    /**
3192     * A fairly fast hashing algorithm in general, Water performs especially well on large arrays, and passes SMHasher's
3193     * newest and most stringent version of tests. The int-hashing {@link #hash(int[])} method is almost twice as fast
3194     * as {@link Hive#hash(int[])} and faster than {@link Arrays#hashCode(int[])}; on longer arrays
3195     * {@link Curlup#hash(int[])} is faster. Based on <a href="https://github.com/wangyi-fudan/wyhash">wyhash</a>,
3196     * specifically <a href="https://github.com/tommyettinger/waterhash">the waterhash variant</a>. This version passes
3197     * SMHasher for both the 32-bit output hash() methods and the 64-bit output hash64() methods (which use the slightly
3198     * tweaked wheathash variant in the waterhash Git repo, or woothash for hashing long arrays). While an earlier
3199     * version passed rurban/smhasher, it failed demerphq/smhasher (Yves' more stringent fork), so some minor tweaks
3200     * allowed the latest code to pass Yves' test. Uses 64-bit math, so it won't be as fast on GWT. Currently, the
3201     * methods that hash types other than int arrays aren't as fast as the int array hash, but they are usually faster
3202     * than the former default Hive implementation, and unlike Hive, these pass SMHasher. If you want to have a seed the
3203     * hash, so hashing the same data with a different seed produces different output, you can use {@link Yolk} or
3204     * {@link Curlup}, preferring Curlup unless all of your data is in small arrays (under 20 length, give or take).
3205     * <br>
3206     * These hash functions are so fast because they operate in bulk on 4 items at a time, such as 4 ints (which is the
3207     * optimal case), 4 bytes, or 4 longs (which uses a different algorithm). This bulk operation usually entails 3
3208     * multiplications and some other, cheaper operations per 4 items hashed. For long arrays, it requires many more
3209     * multiplications, but modern CPUs can pipeline the operations on unrelated longs to run in parallel on one core.
3210     * If any items are left over after the bulk segment, Water uses the least effort possible to hash the remaining 1,
3211     * 2, or 3 items left. Most of these operations use the method {@link #mum(long, long)}, which helps take two inputs
3212     * and multiply them once, getting a more-random result after another small step. The long array code uses
3213     * {@link #wow(long, long)} (similar to mum upside-down), which mixes up its arguments with each other before
3214     * multplying. It finishes with either code similar to mum() for 32-bit output hash() methods, or a somewhat more
3215     * rigorous method for 64-bit output hash64() methods (still similar to mum).
3216     */
3217    public static final class Water {
3218        /**
3219         * Big constant 0.
3220         */
3221        public static final long b0 = 0xA0761D6478BD642FL;
3222        /**
3223         * Big constant 1.
3224         */
3225        public static final long b1 = 0xE7037ED1A0B428DBL;
3226        /**
3227         * Big constant 2.
3228         */
3229        public static final long b2 = 0x8EBC6AF09C88C6E3L;
3230        /**
3231         * Big constant 3.
3232         */
3233        public static final long b3 = 0x589965CC75374CC3L;
3234        /**
3235         * Big constant 4.
3236         */
3237        public static final long b4 = 0x1D8E4E27C47D124FL;
3238        /**
3239         * Big constant 5.
3240         */
3241        public static final long b5 = 0xEB44ACCAB455D165L;
3242
3243        /**
3244         * Takes two arguments that are technically longs, and should be very different, and uses them to get a result
3245         * that is technically a long and mixes the bits of the inputs. The arguments and result are only technically
3246         * longs because their lower 32 bits matter much more than their upper 32, and giving just any long won't work.
3247         * <br>
3248         * This is very similar to wyhash's mum function, but doesn't use 128-bit math because it expects that its
3249         * arguments are only relevant in their lower 32 bits (allowing their product to fit in 64 bits).
3250         * @param a a long that should probably only hold an int's worth of data
3251         * @param b a long that should probably only hold an int's worth of data
3252         * @return a sort-of randomized output dependent on both inputs
3253         */
3254        public static long mum(final long a, final long b) {
3255            final long n = a * b;
3256            return n - (n >>> 32);
3257        }
3258
3259        /**
3260         * A slower but higher-quality variant on {@link #mum(long, long)} that can take two arbitrary longs (with any
3261         * of their 64 bits containing relevant data) instead of mum's 32-bit sections of its inputs, and outputs a
3262         * 64-bit result that can have any of its bits used.
3263         * <br>
3264         * This was changed so it distributes bits from both inputs a little better on July 6, 2019.
3265         * @param a any long
3266         * @param b any long
3267         * @return a sort-of randomized output dependent on both inputs
3268         */
3269        public static long wow(final long a, final long b) {
3270            final long n = (a ^ (b << 39 | b >>> 25)) * (b ^ (a << 39 | a >>> 25));
3271            return n ^ (n >>> 32);
3272        }
3273
3274        public static long hash64(final boolean[] data) {
3275            if (data == null) return 0;
3276            long seed = 9069147967908697017L;//seed = b1 ^ b1 >>> 29 ^ b1 >>> 43 ^ b1 << 7 ^ b1 << 53;
3277            final int len = data.length;
3278            for (int i = 3; i < len; i+=4) {
3279                seed = mum(
3280                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
3281                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
3282            }
3283            switch (len & 3) {
3284                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3285                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
3286                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
3287                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
3288            }
3289            seed = (seed ^ seed << 16) * (len ^ b0);
3290            return seed - (seed >>> 31) + (seed << 33);
3291        }
3292        public static long hash64(final byte[] data) {
3293            if (data == null) return 0;
3294            long seed = 9069147967908697017L;
3295            final int len = data.length;
3296            for (int i = 3; i < len; i+=4) {
3297                seed = mum(
3298                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3299                        mum(data[i-1] ^ b3, data[i] ^ b4));
3300            }
3301            switch (len & 3) {
3302                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3303                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
3304                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
3305                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
3306            }
3307            seed = (seed ^ seed << 16) * (len ^ b0);
3308            return seed - (seed >>> 31) + (seed << 33);
3309        }
3310
3311        public static long hash64(final short[] data) {
3312            if (data == null) return 0;
3313            long seed = 9069147967908697017L;
3314            final int len = data.length;
3315            for (int i = 3; i < len; i+=4) {
3316                seed = mum(
3317                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3318                        mum(data[i-1] ^ b3, data[i] ^ b4));
3319            }
3320            switch (len & 3) {
3321                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3322                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3323                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3324                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3325            }
3326            seed = (seed ^ seed << 16) * (len ^ b0);
3327            return seed - (seed >>> 31) + (seed << 33);
3328        }
3329
3330        public static long hash64(final char[] data) {
3331            if (data == null) return 0;
3332            long seed = 9069147967908697017L;
3333            final int len = data.length;
3334            for (int i = 3; i < len; i+=4) {
3335                seed = mum(
3336                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3337                        mum(data[i-1] ^ b3, data[i] ^ b4));
3338            }
3339            switch (len & 3) {
3340                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3341                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3342                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3343                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3344            }
3345            seed = (seed ^ seed << 16) * (len ^ b0);
3346            return seed - (seed >>> 31) + (seed << 33);
3347        }
3348
3349        public static long hash64(final CharSequence data) {
3350            if (data == null) return 0;
3351            long seed = 9069147967908697017L;
3352            final int len = data.length();
3353            for (int i = 3; i < len; i+=4) {
3354                seed = mum(
3355                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
3356                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
3357            }
3358            switch (len & 3) {
3359                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3360                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
3361                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
3362                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
3363            }
3364            seed = (seed ^ seed << 16) * (len ^ b0);
3365            return seed - (seed >>> 31) + (seed << 33);
3366        }
3367
3368        public static long hash64(final int[] data) {
3369            if (data == null) return 0;
3370            long seed = 9069147967908697017L;
3371            final int len = data.length;
3372            for (int i = 3; i < len; i+=4) {
3373                seed = mum(
3374                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3375                        mum(data[i-1] ^ b3, data[i] ^ b4));
3376            }
3377            switch (len & 3) {
3378                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3379                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
3380                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
3381                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
3382            }
3383            seed = (seed ^ seed << 16) * (len ^ b0);
3384            return seed - (seed >>> 31) + (seed << 33);
3385        }
3386
3387        public static long hash64(final int[] data, final int length) {
3388            if (data == null) return 0;
3389            long seed = 9069147967908697017L;
3390            for (int i = 3; i < length; i+=4) {
3391                seed = mum(
3392                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3393                        mum(data[i-1] ^ b3, data[i] ^ b4));
3394            }
3395            switch (length & 3) {
3396                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3397                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
3398                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
3399                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
3400            }
3401            seed = (seed ^ seed << 16) * (length ^ b0);
3402            return seed - (seed >>> 31) + (seed << 33);
3403        }
3404
3405        public static long hash64(final long[] data) {
3406            if (data == null) return 0;
3407//          long seed = b0 ^ b0 >>> 23 ^ b0 >>> 48 ^ b0 << 7 ^ b0 << 53, 
3408//                    a = seed + b4, b = seed + b3,
3409//                    c = seed + b2, d = seed + b1;
3410            long seed = 0x1E98AE18CA351B28L,
3411                    a = 0x3C26FC408EB22D77L, b = 0x773213E53F6C67EBL,
3412                    c = 0xAD55190966BDE20BL, d = 0x59C2CEA6AE94403L;
3413            final int len = data.length;
3414            for (int i = 3; i < len; i+=4) {
3415                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
3416                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
3417                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
3418                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
3419                seed += a + b + c + d;
3420            }
3421            seed += b5;
3422            switch (len & 3) {
3423                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
3424                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
3425                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
3426            }
3427            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
3428            return seed - (seed >>> 31) + (seed << 33);
3429        }
3430        public static long hash64(final float[] data) {
3431            if (data == null) return 0;
3432            long seed = 9069147967908697017L;
3433            final int len = data.length;
3434            for (int i = 3; i < len; i+=4) {
3435                seed = mum(
3436                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
3437                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
3438            }
3439            switch (len & 3) {
3440                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3441                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
3442                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
3443                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
3444            }
3445            seed = (seed ^ seed << 16) * (len ^ b0);
3446            return seed - (seed >>> 31) + (seed << 33);
3447        }
3448        public static long hash64(final double[] data) {
3449            if (data == null) return 0;
3450            long seed = 9069147967908697017L;
3451            final int len = data.length;
3452            for (int i = 3; i < len; i+=4) {
3453                seed = mum(
3454                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
3455                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
3456            }
3457            switch (len & 3) {
3458                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3459                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
3460                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
3461                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
3462            }
3463            seed = (seed ^ seed << 16) * (len ^ b0);
3464            return seed - (seed >>> 31) + (seed << 33);
3465        }
3466
3467        /**
3468         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
3469         *
3470         * @param data  the char array to hash
3471         * @param start the start of the section to hash (inclusive)
3472         * @param end   the end of the section to hash (exclusive)
3473         * @return a 64-bit hash code for the requested section of data
3474         */
3475        public static long hash64(final char[] data, final int start, final int end) {
3476            if (data == null || start >= end)
3477                return 0;
3478            long seed = 9069147967908697017L;
3479            final int len = Math.min(end, data.length);
3480            for (int i = start + 3; i < len; i+=4) {
3481                seed = mum(
3482                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3483                        mum(data[i-1] ^ b3, data[i] ^ b4));
3484            }
3485            switch (len - start & 3) {
3486                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3487                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3488                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3489                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3490            }
3491            return mum(seed ^ seed << 16, len - start ^ b0);
3492        }
3493
3494        /**
3495         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
3496         *
3497         * @param data  the String or other CharSequence to hash
3498         * @param start the start of the section to hash (inclusive)
3499         * @param end   the end of the section to hash (exclusive)
3500         * @return a 64-bit hash code for the requested section of data
3501         */
3502        public static long hash64(final CharSequence data, final int start, final int end) {
3503            if (data == null || start >= end)
3504                return 0;
3505            long seed = 9069147967908697017L;
3506            final int len = Math.min(end, data.length());
3507            for (int i = start + 3; i < len; i+=4) {
3508                seed = mum(
3509                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
3510                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
3511            }
3512            switch (len - start & 3) {
3513                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3514                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
3515                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
3516                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
3517            }
3518            return mum(seed ^ seed << 16, len - start ^ b0);
3519        }
3520
3521
3522        public static long hash64(final char[][] data) {
3523            if (data == null) return 0;
3524            long seed = 9069147967908697017L;
3525            final int len = data.length;
3526            for (int i = 3; i < len; i+=4) {
3527                seed = mum(
3528                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3529                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3530            }
3531            int t;
3532            switch (len & 3) {
3533                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3534                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3535                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3536                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3537            }
3538            seed = (seed ^ seed << 16) * (len ^ b0);
3539            return seed - (seed >>> 31) + (seed << 33);
3540        }
3541
3542        public static long hash64(final int[][] data) {
3543            if (data == null) return 0;
3544            long seed = 9069147967908697017L;
3545            final int len = data.length;
3546            for (int i = 3; i < len; i+=4) {
3547                seed = mum(
3548                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3549                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3550            }
3551            int t;
3552            switch (len & 3) {
3553                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3554                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3555                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3556                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3557            }
3558            seed = (seed ^ seed << 16) * (len ^ b0);
3559            return seed - (seed >>> 31) + (seed << 33);
3560        }
3561
3562        public static long hash64(final long[][] data) {
3563            if (data == null) return 0;
3564            long seed = 9069147967908697017L;
3565            final int len = data.length;
3566            for (int i = 3; i < len; i+=4) {
3567                seed = mum(
3568                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3569                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3570            }
3571            int t;
3572            switch (len & 3) {
3573                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3574                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3575                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3576                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3577            }
3578            seed = (seed ^ seed << 16) * (len ^ b0);
3579            return seed - (seed >>> 31) + (seed << 33);
3580        }
3581
3582        public static long hash64(final CharSequence[] data) {
3583            if (data == null) return 0;
3584            long seed = 9069147967908697017L;
3585            final int len = data.length;
3586            for (int i = 3; i < len; i+=4) {
3587                seed = mum(
3588                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3589                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3590            }
3591            int t;
3592            switch (len & 3) {
3593                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3594                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3595                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3596                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3597            }
3598            seed = (seed ^ seed << 16) * (len ^ b0);
3599            return seed - (seed >>> 31) + (seed << 33);
3600        }
3601
3602        public static long hash64(final CharSequence[]... data) {
3603            if (data == null) return 0;
3604            long seed = 9069147967908697017L;
3605            final int len = data.length;
3606            for (int i = 3; i < len; i+=4) {
3607                seed = mum(
3608                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3609                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3610            }
3611            int t;
3612            switch (len & 3) {
3613                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3614                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3615                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3616                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3617            }
3618            seed = (seed ^ seed << 16) * (len ^ b0);
3619            return seed - (seed >>> 31) + (seed << 33);
3620        }
3621
3622        public static long hash64(final Iterable<? extends CharSequence> data) {
3623            if (data == null) return 0;
3624            long seed = 9069147967908697017L;
3625            final Iterator<? extends CharSequence> it = data.iterator();
3626            int len = 0;
3627            while (it.hasNext())
3628            {
3629                ++len;
3630                seed = mum(
3631                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
3632                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
3633            }
3634            seed = (seed ^ seed << 16) * (len ^ b0);
3635            return seed - (seed >>> 31) + (seed << 33);
3636        }
3637
3638        public static long hash64(final List<? extends CharSequence> data) {
3639            if (data == null) return 0;
3640            long seed = 9069147967908697017L;
3641            final int len = data.size();
3642            for (int i = 3; i < len; i+=4) {
3643                seed = mum(
3644                        mum(hash(data.get(i-3)) ^ b1, hash(data.get(i-2)) ^ b2) + seed,
3645                        mum(hash(data.get(i-1)) ^ b3, hash(data.get(i  )) ^ b4));
3646            }
3647            int t;
3648            switch (len & 3) {
3649                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3650                case 1: seed = mum(seed ^((t = hash(data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3651                case 2: seed = mum(seed ^ hash(data.get(len-2)), b0 ^ hash(data.get(len-1))); break;
3652                case 3: seed = mum(seed ^ hash(data.get(len-3)), b2 ^ hash(data.get(len-2))) ^ mum(seed ^ hash(data.get(len-1)), b4); break;
3653            }
3654            seed = (seed ^ seed << 16) * (len ^ b0);
3655            return seed - (seed >>> 31) + (seed << 33);
3656
3657        }
3658
3659        public static long hash64(final Object[] data) {
3660            if (data == null) return 0;
3661            long seed = 9069147967908697017L;
3662            final int len = data.length;
3663            for (int i = 3; i < len; i+=4) {
3664                seed = mum(
3665                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3666                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3667            }
3668            int t;
3669            switch (len & 3) {
3670                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3671                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3672                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3673                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3674            }
3675            seed = (seed ^ seed << 16) * (len ^ b0);
3676            return seed - (seed >>> 31) + (seed << 33);
3677        }
3678
3679        public static long hash64(final Object data) {
3680            if (data == null)
3681                return 0;
3682            final long h = data.hashCode() * 0x9E3779B97F4A7C15L;
3683            return h - (h >>> 31) + (h << 33);
3684        }
3685
3686
3687        public static int hash(final boolean[] data) {
3688            if (data == null) return 0;
3689            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3690            final int len = data.length;
3691            for (int i = 3; i < len; i+=4) {
3692                seed = mum(
3693                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
3694                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
3695            }
3696            switch (len & 3) {
3697                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3698                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
3699                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
3700                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
3701            }
3702            return (int) mum(seed ^ seed << 16, len ^ b0);
3703        }
3704        public static int hash(final byte[] data) {
3705            if (data == null) return 0;
3706            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3707            final int len = data.length;
3708            for (int i = 3; i < len; i+=4) {
3709                seed = mum(
3710                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3711                        mum(data[i-1] ^ b3, data[i] ^ b4));
3712            }
3713            switch (len & 3) {
3714                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3715                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
3716                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
3717                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
3718            }
3719            return (int) mum(seed ^ seed << 16, len ^ b0);
3720        }
3721
3722        public static int hash(final short[] data) {
3723            if (data == null) return 0;
3724            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3725            final int len = data.length;
3726            for (int i = 3; i < len; i+=4) {
3727                seed = mum(
3728                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3729                        mum(data[i-1] ^ b3, data[i] ^ b4));
3730            }
3731            switch (len & 3) {
3732                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3733                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3734                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3735                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3736            }
3737            return (int) mum(seed ^ seed << 16, len ^ b0);
3738        }
3739
3740        public static int hash(final char[] data) {
3741            if (data == null) return 0;
3742            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3743            final int len = data.length;
3744            for (int i = 3; i < len; i+=4) {
3745                seed = mum(
3746                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3747                        mum(data[i-1] ^ b3, data[i] ^ b4));
3748            }
3749            switch (len & 3) {
3750                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3751                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3752                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3753                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3754            }
3755            return (int) mum(seed ^ seed << 16, len ^ b0);
3756        }
3757
3758        public static int hash(final CharSequence data) {
3759            if (data == null) return 0;
3760            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3761            final int len = data.length();
3762            for (int i = 3; i < len; i+=4) {
3763                seed = mum(
3764                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
3765                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
3766            }
3767            switch (len & 3) {
3768                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3769                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
3770                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
3771                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
3772            }
3773            return (int) mum(seed ^ seed << 16, len ^ b0);
3774        }
3775        public static int hash(final int[] data) {
3776            if (data == null) return 0;
3777            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3778            final int len = data.length;
3779            for (int i = 3; i < len; i+=4) {
3780                seed = mum(
3781                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3782                        mum(data[i-1] ^ b3, data[i] ^ b4));
3783            }
3784            switch (len & 3) {
3785                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3786                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
3787                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
3788                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
3789            }
3790            return (int) mum(seed ^ seed << 16, len ^ b0);
3791        }
3792        public static int hash(final int[] data, final int length) {
3793            if (data == null) return 0;
3794            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3795            for (int i = 3; i < length; i+=4) {
3796                seed = mum(
3797                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3798                        mum(data[i-1] ^ b3, data[i] ^ b4));
3799            }
3800            switch (length & 3) {
3801                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3802                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
3803                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
3804                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
3805            }
3806            return (int) mum(seed ^ seed << 16, length ^ b0);
3807        }
3808
3809        public static int hash(final long[] data) {
3810            if (data == null) return 0;
3811            //long seed = 0x1E98AE18CA351B28L,// seed = b0 ^ b0 >>> 23 ^ b0 >>> 48 ^ b0 << 7 ^ b0 << 53, 
3812//                    a = seed ^ b4, b = (seed << 17 | seed >>> 47) ^ b3,
3813//                    c = (seed << 31 | seed >>> 33) ^ b2, d = (seed << 47 | seed >>> 17) ^ b1;
3814            //a = 0x316E03F0E480967L, b = 0x4A8F1A6436771F2L,
3815            //        c = 0xEBA6E76493C491EFL, d = 0x6A97719DF7B84DC1L;
3816            long seed = 0x1E98AE18CA351B28L, a = 0x3C26FC408EB22D77L, b = 0x773213E53F6C67EBL, c = 0xAD55190966BDE20BL, d = 0x59C2CEA6AE94403L;
3817            final int len = data.length;
3818            for (int i = 3; i < len; i+=4) {
3819                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
3820                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
3821                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
3822                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
3823                seed += a + b + c + d;
3824            }
3825            seed += b5;
3826            switch (len & 3) {
3827                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
3828                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
3829                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
3830            }
3831            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
3832            return (int)(seed - (seed >>> 32));
3833        }
3834
3835        public static int hash(final float[] data) {
3836            if (data == null) return 0;
3837            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3838            final int len = data.length;
3839            for (int i = 3; i < len; i+=4) {
3840                seed = mum(
3841                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
3842                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
3843            }
3844            switch (len & 3) {
3845                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3846                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
3847                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
3848                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
3849            }
3850            return (int) mum(seed ^ seed << 16, len ^ b0);
3851        }
3852        public static int hash(final double[] data) {
3853            if (data == null) return 0;
3854            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3855            final int len = data.length;
3856            for (int i = 3; i < len; i+=4) {
3857                seed = mum(
3858                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
3859                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
3860            }
3861            switch (len & 3) {
3862                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3863                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
3864                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
3865                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
3866            }
3867            return (int) mum(seed ^ seed << 16, len ^ b0);
3868        }
3869
3870        /**
3871         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
3872         *
3873         * @param data  the char array to hash
3874         * @param start the start of the section to hash (inclusive)
3875         * @param end   the end of the section to hash (exclusive)
3876         * @return a 32-bit hash code for the requested section of data
3877         */
3878        public static int hash(final char[] data, final int start, final int end) {
3879            if (data == null || start >= end)
3880                return 0;
3881            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3882            final int len = Math.min(end, data.length);
3883            for (int i = start + 3; i < len; i+=4) {
3884                seed = mum(
3885                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
3886                        mum(data[i-1] ^ b3, data[i] ^ b4));
3887            }
3888            switch (len - start & 3) {
3889                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3890                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
3891                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
3892                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
3893            }
3894            return (int) mum(seed ^ seed << 16, len - start ^ b0);
3895        }
3896
3897        /**
3898         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
3899         *
3900         * @param data  the String or other CharSequence to hash
3901         * @param start the start of the section to hash (inclusive)
3902         * @param end   the end of the section to hash (exclusive)
3903         * @return a 32-bit hash code for the requested section of data
3904         */
3905        public static int hash(final CharSequence data, final int start, final int end) {
3906            if (data == null || start >= end)
3907                return 0;
3908            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3909            final int len = Math.min(end, data.length());
3910            for (int i = start + 3; i < len; i+=4) {
3911                seed = mum(
3912                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
3913                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
3914            }
3915            switch (len - start & 3) {
3916                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3917                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
3918                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
3919                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
3920            }
3921            return (int) mum(seed ^ seed << 16, len - start ^ b0);
3922        }
3923
3924
3925        public static int hash(final char[][] data) {
3926            if (data == null) return 0;
3927            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3928            final int len = data.length;
3929            for (int i = 3; i < len; i+=4) {
3930                seed = mum(
3931                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3932                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3933            }
3934            int t;
3935            switch (len & 3) {
3936                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3937                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3938                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3939                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3940            }
3941            return (int) mum(seed ^ seed << 16, len ^ b0);
3942        }
3943
3944        public static int hash(final int[][] data) {
3945            if (data == null) return 0;
3946            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3947            final int len = data.length;
3948            for (int i = 3; i < len; i+=4) {
3949                seed = mum(
3950                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3951                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3952            }
3953            int t;
3954            switch (len & 3) {
3955                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3956                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3957                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3958                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3959            }
3960            return (int) mum(seed ^ seed << 16, len ^ b0);
3961        }
3962
3963        public static int hash(final long[][] data) {
3964            if (data == null) return 0;
3965            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3966            final int len = data.length;
3967            for (int i = 3; i < len; i+=4) {
3968                seed = mum(
3969                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3970                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3971            }
3972            int t;
3973            switch (len & 3) {
3974                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3975                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3976                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3977                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3978            }
3979            return (int) mum(seed ^ seed << 16, len ^ b0);
3980        }
3981
3982        public static int hash(final CharSequence[] data) {
3983            if (data == null) return 0;
3984            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
3985            final int len = data.length;
3986            for (int i = 3; i < len; i+=4) {
3987                seed = mum(
3988                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
3989                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
3990            }
3991            int t;
3992            switch (len & 3) {
3993                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
3994                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
3995                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
3996                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
3997            }
3998            return (int) mum(seed ^ seed << 16, len ^ b0);
3999        }
4000
4001        public static int hash(final CharSequence[]... data) {
4002            if (data == null) return 0;
4003            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
4004            final int len = data.length;
4005            for (int i = 3; i < len; i+=4) {
4006                seed = mum(
4007                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4008                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4009            }
4010            int t;
4011            switch (len & 3) {
4012                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4013                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4014                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4015                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4016            }
4017            return (int) mum(seed ^ seed << 16, len ^ b0);
4018        }
4019
4020        public static int hash(final Iterable<? extends CharSequence> data) {
4021            if (data == null) return 0;
4022            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
4023            final Iterator<? extends CharSequence> it = data.iterator();
4024            int len = 0;
4025            while (it.hasNext())
4026            {
4027                ++len;
4028                seed = mum(
4029                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
4030                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
4031            }
4032            return (int) mum(seed ^ seed << 16, len ^ b0);
4033        }
4034
4035        public static int hash(final List<? extends CharSequence> data) {
4036            if (data == null) return 0;
4037            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
4038            final int len = data.size();
4039            for (int i = 3; i < len; i+=4) {
4040                seed = mum(
4041                        mum(hash(data.get(i-3)) ^ b1, hash(data.get(i-2)) ^ b2) + seed,
4042                        mum(hash(data.get(i-1)) ^ b3, hash(data.get(i  )) ^ b4));
4043            }
4044            int t;
4045            switch (len & 3) {
4046                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4047                case 1: seed = mum(seed ^((t = hash(data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4048                case 2: seed = mum(seed ^ hash(data.get(len-2)), b0 ^ hash(data.get(len-1))); break;
4049                case 3: seed = mum(seed ^ hash(data.get(len-3)), b2 ^ hash(data.get(len-2))) ^ mum(seed ^ hash(data.get(len-1)), b4); break;
4050            }
4051            return (int) mum(seed ^ seed << 16, len ^ b0);
4052        }
4053
4054        public static int hash(final Object[] data) {
4055            if (data == null) return 0;
4056            long seed = -260224914646652572L;//b1 ^ b1 >>> 41 ^ b1 << 53;
4057            final int len = data.length;
4058            for (int i = 3; i < len; i+=4) {
4059                seed = mum(
4060                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4061                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4062            }
4063            int t;
4064            switch (len & 3) {
4065                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4066                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4067                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4068                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4069            }
4070            return (int) mum(seed ^ seed << 16, len ^ b0);
4071        }
4072
4073        public static int hash(final Object data) {
4074            if (data == null)
4075                return 0;
4076            final int h = data.hashCode() * 0x9E375;
4077            return h ^ (h >>> 16);
4078        }
4079    }
4080
4081    /**
4082     * Like Mist, this is a class for hash functors, each an object with a 64-bit long seed, but it uses about the same
4083     * algorithm as {@link Water} instead of the older, less-robust style Mist uses. This can be faster than
4084     * {@link Curlup}, but only for small arrays as input (20 length or less); it tends to be slower on larger arrays,
4085     * though not by much, and should be the same for {@code long[]} since they share an implementation for that type.
4086     * Normally you should prefer Curlup if you know some or all of your arrays will be of moderate size or larger.
4087     * Has a lot of predefined functors (192, named after 24 Greek letters and 72 Goetic demons, see
4088     * <a href="https://en.wikipedia.org/wiki/Lesser_Key_of_Solomon#The_Seventy-Two_Demons">Wikipedia for the demons</a>,
4089     * in both lower case and lower case with a trailing underscore). You probably want to use {@link #predefined}
4090     * instead of wrangling demon names; you can always choose an element from predefined with a 7-bit number, and there
4091     * are 64 numbers outside that range so you can choose any of those when a functor must be different.
4092     */
4093    public static final class Yolk {
4094        private final long seed;
4095
4096        public Yolk(){
4097            this.seed = 9069147967908697017L;
4098        }
4099        public Yolk(long seed)
4100        {
4101            seed += b1;
4102            this.seed = seed ^ seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
4103        }
4104        public Yolk(final CharSequence seed)
4105        {
4106            this(Hive.hash64(seed));
4107        }
4108
4109        public static final Yolk alpha = new Yolk("alpha"), beta = new Yolk("beta"), gamma = new Yolk("gamma"),
4110                delta = new Yolk("delta"), epsilon = new Yolk("epsilon"), zeta = new Yolk("zeta"),
4111                eta = new Yolk("eta"), theta = new Yolk("theta"), iota = new Yolk("iota"),
4112                kappa = new Yolk("kappa"), lambda = new Yolk("lambda"), mu = new Yolk("mu"),
4113                nu = new Yolk("nu"), xi = new Yolk("xi"), omicron = new Yolk("omicron"), pi = new Yolk("pi"),
4114                rho = new Yolk("rho"), sigma = new Yolk("sigma"), tau = new Yolk("tau"),
4115                upsilon = new Yolk("upsilon"), phi = new Yolk("phi"), chi = new Yolk("chi"), psi = new Yolk("psi"),
4116                omega = new Yolk("omega"),
4117                alpha_ = new Yolk("ALPHA"), beta_ = new Yolk("BETA"), gamma_ = new Yolk("GAMMA"),
4118                delta_ = new Yolk("DELTA"), epsilon_ = new Yolk("EPSILON"), zeta_ = new Yolk("ZETA"),
4119                eta_ = new Yolk("ETA"), theta_ = new Yolk("THETA"), iota_ = new Yolk("IOTA"),
4120                kappa_ = new Yolk("KAPPA"), lambda_ = new Yolk("LAMBDA"), mu_ = new Yolk("MU"),
4121                nu_ = new Yolk("NU"), xi_ = new Yolk("XI"), omicron_ = new Yolk("OMICRON"), pi_ = new Yolk("PI"),
4122                rho_ = new Yolk("RHO"), sigma_ = new Yolk("SIGMA"), tau_ = new Yolk("TAU"),
4123                upsilon_ = new Yolk("UPSILON"), phi_ = new Yolk("PHI"), chi_ = new Yolk("CHI"), psi_ = new Yolk("PSI"),
4124                omega_ = new Yolk("OMEGA"),
4125                baal = new Yolk("baal"), agares = new Yolk("agares"), vassago = new Yolk("vassago"), samigina = new Yolk("samigina"),
4126                marbas = new Yolk("marbas"), valefor = new Yolk("valefor"), amon = new Yolk("amon"), barbatos = new Yolk("barbatos"),
4127                paimon = new Yolk("paimon"), buer = new Yolk("buer"), gusion = new Yolk("gusion"), sitri = new Yolk("sitri"),
4128                beleth = new Yolk("beleth"), leraje = new Yolk("leraje"), eligos = new Yolk("eligos"), zepar = new Yolk("zepar"),
4129                botis = new Yolk("botis"), bathin = new Yolk("bathin"), sallos = new Yolk("sallos"), purson = new Yolk("purson"),
4130                marax = new Yolk("marax"), ipos = new Yolk("ipos"), aim = new Yolk("aim"), naberius = new Yolk("naberius"),
4131                glasya_labolas = new Yolk("glasya_labolas"), bune = new Yolk("bune"), ronove = new Yolk("ronove"), berith = new Yolk("berith"),
4132                astaroth = new Yolk("astaroth"), forneus = new Yolk("forneus"), foras = new Yolk("foras"), asmoday = new Yolk("asmoday"),
4133                gaap = new Yolk("gaap"), furfur = new Yolk("furfur"), marchosias = new Yolk("marchosias"), stolas = new Yolk("stolas"),
4134                phenex = new Yolk("phenex"), halphas = new Yolk("halphas"), malphas = new Yolk("malphas"), raum = new Yolk("raum"),
4135                focalor = new Yolk("focalor"), vepar = new Yolk("vepar"), sabnock = new Yolk("sabnock"), shax = new Yolk("shax"),
4136                vine = new Yolk("vine"), bifrons = new Yolk("bifrons"), vual = new Yolk("vual"), haagenti = new Yolk("haagenti"),
4137                crocell = new Yolk("crocell"), furcas = new Yolk("furcas"), balam = new Yolk("balam"), alloces = new Yolk("alloces"),
4138                caim = new Yolk("caim"), murmur = new Yolk("murmur"), orobas = new Yolk("orobas"), gremory = new Yolk("gremory"),
4139                ose = new Yolk("ose"), amy = new Yolk("amy"), orias = new Yolk("orias"), vapula = new Yolk("vapula"),
4140                zagan = new Yolk("zagan"), valac = new Yolk("valac"), andras = new Yolk("andras"), flauros = new Yolk("flauros"),
4141                andrealphus = new Yolk("andrealphus"), kimaris = new Yolk("kimaris"), amdusias = new Yolk("amdusias"), belial = new Yolk("belial"),
4142                decarabia = new Yolk("decarabia"), seere = new Yolk("seere"), dantalion = new Yolk("dantalion"), andromalius = new Yolk("andromalius"),
4143                baal_ = new Yolk("BAAL"), agares_ = new Yolk("AGARES"), vassago_ = new Yolk("VASSAGO"), samigina_ = new Yolk("SAMIGINA"),
4144                marbas_ = new Yolk("MARBAS"), valefor_ = new Yolk("VALEFOR"), amon_ = new Yolk("AMON"), barbatos_ = new Yolk("BARBATOS"),
4145                paimon_ = new Yolk("PAIMON"), buer_ = new Yolk("BUER"), gusion_ = new Yolk("GUSION"), sitri_ = new Yolk("SITRI"),
4146                beleth_ = new Yolk("BELETH"), leraje_ = new Yolk("LERAJE"), eligos_ = new Yolk("ELIGOS"), zepar_ = new Yolk("ZEPAR"),
4147                botis_ = new Yolk("BOTIS"), bathin_ = new Yolk("BATHIN"), sallos_ = new Yolk("SALLOS"), purson_ = new Yolk("PURSON"),
4148                marax_ = new Yolk("MARAX"), ipos_ = new Yolk("IPOS"), aim_ = new Yolk("AIM"), naberius_ = new Yolk("NABERIUS"),
4149                glasya_labolas_ = new Yolk("GLASYA_LABOLAS"), bune_ = new Yolk("BUNE"), ronove_ = new Yolk("RONOVE"), berith_ = new Yolk("BERITH"),
4150                astaroth_ = new Yolk("ASTAROTH"), forneus_ = new Yolk("FORNEUS"), foras_ = new Yolk("FORAS"), asmoday_ = new Yolk("ASMODAY"),
4151                gaap_ = new Yolk("GAAP"), furfur_ = new Yolk("FURFUR"), marchosias_ = new Yolk("MARCHOSIAS"), stolas_ = new Yolk("STOLAS"),
4152                phenex_ = new Yolk("PHENEX"), halphas_ = new Yolk("HALPHAS"), malphas_ = new Yolk("MALPHAS"), raum_ = new Yolk("RAUM"),
4153                focalor_ = new Yolk("FOCALOR"), vepar_ = new Yolk("VEPAR"), sabnock_ = new Yolk("SABNOCK"), shax_ = new Yolk("SHAX"),
4154                vine_ = new Yolk("VINE"), bifrons_ = new Yolk("BIFRONS"), vual_ = new Yolk("VUAL"), haagenti_ = new Yolk("HAAGENTI"),
4155                crocell_ = new Yolk("CROCELL"), furcas_ = new Yolk("FURCAS"), balam_ = new Yolk("BALAM"), alloces_ = new Yolk("ALLOCES"),
4156                caim_ = new Yolk("CAIM"), murmur_ = new Yolk("MURMUR"), orobas_ = new Yolk("OROBAS"), gremory_ = new Yolk("GREMORY"),
4157                ose_ = new Yolk("OSE"), amy_ = new Yolk("AMY"), orias_ = new Yolk("ORIAS"), vapula_ = new Yolk("VAPULA"),
4158                zagan_ = new Yolk("ZAGAN"), valac_ = new Yolk("VALAC"), andras_ = new Yolk("ANDRAS"), flauros_ = new Yolk("FLAUROS"),
4159                andrealphus_ = new Yolk("ANDREALPHUS"), kimaris_ = new Yolk("KIMARIS"), amdusias_ = new Yolk("AMDUSIAS"), belial_ = new Yolk("BELIAL"),
4160                decarabia_ = new Yolk("DECARABIA"), seere_ = new Yolk("SEERE"), dantalion_ = new Yolk("DANTALION"), andromalius_ = new Yolk("ANDROMALIUS")
4161                ;
4162        /**
4163         * Has a length of 192, which may be relevant if automatically choosing a predefined hash functor.
4164         */
4165        public static final Yolk[] predefined = new Yolk[]{alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota,
4166                kappa, lambda, mu, nu, xi, omicron, pi, rho, sigma, tau, upsilon, phi, chi, psi, omega,
4167                alpha_, beta_, gamma_, delta_, epsilon_, zeta_, eta_, theta_, iota_,
4168                kappa_, lambda_, mu_, nu_, xi_, omicron_, pi_, rho_, sigma_, tau_, upsilon_, phi_, chi_, psi_, omega_,
4169                baal, agares, vassago, samigina, marbas, valefor, amon, barbatos,
4170                paimon, buer, gusion, sitri, beleth, leraje, eligos, zepar,
4171                botis, bathin, sallos, purson, marax, ipos, aim, naberius,
4172                glasya_labolas, bune, ronove, berith, astaroth, forneus, foras, asmoday,
4173                gaap, furfur, marchosias, stolas, phenex, halphas, malphas, raum,
4174                focalor, vepar, sabnock, shax, vine, bifrons, vual, haagenti,
4175                crocell, furcas, balam, alloces, caim, murmur, orobas, gremory,
4176                ose, amy, orias, vapula, zagan, valac, andras, flauros,
4177                andrealphus, kimaris, amdusias, belial, decarabia, seere, dantalion, andromalius,
4178                baal_, agares_, vassago_, samigina_, marbas_, valefor_, amon_, barbatos_,
4179                paimon_, buer_, gusion_, sitri_, beleth_, leraje_, eligos_, zepar_,
4180                botis_, bathin_, sallos_, purson_, marax_, ipos_, aim_, naberius_,
4181                glasya_labolas_, bune_, ronove_, berith_, astaroth_, forneus_, foras_, asmoday_,
4182                gaap_, furfur_, marchosias_, stolas_, phenex_, halphas_, malphas_, raum_,
4183                focalor_, vepar_, sabnock_, shax_, vine_, bifrons_, vual_, haagenti_,
4184                crocell_, furcas_, balam_, alloces_, caim_, murmur_, orobas_, gremory_,
4185                ose_, amy_, orias_, vapula_, zagan_, valac_, andras_, flauros_,
4186                andrealphus_, kimaris_, amdusias_, belial_, decarabia_, seere_, dantalion_, andromalius_};
4187
4188
4189        public long hash64(final boolean[] data) {
4190            if (data == null) return 0;
4191            long seed = this.seed;//seed = b1 ^ b1 >>> 29 ^ b1 >>> 43 ^ b1 << 7 ^ b1 << 53;
4192            final int len = data.length;
4193            for (int i = 3; i < len; i+=4) {
4194                seed = mum(
4195                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
4196                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
4197            }
4198            switch (len & 3) {
4199                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4200                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
4201                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
4202                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
4203            }
4204            seed = (seed ^ seed << 16) * (len ^ b0);
4205            return seed - (seed >>> 31) + (seed << 33);
4206        }
4207        public long hash64(final byte[] data) {
4208            if (data == null) return 0;
4209            long seed = this.seed;
4210            final int len = data.length;
4211            for (int i = 3; i < len; i+=4) {
4212                seed = mum(
4213                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4214                        mum(data[i-1] ^ b3, data[i] ^ b4));
4215            }
4216            switch (len & 3) {
4217                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4218                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
4219                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
4220                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
4221            }
4222            seed = (seed ^ seed << 16) * (len ^ b0);
4223            return seed - (seed >>> 31) + (seed << 33);
4224        }
4225
4226        public long hash64(final short[] data) {
4227            if (data == null) return 0;
4228            long seed = this.seed;
4229            final int len = data.length;
4230            for (int i = 3; i < len; i+=4) {
4231                seed = mum(
4232                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4233                        mum(data[i-1] ^ b3, data[i] ^ b4));
4234            }
4235            switch (len & 3) {
4236                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4237                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4238                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4239                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4240            }
4241            seed = (seed ^ seed << 16) * (len ^ b0);
4242            return seed - (seed >>> 31) + (seed << 33);
4243        }
4244
4245        public long hash64(final char[] data) {
4246            if (data == null) return 0;
4247            long seed = this.seed;
4248            final int len = data.length;
4249            for (int i = 3; i < len; i+=4) {
4250                seed = mum(
4251                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4252                        mum(data[i-1] ^ b3, data[i] ^ b4));
4253            }
4254            switch (len & 3) {
4255                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4256                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4257                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4258                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4259            }
4260            seed = (seed ^ seed << 16) * (len ^ b0);
4261            return seed - (seed >>> 31) + (seed << 33);
4262        }
4263
4264        public long hash64(final CharSequence data) {
4265            if (data == null) return 0;
4266            long seed = this.seed;
4267            final int len = data.length();
4268            for (int i = 3; i < len; i+=4) {
4269                seed = mum(
4270                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
4271                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
4272            }
4273            switch (len & 3) {
4274                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4275                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
4276                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
4277                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
4278            }
4279            seed = (seed ^ seed << 16) * (len ^ b0);
4280            return seed - (seed >>> 31) + (seed << 33);
4281        }
4282
4283        public long hash64(final int[] data) {
4284            if (data == null) return 0;
4285            long seed = this.seed;
4286            final int len = data.length;
4287            for (int i = 3; i < len; i+=4) {
4288                seed = mum(
4289                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4290                        mum(data[i-1] ^ b3, data[i] ^ b4));
4291            }
4292            switch (len & 3) {
4293                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4294                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
4295                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
4296                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
4297            }
4298            seed = (seed ^ seed << 16) * (len ^ b0);
4299            return seed - (seed >>> 31) + (seed << 33);
4300        }
4301
4302        public long hash64(final int[] data, final int length) {
4303            if (data == null) return 0;
4304            long seed = this.seed;
4305            for (int i = 3; i < length; i+=4) {
4306                seed = mum(
4307                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4308                        mum(data[i-1] ^ b3, data[i] ^ b4));
4309            }
4310            switch (length & 3) {
4311                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4312                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
4313                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
4314                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
4315            }
4316            seed = (seed ^ seed << 16) * (length ^ b0);
4317            return seed - (seed >>> 31) + (seed << 33);
4318        }
4319
4320        public long hash64(final long[] data) {
4321            if (data == null) return 0;
4322            long seed = this.seed, a = this.seed + b4, b = this.seed + b3, c = this.seed + b2, d = this.seed + b1;
4323            final int len = data.length;
4324            for (int i = 3; i < len; i+=4) {
4325                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
4326                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
4327                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
4328                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
4329                seed += a + b + c + d;
4330            }
4331            seed += b5;
4332            switch (len & 3) {
4333                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
4334                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
4335                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
4336            }
4337            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
4338            return seed - (seed >>> 31) + (seed << 33);
4339        }
4340        public long hash64(final float[] data) {
4341            if (data == null) return 0;
4342            long seed = this.seed;
4343            final int len = data.length;
4344            for (int i = 3; i < len; i+=4) {
4345                seed = mum(
4346                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
4347                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
4348            }
4349            switch (len & 3) {
4350                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4351                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
4352                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
4353                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
4354            }
4355            seed = (seed ^ seed << 16) * (len ^ b0);
4356            return seed - (seed >>> 31) + (seed << 33);
4357        }
4358        public long hash64(final double[] data) {
4359            if (data == null) return 0;
4360            long seed = this.seed;
4361            final int len = data.length;
4362            for (int i = 3; i < len; i+=4) {
4363                seed = mum(
4364                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
4365                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
4366            }
4367            switch (len & 3) {
4368                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4369                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
4370                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
4371                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
4372            }
4373            seed = (seed ^ seed << 16) * (len ^ b0);
4374            return seed - (seed >>> 31) + (seed << 33);
4375        }
4376
4377        /**
4378         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
4379         *
4380         * @param data  the char array to hash
4381         * @param start the start of the section to hash (inclusive)
4382         * @param end   the end of the section to hash (exclusive)
4383         * @return a 64-bit hash code for the requested section of data
4384         */
4385        public long hash64(final char[] data, final int start, final int end) {
4386            if (data == null || start >= end)
4387                return 0;
4388            long seed = this.seed;
4389            final int len = Math.min(end, data.length);
4390            for (int i = start + 3; i < len; i+=4) {
4391                seed = mum(
4392                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4393                        mum(data[i-1] ^ b3, data[i] ^ b4));
4394            }
4395            switch (len - start & 3) {
4396                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4397                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4398                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4399                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4400            }
4401            return mum(seed ^ seed << 16, len - start ^ Water.b0);
4402        }
4403
4404        /**
4405         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
4406         *
4407         * @param data  the String or other CharSequence to hash
4408         * @param start the start of the section to hash (inclusive)
4409         * @param end   the end of the section to hash (exclusive)
4410         * @return a 64-bit hash code for the requested section of data
4411         */
4412        public long hash64(final CharSequence data, final int start, final int end) {
4413            if (data == null || start >= end)
4414                return 0;
4415            long seed = this.seed;
4416            final int len = Math.min(end, data.length());
4417            for (int i = start + 3; i < len; i+=4) {
4418                seed = mum(
4419                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
4420                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
4421            }
4422            switch (len - start & 3) {
4423                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4424                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
4425                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
4426                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
4427            }
4428            return mum(seed ^ seed << 16, len - start ^ b0);
4429        }
4430
4431
4432        public long hash64(final char[][] data) {
4433            if (data == null) return 0;
4434            long seed = this.seed;
4435            final int len = data.length;
4436            for (int i = 3; i < len; i+=4) {
4437                seed = mum(
4438                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4439                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4440            }
4441            int t;
4442            switch (len & 3) {
4443                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4444                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4445                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4446                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4447            }
4448            seed = (seed ^ seed << 16) * (len ^ b0);
4449            return seed - (seed >>> 31) + (seed << 33);
4450        }
4451
4452        public long hash64(final int[][] data) {
4453            if (data == null) return 0;
4454            long seed = this.seed;
4455            final int len = data.length;
4456            for (int i = 3; i < len; i+=4) {
4457                seed = mum(
4458                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4459                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4460            }
4461            int t;
4462            switch (len & 3) {
4463                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4464                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4465                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4466                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4467            }
4468            seed = (seed ^ seed << 16) * (len ^ b0);
4469            return seed - (seed >>> 31) + (seed << 33);
4470        }
4471
4472        public long hash64(final long[][] data) {
4473            if (data == null) return 0;
4474            long seed = this.seed;
4475            final int len = data.length;
4476            for (int i = 3; i < len; i+=4) {
4477                seed = mum(
4478                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4479                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4480            }
4481            int t;
4482            switch (len & 3) {
4483                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4484                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4485                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4486                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4487            }
4488            seed = (seed ^ seed << 16) * (len ^ b0);
4489            return seed - (seed >>> 31) + (seed << 33);
4490        }
4491
4492        public long hash64(final CharSequence[] data) {
4493            if (data == null) return 0;
4494            long seed = this.seed;
4495            final int len = data.length;
4496            for (int i = 3; i < len; i+=4) {
4497                seed = mum(
4498                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4499                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4500            }
4501            int t;
4502            switch (len & 3) {
4503                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4504                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4505                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4506                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4507            }
4508            seed = (seed ^ seed << 16) * (len ^ b0);
4509            return seed - (seed >>> 31) + (seed << 33);
4510        }
4511
4512        public long hash64(final CharSequence[]... data) {
4513            if (data == null) return 0;
4514            long seed = this.seed;
4515            final int len = data.length;
4516            for (int i = 3; i < len; i+=4) {
4517                seed = mum(
4518                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4519                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4520            }
4521            int t;
4522            switch (len & 3) {
4523                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4524                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4525                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4526                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4527            }
4528            seed = (seed ^ seed << 16) * (len ^ b0);
4529            return seed - (seed >>> 31) + (seed << 33);
4530        }
4531
4532        public long hash64(final Iterable<? extends CharSequence> data) {
4533            if (data == null) return 0;
4534            long seed = this.seed;
4535            final Iterator<? extends CharSequence> it = data.iterator();
4536            int len = 0;
4537            while (it.hasNext())
4538            {
4539                ++len;
4540                seed = mum(
4541                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
4542                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
4543            }
4544            seed = (seed ^ seed << 16) * (len ^ b0);
4545            return seed - (seed >>> 31) + (seed << 33);
4546        }
4547
4548        public long hash64(final List<? extends CharSequence> data) {
4549            if (data == null) return 0;
4550            long seed = this.seed;
4551            final int len = data.size();
4552            for (int i = 3; i < len; i+=4) {
4553                seed = mum(
4554                        mum(hash(data.get(i-3)) ^ b1, hash(data.get(i-2)) ^ b2) + seed,
4555                        mum(hash(data.get(i-1)) ^ b3, hash(data.get(i  )) ^ b4));
4556            }
4557            int t;
4558            switch (len & 3) {
4559                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4560                case 1: seed = mum(seed ^((t = hash(data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4561                case 2: seed = mum(seed ^ hash(data.get(len-2)), b0 ^ hash(data.get(len-1))); break;
4562                case 3: seed = mum(seed ^ hash(data.get(len-3)), b2 ^ hash(data.get(len-2))) ^ mum(seed ^ hash(data.get(len-1)), b4); break;
4563            }
4564            seed = (seed ^ seed << 16) * (len ^ b0);
4565            return seed - (seed >>> 31) + (seed << 33);
4566
4567        }
4568
4569        public long hash64(final Object[] data) {
4570            if (data == null) return 0;
4571            long seed = this.seed;
4572            final int len = data.length;
4573            for (int i = 3; i < len; i+=4) {
4574                seed = mum(
4575                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4576                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4577            }
4578            int t;
4579            switch (len & 3) {
4580                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4581                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4582                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4583                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4584            }
4585            seed = (seed ^ seed << 16) * (len ^ b0);
4586            return seed - (seed >>> 31) + (seed << 33);
4587        }
4588
4589        public long hash64(final Object data) {
4590            if (data == null)
4591                return 0;
4592            final long h = (data.hashCode() + seed) * 0x9E3779B97F4A7C15L;
4593            return h - (h >>> 31) + (h << 33);
4594        }
4595
4596
4597        public int hash(final boolean[] data) {
4598            if (data == null) return 0;
4599            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4600            final int len = data.length;
4601            for (int i = 3; i < len; i+=4) {
4602                seed = mum(
4603                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
4604                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
4605            }
4606            switch (len & 3) {
4607                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4608                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
4609                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
4610                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
4611            }
4612            return (int) mum(seed ^ seed << 16, len ^ b0);
4613        }
4614        public int hash(final byte[] data) {
4615            if (data == null) return 0;
4616            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4617            final int len = data.length;
4618            for (int i = 3; i < len; i+=4) {
4619                seed = mum(
4620                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4621                        mum(data[i-1] ^ b3, data[i] ^ b4));
4622            }
4623            switch (len & 3) {
4624                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4625                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
4626                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
4627                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
4628            }
4629            return (int) mum(seed ^ seed << 16, len ^ b0);
4630        }
4631
4632        public int hash(final short[] data) {
4633            if (data == null) return 0;
4634            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4635            final int len = data.length;
4636            for (int i = 3; i < len; i+=4) {
4637                seed = mum(
4638                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4639                        mum(data[i-1] ^ b3, data[i] ^ b4));
4640            }
4641            switch (len & 3) {
4642                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4643                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4644                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4645                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4646            }
4647            return (int) mum(seed ^ seed << 16, len ^ b0);
4648        }
4649
4650        public int hash(final char[] data) {
4651            if (data == null) return 0;
4652            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4653            final int len = data.length;
4654            for (int i = 3; i < len; i+=4) {
4655                seed = mum(
4656                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4657                        mum(data[i-1] ^ b3, data[i] ^ b4));
4658            }
4659            switch (len & 3) {
4660                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4661                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4662                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4663                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4664            }
4665            return (int) mum(seed ^ seed << 16, len ^ b0);
4666        }
4667
4668        public int hash(final CharSequence data) {
4669            if (data == null) return 0;
4670            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4671            final int len = data.length();
4672            for (int i = 3; i < len; i+=4) {
4673                seed = mum(
4674                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
4675                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
4676            }
4677            switch (len & 3) {
4678                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4679                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
4680                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
4681                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
4682            }
4683            return (int) mum(seed ^ seed << 16, len ^ b0);
4684        }
4685        public int hash(final int[] data) {
4686            if (data == null) return 0;
4687            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4688            final int len = data.length;
4689            for (int i = 3; i < len; i+=4) {
4690                seed = mum(
4691                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4692                        mum(data[i-1] ^ b3, data[i] ^ b4));
4693            }
4694            switch (len & 3) {
4695                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4696                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
4697                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
4698                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
4699            }
4700            return (int) mum(seed ^ seed << 16, len ^ b0);
4701        }
4702        public int hash(final int[] data, final int length) {
4703            if (data == null) return 0;
4704            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4705            for (int i = 3; i < length; i+=4) {
4706                seed = mum(
4707                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4708                        mum(data[i-1] ^ b3, data[i] ^ b4));
4709            }
4710            switch (length & 3) {
4711                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4712                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
4713                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
4714                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
4715            }
4716            return (int) mum(seed ^ seed << 16, length ^ b0);
4717        }
4718
4719        public int hash(final long[] data) {
4720            if (data == null) return 0;
4721            long seed = this.seed, a = this.seed + b4, b = this.seed + b3, c = this.seed + b2, d = this.seed + b1;
4722            final int len = data.length;
4723            for (int i = 3; i < len; i+=4) {
4724                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
4725                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
4726                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
4727                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
4728                seed += a + b + c + d;
4729            }
4730            seed += b5;
4731            switch (len & 3) {
4732                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
4733                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
4734                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
4735            }
4736            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
4737            return (int)(seed - (seed >>> 32));
4738        }
4739
4740        public int hash(final float[] data) {
4741            if (data == null) return 0;
4742            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4743            final int len = data.length;
4744            for (int i = 3; i < len; i+=4) {
4745                seed = mum(
4746                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
4747                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
4748            }
4749            switch (len & 3) {
4750                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4751                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
4752                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
4753                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
4754            }
4755            return (int) mum(seed ^ seed << 16, len ^ b0);
4756        }
4757        public int hash(final double[] data) {
4758            if (data == null) return 0;
4759            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4760            final int len = data.length;
4761            for (int i = 3; i < len; i+=4) {
4762                seed = mum(
4763                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
4764                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
4765            }
4766            switch (len & 3) {
4767                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4768                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
4769                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
4770                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
4771            }
4772            return (int) mum(seed ^ seed << 16, len ^ b0);
4773        }
4774
4775        /**
4776         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
4777         *
4778         * @param data  the char array to hash
4779         * @param start the start of the section to hash (inclusive)
4780         * @param end   the end of the section to hash (exclusive)
4781         * @return a 32-bit hash code for the requested section of data
4782         */
4783        public int hash(final char[] data, final int start, final int end) {
4784            if (data == null || start >= end)
4785                return 0;
4786            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4787            final int len = Math.min(end, data.length);
4788            for (int i = start + 3; i < len; i+=4) {
4789                seed = mum(
4790                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
4791                        mum(data[i-1] ^ b3, data[i] ^ b4));
4792            }
4793            switch (len - start & 3) {
4794                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4795                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
4796                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
4797                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
4798            }
4799            return (int) mum(seed ^ seed << 16, len - start ^ b0);
4800        }
4801
4802        /**
4803         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
4804         *
4805         * @param data  the String or other CharSequence to hash
4806         * @param start the start of the section to hash (inclusive)
4807         * @param end   the end of the section to hash (exclusive)
4808         * @return a 32-bit hash code for the requested section of data
4809         */
4810        public int hash(final CharSequence data, final int start, final int end) {
4811            if (data == null || start >= end)
4812                return 0;
4813            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4814            final int len = Math.min(end, data.length());
4815            for (int i = start + 3; i < len; i+=4) {
4816                seed = mum(
4817                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
4818                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
4819            }
4820            switch (len - start & 3) {
4821                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4822                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
4823                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
4824                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
4825            }
4826            return (int) mum(seed ^ seed << 16, len - start ^ b0);
4827        }
4828
4829
4830        public int hash(final char[][] data) {
4831            if (data == null) return 0;
4832            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4833            final int len = data.length;
4834            for (int i = 3; i < len; i+=4) {
4835                seed = mum(
4836                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4837                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4838            }
4839            int t;
4840            switch (len & 3) {
4841                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4842                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4843                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4844                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4845            }
4846            return (int) mum(seed ^ seed << 16, len ^ b0);
4847        }
4848
4849        public int hash(final int[][] data) {
4850            if (data == null) return 0;
4851            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4852            final int len = data.length;
4853            for (int i = 3; i < len; i+=4) {
4854                seed = mum(
4855                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4856                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4857            }
4858            int t;
4859            switch (len & 3) {
4860                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4861                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4862                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4863                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4864            }
4865            return (int) mum(seed ^ seed << 16, len ^ b0);
4866        }
4867
4868        public int hash(final long[][] data) {
4869            if (data == null) return 0;
4870            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4871            final int len = data.length;
4872            for (int i = 3; i < len; i+=4) {
4873                seed = mum(
4874                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4875                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4876            }
4877            int t;
4878            switch (len & 3) {
4879                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4880                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4881                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4882                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4883            }
4884            return (int) mum(seed ^ seed << 16, len ^ b0);
4885        }
4886
4887        public int hash(final CharSequence[] data) {
4888            if (data == null) return 0;
4889            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4890            final int len = data.length;
4891            for (int i = 3; i < len; i+=4) {
4892                seed = mum(
4893                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4894                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4895            }
4896            int t;
4897            switch (len & 3) {
4898                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4899                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4900                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4901                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4902            }
4903            return (int) mum(seed ^ seed << 16, len ^ b0);
4904        }
4905
4906        public int hash(final CharSequence[]... data) {
4907            if (data == null) return 0;
4908            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4909            final int len = data.length;
4910            for (int i = 3; i < len; i+=4) {
4911                seed = mum(
4912                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4913                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4914            }
4915            int t;
4916            switch (len & 3) {
4917                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4918                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4919                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4920                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4921            }
4922            return (int) mum(seed ^ seed << 16, len ^ b0);
4923        }
4924
4925        public int hash(final Iterable<? extends CharSequence> data) {
4926            if (data == null) return 0;
4927            long seed = this.seed;
4928            final Iterator<? extends CharSequence> it = data.iterator();
4929            int len = 0;
4930            while (it.hasNext())
4931            {
4932                ++len;
4933                seed = mum(
4934                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
4935                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
4936            }
4937            return (int) mum(seed ^ seed << 16, len ^ b0);
4938        }
4939
4940        public int hash(final List<? extends CharSequence> data) {
4941            if (data == null) return 0;
4942            long seed = this.seed;//b1 ^ b1 >>> 41 ^ b1 << 53;
4943            final int len = data.size();
4944            for (int i = 3; i < len; i+=4) {
4945                seed = mum(
4946                        mum(hash(data.get(i-3)) ^ b1, hash(data.get(i-2)) ^ b2) + seed,
4947                        mum(hash(data.get(i-1)) ^ b3, hash(data.get(i  )) ^ b4));
4948            }
4949            int t;
4950            switch (len & 3) {
4951                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4952                case 1: seed = mum(seed ^((t = hash(data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4953                case 2: seed = mum(seed ^ hash(data.get(len-2)), b0 ^ hash(data.get(len-1))); break;
4954                case 3: seed = mum(seed ^ hash(data.get(len-3)), b2 ^ hash(data.get(len-2))) ^ mum(seed ^ hash(data.get(len-1)), b4); break;
4955            }
4956            return (int) mum(seed ^ seed << 16, len ^ b0);
4957        }
4958
4959        public int hash(final Object[] data) {
4960            if (data == null) return 0;
4961            long seed = this.seed;
4962            final int len = data.length;
4963            for (int i = 3; i < len; i+=4) {
4964                seed = mum(
4965                        mum(hash(data[i-3]) ^ b1, hash(data[i-2]) ^ b2) + seed,
4966                        mum(hash(data[i-1]) ^ b3, hash(data[i  ]) ^ b4));
4967            }
4968            int t;
4969            switch (len & 3) {
4970                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4971                case 1: seed = mum(seed ^((t = hash(data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
4972                case 2: seed = mum(seed ^ hash(data[len-2]), b0 ^ hash(data[len-1])); break;
4973                case 3: seed = mum(seed ^ hash(data[len-3]), b2 ^ hash(data[len-2])) ^ mum(seed ^ hash(data[len-1]), b4); break;
4974            }
4975            return (int) mum(seed ^ seed << 16, len ^ b0);
4976        }
4977
4978        public int hash(final Object data) {
4979            if (data == null) return 0;
4980            return (int)((data.hashCode() + seed) * 0x9E3779B97F4A7C15L >>> 32);
4981        }
4982
4983
4984        public static long hash64(long seed, final boolean[] data) {
4985            if (data == null) return 0L;
4986            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
4987            final int len = data.length;
4988            for (int i = 3; i < len; i+=4) {
4989                seed = mum(
4990                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
4991                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
4992            }
4993            switch (len & 3) {
4994                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
4995                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
4996                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
4997                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
4998            }
4999            seed = (seed ^ seed << 16) * (len ^ b0);
5000            return seed - (seed >>> 31) + (seed << 33);
5001        }
5002        public static long hash64(long seed, final byte[] data) {
5003            if (data == null) return 0L;
5004            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5005            final int len = data.length;
5006            for (int i = 3; i < len; i+=4) {
5007                seed = mum(
5008                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5009                        mum(data[i-1] ^ b3, data[i] ^ b4));
5010            }
5011            switch (len & 3) {
5012                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5013                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
5014                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
5015                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
5016            }
5017            seed = (seed ^ seed << 16) * (len ^ b0);
5018            return seed - (seed >>> 31) + (seed << 33);
5019        }
5020
5021        public static long hash64(long seed, final short[] data) {
5022            if (data == null) return 0L;
5023            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5024            final int len = data.length;
5025            for (int i = 3; i < len; i+=4) {
5026                seed = mum(
5027                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5028                        mum(data[i-1] ^ b3, data[i] ^ b4));
5029            }
5030            switch (len & 3) {
5031                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5032                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5033                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5034                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5035            }
5036            seed = (seed ^ seed << 16) * (len ^ b0);
5037            return seed - (seed >>> 31) + (seed << 33);
5038        }
5039
5040        public static long hash64(long seed, final char[] data) {
5041            if (data == null) return 0L;
5042            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5043            final int len = data.length;
5044            for (int i = 3; i < len; i+=4) {
5045                seed = mum(
5046                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5047                        mum(data[i-1] ^ b3, data[i] ^ b4));
5048            }
5049            switch (len & 3) {
5050                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5051                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5052                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5053                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5054            }
5055            seed = (seed ^ seed << 16) * (len ^ b0);
5056            return seed - (seed >>> 31) + (seed << 33);
5057        }
5058
5059        public static long hash64(long seed, final CharSequence data) {
5060            if (data == null) return 0L;
5061            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5062            final int len = data.length();
5063            for (int i = 3; i < len; i+=4) {
5064                seed = mum(
5065                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
5066                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
5067            }
5068            switch (len & 3) {
5069                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5070                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
5071                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
5072                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
5073            }
5074            seed = (seed ^ seed << 16) * (len ^ b0);
5075            return seed - (seed >>> 31) + (seed << 33);
5076        }
5077
5078        public static long hash64(long seed, final int[] data) {
5079            if (data == null) return 0L;
5080            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5081            final int len = data.length;
5082            for (int i = 3; i < len; i+=4) {
5083                seed = mum(
5084                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5085                        mum(data[i-1] ^ b3, data[i] ^ b4));
5086            }
5087            switch (len & 3) {
5088                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5089                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
5090                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
5091                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
5092            }
5093            seed = (seed ^ seed << 16) * (len ^ b0);
5094            return seed - (seed >>> 31) + (seed << 33);
5095        }
5096
5097        public static long hash64(long seed, final int[] data, final int length) {
5098            if (data == null) return 0L;
5099            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5100            for (int i = 3; i < length; i+=4) {
5101                seed = mum(
5102                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5103                        mum(data[i-1] ^ b3, data[i] ^ b4));
5104            }
5105            switch (length & 3) {
5106                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5107                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
5108                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
5109                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
5110            }
5111            seed = (seed ^ seed << 16) * (length ^ b0);
5112            return seed - (seed >>> 31) + (seed << 33);
5113        }
5114
5115        public static long hash64(long seed, final long[] data) {
5116            if (data == null) return 0L;
5117            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5118            long a = seed + b4, b = seed + b3, c = seed + b2, d = seed + b1;
5119            final int len = data.length;
5120            for (int i = 3; i < len; i+=4) {
5121                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
5122                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
5123                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
5124                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
5125                seed += a + b + c + d;
5126            }
5127            seed += b5;
5128            switch (len & 3) {
5129                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
5130                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
5131                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
5132            }
5133            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
5134            return seed - (seed >>> 31) + (seed << 33);
5135        }
5136        public static long hash64(long seed, final float[] data) {
5137            if (data == null) return 0L;
5138            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5139            final int len = data.length;
5140            for (int i = 3; i < len; i+=4) {
5141                seed = mum(
5142                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
5143                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
5144            }
5145            switch (len & 3) {
5146                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5147                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
5148                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
5149                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
5150            }
5151            seed = (seed ^ seed << 16) * (len ^ b0);
5152            return seed - (seed >>> 31) + (seed << 33);
5153        }
5154        public static long hash64(long seed, final double[] data) {
5155            if (data == null) return 0L;
5156            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5157            final int len = data.length;
5158            for (int i = 3; i < len; i+=4) {
5159                seed = mum(
5160                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
5161                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
5162            }
5163            switch (len & 3) {
5164                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5165                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
5166                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
5167                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
5168            }
5169            seed = (seed ^ seed << 16) * (len ^ b0);
5170            return seed - (seed >>> 31) + (seed << 33);
5171        }
5172
5173        /**
5174         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
5175         *
5176         * @param data  the char array to hash
5177         * @param start the start of the section to hash (inclusive)
5178         * @param end   the end of the section to hash (exclusive)
5179         * @return a 32-bit hash code for the requested section of data
5180         */
5181        public static long hash64(long seed, final char[] data, final int start, final int end) {
5182            if (data == null || start >= end)
5183                return 0L;
5184            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5185            final int len = Math.min(end, data.length);
5186            for (int i = start + 3; i < len; i+=4) {
5187                seed = mum(
5188                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5189                        mum(data[i-1] ^ b3, data[i] ^ b4));
5190            }
5191            switch (len - start & 3) {
5192                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5193                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5194                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5195                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5196            }
5197            return mum(seed ^ seed << 16, len - start ^ b0);
5198        }
5199
5200        /**
5201         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
5202         *
5203         * @param data  the String or other CharSequence to hash
5204         * @param start the start of the section to hash (inclusive)
5205         * @param end   the end of the section to hash (exclusive)
5206         * @return a 32-bit hash code for the requested section of data
5207         */
5208        public static long hash64(long seed, final CharSequence data, final int start, final int end) {
5209            if (data == null || start >= end)
5210                return 0L;
5211            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5212            final int len = Math.min(end, data.length());
5213            for (int i = start + 3; i < len; i+=4) {
5214                seed = mum(
5215                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
5216                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
5217            }
5218            switch (len - start & 3) {
5219                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5220                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
5221                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
5222                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
5223            }
5224            return mum(seed ^ seed << 16, len - start ^ b0);
5225        }
5226
5227
5228        public static long hash64(long seed, final char[][] data) {
5229            if (data == null) return 0L;
5230            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5231            final int len = data.length;
5232            for (int i = 3; i < len; i+=4) {
5233                seed = mum(
5234                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5235                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5236            }
5237            int t;
5238            switch (len & 3) {
5239                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5240                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5241                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5242                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5243            }
5244            seed = (seed ^ seed << 16) * (len ^ b0);
5245            return seed - (seed >>> 31) + (seed << 33);
5246        }
5247
5248        public static long hash64(long seed, final int[][] data) {
5249            if (data == null) return 0L;
5250            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5251            final int len = data.length;
5252            for (int i = 3; i < len; i+=4) {
5253                seed = mum(
5254                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5255                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5256            }
5257            int t;
5258            switch (len & 3) {
5259                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5260                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5261                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5262                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5263            }
5264            seed = (seed ^ seed << 16) * (len ^ b0);
5265            return seed - (seed >>> 31) + (seed << 33);
5266        }
5267
5268        public static long hash64(long seed, final long[][] data) {
5269            if (data == null) return 0L;
5270            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5271            final int len = data.length;
5272            for (int i = 3; i < len; i+=4) {
5273                seed = mum(
5274                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5275                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5276            }
5277            int t;
5278            switch (len & 3) {
5279                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5280                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5281                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5282                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5283            }
5284            seed = (seed ^ seed << 16) * (len ^ b0);
5285            return seed - (seed >>> 31) + (seed << 33);
5286        }
5287
5288        public static long hash64(long seed, final CharSequence[] data) {
5289            if (data == null) return 0L;
5290            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5291            final int len = data.length;
5292            for (int i = 3; i < len; i+=4) {
5293                seed = mum(
5294                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5295                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5296            }
5297            int t;
5298            switch (len & 3) {
5299                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5300                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5301                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5302                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5303            }
5304            seed = (seed ^ seed << 16) * (len ^ b0);
5305            return seed - (seed >>> 31) + (seed << 33);
5306        }
5307
5308        public static long hash64(long seed, final CharSequence[]... data) {
5309            if (data == null) return 0L;
5310            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5311            final int len = data.length;
5312            for (int i = 3; i < len; i+=4) {
5313                seed = mum(
5314                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5315                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5316            }
5317            int t;
5318            switch (len & 3) {
5319                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5320                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5321                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5322                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5323            }
5324            seed = (seed ^ seed << 16) * (len ^ b0);
5325            return seed - (seed >>> 31) + (seed << 33);
5326        }
5327
5328        public static long hash64(long seed, final Iterable<? extends CharSequence> data) {
5329            if (data == null) return 0L;
5330            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5331            final Iterator<? extends CharSequence> it = data.iterator();
5332            int len = 0;
5333            while (it.hasNext())
5334            {
5335                ++len;
5336                seed = mum(
5337                        mum(hash(seed, it.next()) ^ b1, (it.hasNext() ? hash(seed, it.next()) ^ b2 ^ ++len : b2)) + seed,
5338                        mum((it.hasNext() ? hash(seed, it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(seed, it.next()) ^ b4 ^ ++len : b4)));
5339            }
5340            seed = (seed ^ seed << 16) * (len ^ b0);
5341            return seed - (seed >>> 31) + (seed << 33);
5342        }
5343
5344        public static long hash64(long seed, final List<? extends CharSequence> data) {
5345            if (data == null) return 0L;
5346            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5347            final int len = data.size();
5348            for (int i = 3; i < len; i+=4) {
5349                seed = mum(
5350                        mum(hash(seed, data.get(i-3)) ^ b1, hash(seed, data.get(i-2)) ^ b2) + seed,
5351                        mum(hash(seed, data.get(i-1)) ^ b3, hash(seed, data.get(i  )) ^ b4));
5352            }
5353            int t;
5354            switch (len & 3) {
5355                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5356                case 1: seed = mum(seed ^((t = hash(seed, data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5357                case 2: seed = mum(seed ^ hash(seed, data.get(len-2)), b0 ^ hash(seed, data.get(len-1))); break;
5358                case 3: seed = mum(seed ^ hash(seed, data.get(len-3)), b2 ^ hash(seed, data.get(len-2))) ^ mum(seed ^ hash(seed, data.get(len-1)), b4); break;
5359            }
5360            seed = (seed ^ seed << 16) * (len ^ b0);
5361            return seed - (seed >>> 31) + (seed << 33);
5362
5363        }
5364
5365        public static long hash64(long seed, final Object[] data) {
5366            if (data == null) return 0L;
5367            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5368            final int len = data.length;
5369            for (int i = 3; i < len; i+=4) {
5370                seed = mum(
5371                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5372                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5373            }
5374            int t;
5375            switch (len & 3) {
5376                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5377                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5378                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5379                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5380            }
5381            seed = (seed ^ seed << 16) * (len ^ b0);
5382            return seed - (seed >>> 31) + (seed << 33);
5383        }
5384
5385        public static long hash64(long seed, final Object data) {
5386            if (data == null)
5387                return 0;
5388            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5389            final long h = (data.hashCode() + seed) * 0x9E3779B97F4A7C15L;
5390            return h - (h >>> 31) + (h << 33);
5391        }
5392
5393
5394        public static int hash(long seed, final boolean[] data) {
5395            if (data == null) return 0;
5396            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5397            final int len = data.length;
5398            for (int i = 3; i < len; i+=4) {
5399                seed = mum(
5400                        mum((data[i-3] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b1, (data[i-2] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b2) + seed,
5401                        mum((data[i-1] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b3, (data[i] ? 0x9E3779B9L : 0x7F4A7C15L) ^ b4));
5402            }
5403            switch (len & 3) {
5404                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5405                case 1: seed = mum(seed ^ (data[len-1] ? 0x9E37L : 0x7F4AL), b3 ^ (data[len-1]  ? 0x79B9L : 0x7C15L)); break;
5406                case 2: seed = mum(seed ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L), b0 ^ (data[len-1] ? 0x9E3779B9L : 0x7F4A7C15L)); break;
5407                case 3: seed = mum(seed ^ (data[len-3] ? 0x9E3779B9L : 0x7F4A7C15L), b2 ^ (data[len-2] ? 0x9E3779B9L : 0x7F4A7C15L)) ^ mum(seed ^ (data[len-1] ? 0x9E3779B9 : 0x7F4A7C15), b4); break;
5408            }
5409            return (int) mum(seed ^ seed << 16, len ^ b0);
5410        }
5411        public static int hash(long seed, final byte[] data) {
5412            if (data == null) return 0;
5413            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5414            final int len = data.length;
5415            for (int i = 3; i < len; i+=4) {
5416                seed = mum(
5417                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5418                        mum(data[i-1] ^ b3, data[i] ^ b4));
5419            }
5420            switch (len & 3) {
5421                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5422                case 1: seed = mum(seed ^ b2, b1 ^ data[len-1]); break;
5423                case 2: seed = mum(seed ^ b3, data[len-2] ^ data[len-1] << 8 ^ b4); break;
5424                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 8, b2 ^ data[len-1]); break;
5425            }
5426            return (int) mum(seed ^ seed << 16, len ^ b0);
5427        }
5428
5429        public static int hash(long seed, final short[] data) {
5430            if (data == null) return 0;
5431            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5432            final int len = data.length;
5433            for (int i = 3; i < len; i+=4) {
5434                seed = mum(
5435                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5436                        mum(data[i-1] ^ b3, data[i] ^ b4));
5437            }
5438            switch (len & 3) {
5439                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5440                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5441                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5442                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5443            }
5444            return (int) mum(seed ^ seed << 16, len ^ b0);
5445        }
5446
5447        public static int hash(long seed, final char[] data) {
5448            if (data == null) return 0;
5449            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5450            final int len = data.length;
5451            for (int i = 3; i < len; i+=4) {
5452                seed = mum(
5453                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5454                        mum(data[i-1] ^ b3, data[i] ^ b4));
5455            }
5456            switch (len & 3) {
5457                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5458                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5459                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5460                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5461            }
5462            return (int) mum(seed ^ seed << 16, len ^ b0);
5463        }
5464
5465        public static int hash(long seed, final CharSequence data) {
5466            if (data == null) return 0;
5467            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5468            final int len = data.length();
5469            for (int i = 3; i < len; i+=4) {
5470                seed = mum(
5471                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
5472                        mum(data.charAt(i-1) ^ b3, data.charAt(i  ) ^ b4));
5473            }
5474            switch (len & 3) {
5475                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5476                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
5477                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
5478                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
5479            }
5480            return (int) mum(seed ^ seed << 16, len ^ b0);
5481        }
5482        public static int hash(long seed, final int[] data) {
5483            if (data == null) return 0;
5484            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5485            final int len = data.length;
5486            for (int i = 3; i < len; i+=4) {
5487                seed = mum(
5488                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5489                        mum(data[i-1] ^ b3, data[i] ^ b4));
5490            }
5491            switch (len & 3) {
5492                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5493                case 1: seed = mum(seed ^ (data[len-1] >>> 16), b3 ^ (data[len-1] & 0xFFFFL)); break;
5494                case 2: seed = mum(seed ^ data[len-2], b0 ^ data[len-1]); break;
5495                case 3: seed = mum(seed ^ data[len-3], b2 ^ data[len-2]) ^ mum(seed ^ data[len-1], b4); break;
5496            }
5497            return (int) mum(seed ^ seed << 16, len ^ b0);
5498        }
5499        public static int hash(long seed, final int[] data, final int length) {
5500            if (data == null) return 0;
5501            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5502            for (int i = 3; i < length; i+=4) {
5503                seed = mum(
5504                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5505                        mum(data[i-1] ^ b3, data[i] ^ b4));
5506            }
5507            switch (length & 3) {
5508                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5509                case 1: seed = mum(seed ^ (data[length-1] >>> 16), b3 ^ (data[length-1] & 0xFFFFL)); break;
5510                case 2: seed = mum(seed ^ data[length-2], b0 ^ data[length-1]); break;
5511                case 3: seed = mum(seed ^ data[length-3], b2 ^ data[length-2]) ^ mum(seed ^ data[length-1], b4); break;
5512            }
5513            return (int) mum(seed ^ seed << 16, length ^ b0);
5514        }
5515
5516        public static int hash(long seed, final long[] data) {
5517            if (data == null) return 0;
5518            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5519            long a = seed + b4, b = seed + b3, c = seed + b2, d = seed + b1;
5520            final int len = data.length;
5521            for (int i = 3; i < len; i+=4) {
5522                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
5523                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
5524                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
5525                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
5526                seed += a + b + c + d;
5527            }
5528            seed += b5;
5529            switch (len & 3) {
5530                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
5531                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
5532                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
5533            }
5534            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
5535            return (int)(seed - (seed >>> 32));
5536        }
5537
5538        public static int hash(long seed, final float[] data) {
5539            if (data == null) return 0;
5540            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5541            final int len = data.length;
5542            for (int i = 3; i < len; i+=4) {
5543                seed = mum(
5544                        mum(floatToIntBits(data[i-3]) ^ b1, floatToIntBits(data[i-2]) ^ b2) + seed,
5545                        mum(floatToIntBits(data[i-1]) ^ b3, floatToIntBits(data[i]) ^ b4));
5546            }
5547            switch (len & 3) {
5548                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5549                case 1: seed = mum(seed ^ (floatToIntBits(data[len-1]) >>> 16), b3 ^ (floatToIntBits(data[len-1]) & 0xFFFFL)); break;
5550                case 2: seed = mum(seed ^ floatToIntBits(data[len-2]), b0 ^ floatToIntBits(data[len-1])); break;
5551                case 3: seed = mum(seed ^ floatToIntBits(data[len-3]), b2 ^ floatToIntBits(data[len-2])) ^ mum(seed ^ floatToIntBits(data[len-1]), b4); break;
5552            }
5553            return (int) mum(seed ^ seed << 16, len ^ b0);
5554        }
5555        public static int hash(long seed, final double[] data) {
5556            if (data == null) return 0;
5557            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5558            final int len = data.length;
5559            for (int i = 3; i < len; i+=4) {
5560                seed = mum(
5561                        mum(doubleToMixedIntBits(data[i-3]) ^ b1, doubleToMixedIntBits(data[i-2]) ^ b2) + seed,
5562                        mum(doubleToMixedIntBits(data[i-1]) ^ b3, doubleToMixedIntBits(data[i]) ^ b4));
5563            }
5564            switch (len & 3) {
5565                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5566                case 1: seed = mum(seed ^ (doubleToMixedIntBits(data[len-1]) >>> 16), b3 ^ (doubleToMixedIntBits(data[len-1]) & 0xFFFFL)); break;
5567                case 2: seed = mum(seed ^ doubleToMixedIntBits(data[len-2]), b0 ^ doubleToMixedIntBits(data[len-1])); break;
5568                case 3: seed = mum(seed ^ doubleToMixedIntBits(data[len-3]), b2 ^ doubleToMixedIntBits(data[len-2])) ^ mum(seed ^ doubleToMixedIntBits(data[len-1]), b4); break;
5569            }
5570            return (int) mum(seed ^ seed << 16, len ^ b0);
5571        }
5572
5573        /**
5574         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
5575         *
5576         * @param data  the char array to hash
5577         * @param start the start of the section to hash (inclusive)
5578         * @param end   the end of the section to hash (exclusive)
5579         * @return a 32-bit hash code for the requested section of data
5580         */
5581        public static int hash(long seed, final char[] data, final int start, final int end) {
5582            if (data == null || start >= end)
5583                return 0;
5584            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5585            final int len = Math.min(end, data.length);
5586            for (int i = start + 3; i < len; i+=4) {
5587                seed = mum(
5588                        mum(data[i-3] ^ b1, data[i-2] ^ b2) + seed,
5589                        mum(data[i-1] ^ b3, data[i] ^ b4));
5590            }
5591            switch (len - start & 3) {
5592                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5593                case 1: seed = mum(seed ^ b3, b4 ^ data[len-1]); break;
5594                case 2: seed = mum(seed ^ data[len-2], b3 ^ data[len-1]); break;
5595                case 3: seed = mum(seed ^ data[len-3] ^ data[len-2] << 16, b1 ^ data[len-1]); break;
5596            }
5597            return (int) mum(seed ^ seed << 16, len - start ^ b0);
5598        }
5599
5600        /**
5601         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
5602         *
5603         * @param data  the String or other CharSequence to hash
5604         * @param start the start of the section to hash (inclusive)
5605         * @param end   the end of the section to hash (exclusive)
5606         * @return a 32-bit hash code for the requested section of data
5607         */
5608        public static int hash(long seed, final CharSequence data, final int start, final int end) {
5609            if (data == null || start >= end)
5610                return 0;
5611            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5612            final int len = Math.min(end, data.length());
5613            for (int i = start + 3; i < len; i+=4) {
5614                seed = mum(
5615                        mum(data.charAt(i-3) ^ b1, data.charAt(i-2) ^ b2) + seed,
5616                        mum(data.charAt(i-1) ^ b3, data.charAt(i) ^ b4));
5617            }
5618            switch (len - start & 3) {
5619                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5620                case 1: seed = mum(seed ^ b3, b4 ^ data.charAt(len-1)); break;
5621                case 2: seed = mum(seed ^ data.charAt(len-2), b3 ^ data.charAt(len-1)); break;
5622                case 3: seed = mum(seed ^ data.charAt(len-3) ^ data.charAt(len-2) << 16, b1 ^ data.charAt(len-1)); break;
5623            }
5624            return (int) mum(seed ^ seed << 16, len - start ^ b0);
5625        }
5626
5627
5628        public static int hash(long seed, final char[][] data) {
5629            if (data == null) return 0;
5630            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5631            final int len = data.length;
5632            for (int i = 3; i < len; i+=4) {
5633                seed = mum(
5634                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5635                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5636            }
5637            int t;
5638            switch (len & 3) {
5639                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5640                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5641                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5642                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5643            }
5644            return (int) mum(seed ^ seed << 16, len ^ b0);
5645        }
5646
5647        public static int hash(long seed, final int[][] data) {
5648            if (data == null) return 0;
5649            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5650            final int len = data.length;
5651            for (int i = 3; i < len; i+=4) {
5652                seed = mum(
5653                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5654                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5655            }
5656            int t;
5657            switch (len & 3) {
5658                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5659                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5660                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5661                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5662            }
5663            return (int) mum(seed ^ seed << 16, len ^ b0);
5664        }
5665
5666        public static int hash(long seed, final long[][] data) {
5667            if (data == null) return 0;
5668            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5669            final int len = data.length;
5670            for (int i = 3; i < len; i+=4) {
5671                seed = mum(
5672                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5673                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5674            }
5675            int t;
5676            switch (len & 3) {
5677                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5678                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5679                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5680                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5681            }
5682            return (int) mum(seed ^ seed << 16, len ^ b0);
5683        }
5684
5685        public static int hash(long seed, final CharSequence[] data) {
5686            if (data == null) return 0;
5687            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5688            final int len = data.length;
5689            for (int i = 3; i < len; i+=4) {
5690                seed = mum(
5691                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5692                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5693            }
5694            int t;
5695            switch (len & 3) {
5696                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5697                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5698                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5699                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5700            }
5701            return (int) mum(seed ^ seed << 16, len ^ b0);
5702        }
5703
5704        public static int hash(long seed, final CharSequence[]... data) {
5705            if (data == null) return 0;
5706            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5707            final int len = data.length;
5708            for (int i = 3; i < len; i+=4) {
5709                seed = mum(
5710                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5711                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5712            }
5713            int t;
5714            switch (len & 3) {
5715                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5716                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5717                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5718                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5719            }
5720            return (int) mum(seed ^ seed << 16, len ^ b0);
5721        }
5722
5723        public static int hash(long seed, final Iterable<? extends CharSequence> data) {
5724            if (data == null) return 0;
5725            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5726            final Iterator<? extends CharSequence> it = data.iterator();
5727            int len = 0;
5728            while (it.hasNext())
5729            {
5730                ++len;
5731                seed = mum(
5732                        mum(hash(seed, it.next()) ^ b1, (it.hasNext() ? hash(seed, it.next()) ^ b2 ^ ++len : b2)) + seed,
5733                        mum((it.hasNext() ? hash(seed, it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(seed, it.next()) ^ b4 ^ ++len : b4)));
5734            }
5735            return (int) mum(seed ^ seed << 16, len ^ b0);
5736        }
5737
5738        public static int hash(long seed, final List<? extends CharSequence> data) {
5739            if (data == null) return 0;
5740            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5741            final int len = data.size();
5742            for (int i = 3; i < len; i+=4) {
5743                seed = mum(
5744                        mum(hash(seed, data.get(i-3)) ^ b1, hash(seed, data.get(i-2)) ^ b2) + seed,
5745                        mum(hash(seed, data.get(i-1)) ^ b3, hash(seed, data.get(i  )) ^ b4));
5746            }
5747            int t;
5748            switch (len & 3) {
5749                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5750                case 1: seed = mum(seed ^((t = hash(seed, data.get(len-1))) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5751                case 2: seed = mum(seed ^ hash(seed, data.get(len-2)), b0 ^ hash(seed, data.get(len-1))); break;
5752                case 3: seed = mum(seed ^ hash(seed, data.get(len-3)), b2 ^ hash(seed, data.get(len-2))) ^ mum(seed ^ hash(seed, data.get(len-1)), b4); break;
5753            }
5754            return (int) mum(seed ^ seed << 16, len ^ b0);
5755        }
5756
5757        public static int hash(long seed, final Object[] data) {
5758            if (data == null) return 0;
5759            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5760            final int len = data.length;
5761            for (int i = 3; i < len; i+=4) {
5762                seed = mum(
5763                        mum(hash(seed, data[i-3]) ^ b1, hash(seed, data[i-2]) ^ b2) + seed,
5764                        mum(hash(seed, data[i-1]) ^ b3, hash(seed, data[i  ]) ^ b4));
5765            }
5766            int t;
5767            switch (len & 3) {
5768                case 0: seed = mum(b1 ^ seed, b4 + seed); break;
5769                case 1: seed = mum(seed ^((t = hash(seed, data[len-1])) >>> 16), b3 ^ (t & 0xFFFFL)); break;
5770                case 2: seed = mum(seed ^ hash(seed, data[len-2]), b0 ^ hash(seed, data[len-1])); break;
5771                case 3: seed = mum(seed ^ hash(seed, data[len-3]), b2 ^ hash(seed, data[len-2])) ^ mum(seed ^ hash(seed, data[len-1]), b4); break;
5772            }
5773            return (int) mum(seed ^ seed << 16, len ^ b0);
5774        }
5775
5776        public static int hash(long seed, final Object data) {
5777            if (data == null)
5778                return 0;
5779            seed += b1; seed ^= seed >>> 23 ^ seed >>> 48 ^ seed << 7 ^ seed << 53;
5780            return (int)((data.hashCode() + seed) * 0x9E3779B97F4A7C15L >>> 32);
5781        }
5782
5783
5784    }
5785
5786    /**
5787     * Like Yolk, this is a class for hash functors, each an object with a 64-bit long seed. It uses an odd-but-fast
5788     * SIMD-friendly technique when hashing 32-bit items or smaller, and falls back to Yolk's algorithm when hashing
5789     * long values. If you are mainly hashing int arrays, short arrays, or byte arrays, this is probably the fastest
5790     * hash here unless the arrays are small (it outperforms all of the other hashes here on int arrays when those
5791     * arrays have length 50, and probably is faster than some sooner than that). Notably, on arrays 50 or longer this
5792     * runs in very close to half the time of {@link Arrays#hashCode(int[])}. This passes SMHasher for at least 64-bit
5793     * output. Has a lot of predefined functors (192, named after 24 Greek letters and 72 Goetic demons, see
5794     * <a href="https://en.wikipedia.org/wiki/Lesser_Key_of_Solomon#The_Seventy-Two_Demons">Wikipedia for the demons</a>,
5795     * in both lower case and lower case with a trailing underscore). You probably want to use {@link #predefined}
5796     * instead of wrangling demon names; you can always choose an element from predefined with a 7-bit number, and there
5797     * are 64 numbers outside that range so you can choose any of those when a functor must be different.
5798     * <br>
5799     * This hash is much more effective with large inputs because it takes advantage of HotSpot's optimizations for code
5800     * that looks like a dot product over part of an array. The general concept for this hash came from the "Unrolled"
5801     * hash in <a href="https://richardstartin.github.io/posts/collecting-rocks-and-benchmarks">one of Richard Startin's
5802     * blog posts</a>, which traces back to
5803     * <a href="http://mail.openjdk.java.net/pipermail/core-libs-dev/2014-September/028898.html">Peter Levart posting a
5804     * related improvement on String.hashCode()</a> in 2014. This isn't as fast as Startin's "Vectorized" hash, but this
5805     * works on variable array lengths and also passes SMHasher.
5806     * <br>
5807     * The name curlup comes from an M.C. Escher painting of a creature, whose name translates to curl-up, that could
5808     * walk on six legs to climb stairs, or roll at high speeds when the conditions were right.
5809     */
5810    public static final class Curlup {
5811        private final long seed;
5812
5813        public Curlup(){
5814            this.seed = 0xC4CEB9FE1A85EC53L;
5815        }
5816        public Curlup(long seed)
5817        {
5818            this.seed = randomize(seed);
5819        }
5820
5821        /**
5822         * Very similar to Pelican and related unary hashes; uses "xor rotate xor rotate" as an early step to mix any
5823         * clustered bits all around the result, then the rest is like MurmurHash3's mixer.
5824         * @param seed any long; there is no fix point at 0
5825         * @return any long
5826         */
5827        public static long randomize(long seed) {
5828            seed ^= (seed << 41 | seed >>> 23) ^ (seed << 17 | seed >>> 47) ^ 0xCB9C59B3F9F87D4DL;
5829            seed *= 0x369DEA0F31A53F85L;
5830            seed ^= seed >>> 31;
5831            seed *= 0xDB4F0B9175AE2165L;
5832            return seed ^ seed >>> 28;
5833        }
5834
5835        public Curlup(final CharSequence seed)
5836        {
5837            this(Water.hash64(seed));
5838        }
5839
5840        public static final Curlup alpha = new Curlup("alpha"), beta = new Curlup("beta"), gamma = new Curlup("gamma"),
5841                delta = new Curlup("delta"), epsilon = new Curlup("epsilon"), zeta = new Curlup("zeta"),
5842                eta = new Curlup("eta"), theta = new Curlup("theta"), iota = new Curlup("iota"),
5843                kappa = new Curlup("kappa"), lambda = new Curlup("lambda"), mu = new Curlup("mu"),
5844                nu = new Curlup("nu"), xi = new Curlup("xi"), omicron = new Curlup("omicron"), pi = new Curlup("pi"),
5845                rho = new Curlup("rho"), sigma = new Curlup("sigma"), tau = new Curlup("tau"),
5846                upsilon = new Curlup("upsilon"), phi = new Curlup("phi"), chi = new Curlup("chi"), psi = new Curlup("psi"),
5847                omega = new Curlup("omega"),
5848                alpha_ = new Curlup("ALPHA"), beta_ = new Curlup("BETA"), gamma_ = new Curlup("GAMMA"),
5849                delta_ = new Curlup("DELTA"), epsilon_ = new Curlup("EPSILON"), zeta_ = new Curlup("ZETA"),
5850                eta_ = new Curlup("ETA"), theta_ = new Curlup("THETA"), iota_ = new Curlup("IOTA"),
5851                kappa_ = new Curlup("KAPPA"), lambda_ = new Curlup("LAMBDA"), mu_ = new Curlup("MU"),
5852                nu_ = new Curlup("NU"), xi_ = new Curlup("XI"), omicron_ = new Curlup("OMICRON"), pi_ = new Curlup("PI"),
5853                rho_ = new Curlup("RHO"), sigma_ = new Curlup("SIGMA"), tau_ = new Curlup("TAU"),
5854                upsilon_ = new Curlup("UPSILON"), phi_ = new Curlup("PHI"), chi_ = new Curlup("CHI"), psi_ = new Curlup("PSI"),
5855                omega_ = new Curlup("OMEGA"),
5856                baal = new Curlup("baal"), agares = new Curlup("agares"), vassago = new Curlup("vassago"), samigina = new Curlup("samigina"),
5857                marbas = new Curlup("marbas"), valefor = new Curlup("valefor"), amon = new Curlup("amon"), barbatos = new Curlup("barbatos"),
5858                paimon = new Curlup("paimon"), buer = new Curlup("buer"), gusion = new Curlup("gusion"), sitri = new Curlup("sitri"),
5859                beleth = new Curlup("beleth"), leraje = new Curlup("leraje"), eligos = new Curlup("eligos"), zepar = new Curlup("zepar"),
5860                botis = new Curlup("botis"), bathin = new Curlup("bathin"), sallos = new Curlup("sallos"), purson = new Curlup("purson"),
5861                marax = new Curlup("marax"), ipos = new Curlup("ipos"), aim = new Curlup("aim"), naberius = new Curlup("naberius"),
5862                glasya_labolas = new Curlup("glasya_labolas"), bune = new Curlup("bune"), ronove = new Curlup("ronove"), berith = new Curlup("berith"),
5863                astaroth = new Curlup("astaroth"), forneus = new Curlup("forneus"), foras = new Curlup("foras"), asmoday = new Curlup("asmoday"),
5864                gaap = new Curlup("gaap"), furfur = new Curlup("furfur"), marchosias = new Curlup("marchosias"), stolas = new Curlup("stolas"),
5865                phenex = new Curlup("phenex"), halphas = new Curlup("halphas"), malphas = new Curlup("malphas"), raum = new Curlup("raum"),
5866                focalor = new Curlup("focalor"), vepar = new Curlup("vepar"), sabnock = new Curlup("sabnock"), shax = new Curlup("shax"),
5867                vine = new Curlup("vine"), bifrons = new Curlup("bifrons"), vual = new Curlup("vual"), haagenti = new Curlup("haagenti"),
5868                crocell = new Curlup("crocell"), furcas = new Curlup("furcas"), balam = new Curlup("balam"), alloces = new Curlup("alloces"),
5869                caim = new Curlup("caim"), murmur = new Curlup("murmur"), orobas = new Curlup("orobas"), gremory = new Curlup("gremory"),
5870                ose = new Curlup("ose"), amy = new Curlup("amy"), orias = new Curlup("orias"), vapula = new Curlup("vapula"),
5871                zagan = new Curlup("zagan"), valac = new Curlup("valac"), andras = new Curlup("andras"), flauros = new Curlup("flauros"),
5872                andrealphus = new Curlup("andrealphus"), kimaris = new Curlup("kimaris"), amdusias = new Curlup("amdusias"), belial = new Curlup("belial"),
5873                decarabia = new Curlup("decarabia"), seere = new Curlup("seere"), dantalion = new Curlup("dantalion"), andromalius = new Curlup("andromalius"),
5874                baal_ = new Curlup("BAAL"), agares_ = new Curlup("AGARES"), vassago_ = new Curlup("VASSAGO"), samigina_ = new Curlup("SAMIGINA"),
5875                marbas_ = new Curlup("MARBAS"), valefor_ = new Curlup("VALEFOR"), amon_ = new Curlup("AMON"), barbatos_ = new Curlup("BARBATOS"),
5876                paimon_ = new Curlup("PAIMON"), buer_ = new Curlup("BUER"), gusion_ = new Curlup("GUSION"), sitri_ = new Curlup("SITRI"),
5877                beleth_ = new Curlup("BELETH"), leraje_ = new Curlup("LERAJE"), eligos_ = new Curlup("ELIGOS"), zepar_ = new Curlup("ZEPAR"),
5878                botis_ = new Curlup("BOTIS"), bathin_ = new Curlup("BATHIN"), sallos_ = new Curlup("SALLOS"), purson_ = new Curlup("PURSON"),
5879                marax_ = new Curlup("MARAX"), ipos_ = new Curlup("IPOS"), aim_ = new Curlup("AIM"), naberius_ = new Curlup("NABERIUS"),
5880                glasya_labolas_ = new Curlup("GLASYA_LABOLAS"), bune_ = new Curlup("BUNE"), ronove_ = new Curlup("RONOVE"), berith_ = new Curlup("BERITH"),
5881                astaroth_ = new Curlup("ASTAROTH"), forneus_ = new Curlup("FORNEUS"), foras_ = new Curlup("FORAS"), asmoday_ = new Curlup("ASMODAY"),
5882                gaap_ = new Curlup("GAAP"), furfur_ = new Curlup("FURFUR"), marchosias_ = new Curlup("MARCHOSIAS"), stolas_ = new Curlup("STOLAS"),
5883                phenex_ = new Curlup("PHENEX"), halphas_ = new Curlup("HALPHAS"), malphas_ = new Curlup("MALPHAS"), raum_ = new Curlup("RAUM"),
5884                focalor_ = new Curlup("FOCALOR"), vepar_ = new Curlup("VEPAR"), sabnock_ = new Curlup("SABNOCK"), shax_ = new Curlup("SHAX"),
5885                vine_ = new Curlup("VINE"), bifrons_ = new Curlup("BIFRONS"), vual_ = new Curlup("VUAL"), haagenti_ = new Curlup("HAAGENTI"),
5886                crocell_ = new Curlup("CROCELL"), furcas_ = new Curlup("FURCAS"), balam_ = new Curlup("BALAM"), alloces_ = new Curlup("ALLOCES"),
5887                caim_ = new Curlup("CAIM"), murmur_ = new Curlup("MURMUR"), orobas_ = new Curlup("OROBAS"), gremory_ = new Curlup("GREMORY"),
5888                ose_ = new Curlup("OSE"), amy_ = new Curlup("AMY"), orias_ = new Curlup("ORIAS"), vapula_ = new Curlup("VAPULA"),
5889                zagan_ = new Curlup("ZAGAN"), valac_ = new Curlup("VALAC"), andras_ = new Curlup("ANDRAS"), flauros_ = new Curlup("FLAUROS"),
5890                andrealphus_ = new Curlup("ANDREALPHUS"), kimaris_ = new Curlup("KIMARIS"), amdusias_ = new Curlup("AMDUSIAS"), belial_ = new Curlup("BELIAL"),
5891                decarabia_ = new Curlup("DECARABIA"), seere_ = new Curlup("SEERE"), dantalion_ = new Curlup("DANTALION"), andromalius_ = new Curlup("ANDROMALIUS")
5892                ;
5893        /**
5894         * Has a length of 192, which may be relevant if automatically choosing a predefined hash functor.
5895         */
5896        public static final Curlup[] predefined = new Curlup[]{alpha, beta, gamma, delta, epsilon, zeta, eta, theta, iota,
5897                kappa, lambda, mu, nu, xi, omicron, pi, rho, sigma, tau, upsilon, phi, chi, psi, omega,
5898                alpha_, beta_, gamma_, delta_, epsilon_, zeta_, eta_, theta_, iota_,
5899                kappa_, lambda_, mu_, nu_, xi_, omicron_, pi_, rho_, sigma_, tau_, upsilon_, phi_, chi_, psi_, omega_,
5900                baal, agares, vassago, samigina, marbas, valefor, amon, barbatos,
5901                paimon, buer, gusion, sitri, beleth, leraje, eligos, zepar,
5902                botis, bathin, sallos, purson, marax, ipos, aim, naberius,
5903                glasya_labolas, bune, ronove, berith, astaroth, forneus, foras, asmoday,
5904                gaap, furfur, marchosias, stolas, phenex, halphas, malphas, raum,
5905                focalor, vepar, sabnock, shax, vine, bifrons, vual, haagenti,
5906                crocell, furcas, balam, alloces, caim, murmur, orobas, gremory,
5907                ose, amy, orias, vapula, zagan, valac, andras, flauros,
5908                andrealphus, kimaris, amdusias, belial, decarabia, seere, dantalion, andromalius,
5909                baal_, agares_, vassago_, samigina_, marbas_, valefor_, amon_, barbatos_,
5910                paimon_, buer_, gusion_, sitri_, beleth_, leraje_, eligos_, zepar_,
5911                botis_, bathin_, sallos_, purson_, marax_, ipos_, aim_, naberius_,
5912                glasya_labolas_, bune_, ronove_, berith_, astaroth_, forneus_, foras_, asmoday_,
5913                gaap_, furfur_, marchosias_, stolas_, phenex_, halphas_, malphas_, raum_,
5914                focalor_, vepar_, sabnock_, shax_, vine_, bifrons_, vual_, haagenti_,
5915                crocell_, furcas_, balam_, alloces_, caim_, murmur_, orobas_, gremory_,
5916                ose_, amy_, orias_, vapula_, zagan_, valac_, andras_, flauros_,
5917                andrealphus_, kimaris_, amdusias_, belial_, decarabia_, seere_, dantalion_, andromalius_};
5918
5919
5920        public long hash64(final boolean[] data) {
5921            if (data == null) return 0;
5922            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
5923            int i = 0;
5924            for (; i + 7 < data.length; i += 8) {
5925                result =  result      * 0xEBEDEED9D803C815L
5926                        + (data[i]     ? 0xD96EB1A810CAAF5FL : 0xCAAF5FD96EB1A810L)
5927                        + (data[i + 1] ? 0xC862B36DAF790DD5L : 0x790DD5C862B36DAFL)
5928                        + (data[i + 2] ? 0xB8ACD90C142FE10BL : 0x2FE10BB8ACD90C14L)
5929                        + (data[i + 3] ? 0xAA324F90DED86B69L : 0xD86B69AA324F90DEL)
5930                        + (data[i + 4] ? 0x9CDA5E693FEA10AFL : 0xEA10AF9CDA5E693FL)
5931                        + (data[i + 5] ? 0x908E3D2C82567A73L : 0x567A73908E3D2C82L)
5932                        + (data[i + 6] ? 0x8538ECB5BD456EA3L : 0x456EA38538ECB5BDL)
5933                        + (data[i + 7] ? 0xD1B54A32D192ED03L : 0x92ED03D1B54A32D1L)
5934                ;
5935            }
5936            for (; i < data.length; i++) {
5937                result = 0x9E3779B97F4A7C15L * result + (data[i] ? 0xEBEDEED9D803C815L : 0xD9D803C815EBEDEEL);
5938            }
5939            result *= 0x94D049BB133111EBL;
5940            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
5941            result *= 0x369DEA0F31A53F85L;
5942            result ^= result >>> 31;
5943            result *= 0xDB4F0B9175AE2165L;
5944            return (result ^ result >>> 28);
5945        }
5946        public long hash64(final byte[] data) {
5947            if (data == null) return 0;
5948            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
5949            int i = 0;
5950            for (; i + 7 < data.length; i += 8) {
5951                result =  0xEBEDEED9D803C815L * result
5952                        + 0xD96EB1A810CAAF5FL * data[i]
5953                        + 0xC862B36DAF790DD5L * data[i + 1]
5954                        + 0xB8ACD90C142FE10BL * data[i + 2]
5955                        + 0xAA324F90DED86B69L * data[i + 3]
5956                        + 0x9CDA5E693FEA10AFL * data[i + 4]
5957                        + 0x908E3D2C82567A73L * data[i + 5]
5958                        + 0x8538ECB5BD456EA3L * data[i + 6]
5959                        + 0xD1B54A32D192ED03L * data[i + 7]
5960                ;
5961            }
5962            for (; i < data.length; i++) {
5963                result = 0x9E3779B97F4A7C15L * result + data[i];
5964            }
5965            result *= 0x94D049BB133111EBL;
5966            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
5967            result *= 0x369DEA0F31A53F85L;
5968            result ^= result >>> 31;
5969            result *= 0xDB4F0B9175AE2165L;
5970            return (result ^ result >>> 28);
5971        }
5972
5973        public long hash64(final short[] data) {
5974            if (data == null) return 0;
5975            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
5976            int i = 0;
5977            for (; i + 7 < data.length; i += 8) {
5978                result =  0xEBEDEED9D803C815L * result
5979                        + 0xD96EB1A810CAAF5FL * data[i]
5980                        + 0xC862B36DAF790DD5L * data[i + 1]
5981                        + 0xB8ACD90C142FE10BL * data[i + 2]
5982                        + 0xAA324F90DED86B69L * data[i + 3]
5983                        + 0x9CDA5E693FEA10AFL * data[i + 4]
5984                        + 0x908E3D2C82567A73L * data[i + 5]
5985                        + 0x8538ECB5BD456EA3L * data[i + 6]
5986                        + 0xD1B54A32D192ED03L * data[i + 7]
5987                ;
5988            }
5989            for (; i < data.length; i++) {
5990                result = 0x9E3779B97F4A7C15L * result + data[i];
5991            }
5992            result *= 0x94D049BB133111EBL;
5993            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
5994            result *= 0x369DEA0F31A53F85L;
5995            result ^= result >>> 31;
5996            result *= 0xDB4F0B9175AE2165L;
5997            return (result ^ result >>> 28);
5998        }
5999
6000        public long hash64(final char[] data) {
6001            if (data == null) return 0;
6002            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6003            int i = 0;
6004            for (; i + 7 < data.length; i += 8) {
6005                result =  0xEBEDEED9D803C815L * result
6006                        + 0xD96EB1A810CAAF5FL * data[i]
6007                        + 0xC862B36DAF790DD5L * data[i + 1]
6008                        + 0xB8ACD90C142FE10BL * data[i + 2]
6009                        + 0xAA324F90DED86B69L * data[i + 3]
6010                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6011                        + 0x908E3D2C82567A73L * data[i + 5]
6012                        + 0x8538ECB5BD456EA3L * data[i + 6]
6013                        + 0xD1B54A32D192ED03L * data[i + 7]
6014                ;
6015            }
6016            for (; i < data.length; i++) {
6017                result = 0x9E3779B97F4A7C15L * result + data[i];
6018            }
6019            result *= 0x94D049BB133111EBL;
6020            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6021            result *= 0x369DEA0F31A53F85L;
6022            result ^= result >>> 31;
6023            result *= 0xDB4F0B9175AE2165L;
6024            return (result ^ result >>> 28);
6025        }
6026
6027        public long hash64(final CharSequence data) {
6028            if (data == null) return 0;
6029            final int length = data.length();
6030            long result = seed ^ length * 0x9E3779B97F4A7C15L;
6031            int i = 0;
6032            for (; i + 7 < length; i += 8) {
6033                result =  0xEBEDEED9D803C815L * result
6034                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
6035                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
6036                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
6037                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
6038                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
6039                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
6040                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
6041                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
6042                ;
6043            }
6044            for (; i < length; i++) {
6045                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
6046            }
6047            result *= 0x94D049BB133111EBL;
6048            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6049            result *= 0x369DEA0F31A53F85L;
6050            result ^= result >>> 31;
6051            result *= 0xDB4F0B9175AE2165L;
6052            return (result ^ result >>> 28);
6053        }
6054
6055        public long hash64(final int[] data) {
6056            if (data == null) return 0;
6057            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6058            int i = 0;
6059            for (; i + 7 < data.length; i += 8) {
6060                result =  0xEBEDEED9D803C815L * result
6061                        + 0xD96EB1A810CAAF5FL * data[i]
6062                        + 0xC862B36DAF790DD5L * data[i + 1]
6063                        + 0xB8ACD90C142FE10BL * data[i + 2]
6064                        + 0xAA324F90DED86B69L * data[i + 3]
6065                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6066                        + 0x908E3D2C82567A73L * data[i + 5]
6067                        + 0x8538ECB5BD456EA3L * data[i + 6]
6068                        + 0xD1B54A32D192ED03L * data[i + 7]
6069                ;
6070            }
6071            for (; i < data.length; i++) {
6072                result = 0x9E3779B97F4A7C15L * result + data[i];
6073            }
6074            result *= 0x94D049BB133111EBL;
6075            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6076            result *= 0x369DEA0F31A53F85L;
6077            result ^= result >>> 31;
6078            result *= 0xDB4F0B9175AE2165L;
6079            return (result ^ result >>> 28);
6080        }
6081
6082        public long hash64(final int[] data, final int length) {
6083            if (data == null) return 0;
6084            final int len = Math.min(length, data.length);
6085            long result = seed ^ len * 0x9E3779B97F4A7C15L;
6086            int i = 0;
6087            for (; i + 7 < len; i += 8) {
6088                result =  0xEBEDEED9D803C815L * result
6089                        + 0xD96EB1A810CAAF5FL * data[i]
6090                        + 0xC862B36DAF790DD5L * data[i + 1]
6091                        + 0xB8ACD90C142FE10BL * data[i + 2]
6092                        + 0xAA324F90DED86B69L * data[i + 3]
6093                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6094                        + 0x908E3D2C82567A73L * data[i + 5]
6095                        + 0x8538ECB5BD456EA3L * data[i + 6]
6096                        + 0xD1B54A32D192ED03L * data[i + 7]
6097                ;
6098            }
6099            for (; i < len; i++) {
6100                result = 0x9E3779B97F4A7C15L * result + data[i];
6101            }
6102            result *= 0x94D049BB133111EBL;
6103            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6104            result *= 0x369DEA0F31A53F85L;
6105            result ^= result >>> 31;
6106            result *= 0xDB4F0B9175AE2165L;
6107            return (result ^ result >>> 28);
6108        }
6109
6110        public long hash64(final long[] data) {
6111            if (data == null) return 0;
6112            long seed = this.seed, a = this.seed + b4, b = this.seed + b3, c = this.seed + b2, d = this.seed + b1;
6113            final int len = data.length;
6114            for (int i = 3; i < len; i+=4) {
6115                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
6116                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
6117                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
6118                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
6119                seed += a + b + c + d;
6120            }
6121            seed += b5;
6122            switch (len & 3) {
6123                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
6124                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
6125                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
6126            }
6127            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
6128            return seed - (seed >>> 31) + (seed << 33);
6129        }
6130        public long hash64(final float[] data) {
6131            if (data == null) return 0;
6132            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6133            int i = 0;
6134            for (; i + 7 < data.length; i += 8) {
6135                result =  0xEBEDEED9D803C815L * result
6136                        + 0xD96EB1A810CAAF5FL * floatToIntBits(data[i])
6137                        + 0xC862B36DAF790DD5L * floatToIntBits(data[i + 1])
6138                        + 0xB8ACD90C142FE10BL * floatToIntBits(data[i + 2])
6139                        + 0xAA324F90DED86B69L * floatToIntBits(data[i + 3])
6140                        + 0x9CDA5E693FEA10AFL * floatToIntBits(data[i + 4])
6141                        + 0x908E3D2C82567A73L * floatToIntBits(data[i + 5])
6142                        + 0x8538ECB5BD456EA3L * floatToIntBits(data[i + 6])
6143                        + 0xD1B54A32D192ED03L * floatToIntBits(data[i + 7])
6144                ;
6145            }
6146            for (; i < data.length; i++) {
6147                result = 0x9E3779B97F4A7C15L * result + floatToIntBits(data[i]);
6148            }
6149            result *= 0x94D049BB133111EBL;
6150            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6151            result *= 0x369DEA0F31A53F85L;
6152            result ^= result >>> 31;
6153            result *= 0xDB4F0B9175AE2165L;
6154            return (result ^ result >>> 28);
6155        }
6156        public long hash64(final double[] data) {
6157            if (data == null) return 0;
6158            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6159            int i = 0;
6160            for (; i + 7 < data.length; i += 8) {
6161                result =  0xEBEDEED9D803C815L * result
6162                        + 0xD96EB1A810CAAF5FL * doubleToMixedIntBits(data[i])
6163                        + 0xC862B36DAF790DD5L * doubleToMixedIntBits(data[i + 1])
6164                        + 0xB8ACD90C142FE10BL * doubleToMixedIntBits(data[i + 2])
6165                        + 0xAA324F90DED86B69L * doubleToMixedIntBits(data[i + 3])
6166                        + 0x9CDA5E693FEA10AFL * doubleToMixedIntBits(data[i + 4])
6167                        + 0x908E3D2C82567A73L * doubleToMixedIntBits(data[i + 5])
6168                        + 0x8538ECB5BD456EA3L * doubleToMixedIntBits(data[i + 6])
6169                        + 0xD1B54A32D192ED03L * doubleToMixedIntBits(data[i + 7])
6170                ;
6171            }
6172            for (; i < data.length; i++) {
6173                result = 0x9E3779B97F4A7C15L * result + doubleToMixedIntBits(data[i]);
6174            }
6175            result *= 0x94D049BB133111EBL;
6176            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6177            result *= 0x369DEA0F31A53F85L;
6178            result ^= result >>> 31;
6179            result *= 0xDB4F0B9175AE2165L;
6180            return (result ^ result >>> 28);
6181        }
6182
6183        /**
6184         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
6185         *
6186         * @param data  the char array to hash
6187         * @param start the start of the section to hash (inclusive)
6188         * @param end   the end of the section to hash (exclusive)
6189         * @return a 64-bit hash code for the requested section of data
6190         */
6191        public long hash64(final char[] data, final int start, final int end) {
6192            if (data == null || start >= end) return 0;
6193            final int len = Math.min(end, data.length);
6194
6195            long result = seed ^ (len - start) * 0x9E3779B97F4A7C15L;
6196            int i = start;
6197            for (; i + 7 < len; i += 8) {
6198                result =  0xEBEDEED9D803C815L * result
6199                        + 0xD96EB1A810CAAF5FL * data[i]
6200                        + 0xC862B36DAF790DD5L * data[i + 1]
6201                        + 0xB8ACD90C142FE10BL * data[i + 2]
6202                        + 0xAA324F90DED86B69L * data[i + 3]
6203                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6204                        + 0x908E3D2C82567A73L * data[i + 5]
6205                        + 0x8538ECB5BD456EA3L * data[i + 6]
6206                        + 0xD1B54A32D192ED03L * data[i + 7]
6207                ;
6208            }
6209            for (; i < len; i++) {
6210                result = 0x9E3779B97F4A7C15L * result + data[i];
6211            }
6212            result *= 0x94D049BB133111EBL;
6213            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6214            result *= 0x369DEA0F31A53F85L;
6215            result ^= result >>> 31;
6216            result *= 0xDB4F0B9175AE2165L;
6217            return (result ^ result >>> 28);
6218        }
6219
6220        /**
6221         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
6222         *
6223         * @param data  the String or other CharSequence to hash
6224         * @param start the start of the section to hash (inclusive)
6225         * @param end   the end of the section to hash (exclusive)
6226         * @return a 64-bit hash code for the requested section of data
6227         */
6228        public long hash64(final CharSequence data, final int start, final int end) {
6229            if (data == null || start >= end) return 0;
6230            final int len = Math.min(end, data.length());
6231
6232            long result = seed ^ (len - start) * 0x9E3779B97F4A7C15L;
6233            int i = start;
6234            for (; i + 7 < len; i += 8) {
6235                result =  0xEBEDEED9D803C815L * result
6236                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
6237                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
6238                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
6239                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
6240                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
6241                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
6242                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
6243                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
6244                ;
6245            }
6246            for (; i < len; i++) {
6247                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
6248            }
6249            result *= 0x94D049BB133111EBL;
6250            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6251            result *= 0x369DEA0F31A53F85L;
6252            result ^= result >>> 31;
6253            result *= 0xDB4F0B9175AE2165L;
6254            return (result ^ result >>> 28);
6255        }
6256
6257
6258        public long hash64(final char[][] data) {
6259            if (data == null) return 0;
6260            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6261            int i = 0;
6262            for (; i + 7 < data.length; i += 8) {
6263                result =  0xEBEDEED9D803C815L * result
6264                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6265                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6266                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6267                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6268                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6269                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6270                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6271                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6272                ;
6273            }
6274            for (; i < data.length; i++) {
6275                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6276            }
6277            result *= 0x94D049BB133111EBL;
6278            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6279            result *= 0x369DEA0F31A53F85L;
6280            result ^= result >>> 31;
6281            result *= 0xDB4F0B9175AE2165L;
6282            return (result ^ result >>> 28);
6283        }
6284
6285        public long hash64(final int[][] data) {
6286            if (data == null) return 0;
6287            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6288            int i = 0;
6289            for (; i + 7 < data.length; i += 8) {
6290                result =  0xEBEDEED9D803C815L * result
6291                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6292                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6293                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6294                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6295                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6296                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6297                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6298                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6299                ;
6300            }
6301            for (; i < data.length; i++) {
6302                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6303            }
6304            result *= 0x94D049BB133111EBL;
6305            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6306            result *= 0x369DEA0F31A53F85L;
6307            result ^= result >>> 31;
6308            result *= 0xDB4F0B9175AE2165L;
6309            return (result ^ result >>> 28);
6310        }
6311
6312        public long hash64(final long[][] data) {
6313            if (data == null) return 0;
6314            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6315            int i = 0;
6316            for (; i + 7 < data.length; i += 8) {
6317                result =  0xEBEDEED9D803C815L * result
6318                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6319                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6320                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6321                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6322                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6323                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6324                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6325                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6326                ;
6327            }
6328            for (; i < data.length; i++) {
6329                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6330            }
6331            result *= 0x94D049BB133111EBL;
6332            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6333            result *= 0x369DEA0F31A53F85L;
6334            result ^= result >>> 31;
6335            result *= 0xDB4F0B9175AE2165L;
6336            return (result ^ result >>> 28);
6337        }
6338
6339        public long hash64(final CharSequence[] data) {
6340            if (data == null) return 0;
6341            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6342            int i = 0;
6343            for (; i + 7 < data.length; i += 8) {
6344                result =  0xEBEDEED9D803C815L * result
6345                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6346                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6347                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6348                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6349                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6350                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6351                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6352                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6353                ;
6354            }
6355            for (; i < data.length; i++) {
6356                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6357            }
6358            result *= 0x94D049BB133111EBL;
6359            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6360            result *= 0x369DEA0F31A53F85L;
6361            result ^= result >>> 31;
6362            result *= 0xDB4F0B9175AE2165L;
6363            return (result ^ result >>> 28);
6364        }
6365
6366        public long hash64(final CharSequence[]... data) {
6367            if (data == null) return 0;
6368            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6369            int i = 0;
6370            for (; i + 7 < data.length; i += 8) {
6371                result =  0xEBEDEED9D803C815L * result
6372                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6373                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6374                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6375                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6376                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6377                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6378                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6379                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6380                ;
6381            }
6382            for (; i < data.length; i++) {
6383                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6384            }
6385            result *= 0x94D049BB133111EBL;
6386            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6387            result *= 0x369DEA0F31A53F85L;
6388            result ^= result >>> 31;
6389            result *= 0xDB4F0B9175AE2165L;
6390            return (result ^ result >>> 28);
6391        }
6392
6393        public long hash64(final Iterable<? extends CharSequence> data) {
6394            if (data == null) return 0;
6395            long seed = this.seed;
6396            final Iterator<? extends CharSequence> it = data.iterator();
6397            int len = 0;
6398            while (it.hasNext())
6399            {
6400                ++len;
6401                seed = mum(
6402                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
6403                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
6404            }
6405            seed = (seed ^ seed << 16) * (len ^ b0);
6406            return seed - (seed >>> 31) + (seed << 33);
6407        }
6408
6409        public long hash64(final List<? extends CharSequence> data) {
6410            if (data == null) return 0;
6411            final int len = data.size();
6412            long result = seed ^ len * 0x9E3779B97F4A7C15L;
6413            int i = 0;
6414            for (; i + 7 < len; i += 8) {
6415                result =  0xEBEDEED9D803C815L * result
6416                        + 0xD96EB1A810CAAF5FL * hash(data.get(i))
6417                        + 0xC862B36DAF790DD5L * hash(data.get(i + 1))
6418                        + 0xB8ACD90C142FE10BL * hash(data.get(i + 2))
6419                        + 0xAA324F90DED86B69L * hash(data.get(i + 3))
6420                        + 0x9CDA5E693FEA10AFL * hash(data.get(i + 4))
6421                        + 0x908E3D2C82567A73L * hash(data.get(i + 5))
6422                        + 0x8538ECB5BD456EA3L * hash(data.get(i + 6))
6423                        + 0xD1B54A32D192ED03L * hash(data.get(i + 7))
6424                ;
6425            }
6426            for (; i < len; i++) {
6427                result = 0x9E3779B97F4A7C15L * result + hash(data.get(i));
6428            }
6429            result *= 0x94D049BB133111EBL;
6430            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6431            result *= 0x369DEA0F31A53F85L;
6432            result ^= result >>> 31;
6433            result *= 0xDB4F0B9175AE2165L;
6434            return (result ^ result >>> 28);
6435
6436        }
6437
6438        public long hash64(final Object[] data) {
6439            if (data == null) return 0;
6440            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6441            int i = 0;
6442            for (; i + 7 < data.length; i += 8) {
6443                result =  0xEBEDEED9D803C815L * result
6444                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6445                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6446                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6447                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6448                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6449                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6450                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6451                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6452                ;
6453            }
6454            for (; i < data.length; i++) {
6455                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6456            }
6457            result *= 0x94D049BB133111EBL;
6458            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6459            result *= 0x369DEA0F31A53F85L;
6460            result ^= result >>> 31;
6461            result *= 0xDB4F0B9175AE2165L;
6462            return (result ^ result >>> 28);
6463        }
6464
6465        public long hash64(final Object data) {
6466            if (data == null)
6467                return 0;
6468            final long h = (data.hashCode() + seed) * 0x9E3779B97F4A7C15L;
6469            return h - (h >>> 31) + (h << 33);
6470        }
6471
6472        public int hash(final boolean[] data) {
6473            if (data == null) return 0;
6474            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6475            int i = 0;
6476            for (; i + 7 < data.length; i += 8) {
6477                result =  result      * 0xEBEDEED9D803C815L
6478                        + (data[i]     ? 0xD96EB1A810CAAF5FL : 0xCAAF5FD96EB1A810L)
6479                        + (data[i + 1] ? 0xC862B36DAF790DD5L : 0x790DD5C862B36DAFL)
6480                        + (data[i + 2] ? 0xB8ACD90C142FE10BL : 0x2FE10BB8ACD90C14L)
6481                        + (data[i + 3] ? 0xAA324F90DED86B69L : 0xD86B69AA324F90DEL)
6482                        + (data[i + 4] ? 0x9CDA5E693FEA10AFL : 0xEA10AF9CDA5E693FL)
6483                        + (data[i + 5] ? 0x908E3D2C82567A73L : 0x567A73908E3D2C82L)
6484                        + (data[i + 6] ? 0x8538ECB5BD456EA3L : 0x456EA38538ECB5BDL)
6485                        + (data[i + 7] ? 0xD1B54A32D192ED03L : 0x92ED03D1B54A32D1L)
6486                ;
6487            }
6488            for (; i < data.length; i++) {
6489                result = 0x9E3779B97F4A7C15L * result + (data[i] ? 0xEBEDEED9D803C815L : 0xD9D803C815EBEDEEL);
6490            }
6491            result *= 0x94D049BB133111EBL;
6492            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6493            result *= 0x369DEA0F31A53F85L;
6494            result ^= result >>> 31;
6495            result *= 0xDB4F0B9175AE2165L;
6496            return (int)(result ^ result >>> 28);
6497        }
6498        public int hash(final byte[] data) {
6499            if (data == null) return 0;
6500            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6501            int i = 0;
6502            for (; i + 7 < data.length; i += 8) {
6503                result =  0xEBEDEED9D803C815L * result
6504                        + 0xD96EB1A810CAAF5FL * data[i]
6505                        + 0xC862B36DAF790DD5L * data[i + 1]
6506                        + 0xB8ACD90C142FE10BL * data[i + 2]
6507                        + 0xAA324F90DED86B69L * data[i + 3]
6508                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6509                        + 0x908E3D2C82567A73L * data[i + 5]
6510                        + 0x8538ECB5BD456EA3L * data[i + 6]
6511                        + 0xD1B54A32D192ED03L * data[i + 7]
6512                ;
6513            }
6514            for (; i < data.length; i++) {
6515                result = 0x9E3779B97F4A7C15L * result + data[i];
6516            }
6517            result *= 0x94D049BB133111EBL;
6518            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6519            result *= 0x369DEA0F31A53F85L;
6520            result ^= result >>> 31;
6521            result *= 0xDB4F0B9175AE2165L;
6522            return (int)(result ^ result >>> 28);
6523        }
6524
6525        public int hash(final short[] data) {
6526            if (data == null) return 0;
6527            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6528            int i = 0;
6529            for (; i + 7 < data.length; i += 8) {
6530                result =  0xEBEDEED9D803C815L * result
6531                        + 0xD96EB1A810CAAF5FL * data[i]
6532                        + 0xC862B36DAF790DD5L * data[i + 1]
6533                        + 0xB8ACD90C142FE10BL * data[i + 2]
6534                        + 0xAA324F90DED86B69L * data[i + 3]
6535                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6536                        + 0x908E3D2C82567A73L * data[i + 5]
6537                        + 0x8538ECB5BD456EA3L * data[i + 6]
6538                        + 0xD1B54A32D192ED03L * data[i + 7]
6539                ;
6540            }
6541            for (; i < data.length; i++) {
6542                result = 0x9E3779B97F4A7C15L * result + data[i];
6543            }
6544            result *= 0x94D049BB133111EBL;
6545            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6546            result *= 0x369DEA0F31A53F85L;
6547            result ^= result >>> 31;
6548            result *= 0xDB4F0B9175AE2165L;
6549            return (int)(result ^ result >>> 28);
6550        }
6551
6552        public int hash(final char[] data) {
6553            if (data == null) return 0;
6554            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6555            int i = 0;
6556            for (; i + 7 < data.length; i += 8) {
6557                result =  0xEBEDEED9D803C815L * result
6558                        + 0xD96EB1A810CAAF5FL * data[i]
6559                        + 0xC862B36DAF790DD5L * data[i + 1]
6560                        + 0xB8ACD90C142FE10BL * data[i + 2]
6561                        + 0xAA324F90DED86B69L * data[i + 3]
6562                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6563                        + 0x908E3D2C82567A73L * data[i + 5]
6564                        + 0x8538ECB5BD456EA3L * data[i + 6]
6565                        + 0xD1B54A32D192ED03L * data[i + 7]
6566                ;
6567            }
6568            for (; i < data.length; i++) {
6569                result = 0x9E3779B97F4A7C15L * result + data[i];
6570            }
6571            result *= 0x94D049BB133111EBL;
6572            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6573            result *= 0x369DEA0F31A53F85L;
6574            result ^= result >>> 31;
6575            result *= 0xDB4F0B9175AE2165L;
6576            return (int)(result ^ result >>> 28);
6577        }
6578
6579        public int hash(final CharSequence data) {
6580            if (data == null) return 0;
6581            final int length = data.length();
6582            long result = seed ^ length * 0x9E3779B97F4A7C15L;
6583            int i = 0;
6584            for (; i + 7 < length; i += 8) {
6585                result =  0xEBEDEED9D803C815L * result
6586                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
6587                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
6588                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
6589                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
6590                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
6591                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
6592                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
6593                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
6594                ;
6595            }
6596            for (; i < length; i++) {
6597                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
6598            }
6599            result *= 0x94D049BB133111EBL;
6600            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6601            result *= 0x369DEA0F31A53F85L;
6602            result ^= result >>> 31;
6603            result *= 0xDB4F0B9175AE2165L;
6604            return (int)(result ^ result >>> 28);
6605        }
6606
6607        public int hash(final int[] data) {
6608            if (data == null) return 0;
6609            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6610            int i = 0;
6611            for (; i + 7 < data.length; i += 8) {
6612                result =  0xEBEDEED9D803C815L * result
6613                        + 0xD96EB1A810CAAF5FL * data[i]
6614                        + 0xC862B36DAF790DD5L * data[i + 1]
6615                        + 0xB8ACD90C142FE10BL * data[i + 2]
6616                        + 0xAA324F90DED86B69L * data[i + 3]
6617                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6618                        + 0x908E3D2C82567A73L * data[i + 5]
6619                        + 0x8538ECB5BD456EA3L * data[i + 6]
6620                        + 0xD1B54A32D192ED03L * data[i + 7]
6621                ;
6622            }
6623            for (; i < data.length; i++) {
6624                result = 0x9E3779B97F4A7C15L * result + data[i];
6625            }
6626            result *= 0x94D049BB133111EBL;
6627            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6628            result *= 0x369DEA0F31A53F85L;
6629            result ^= result >>> 31;
6630            result *= 0xDB4F0B9175AE2165L;
6631            return (int)(result ^ result >>> 28);
6632        }
6633
6634        public int hash(final int[] data, final int length) {
6635            if (data == null) return 0;
6636            final int len = Math.min(length, data.length);
6637            long result = seed ^ len * 0x9E3779B97F4A7C15L;
6638            int i = 0;
6639            for (; i + 7 < len; i += 8) {
6640                result =  0xEBEDEED9D803C815L * result
6641                        + 0xD96EB1A810CAAF5FL * data[i]
6642                        + 0xC862B36DAF790DD5L * data[i + 1]
6643                        + 0xB8ACD90C142FE10BL * data[i + 2]
6644                        + 0xAA324F90DED86B69L * data[i + 3]
6645                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6646                        + 0x908E3D2C82567A73L * data[i + 5]
6647                        + 0x8538ECB5BD456EA3L * data[i + 6]
6648                        + 0xD1B54A32D192ED03L * data[i + 7]
6649                ;
6650            }
6651            for (; i < len; i++) {
6652                result = 0x9E3779B97F4A7C15L * result + data[i];
6653            }
6654            result *= 0x94D049BB133111EBL;
6655            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6656            result *= 0x369DEA0F31A53F85L;
6657            result ^= result >>> 31;
6658            result *= 0xDB4F0B9175AE2165L;
6659            return (int)(result ^ result >>> 28);
6660        }
6661
6662        public int hash(final long[] data) {
6663            if (data == null) return 0;
6664            long seed = this.seed, a = this.seed + b4, b = this.seed + b3, c = this.seed + b2, d = this.seed + b1;
6665            final int len = data.length;
6666            for (int i = 3; i < len; i+=4) {
6667                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
6668                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
6669                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
6670                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
6671                seed += a + b + c + d;
6672            }
6673            seed += b5;
6674            switch (len & 3) {
6675                case 1: seed = wow(seed, b1 ^ data[len-1]); break;
6676                case 2: seed = wow(seed + data[len-2], b2 + data[len-1]); break;
6677                case 3: seed = wow(seed + data[len-3], b2 + data[len-2]) ^ wow(seed + data[len-1], seed ^ b3); break;
6678            }
6679            seed = (seed ^ seed << 16) * (len ^ b0 ^ seed >>> 32);
6680            return (int)(seed - (seed >>> 32));
6681        }
6682
6683        public int hash(final float[] data) {
6684            if (data == null) return 0;
6685            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6686            int i = 0;
6687            for (; i + 7 < data.length; i += 8) {
6688                result =  0xEBEDEED9D803C815L * result
6689                        + 0xD96EB1A810CAAF5FL * floatToIntBits(data[i])
6690                        + 0xC862B36DAF790DD5L * floatToIntBits(data[i + 1])
6691                        + 0xB8ACD90C142FE10BL * floatToIntBits(data[i + 2])
6692                        + 0xAA324F90DED86B69L * floatToIntBits(data[i + 3])
6693                        + 0x9CDA5E693FEA10AFL * floatToIntBits(data[i + 4])
6694                        + 0x908E3D2C82567A73L * floatToIntBits(data[i + 5])
6695                        + 0x8538ECB5BD456EA3L * floatToIntBits(data[i + 6])
6696                        + 0xD1B54A32D192ED03L * floatToIntBits(data[i + 7])
6697                ;
6698            }
6699            for (; i < data.length; i++) {
6700                result = 0x9E3779B97F4A7C15L * result + floatToIntBits(data[i]);
6701            }
6702            result *= 0x94D049BB133111EBL;
6703            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6704            result *= 0x369DEA0F31A53F85L;
6705            result ^= result >>> 31;
6706            result *= 0xDB4F0B9175AE2165L;
6707            return (int)(result ^ result >>> 28);
6708        }
6709        public int hash(final double[] data) {
6710            if (data == null) return 0;
6711            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6712            int i = 0;
6713            for (; i + 7 < data.length; i += 8) {
6714                result =  0xEBEDEED9D803C815L * result
6715                        + 0xD96EB1A810CAAF5FL * doubleToMixedIntBits(data[i])
6716                        + 0xC862B36DAF790DD5L * doubleToMixedIntBits(data[i + 1])
6717                        + 0xB8ACD90C142FE10BL * doubleToMixedIntBits(data[i + 2])
6718                        + 0xAA324F90DED86B69L * doubleToMixedIntBits(data[i + 3])
6719                        + 0x9CDA5E693FEA10AFL * doubleToMixedIntBits(data[i + 4])
6720                        + 0x908E3D2C82567A73L * doubleToMixedIntBits(data[i + 5])
6721                        + 0x8538ECB5BD456EA3L * doubleToMixedIntBits(data[i + 6])
6722                        + 0xD1B54A32D192ED03L * doubleToMixedIntBits(data[i + 7])
6723                ;
6724            }
6725            for (; i < data.length; i++) {
6726                result = 0x9E3779B97F4A7C15L * result + doubleToMixedIntBits(data[i]);
6727            }
6728            result *= 0x94D049BB133111EBL;
6729            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6730            result *= 0x369DEA0F31A53F85L;
6731            result ^= result >>> 31;
6732            result *= 0xDB4F0B9175AE2165L;
6733            return (int)(result ^ result >>> 28);
6734        }
6735
6736        /**
6737         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
6738         *
6739         * @param data  the char array to hash
6740         * @param start the start of the section to hash (inclusive)
6741         * @param end   the end of the section to hash (exclusive)
6742         * @return a 64-bit hash code for the requested section of data
6743         */
6744        public int hash(final char[] data, final int start, final int end) {
6745            if (data == null || start >= end) return 0;
6746            final int len = Math.min(end, data.length);
6747
6748            long result = seed ^ (len - start) * 0x9E3779B97F4A7C15L;
6749            int i = start;
6750            for (; i + 7 < len; i += 8) {
6751                result =  0xEBEDEED9D803C815L * result
6752                        + 0xD96EB1A810CAAF5FL * data[i]
6753                        + 0xC862B36DAF790DD5L * data[i + 1]
6754                        + 0xB8ACD90C142FE10BL * data[i + 2]
6755                        + 0xAA324F90DED86B69L * data[i + 3]
6756                        + 0x9CDA5E693FEA10AFL * data[i + 4]
6757                        + 0x908E3D2C82567A73L * data[i + 5]
6758                        + 0x8538ECB5BD456EA3L * data[i + 6]
6759                        + 0xD1B54A32D192ED03L * data[i + 7]
6760                ;
6761            }
6762            for (; i < len; i++) {
6763                result = 0x9E3779B97F4A7C15L * result + data[i];
6764            }
6765            result *= 0x94D049BB133111EBL;
6766            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6767            result *= 0x369DEA0F31A53F85L;
6768            result ^= result >>> 31;
6769            result *= 0xDB4F0B9175AE2165L;
6770            return (int)(result ^ result >>> 28);
6771        }
6772
6773        /**
6774         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
6775         *
6776         * @param data  the String or other CharSequence to hash
6777         * @param start the start of the section to hash (inclusive)
6778         * @param end   the end of the section to hash (exclusive)
6779         * @return a 64-bit hash code for the requested section of data
6780         */
6781        public int hash(final CharSequence data, final int start, final int end) {
6782            if (data == null || start >= end) return 0;
6783            final int len = Math.min(end, data.length());
6784
6785            long result = seed ^ (len - start) * 0x9E3779B97F4A7C15L;
6786            int i = start;
6787            for (; i + 7 < len; i += 8) {
6788                result =  0xEBEDEED9D803C815L * result
6789                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
6790                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
6791                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
6792                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
6793                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
6794                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
6795                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
6796                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
6797                ;
6798            }
6799            for (; i < len; i++) {
6800                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
6801            }
6802            result *= 0x94D049BB133111EBL;
6803            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6804            result *= 0x369DEA0F31A53F85L;
6805            result ^= result >>> 31;
6806            result *= 0xDB4F0B9175AE2165L;
6807            return (int)(result ^ result >>> 28);
6808        }
6809
6810
6811        public int hash(final char[][] data) {
6812            if (data == null) return 0;
6813            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6814            int i = 0;
6815            for (; i + 7 < data.length; i += 8) {
6816                result =  0xEBEDEED9D803C815L * result
6817                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6818                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6819                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6820                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6821                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6822                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6823                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6824                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6825                ;
6826            }
6827            for (; i < data.length; i++) {
6828                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6829            }
6830            result *= 0x94D049BB133111EBL;
6831            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6832            result *= 0x369DEA0F31A53F85L;
6833            result ^= result >>> 31;
6834            result *= 0xDB4F0B9175AE2165L;
6835            return (int)(result ^ result >>> 28);
6836        }
6837
6838        public int hash(final int[][] data) {
6839            if (data == null) return 0;
6840            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6841            int i = 0;
6842            for (; i + 7 < data.length; i += 8) {
6843                result =  0xEBEDEED9D803C815L * result
6844                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6845                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6846                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6847                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6848                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6849                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6850                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6851                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6852                ;
6853            }
6854            for (; i < data.length; i++) {
6855                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6856            }
6857            result *= 0x94D049BB133111EBL;
6858            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6859            result *= 0x369DEA0F31A53F85L;
6860            result ^= result >>> 31;
6861            result *= 0xDB4F0B9175AE2165L;
6862            return (int)(result ^ result >>> 28);
6863        }
6864
6865        public int hash(final long[][] data) {
6866            if (data == null) return 0;
6867            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6868            int i = 0;
6869            for (; i + 7 < data.length; i += 8) {
6870                result =  0xEBEDEED9D803C815L * result
6871                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6872                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6873                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6874                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6875                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6876                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6877                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6878                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6879                ;
6880            }
6881            for (; i < data.length; i++) {
6882                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6883            }
6884            result *= 0x94D049BB133111EBL;
6885            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6886            result *= 0x369DEA0F31A53F85L;
6887            result ^= result >>> 31;
6888            result *= 0xDB4F0B9175AE2165L;
6889            return (int)(result ^ result >>> 28);
6890        }
6891
6892        public int hash(final CharSequence[] data) {
6893            if (data == null) return 0;
6894            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6895            int i = 0;
6896            for (; i + 7 < data.length; i += 8) {
6897                result =  0xEBEDEED9D803C815L * result
6898                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6899                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6900                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6901                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6902                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6903                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6904                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6905                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6906                ;
6907            }
6908            for (; i < data.length; i++) {
6909                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6910            }
6911            result *= 0x94D049BB133111EBL;
6912            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6913            result *= 0x369DEA0F31A53F85L;
6914            result ^= result >>> 31;
6915            result *= 0xDB4F0B9175AE2165L;
6916            return (int)(result ^ result >>> 28);
6917        }
6918
6919        public int hash(final CharSequence[]... data) {
6920            if (data == null) return 0;
6921            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6922            int i = 0;
6923            for (; i + 7 < data.length; i += 8) {
6924                result =  0xEBEDEED9D803C815L * result
6925                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6926                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6927                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6928                        + 0xAA324F90DED86B69L * hash(data[i + 3])
6929                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
6930                        + 0x908E3D2C82567A73L * hash(data[i + 5])
6931                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
6932                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
6933                ;
6934            }
6935            for (; i < data.length; i++) {
6936                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
6937            }
6938            result *= 0x94D049BB133111EBL;
6939            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6940            result *= 0x369DEA0F31A53F85L;
6941            result ^= result >>> 31;
6942            result *= 0xDB4F0B9175AE2165L;
6943            return (int)(result ^ result >>> 28);
6944        }
6945
6946        public int hash(final Iterable<? extends CharSequence> data) {
6947            if (data == null) return 0;
6948            long seed = this.seed;
6949            final Iterator<? extends CharSequence> it = data.iterator();
6950            int len = 0;
6951            while (it.hasNext())
6952            {
6953                ++len;
6954                seed = mum(
6955                        mum(hash(it.next()) ^ b1, (it.hasNext() ? hash(it.next()) ^ b2 ^ ++len : b2)) + seed,
6956                        mum((it.hasNext() ? hash(it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(it.next()) ^ b4 ^ ++len : b4)));
6957            }
6958            return (int) mum(seed ^ seed << 16, len ^ b0);
6959        }
6960
6961        public int hash(final List<? extends CharSequence> data) {
6962            if (data == null) return 0;
6963            final int len = data.size();
6964            long result = seed ^ len * 0x9E3779B97F4A7C15L;
6965            int i = 0;
6966            for (; i + 7 < len; i += 8) {
6967                result =  0xEBEDEED9D803C815L * result
6968                        + 0xD96EB1A810CAAF5FL * hash(data.get(i))
6969                        + 0xC862B36DAF790DD5L * hash(data.get(i + 1))
6970                        + 0xB8ACD90C142FE10BL * hash(data.get(i + 2))
6971                        + 0xAA324F90DED86B69L * hash(data.get(i + 3))
6972                        + 0x9CDA5E693FEA10AFL * hash(data.get(i + 4))
6973                        + 0x908E3D2C82567A73L * hash(data.get(i + 5))
6974                        + 0x8538ECB5BD456EA3L * hash(data.get(i + 6))
6975                        + 0xD1B54A32D192ED03L * hash(data.get(i + 7))
6976                ;
6977            }
6978            for (; i < len; i++) {
6979                result = 0x9E3779B97F4A7C15L * result + hash(data.get(i));
6980            }
6981            result *= 0x94D049BB133111EBL;
6982            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
6983            result *= 0x369DEA0F31A53F85L;
6984            result ^= result >>> 31;
6985            result *= 0xDB4F0B9175AE2165L;
6986            return (int)(result ^ result >>> 28);
6987
6988        }
6989
6990        public int hash(final Object[] data) {
6991            if (data == null) return 0;
6992            long result = seed ^ data.length * 0x9E3779B97F4A7C15L;
6993            int i = 0;
6994            for (; i + 7 < data.length; i += 8) {
6995                result =  0xEBEDEED9D803C815L * result
6996                        + 0xD96EB1A810CAAF5FL * hash(data[i])
6997                        + 0xC862B36DAF790DD5L * hash(data[i + 1])
6998                        + 0xB8ACD90C142FE10BL * hash(data[i + 2])
6999                        + 0xAA324F90DED86B69L * hash(data[i + 3])
7000                        + 0x9CDA5E693FEA10AFL * hash(data[i + 4])
7001                        + 0x908E3D2C82567A73L * hash(data[i + 5])
7002                        + 0x8538ECB5BD456EA3L * hash(data[i + 6])
7003                        + 0xD1B54A32D192ED03L * hash(data[i + 7])
7004                ;
7005            }
7006            for (; i < data.length; i++) {
7007                result = 0x9E3779B97F4A7C15L * result + hash(data[i]);
7008            }
7009            result *= 0x94D049BB133111EBL;
7010            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7011            result *= 0x369DEA0F31A53F85L;
7012            result ^= result >>> 31;
7013            result *= 0xDB4F0B9175AE2165L;
7014            return (int)(result ^ result >>> 28);
7015        }
7016
7017        public int hash(final Object data) {
7018            if (data == null) return 0;
7019            return (int)((data.hashCode() + seed) * 0x9E3779B97F4A7C15L >>> 32);
7020        }
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054        public static long hash64(final long seed, final boolean[] data) {
7055            if (data == null) return 0;
7056            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7057            int i = 0;
7058            for (; i + 7 < data.length; i += 8) {
7059                result =  result      * 0xEBEDEED9D803C815L
7060                        + (data[i]     ? 0xD96EB1A810CAAF5FL : 0xCAAF5FD96EB1A810L)
7061                        + (data[i + 1] ? 0xC862B36DAF790DD5L : 0x790DD5C862B36DAFL)
7062                        + (data[i + 2] ? 0xB8ACD90C142FE10BL : 0x2FE10BB8ACD90C14L)
7063                        + (data[i + 3] ? 0xAA324F90DED86B69L : 0xD86B69AA324F90DEL)
7064                        + (data[i + 4] ? 0x9CDA5E693FEA10AFL : 0xEA10AF9CDA5E693FL)
7065                        + (data[i + 5] ? 0x908E3D2C82567A73L : 0x567A73908E3D2C82L)
7066                        + (data[i + 6] ? 0x8538ECB5BD456EA3L : 0x456EA38538ECB5BDL)
7067                        + (data[i + 7] ? 0xD1B54A32D192ED03L : 0x92ED03D1B54A32D1L)
7068                ;
7069            }
7070            for (; i < data.length; i++) {
7071                result = 0x9E3779B97F4A7C15L * result + (data[i] ? 0xEBEDEED9D803C815L : 0xD9D803C815EBEDEEL);
7072            }
7073            result *= 0x94D049BB133111EBL;
7074            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7075            result *= 0x369DEA0F31A53F85L;
7076            result ^= result >>> 31;
7077            result *= 0xDB4F0B9175AE2165L;
7078            return (result ^ result >>> 28);
7079        }
7080        public static long hash64(final long seed, final byte[] data) {
7081            if (data == null) return 0;
7082            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7083            int i = 0;
7084            for (; i + 7 < data.length; i += 8) {
7085                result =  0xEBEDEED9D803C815L * result
7086                        + 0xD96EB1A810CAAF5FL * data[i]
7087                        + 0xC862B36DAF790DD5L * data[i + 1]
7088                        + 0xB8ACD90C142FE10BL * data[i + 2]
7089                        + 0xAA324F90DED86B69L * data[i + 3]
7090                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7091                        + 0x908E3D2C82567A73L * data[i + 5]
7092                        + 0x8538ECB5BD456EA3L * data[i + 6]
7093                        + 0xD1B54A32D192ED03L * data[i + 7]
7094                ;
7095            }
7096            for (; i < data.length; i++) {
7097                result = 0x9E3779B97F4A7C15L * result + data[i];
7098            }
7099            result *= 0x94D049BB133111EBL;
7100            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7101            result *= 0x369DEA0F31A53F85L;
7102            result ^= result >>> 31;
7103            result *= 0xDB4F0B9175AE2165L;
7104            return (result ^ result >>> 28);
7105        }
7106
7107        public static long hash64(final long seed, final short[] data) {
7108            if (data == null) return 0;
7109            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7110            int i = 0;
7111            for (; i + 7 < data.length; i += 8) {
7112                result =  0xEBEDEED9D803C815L * result
7113                        + 0xD96EB1A810CAAF5FL * data[i]
7114                        + 0xC862B36DAF790DD5L * data[i + 1]
7115                        + 0xB8ACD90C142FE10BL * data[i + 2]
7116                        + 0xAA324F90DED86B69L * data[i + 3]
7117                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7118                        + 0x908E3D2C82567A73L * data[i + 5]
7119                        + 0x8538ECB5BD456EA3L * data[i + 6]
7120                        + 0xD1B54A32D192ED03L * data[i + 7]
7121                ;
7122            }
7123            for (; i < data.length; i++) {
7124                result = 0x9E3779B97F4A7C15L * result + data[i];
7125            }
7126            result *= 0x94D049BB133111EBL;
7127            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7128            result *= 0x369DEA0F31A53F85L;
7129            result ^= result >>> 31;
7130            result *= 0xDB4F0B9175AE2165L;
7131            return (result ^ result >>> 28);
7132        }
7133
7134        public static long hash64(final long seed, final char[] data) {
7135            if (data == null) return 0;
7136            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7137            int i = 0;
7138            for (; i + 7 < data.length; i += 8) {
7139                result =  0xEBEDEED9D803C815L * result
7140                        + 0xD96EB1A810CAAF5FL * data[i]
7141                        + 0xC862B36DAF790DD5L * data[i + 1]
7142                        + 0xB8ACD90C142FE10BL * data[i + 2]
7143                        + 0xAA324F90DED86B69L * data[i + 3]
7144                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7145                        + 0x908E3D2C82567A73L * data[i + 5]
7146                        + 0x8538ECB5BD456EA3L * data[i + 6]
7147                        + 0xD1B54A32D192ED03L * data[i + 7]
7148                ;
7149            }
7150            for (; i < data.length; i++) {
7151                result = 0x9E3779B97F4A7C15L * result + data[i];
7152            }
7153            result *= 0x94D049BB133111EBL;
7154            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7155            result *= 0x369DEA0F31A53F85L;
7156            result ^= result >>> 31;
7157            result *= 0xDB4F0B9175AE2165L;
7158            return (result ^ result >>> 28);
7159        }
7160
7161        public static long hash64(final long seed, final CharSequence data) {
7162            if (data == null) return 0;
7163            final int length = data.length();
7164            long result = randomize(seed) ^ length * 0x9E3779B97F4A7C15L;
7165            int i = 0;
7166            for (; i + 7 < length; i += 8) {
7167                result =  0xEBEDEED9D803C815L * result
7168                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
7169                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
7170                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
7171                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
7172                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
7173                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
7174                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
7175                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
7176                ;
7177            }
7178            for (; i < length; i++) {
7179                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
7180            }
7181            result *= 0x94D049BB133111EBL;
7182            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7183            result *= 0x369DEA0F31A53F85L;
7184            result ^= result >>> 31;
7185            result *= 0xDB4F0B9175AE2165L;
7186            return (result ^ result >>> 28);
7187        }
7188
7189        public static long hash64(final long seed, final int[] data) {
7190            if (data == null) return 0;
7191            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7192            int i = 0;
7193            for (; i + 7 < data.length; i += 8) {
7194                result =  0xEBEDEED9D803C815L * result
7195                        + 0xD96EB1A810CAAF5FL * data[i]
7196                        + 0xC862B36DAF790DD5L * data[i + 1]
7197                        + 0xB8ACD90C142FE10BL * data[i + 2]
7198                        + 0xAA324F90DED86B69L * data[i + 3]
7199                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7200                        + 0x908E3D2C82567A73L * data[i + 5]
7201                        + 0x8538ECB5BD456EA3L * data[i + 6]
7202                        + 0xD1B54A32D192ED03L * data[i + 7]
7203                ;
7204            }
7205            for (; i < data.length; i++) {
7206                result = 0x9E3779B97F4A7C15L * result + data[i];
7207            }
7208            result *= 0x94D049BB133111EBL;
7209            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7210            result *= 0x369DEA0F31A53F85L;
7211            result ^= result >>> 31;
7212            result *= 0xDB4F0B9175AE2165L;
7213            return (result ^ result >>> 28);
7214        }
7215
7216        public static long hash64(final long seed, final int[] data, final int length) {
7217            if (data == null) return 0;
7218            final int len = Math.min(length, data.length);
7219            long result = randomize(seed) ^ len * 0x9E3779B97F4A7C15L;
7220            int i = 0;
7221            for (; i + 7 < len; i += 8) {
7222                result =  0xEBEDEED9D803C815L * result
7223                        + 0xD96EB1A810CAAF5FL * data[i]
7224                        + 0xC862B36DAF790DD5L * data[i + 1]
7225                        + 0xB8ACD90C142FE10BL * data[i + 2]
7226                        + 0xAA324F90DED86B69L * data[i + 3]
7227                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7228                        + 0x908E3D2C82567A73L * data[i + 5]
7229                        + 0x8538ECB5BD456EA3L * data[i + 6]
7230                        + 0xD1B54A32D192ED03L * data[i + 7]
7231                ;
7232            }
7233            for (; i < len; i++) {
7234                result = 0x9E3779B97F4A7C15L * result + data[i];
7235            }
7236            result *= 0x94D049BB133111EBL;
7237            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7238            result *= 0x369DEA0F31A53F85L;
7239            result ^= result >>> 31;
7240            result *= 0xDB4F0B9175AE2165L;
7241            return (result ^ result >>> 28);
7242        }
7243
7244        public static long hash64(final long seed, final long[] data) {
7245            if (data == null) return 0;
7246            long s = randomize(seed), a = s + b4, b = s + b3, c = s + b2, d = s + b1;
7247            final int len = data.length;
7248            for (int i = 3; i < len; i+=4) {
7249                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
7250                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
7251                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
7252                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
7253                s += a + b + c + d;
7254            }
7255            s += b5;
7256            switch (len & 3) {
7257                case 1: s = wow(s, b1 ^ data[len-1]); break;
7258                case 2: s = wow(s + data[len-2], b2 + data[len-1]); break;
7259                case 3: s = wow(s + data[len-3], b2 + data[len-2]) ^ wow(s + data[len-1], s ^ b3); break;
7260            }
7261            s = (s ^ s << 16) * (len ^ b0 ^ s >>> 32);
7262            return s - (s >>> 31) + (s << 33);
7263        }
7264        public static long hash64(final long seed, final float[] data) {
7265            if (data == null) return 0;
7266            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7267            int i = 0;
7268            for (; i + 7 < data.length; i += 8) {
7269                result =  0xEBEDEED9D803C815L * result
7270                        + 0xD96EB1A810CAAF5FL * floatToIntBits(data[i])
7271                        + 0xC862B36DAF790DD5L * floatToIntBits(data[i + 1])
7272                        + 0xB8ACD90C142FE10BL * floatToIntBits(data[i + 2])
7273                        + 0xAA324F90DED86B69L * floatToIntBits(data[i + 3])
7274                        + 0x9CDA5E693FEA10AFL * floatToIntBits(data[i + 4])
7275                        + 0x908E3D2C82567A73L * floatToIntBits(data[i + 5])
7276                        + 0x8538ECB5BD456EA3L * floatToIntBits(data[i + 6])
7277                        + 0xD1B54A32D192ED03L * floatToIntBits(data[i + 7])
7278                ;
7279            }
7280            for (; i < data.length; i++) {
7281                result = 0x9E3779B97F4A7C15L * result + floatToIntBits(data[i]);
7282            }
7283            result *= 0x94D049BB133111EBL;
7284            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7285            result *= 0x369DEA0F31A53F85L;
7286            result ^= result >>> 31;
7287            result *= 0xDB4F0B9175AE2165L;
7288            return (result ^ result >>> 28);
7289        }
7290        public static long hash64(final long seed, final double[] data) {
7291            if (data == null) return 0;
7292            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7293            int i = 0;
7294            for (; i + 7 < data.length; i += 8) {
7295                result =  0xEBEDEED9D803C815L * result
7296                        + 0xD96EB1A810CAAF5FL * doubleToMixedIntBits(data[i])
7297                        + 0xC862B36DAF790DD5L * doubleToMixedIntBits(data[i + 1])
7298                        + 0xB8ACD90C142FE10BL * doubleToMixedIntBits(data[i + 2])
7299                        + 0xAA324F90DED86B69L * doubleToMixedIntBits(data[i + 3])
7300                        + 0x9CDA5E693FEA10AFL * doubleToMixedIntBits(data[i + 4])
7301                        + 0x908E3D2C82567A73L * doubleToMixedIntBits(data[i + 5])
7302                        + 0x8538ECB5BD456EA3L * doubleToMixedIntBits(data[i + 6])
7303                        + 0xD1B54A32D192ED03L * doubleToMixedIntBits(data[i + 7])
7304                ;
7305            }
7306            for (; i < data.length; i++) {
7307                result = 0x9E3779B97F4A7C15L * result + doubleToMixedIntBits(data[i]);
7308            }
7309            result *= 0x94D049BB133111EBL;
7310            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7311            result *= 0x369DEA0F31A53F85L;
7312            result ^= result >>> 31;
7313            result *= 0xDB4F0B9175AE2165L;
7314            return (result ^ result >>> 28);
7315        }
7316
7317        /**
7318         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
7319         *
7320         * @param data  the char array to hash
7321         * @param start the start of the section to hash (inclusive)
7322         * @param end   the end of the section to hash (exclusive)
7323         * @return a 64-bit hash code for the requested section of data
7324         */
7325        public static long hash64(final long seed, final char[] data, final int start, final int end) {
7326            if (data == null || start >= end) return 0;
7327            final int len = Math.min(end, data.length);
7328
7329            long result = randomize(seed) ^ (len - start) * 0x9E3779B97F4A7C15L;
7330            int i = start;
7331            for (; i + 7 < len; i += 8) {
7332                result =  0xEBEDEED9D803C815L * result
7333                        + 0xD96EB1A810CAAF5FL * data[i]
7334                        + 0xC862B36DAF790DD5L * data[i + 1]
7335                        + 0xB8ACD90C142FE10BL * data[i + 2]
7336                        + 0xAA324F90DED86B69L * data[i + 3]
7337                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7338                        + 0x908E3D2C82567A73L * data[i + 5]
7339                        + 0x8538ECB5BD456EA3L * data[i + 6]
7340                        + 0xD1B54A32D192ED03L * data[i + 7]
7341                ;
7342            }
7343            for (; i < len; i++) {
7344                result = 0x9E3779B97F4A7C15L * result + data[i];
7345            }
7346            result *= 0x94D049BB133111EBL;
7347            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7348            result *= 0x369DEA0F31A53F85L;
7349            result ^= result >>> 31;
7350            result *= 0xDB4F0B9175AE2165L;
7351            return (result ^ result >>> 28);
7352        }
7353
7354        /**
7355         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
7356         *
7357         * @param data  the String or other CharSequence to hash
7358         * @param start the start of the section to hash (inclusive)
7359         * @param end   the end of the section to hash (exclusive)
7360         * @return a 64-bit hash code for the requested section of data
7361         */
7362        public static long hash64(final long seed, final CharSequence data, final int start, final int end) {
7363            if (data == null || start >= end) return 0;
7364            final int len = Math.min(end, data.length());
7365
7366            long result = randomize(seed) ^ (len - start) * 0x9E3779B97F4A7C15L;
7367            int i = start;
7368            for (; i + 7 < len; i += 8) {
7369                result =  0xEBEDEED9D803C815L * result
7370                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
7371                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
7372                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
7373                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
7374                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
7375                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
7376                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
7377                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
7378                ;
7379            }
7380            for (; i < len; i++) {
7381                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
7382            }
7383            result *= 0x94D049BB133111EBL;
7384            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7385            result *= 0x369DEA0F31A53F85L;
7386            result ^= result >>> 31;
7387            result *= 0xDB4F0B9175AE2165L;
7388            return (result ^ result >>> 28);
7389        }
7390
7391
7392        public static long hash64(final long seed, final char[][] data) {
7393            if (data == null) return 0;
7394            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7395            int i = 0;
7396            for (; i + 7 < data.length; i += 8) {
7397                result =  0xEBEDEED9D803C815L * result
7398                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7399                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7400                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7401                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7402                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7403                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7404                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7405                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7406                ;
7407            }
7408            for (; i < data.length; i++) {
7409                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7410            }
7411            result *= 0x94D049BB133111EBL;
7412            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7413            result *= 0x369DEA0F31A53F85L;
7414            result ^= result >>> 31;
7415            result *= 0xDB4F0B9175AE2165L;
7416            return (result ^ result >>> 28);
7417        }
7418
7419        public static long hash64(final long seed, final int[][] data) {
7420            if (data == null) return 0;
7421            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7422            int i = 0;
7423            for (; i + 7 < data.length; i += 8) {
7424                result =  0xEBEDEED9D803C815L * result
7425                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7426                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7427                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7428                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7429                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7430                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7431                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7432                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7433                ;
7434            }
7435            for (; i < data.length; i++) {
7436                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7437            }
7438            result *= 0x94D049BB133111EBL;
7439            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7440            result *= 0x369DEA0F31A53F85L;
7441            result ^= result >>> 31;
7442            result *= 0xDB4F0B9175AE2165L;
7443            return (result ^ result >>> 28);
7444        }
7445
7446        public static long hash64(final long seed, final long[][] data) {
7447            if (data == null) return 0;
7448            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7449            int i = 0;
7450            for (; i + 7 < data.length; i += 8) {
7451                result =  0xEBEDEED9D803C815L * result
7452                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7453                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7454                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7455                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7456                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7457                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7458                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7459                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7460                ;
7461            }
7462            for (; i < data.length; i++) {
7463                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7464            }
7465            result *= 0x94D049BB133111EBL;
7466            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7467            result *= 0x369DEA0F31A53F85L;
7468            result ^= result >>> 31;
7469            result *= 0xDB4F0B9175AE2165L;
7470            return (result ^ result >>> 28);
7471        }
7472
7473        public static long hash64(final long seed, final CharSequence[] data) {
7474            if (data == null) return 0;
7475            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7476            int i = 0;
7477            for (; i + 7 < data.length; i += 8) {
7478                result =  0xEBEDEED9D803C815L * result
7479                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7480                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7481                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7482                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7483                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7484                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7485                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7486                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7487                ;
7488            }
7489            for (; i < data.length; i++) {
7490                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7491            }
7492            result *= 0x94D049BB133111EBL;
7493            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7494            result *= 0x369DEA0F31A53F85L;
7495            result ^= result >>> 31;
7496            result *= 0xDB4F0B9175AE2165L;
7497            return (result ^ result >>> 28);
7498        }
7499
7500        public static long hash64(final long seed, final CharSequence[]... data) {
7501            if (data == null) return 0;
7502            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7503            int i = 0;
7504            for (; i + 7 < data.length; i += 8) {
7505                result =  0xEBEDEED9D803C815L * result
7506                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7507                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7508                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7509                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7510                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7511                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7512                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7513                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7514                ;
7515            }
7516            for (; i < data.length; i++) {
7517                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7518            }
7519            result *= 0x94D049BB133111EBL;
7520            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7521            result *= 0x369DEA0F31A53F85L;
7522            result ^= result >>> 31;
7523            result *= 0xDB4F0B9175AE2165L;
7524            return (result ^ result >>> 28);
7525        }
7526
7527        public static long hash64(final long seed, final Iterable<? extends CharSequence> data) {
7528            if (data == null) return 0;
7529            long s = randomize(seed);
7530            final Iterator<? extends CharSequence> it = data.iterator();
7531            int len = 0;
7532            while (it.hasNext())
7533            {
7534                ++len;
7535                s = mum(
7536                        mum(hash(seed, it.next()) ^ b1, (it.hasNext() ? hash(seed, it.next()) ^ b2 ^ ++len : b2)) + s,
7537                        mum((it.hasNext() ? hash(seed, it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(seed, it.next()) ^ b4 ^ ++len : b4)));
7538            }
7539            s = (s ^ s << 16) * (len ^ b0);
7540            return s - (s >>> 31) + (s << 33);
7541        }
7542
7543        public static long hash64(final long seed, final List<? extends CharSequence> data) {
7544            if (data == null) return 0;
7545            final int len = data.size();
7546            long result = randomize(seed) ^ len * 0x9E3779B97F4A7C15L;
7547            int i = 0;
7548            for (; i + 7 < len; i += 8) {
7549                result =  0xEBEDEED9D803C815L * result
7550                        + 0xD96EB1A810CAAF5FL * hash(seed, data.get(i))
7551                        + 0xC862B36DAF790DD5L * hash(seed, data.get(i + 1))
7552                        + 0xB8ACD90C142FE10BL * hash(seed, data.get(i + 2))
7553                        + 0xAA324F90DED86B69L * hash(seed, data.get(i + 3))
7554                        + 0x9CDA5E693FEA10AFL * hash(seed, data.get(i + 4))
7555                        + 0x908E3D2C82567A73L * hash(seed, data.get(i + 5))
7556                        + 0x8538ECB5BD456EA3L * hash(seed, data.get(i + 6))
7557                        + 0xD1B54A32D192ED03L * hash(seed, data.get(i + 7))
7558                ;
7559            }
7560            for (; i < len; i++) {
7561                result = 0x9E3779B97F4A7C15L * result + hash(seed, data.get(i));
7562            }
7563            result *= 0x94D049BB133111EBL;
7564            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7565            result *= 0x369DEA0F31A53F85L;
7566            result ^= result >>> 31;
7567            result *= 0xDB4F0B9175AE2165L;
7568            return (result ^ result >>> 28);
7569
7570        }
7571
7572        public static long hash64(final long seed, final Object[] data) {
7573            if (data == null) return 0;
7574            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7575            int i = 0;
7576            for (; i + 7 < data.length; i += 8) {
7577                result =  0xEBEDEED9D803C815L * result
7578                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7579                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7580                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7581                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7582                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7583                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7584                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7585                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7586                ;
7587            }
7588            for (; i < data.length; i++) {
7589                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7590            }
7591            result *= 0x94D049BB133111EBL;
7592            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7593            result *= 0x369DEA0F31A53F85L;
7594            result ^= result >>> 31;
7595            result *= 0xDB4F0B9175AE2165L;
7596            return (result ^ result >>> 28);
7597        }
7598
7599        public static long hash64(final long seed, final Object data) {
7600            if (data == null)
7601                return 0;
7602            final long h = (data.hashCode() + randomize(seed)) * 0x9E3779B97F4A7C15L;
7603            return h - (h >>> 31) + (h << 33);
7604        }
7605
7606        public static int hash(final long seed, final boolean[] data) {
7607            if (data == null) return 0;
7608            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7609            int i = 0;
7610            for (; i + 7 < data.length; i += 8) {
7611                result =  result      * 0xEBEDEED9D803C815L
7612                        + (data[i]     ? 0xD96EB1A810CAAF5FL : 0xCAAF5FD96EB1A810L)
7613                        + (data[i + 1] ? 0xC862B36DAF790DD5L : 0x790DD5C862B36DAFL)
7614                        + (data[i + 2] ? 0xB8ACD90C142FE10BL : 0x2FE10BB8ACD90C14L)
7615                        + (data[i + 3] ? 0xAA324F90DED86B69L : 0xD86B69AA324F90DEL)
7616                        + (data[i + 4] ? 0x9CDA5E693FEA10AFL : 0xEA10AF9CDA5E693FL)
7617                        + (data[i + 5] ? 0x908E3D2C82567A73L : 0x567A73908E3D2C82L)
7618                        + (data[i + 6] ? 0x8538ECB5BD456EA3L : 0x456EA38538ECB5BDL)
7619                        + (data[i + 7] ? 0xD1B54A32D192ED03L : 0x92ED03D1B54A32D1L)
7620                ;
7621            }
7622            for (; i < data.length; i++) {
7623                result = 0x9E3779B97F4A7C15L * result + (data[i] ? 0xEBEDEED9D803C815L : 0xD9D803C815EBEDEEL);
7624            }
7625            result *= 0x94D049BB133111EBL;
7626            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7627            result *= 0x369DEA0F31A53F85L;
7628            result ^= result >>> 31;
7629            result *= 0xDB4F0B9175AE2165L;
7630            return (int)(result ^ result >>> 28);
7631        }
7632        public static int hash(final long seed, final byte[] data) {
7633            if (data == null) return 0;
7634            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7635            int i = 0;
7636            for (; i + 7 < data.length; i += 8) {
7637                result =  0xEBEDEED9D803C815L * result
7638                        + 0xD96EB1A810CAAF5FL * data[i]
7639                        + 0xC862B36DAF790DD5L * data[i + 1]
7640                        + 0xB8ACD90C142FE10BL * data[i + 2]
7641                        + 0xAA324F90DED86B69L * data[i + 3]
7642                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7643                        + 0x908E3D2C82567A73L * data[i + 5]
7644                        + 0x8538ECB5BD456EA3L * data[i + 6]
7645                        + 0xD1B54A32D192ED03L * data[i + 7]
7646                ;
7647            }
7648            for (; i < data.length; i++) {
7649                result = 0x9E3779B97F4A7C15L * result + data[i];
7650            }
7651            result *= 0x94D049BB133111EBL;
7652            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7653            result *= 0x369DEA0F31A53F85L;
7654            result ^= result >>> 31;
7655            result *= 0xDB4F0B9175AE2165L;
7656            return (int)(result ^ result >>> 28);
7657        }
7658
7659        public static int hash(final long seed, final short[] data) {
7660            if (data == null) return 0;
7661            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7662            int i = 0;
7663            for (; i + 7 < data.length; i += 8) {
7664                result =  0xEBEDEED9D803C815L * result
7665                        + 0xD96EB1A810CAAF5FL * data[i]
7666                        + 0xC862B36DAF790DD5L * data[i + 1]
7667                        + 0xB8ACD90C142FE10BL * data[i + 2]
7668                        + 0xAA324F90DED86B69L * data[i + 3]
7669                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7670                        + 0x908E3D2C82567A73L * data[i + 5]
7671                        + 0x8538ECB5BD456EA3L * data[i + 6]
7672                        + 0xD1B54A32D192ED03L * data[i + 7]
7673                ;
7674            }
7675            for (; i < data.length; i++) {
7676                result = 0x9E3779B97F4A7C15L * result + data[i];
7677            }
7678            result *= 0x94D049BB133111EBL;
7679            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7680            result *= 0x369DEA0F31A53F85L;
7681            result ^= result >>> 31;
7682            result *= 0xDB4F0B9175AE2165L;
7683            return (int)(result ^ result >>> 28);
7684        }
7685
7686        public static int hash(final long seed, final char[] data) {
7687            if (data == null) return 0;
7688            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7689            int i = 0;
7690            for (; i + 7 < data.length; i += 8) {
7691                result =  0xEBEDEED9D803C815L * result
7692                        + 0xD96EB1A810CAAF5FL * data[i]
7693                        + 0xC862B36DAF790DD5L * data[i + 1]
7694                        + 0xB8ACD90C142FE10BL * data[i + 2]
7695                        + 0xAA324F90DED86B69L * data[i + 3]
7696                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7697                        + 0x908E3D2C82567A73L * data[i + 5]
7698                        + 0x8538ECB5BD456EA3L * data[i + 6]
7699                        + 0xD1B54A32D192ED03L * data[i + 7]
7700                ;
7701            }
7702            for (; i < data.length; i++) {
7703                result = 0x9E3779B97F4A7C15L * result + data[i];
7704            }
7705            result *= 0x94D049BB133111EBL;
7706            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7707            result *= 0x369DEA0F31A53F85L;
7708            result ^= result >>> 31;
7709            result *= 0xDB4F0B9175AE2165L;
7710            return (int)(result ^ result >>> 28);
7711        }
7712
7713        public static int hash(final long seed, final CharSequence data) {
7714            if (data == null) return 0;
7715            final int length = data.length();
7716            long result = randomize(seed) ^ length * 0x9E3779B97F4A7C15L;
7717            int i = 0;
7718            for (; i + 7 < length; i += 8) {
7719                result =  0xEBEDEED9D803C815L * result
7720                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
7721                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
7722                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
7723                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
7724                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
7725                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
7726                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
7727                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
7728                ;
7729            }
7730            for (; i < length; i++) {
7731                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
7732            }
7733            result *= 0x94D049BB133111EBL;
7734            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7735            result *= 0x369DEA0F31A53F85L;
7736            result ^= result >>> 31;
7737            result *= 0xDB4F0B9175AE2165L;
7738            return (int)(result ^ result >>> 28);
7739        }
7740
7741        public static int hash(final long seed, final int[] data) {
7742            if (data == null) return 0;
7743            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7744            int i = 0;
7745            for (; i + 7 < data.length; i += 8) {
7746                result =  0xEBEDEED9D803C815L * result
7747                        + 0xD96EB1A810CAAF5FL * data[i]
7748                        + 0xC862B36DAF790DD5L * data[i + 1]
7749                        + 0xB8ACD90C142FE10BL * data[i + 2]
7750                        + 0xAA324F90DED86B69L * data[i + 3]
7751                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7752                        + 0x908E3D2C82567A73L * data[i + 5]
7753                        + 0x8538ECB5BD456EA3L * data[i + 6]
7754                        + 0xD1B54A32D192ED03L * data[i + 7]
7755                ;
7756            }
7757            for (; i < data.length; i++) {
7758                result = 0x9E3779B97F4A7C15L * result + data[i];
7759            }
7760            result *= 0x94D049BB133111EBL;
7761            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7762            result *= 0x369DEA0F31A53F85L;
7763            result ^= result >>> 31;
7764            result *= 0xDB4F0B9175AE2165L;
7765            return (int)(result ^ result >>> 28);
7766        }
7767
7768        public static int hash(final long seed, final int[] data, final int length) {
7769            if (data == null) return 0;
7770            final int len = Math.min(length, data.length);
7771            long result = randomize(seed) ^ len * 0x9E3779B97F4A7C15L;
7772            int i = 0;
7773            for (; i + 7 < len; i += 8) {
7774                result =  0xEBEDEED9D803C815L * result
7775                        + 0xD96EB1A810CAAF5FL * data[i]
7776                        + 0xC862B36DAF790DD5L * data[i + 1]
7777                        + 0xB8ACD90C142FE10BL * data[i + 2]
7778                        + 0xAA324F90DED86B69L * data[i + 3]
7779                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7780                        + 0x908E3D2C82567A73L * data[i + 5]
7781                        + 0x8538ECB5BD456EA3L * data[i + 6]
7782                        + 0xD1B54A32D192ED03L * data[i + 7]
7783                ;
7784            }
7785            for (; i < len; i++) {
7786                result = 0x9E3779B97F4A7C15L * result + data[i];
7787            }
7788            result *= 0x94D049BB133111EBL;
7789            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7790            result *= 0x369DEA0F31A53F85L;
7791            result ^= result >>> 31;
7792            result *= 0xDB4F0B9175AE2165L;
7793            return (int)(result ^ result >>> 28);
7794        }
7795
7796        public static int hash(final long seed, final long[] data) {
7797            if (data == null) return 0;
7798            long s = randomize(seed), a = s + b4, b = s + b3, c = s + b2, d = s + b1;
7799            final int len = data.length;
7800            for (int i = 3; i < len; i+=4) {
7801                a ^= data[i-3] * b1; a = (a << 23 | a >>> 41) * b3;
7802                b ^= data[i-2] * b2; b = (b << 25 | b >>> 39) * b4;
7803                c ^= data[i-1] * b3; c = (c << 29 | c >>> 35) * b5;
7804                d ^= data[i  ] * b4; d = (d << 31 | d >>> 33) * b1;
7805                s += a + b + c + d;
7806            }
7807            s += b5;
7808            switch (len & 3) {
7809                case 1: s = wow(s, b1 ^ data[len-1]); break;
7810                case 2: s = wow(s + data[len-2], b2 + data[len-1]); break;
7811                case 3: s = wow(s + data[len-3], b2 + data[len-2]) ^ wow(s + data[len-1], s ^ b3); break;
7812            }
7813            s = (s ^ s << 16) * (len ^ b0 ^ s >>> 32);
7814            return (int)(s - (s >>> 32));
7815        }
7816
7817        public static int hash(final long seed, final float[] data) {
7818            if (data == null) return 0;
7819            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7820            int i = 0;
7821            for (; i + 7 < data.length; i += 8) {
7822                result =  0xEBEDEED9D803C815L * result
7823                        + 0xD96EB1A810CAAF5FL * floatToIntBits(data[i])
7824                        + 0xC862B36DAF790DD5L * floatToIntBits(data[i + 1])
7825                        + 0xB8ACD90C142FE10BL * floatToIntBits(data[i + 2])
7826                        + 0xAA324F90DED86B69L * floatToIntBits(data[i + 3])
7827                        + 0x9CDA5E693FEA10AFL * floatToIntBits(data[i + 4])
7828                        + 0x908E3D2C82567A73L * floatToIntBits(data[i + 5])
7829                        + 0x8538ECB5BD456EA3L * floatToIntBits(data[i + 6])
7830                        + 0xD1B54A32D192ED03L * floatToIntBits(data[i + 7])
7831                ;
7832            }
7833            for (; i < data.length; i++) {
7834                result = 0x9E3779B97F4A7C15L * result + floatToIntBits(data[i]);
7835            }
7836            result *= 0x94D049BB133111EBL;
7837            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7838            result *= 0x369DEA0F31A53F85L;
7839            result ^= result >>> 31;
7840            result *= 0xDB4F0B9175AE2165L;
7841            return (int)(result ^ result >>> 28);
7842        }
7843        public static int hash(final long seed, final double[] data) {
7844            if (data == null) return 0;
7845            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7846            int i = 0;
7847            for (; i + 7 < data.length; i += 8) {
7848                result =  0xEBEDEED9D803C815L * result
7849                        + 0xD96EB1A810CAAF5FL * doubleToMixedIntBits(data[i])
7850                        + 0xC862B36DAF790DD5L * doubleToMixedIntBits(data[i + 1])
7851                        + 0xB8ACD90C142FE10BL * doubleToMixedIntBits(data[i + 2])
7852                        + 0xAA324F90DED86B69L * doubleToMixedIntBits(data[i + 3])
7853                        + 0x9CDA5E693FEA10AFL * doubleToMixedIntBits(data[i + 4])
7854                        + 0x908E3D2C82567A73L * doubleToMixedIntBits(data[i + 5])
7855                        + 0x8538ECB5BD456EA3L * doubleToMixedIntBits(data[i + 6])
7856                        + 0xD1B54A32D192ED03L * doubleToMixedIntBits(data[i + 7])
7857                ;
7858            }
7859            for (; i < data.length; i++) {
7860                result = 0x9E3779B97F4A7C15L * result + doubleToMixedIntBits(data[i]);
7861            }
7862            result *= 0x94D049BB133111EBL;
7863            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7864            result *= 0x369DEA0F31A53F85L;
7865            result ^= result >>> 31;
7866            result *= 0xDB4F0B9175AE2165L;
7867            return (int)(result ^ result >>> 28);
7868        }
7869
7870        /**
7871         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
7872         *
7873         * @param data  the char array to hash
7874         * @param start the start of the section to hash (inclusive)
7875         * @param end   the end of the section to hash (exclusive)
7876         * @return a 64-bit hash code for the requested section of data
7877         */
7878        public static int hash(final long seed, final char[] data, final int start, final int end) {
7879            if (data == null || start >= end) return 0;
7880            final int len = Math.min(end, data.length);
7881
7882            long result = randomize(seed) ^ (len - start) * 0x9E3779B97F4A7C15L;
7883            int i = start;
7884            for (; i + 7 < len; i += 8) {
7885                result =  0xEBEDEED9D803C815L * result
7886                        + 0xD96EB1A810CAAF5FL * data[i]
7887                        + 0xC862B36DAF790DD5L * data[i + 1]
7888                        + 0xB8ACD90C142FE10BL * data[i + 2]
7889                        + 0xAA324F90DED86B69L * data[i + 3]
7890                        + 0x9CDA5E693FEA10AFL * data[i + 4]
7891                        + 0x908E3D2C82567A73L * data[i + 5]
7892                        + 0x8538ECB5BD456EA3L * data[i + 6]
7893                        + 0xD1B54A32D192ED03L * data[i + 7]
7894                ;
7895            }
7896            for (; i < len; i++) {
7897                result = 0x9E3779B97F4A7C15L * result + data[i];
7898            }
7899            result *= 0x94D049BB133111EBL;
7900            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7901            result *= 0x369DEA0F31A53F85L;
7902            result ^= result >>> 31;
7903            result *= 0xDB4F0B9175AE2165L;
7904            return (int)(result ^ result >>> 28);
7905        }
7906
7907        /**
7908         * Hashes only a subsection of the given data, starting at start (inclusive) and ending before end (exclusive).
7909         *
7910         * @param data  the String or other CharSequence to hash
7911         * @param start the start of the section to hash (inclusive)
7912         * @param end   the end of the section to hash (exclusive)
7913         * @return a 64-bit hash code for the requested section of data
7914         */
7915        public static int hash(final long seed, final CharSequence data, final int start, final int end) {
7916            if (data == null || start >= end) return 0;
7917            final int len = Math.min(end, data.length());
7918
7919            long result = randomize(seed) ^ (len - start) * 0x9E3779B97F4A7C15L;
7920            int i = start;
7921            for (; i + 7 < len; i += 8) {
7922                result =  0xEBEDEED9D803C815L * result
7923                        + 0xD96EB1A810CAAF5FL * data.charAt(i)
7924                        + 0xC862B36DAF790DD5L * data.charAt(i + 1)
7925                        + 0xB8ACD90C142FE10BL * data.charAt(i + 2)
7926                        + 0xAA324F90DED86B69L * data.charAt(i + 3)
7927                        + 0x9CDA5E693FEA10AFL * data.charAt(i + 4)
7928                        + 0x908E3D2C82567A73L * data.charAt(i + 5)
7929                        + 0x8538ECB5BD456EA3L * data.charAt(i + 6)
7930                        + 0xD1B54A32D192ED03L * data.charAt(i + 7)
7931                ;
7932            }
7933            for (; i < len; i++) {
7934                result = 0x9E3779B97F4A7C15L * result + data.charAt(i);
7935            }
7936            result *= 0x94D049BB133111EBL;
7937            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7938            result *= 0x369DEA0F31A53F85L;
7939            result ^= result >>> 31;
7940            result *= 0xDB4F0B9175AE2165L;
7941            return (int)(result ^ result >>> 28);
7942        }
7943
7944
7945        public static int hash(final long seed, final char[][] data) {
7946            if (data == null) return 0;
7947            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7948            int i = 0;
7949            for (; i + 7 < data.length; i += 8) {
7950                result =  0xEBEDEED9D803C815L * result
7951                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7952                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7953                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7954                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7955                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7956                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7957                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7958                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7959                ;
7960            }
7961            for (; i < data.length; i++) {
7962                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7963            }
7964            result *= 0x94D049BB133111EBL;
7965            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7966            result *= 0x369DEA0F31A53F85L;
7967            result ^= result >>> 31;
7968            result *= 0xDB4F0B9175AE2165L;
7969            return (int)(result ^ result >>> 28);
7970        }
7971
7972        public static int hash(final long seed, final int[][] data) {
7973            if (data == null) return 0;
7974            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
7975            int i = 0;
7976            for (; i + 7 < data.length; i += 8) {
7977                result =  0xEBEDEED9D803C815L * result
7978                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
7979                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
7980                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
7981                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
7982                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
7983                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
7984                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
7985                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
7986                ;
7987            }
7988            for (; i < data.length; i++) {
7989                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
7990            }
7991            result *= 0x94D049BB133111EBL;
7992            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
7993            result *= 0x369DEA0F31A53F85L;
7994            result ^= result >>> 31;
7995            result *= 0xDB4F0B9175AE2165L;
7996            return (int)(result ^ result >>> 28);
7997        }
7998
7999        public static int hash(final long seed, final long[][] data) {
8000            if (data == null) return 0;
8001            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
8002            int i = 0;
8003            for (; i + 7 < data.length; i += 8) {
8004                result =  0xEBEDEED9D803C815L * result
8005                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
8006                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
8007                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
8008                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
8009                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
8010                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
8011                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
8012                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
8013                ;
8014            }
8015            for (; i < data.length; i++) {
8016                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
8017            }
8018            result *= 0x94D049BB133111EBL;
8019            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
8020            result *= 0x369DEA0F31A53F85L;
8021            result ^= result >>> 31;
8022            result *= 0xDB4F0B9175AE2165L;
8023            return (int)(result ^ result >>> 28);
8024        }
8025
8026        public static int hash(final long seed, final CharSequence[] data) {
8027            if (data == null) return 0;
8028            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
8029            int i = 0;
8030            for (; i + 7 < data.length; i += 8) {
8031                result =  0xEBEDEED9D803C815L * result
8032                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
8033                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
8034                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
8035                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
8036                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
8037                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
8038                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
8039                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
8040                ;
8041            }
8042            for (; i < data.length; i++) {
8043                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
8044            }
8045            result *= 0x94D049BB133111EBL;
8046            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
8047            result *= 0x369DEA0F31A53F85L;
8048            result ^= result >>> 31;
8049            result *= 0xDB4F0B9175AE2165L;
8050            return (int)(result ^ result >>> 28);
8051        }
8052
8053        public static int hash(final long seed, final CharSequence[]... data) {
8054            if (data == null) return 0;
8055            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
8056            int i = 0;
8057            for (; i + 7 < data.length; i += 8) {
8058                result =  0xEBEDEED9D803C815L * result
8059                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
8060                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
8061                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
8062                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
8063                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
8064                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
8065                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
8066                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
8067                ;
8068            }
8069            for (; i < data.length; i++) {
8070                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
8071            }
8072            result *= 0x94D049BB133111EBL;
8073            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
8074            result *= 0x369DEA0F31A53F85L;
8075            result ^= result >>> 31;
8076            result *= 0xDB4F0B9175AE2165L;
8077            return (int)(result ^ result >>> 28);
8078        }
8079
8080        public static int hash(final long seed, final Iterable<? extends CharSequence> data) {
8081            if (data == null) return 0;
8082            long s = randomize(seed);
8083            final Iterator<? extends CharSequence> it = data.iterator();
8084            int len = 0;
8085            while (it.hasNext())
8086            {
8087                ++len;
8088                s = mum(
8089                        mum(hash(seed, it.next()) ^ b1, (it.hasNext() ? hash(seed, it.next()) ^ b2 ^ ++len : b2)) + s,
8090                        mum((it.hasNext() ? hash(seed, it.next()) ^ b3 ^ ++len : b3), (it.hasNext() ? hash(seed, it.next()) ^ b4 ^ ++len : b4)));
8091            }
8092            return (int) mum(s ^ s << 16, len ^ b0);
8093        }
8094
8095        public static int hash(final long seed, final List<? extends CharSequence> data) {
8096            if (data == null) return 0;
8097            final int len = data.size();
8098            long result = randomize(seed) ^ len * 0x9E3779B97F4A7C15L;
8099            int i = 0;
8100            for (; i + 7 < len; i += 8) {
8101                result =  0xEBEDEED9D803C815L * result
8102                        + 0xD96EB1A810CAAF5FL * hash(seed, data.get(i))
8103                        + 0xC862B36DAF790DD5L * hash(seed, data.get(i + 1))
8104                        + 0xB8ACD90C142FE10BL * hash(seed, data.get(i + 2))
8105                        + 0xAA324F90DED86B69L * hash(seed, data.get(i + 3))
8106                        + 0x9CDA5E693FEA10AFL * hash(seed, data.get(i + 4))
8107                        + 0x908E3D2C82567A73L * hash(seed, data.get(i + 5))
8108                        + 0x8538ECB5BD456EA3L * hash(seed, data.get(i + 6))
8109                        + 0xD1B54A32D192ED03L * hash(seed, data.get(i + 7))
8110                ;
8111            }
8112            for (; i < len; i++) {
8113                result = 0x9E3779B97F4A7C15L * result + hash(seed, data.get(i));
8114            }
8115            result *= 0x94D049BB133111EBL;
8116            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
8117            result *= 0x369DEA0F31A53F85L;
8118            result ^= result >>> 31;
8119            result *= 0xDB4F0B9175AE2165L;
8120            return (int)(result ^ result >>> 28);
8121
8122        }
8123
8124        public static int hash(final long seed, final Object[] data) {
8125            if (data == null) return 0;
8126            long result = randomize(seed) ^ data.length * 0x9E3779B97F4A7C15L;
8127            int i = 0;
8128            for (; i + 7 < data.length; i += 8) {
8129                result =  0xEBEDEED9D803C815L * result
8130                        + 0xD96EB1A810CAAF5FL * hash(seed, data[i])
8131                        + 0xC862B36DAF790DD5L * hash(seed, data[i + 1])
8132                        + 0xB8ACD90C142FE10BL * hash(seed, data[i + 2])
8133                        + 0xAA324F90DED86B69L * hash(seed, data[i + 3])
8134                        + 0x9CDA5E693FEA10AFL * hash(seed, data[i + 4])
8135                        + 0x908E3D2C82567A73L * hash(seed, data[i + 5])
8136                        + 0x8538ECB5BD456EA3L * hash(seed, data[i + 6])
8137                        + 0xD1B54A32D192ED03L * hash(seed, data[i + 7])
8138                ;
8139            }
8140            for (; i < data.length; i++) {
8141                result = 0x9E3779B97F4A7C15L * result + hash(seed, data[i]);
8142            }
8143            result *= 0x94D049BB133111EBL;
8144            result ^= (result << 41 | result >>> 23) ^ (result << 17 | result >>> 47);
8145            result *= 0x369DEA0F31A53F85L;
8146            result ^= result >>> 31;
8147            result *= 0xDB4F0B9175AE2165L;
8148            return (int)(result ^ result >>> 28);
8149        }
8150
8151        public static int hash(final long seed, final Object data) {
8152            if (data == null) return 0;
8153            return (int)((data.hashCode() + randomize(seed)) * 0x9E3779B97F4A7C15L >>> 32);
8154        }
8155
8156    }
8157}