class SpookyHash32 {

    public static long hash(byte[] src, int start, int length, long[] seedResult) {
            if (length < SMALLHASH_LIMIT_BYTES) {
                    smallHash(src, start, length, seedResult);
                    return seedResult[0];
            }

            long h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
            h0 = h3 = h6 = h9 = seedResult[0];
            h1 = h4 = h7 = h10 = seedResult[1];
            h2 = h5 = h8 = h11 = ARBITRARY_BITS;

            int remaining = length;
            int pos = start;
            while (remaining >= BLOCK_SIZE_BYTES) {		
                    h0 += packLong(src, pos); 
                    h2 ^= h10;     
                    h11 ^= h0;   
                    h0 = (h0 << 11) | (h0 >>> 53);     
                    h11 += h1;

                    h1 += packLong(src, pos+8); 
                    h3 ^= h11;     
                    h0 ^= h1;     
                    h1 = (h1 << 32) | (h1 >>> 32);     
                    h0 += h2;

                    h2 += packLong(src, pos+16); 
                    h4 ^= h0;      
                    h1 ^= h2;     
                    h2 = (h2 << 43) | (h2 >>> 21);     
                    h1 += h3;

                    h3 += packLong(src, pos+24); 
                    h5 ^= h1;      
                    h2 ^= h3;     
                    h3 = (h3 << 31) | (h3 >>> 33);     
                    h2 += h4;

                    h4 += packLong(src, pos+32); 
                    h6 ^= h2;      
                    h3 ^= h4;     
                    h4 = (h4 << 17) | (h4 >>> 47);     
                    h3 += h5;

                    h5 += packLong(src, pos+40); 
                    h7 ^= h3;      
                    h4 ^= h5;     
                    h5 = (h5 << 28) | (h5 >>> 36);     
                    h4 += h6;

                    h6 += packLong(src, pos+48); 
                    h8 ^= h4;      
                    h5 ^= h6;     
                    h6 = (h6 << 39) | (h6 >>> 25);     
                    h5 += h7;

                    h7 += packLong(src, pos+56); 
                    h9 ^= h5;      
                    h6 ^= h7;     
                    h7 = (h7 << 57) | (h7 >>> 7);     
                    h6 += h8;

                    h8 += packLong(src, pos+64); 
                    h10 ^= h6;     
                    h7 ^= h8;     
                    h8 = (h8 << 55) | (h8 >>> 9);     
                    h7 += h9;

                    h9 += packLong(src, pos+72); 
                    h11 ^= h7;     
                    h8 ^= h9;     
                    h9 = (h9 << 54) | (h9 >>> 10);     
                    h8 += h10;

                    h10 += packLong(src, pos+80); 
                    h0 ^= h8;      
                    h9 ^= h10;    
                    h10 = (h10 << 22) | (h10 >>> 42);  
                    h9 += h11;

                    h11 += packLong(src, pos+88); 
                    h1 ^= h9;      
                    h10 ^= h11;   
                    h11 = (h11 << 46) | (h11 >>> 18);  
                    h10 += h0;

                    remaining -= BLOCK_SIZE_BYTES;
                    pos += BLOCK_SIZE_BYTES;
            }

            // assert remaining < BLOCK_SIZE_BYTES;
            int partialSize = remaining & 7;
            int wholeWords = remaining >>> 3;
            if (partialSize > 0) {
                    long partial = packPartial(src, pos + (wholeWords << 3), partialSize);
                    switch (wholeWords) {
                    case 0:
                            h0 += partial;
                            break;
                    case 1:
                            h1 += partial;
                            break;
                    case 2:
                            h2 += partial;
                            break;
                    case 3:
                            h3 += partial;
                            break;
                    case 4:
                            h4 += partial;
                            break;
                    case 5:
                            h5 += partial;
                            break;
                    case 6:
                            h6 += partial;
                            break;
                    case 7:
                            h7 += partial;
                            break;
                    case 8:
                            h8 += partial;
                            break;
                    case 9:
                            h9 += partial;
                            break;
                    case 10:
                            h10 += partial;
                            break;
                    case 11:
                            h11 += partial;
                            break;
                    }
            }
            switch (wholeWords) { // fall-through is intentional
            case 11:
                    h10 += packLong(src, pos+80);
            case 10:
                    h9 += packLong(src, pos+72);
            case 9:
                    h8 += packLong(src, pos+64);
            case 8:
                    h7 += packLong(src, pos+56);
            case 7:
                    h6 += packLong(src, pos+48);
            case 6:
                    h5 += packLong(src, pos+40);
            case 5:
                    h4 += packLong(src, pos+32);
            case 4:
                    h3 += packLong(src, pos+24);
            case 3:
                    h2 += packLong(src, pos+16);
            case 2:
                    h1 += packLong(src, pos+8);
            case 1:
                    h0 += packLong(src, pos);
            default:
                    break;
            }

            h11 += ((long)remaining) << 56;

            for (int i = 0; i < 3; i++) {
            h11 += h1;   
            h2 ^= h11;   
            h1 = (h1 << 44)  | (h1 >>> 20);
            h0 += h2;    
            h3 ^= h0;    
            h2 = (h2 << 15)  | (h2 >>> 49);
            h1 += h3;    
            h4 ^= h1;    
            h3 = (h3 << 34)  | (h3 >>> 30);
            h2 += h4;    
            h5 ^= h2;    
            h4 = (h4 << 21)  | (h4 >>> 43);
            h3 += h5;    
            h6 ^= h3;    
            h5 = (h5 << 38)  | (h5 >>> 26);
            h4 += h6;    
            h7 ^= h4;    
            h6 = (h6 << 33)  | (h6 >>> 31);
            h5 += h7;    
            h8 ^= h5;    
            h7 = (h7 << 10)  | (h7 >>> 54);
            h6 += h8;    
            h9 ^= h6;    
            h8 = (h8 << 13)  | (h8 >>> 51);
            h7 += h9;    
            h10 ^= h7;    
            h9 = (h9 << 38)  | (h9 >>> 26);
            h8 += h10;   
            h11 ^= h8;    
            h10 = (h10 << 53) | (h10 >>> 11);
            h9 += h11;   
            h0 ^= h9;    
            h11 = (h11 << 42) | (h11 >>> 22);
            h10 += h0;   
            h1 ^= h10;   
            h0 = (h0 << 54)  | (h0 >>> 10);
            }
            seedResult[0] = h0;
            seedResult[1] = h1;
            return h0;
    }

    public  SpookyHash32();
    public  SpookyHash32(long seed0, long seed1);

}