//On *nix/mono: compile using: gmcs DictionaryBenchmark.cs PCADLODictionary.cs
    static void Main(string[] args)
    {
        if(args.Length < 1) {
            Console.WriteLine("mono DictionaryBenchmark -k <key-strat> -p <key-prefix> "
            +"-i <num-inserts> -l <num-lookups> -r <num-removes> -s <seed> -f <failed-lookup-fraction> "
            +"--dump <what-to-dump>");
            return;
        }

        //Dictionary<string, PCADLODictionary.Hasher> hashers = new Dictionary<string, PCADLODictionary.Hasher>();
        //hashers.Add("default", PCADLODictionary.defaultHasher);

        int iters = 1;
        int seed = 0;
        string validate = null;
        DictionaryBenchmark hmb = new DictionaryBenchmark();
        for(int i = 0; i < args.Length; i+=2) {
            if(i >= (args.Length - 1)) {
                break;
            }
            if(args[i].Equals("-k")) {
                hmb.keyStrat = args[i + 1];
            }
            if(args[i].Equals("-p")) {
                hmb.keyPrefix = args[i + 1];
            }
            else if(args[i].Equals("-n")) {
                hmb.nKeys = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("-i")) {
                hmb.nInserts = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("-l")) {
                hmb.nLookups = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("-r")) {
                hmb.nRemoves = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("-s")) {
                hmb.seed = seed = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("--reps")) {
                iters = Convert.ToInt32(args[i + 1]);
            }
            else if(args[i].Equals("--init")) {
                hmb.initMapSizeFraction = (float)Convert.ToDouble(args[i + 1]);
            }
            else if(args[i].Equals("-f")) {
                hmb.fractionUnsuccessfulLookups = (float)Convert.ToDouble(args[i + 1]);
            }
            else if(args[i].Equals("-h")) {
                //hmb.hashFunc = hashers.get(args[i + 1]);
            }
            else if(args[i].Equals("--dump")) {
                if(args[i + 1].StartsWith("col")) {
                    //PCADLO.PCADLODictionary.dumpHashCollisions = true;
                }
                if(args[i + 1].StartsWith("valid8")) {
                    validate = args[i + 1];
                }
            }

        }
        Console.WriteLine("Generating keys...");
        hmb.init();
        if(seed < 0) {
            hmb.seed = System.Environment.TickCount;
            Console.WriteLine("Temp seed = "+hmb.seed);
        }
        List<string> keyList = hmb.generateKeys();
        demoFailureCase();
        if(validate != null) {
            hmb.validateMaps(keyList, new Dictionary<string,string>(), new PCADLO.PCADLODictionary<string, string>(), validate);
        }
        hmb.testMapGrow("Dictionary", keyList, new Dictionary<string, string>());
        hmb.testMapGrow("PCADLO Dictionary", keyList, new PCADLO.PCADLODictionary<string, string>());

        for(int i = 0; i < iters; i++) {
            Console.WriteLine("\n------\nIteration #"+(i + 1));
            //randomize order of tests to check if running one before the other affects results
            hmb.random = new Random(System.Environment.TickCount);
            float [] avglatPlain = null;
            float [] avglatPCADLO = null;
            long checksumPlain = 0;
            long checksumPCADLO = 0;
            if(seed < 0) {
                hmb.seed = System.Environment.TickCount;
                Console.WriteLine("Temp seed = "+hmb.seed);
            }
            if(hmb.random.Next() % 2 == 0) {
                Console.WriteLine("\nPlain Dictionary");
                avglatPlain = hmb.testPlainDictionary(keyList, out checksumPlain);
                Console.WriteLine("\nPCADLO Dictionary");
                avglatPCADLO = hmb.testPCADLODictionary(keyList, out checksumPCADLO);
            }
            else {
                Console.WriteLine("\nPCADLO Dictionary");
                avglatPCADLO = hmb.testPCADLODictionary(keyList, out checksumPCADLO);
                Console.WriteLine("\nPlain Dictionary");
                avglatPlain = hmb.testPlainDictionary(keyList, out checksumPlain);
            }
            if(checksumPCADLO != checksumPlain) {
                Console.WriteLine("\nChecksum mismatch: Hash-collision detected!!!!");
            }
            Console.WriteLine("\nPCADLO : Plain % improvement: ");
            Console.WriteLine(string.Format("Avg Insert: {0:00.000}%, Lookup: {1:00.000}%, Remove {2:00.000}%",
                (100.0f * (avglatPlain[0] - avglatPCADLO[0])/avglatPlain[0]),
                (100.0f * (avglatPlain[1] - avglatPCADLO[1])/avglatPlain[1]),
                (100.0f * (avglatPlain[2] - avglatPCADLO[2])/avglatPlain[2])));
        }
    }
    //On *nix/mono: compile using: gmcs DictionaryBenchmark.cs PCADLODictionary.cs
    static void Main(string[] args)
    {
        if (args.Length < 1)
        {
            Console.WriteLine("mono DictionaryBenchmark -k <key-strat> -p <key-prefix> "
                              + "-i <num-inserts> -l <num-lookups> -r <num-removes> -s <seed> -f <failed-lookup-fraction> "
                              + "--dump <what-to-dump>");
            return;
        }

        //Dictionary<string, PCADLODictionary.Hasher> hashers = new Dictionary<string, PCADLODictionary.Hasher>();
        //hashers.Add("default", PCADLODictionary.defaultHasher);

        int    iters            = 1;
        int    seed             = 0;
        string validate         = null;
        DictionaryBenchmark hmb = new DictionaryBenchmark();

        for (int i = 0; i < args.Length; i += 2)
        {
            if (i >= (args.Length - 1))
            {
                break;
            }
            if (args[i].Equals("-k"))
            {
                hmb.keyStrat = args[i + 1];
            }
            if (args[i].Equals("-p"))
            {
                hmb.keyPrefix = args[i + 1];
            }
            else if (args[i].Equals("-n"))
            {
                hmb.nKeys = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("-i"))
            {
                hmb.nInserts = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("-l"))
            {
                hmb.nLookups = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("-r"))
            {
                hmb.nRemoves = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("-s"))
            {
                hmb.seed = seed = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("--reps"))
            {
                iters = Convert.ToInt32(args[i + 1]);
            }
            else if (args[i].Equals("--init"))
            {
                hmb.initMapSizeFraction = (float)Convert.ToDouble(args[i + 1]);
            }
            else if (args[i].Equals("-f"))
            {
                hmb.fractionUnsuccessfulLookups = (float)Convert.ToDouble(args[i + 1]);
            }
            else if (args[i].Equals("-h"))
            {
                //hmb.hashFunc = hashers.get(args[i + 1]);
            }
            else if (args[i].Equals("--dump"))
            {
                if (args[i + 1].StartsWith("col"))
                {
                    //PCADLO.PCADLODictionary.dumpHashCollisions = true;
                }
                if (args[i + 1].StartsWith("valid8"))
                {
                    validate = args[i + 1];
                }
            }
        }
        Console.WriteLine("Generating keys...");
        hmb.init();
        if (seed < 0)
        {
            hmb.seed = System.Environment.TickCount;
            Console.WriteLine("Temp seed = " + hmb.seed);
        }
        List <string> keyList = hmb.generateKeys();

        demoFailureCase();
        if (validate != null)
        {
            hmb.validateMaps(keyList, new Dictionary <string, string>(), new PCADLO.PCADLODictionary <string, string>(), validate);
        }
        hmb.testMapGrow("Dictionary", keyList, new Dictionary <string, string>());
        hmb.testMapGrow("PCADLO Dictionary", keyList, new PCADLO.PCADLODictionary <string, string>());

        for (int i = 0; i < iters; i++)
        {
            Console.WriteLine("\n------\nIteration #" + (i + 1));
            //randomize order of tests to check if running one before the other affects results
            hmb.random = new Random(System.Environment.TickCount);
            float [] avglatPlain    = null;
            float [] avglatPCADLO   = null;
            long     checksumPlain  = 0;
            long     checksumPCADLO = 0;
            if (seed < 0)
            {
                hmb.seed = System.Environment.TickCount;
                Console.WriteLine("Temp seed = " + hmb.seed);
            }
            if (hmb.random.Next() % 2 == 0)
            {
                Console.WriteLine("\nPlain Dictionary");
                avglatPlain = hmb.testPlainDictionary(keyList, out checksumPlain);
                Console.WriteLine("\nPCADLO Dictionary");
                avglatPCADLO = hmb.testPCADLODictionary(keyList, out checksumPCADLO);
            }
            else
            {
                Console.WriteLine("\nPCADLO Dictionary");
                avglatPCADLO = hmb.testPCADLODictionary(keyList, out checksumPCADLO);
                Console.WriteLine("\nPlain Dictionary");
                avglatPlain = hmb.testPlainDictionary(keyList, out checksumPlain);
            }
            if (checksumPCADLO != checksumPlain)
            {
                Console.WriteLine("\nChecksum mismatch: Hash-collision detected!!!!");
            }
            Console.WriteLine("\nPCADLO : Plain % improvement: ");
            Console.WriteLine(string.Format("Avg Insert: {0:00.000}%, Lookup: {1:00.000}%, Remove {2:00.000}%",
                                            (100.0f * (avglatPlain[0] - avglatPCADLO[0]) / avglatPlain[0]),
                                            (100.0f * (avglatPlain[1] - avglatPCADLO[1]) / avglatPlain[1]),
                                            (100.0f * (avglatPlain[2] - avglatPCADLO[2]) / avglatPlain[2])));
        }
    }