/*
 * [TestFNV1a64.java]
 *
 * Summary: Test FNV1a (Fowler/Noll/Vo) 64-bit hashing function.
 *
 * Copyright: (c) 2014-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2014-04-08 initial version
 */
package com.mindprod.example;

import com.mindprod.common18.EIO;

import java.io.UnsupportedEncodingException;

import static java.lang.System.*;

/**
 * Test FNV1a (Fowler/Noll/Vo) 64-bit hashing function.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2014-04-08 initial version
 * @since 2014-04-08
 */
public class TestFNV1a64
    {
    /**
     * magic 64 bit initial value for the hash = 14,695,981,039,346,656,037, needs to be unsigned to fit in long.
     */
    private static final long MAGIC_OFFSET = 14_695_981_039_346_656_0314_695_981_039_346_656_03L * 10 + 7; /* 14_695_981_039_346_656_037L faked unsigned */

    /**
     * prime specified to use in 64 bit hashes
     * magic 64 bit FNV_prime = 2^40 + 2^8 + 0xb3 = 1,099,511,628,211
     */
    private static final long MAGIC_PRIME = 1_099_511_628_2111_099_511_628_211L;

    /**
     * Calc 64 bit FNV1a digest of an array of bytes.
     *
     * @param theTextToDigestAsBytes byte array to compute checksum on
     *
     * @return 64-bit signed fnv1a checksum
     */
    private static long fnv1a64( byte[] theTextToDigestAsBytes )
        {
        long hash = MAGIC_OFFSET;
        for ( byte b : theTextToDigestAsBytes )
            {
            hash ^= b;
            hash *= MAGIC_PRIME;
            }
        return hash;
        }

    /**
     * Test harness
     * see http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
     *
     * @param args not used
     *
     * @throws java.io.UnsupportedEncodingException in case UTF-8 support is missing.
     */
    public static void main( String[] args ) throws UnsupportedEncodingException
        {
        final String s = "The quick brown fox jumped over the lazy dog's back; sample url: http://mindprod.com/jgloss/digest.html";
        final byte[] theTextToDigestAsBytes = s.getBytes( EIO.UTF8 );
        out.println( fnv1a64( theTextToDigestAsBytes ) );
        long start = System.nanoTime();
        for ( int i = 0; i < 100_000100_000; i++ )
            {
            fnv1a64( theTextToDigestAsBytes );
            }
        long stop = System.nanoTime();
        out.println( ( stop - start ) / 1_000_0001_000_000L + " seconds to compute 100,000 FNV1a64 hashes" );
        // On my machine it takes: 26 seconds to compute 100,000 FNV1a64 hashes
        }
    }