예제 #1
0
파일: Program.cs 프로젝트: wenij/MFORTH
        /// <summary>
        /// Hash the given name using the given hash functions.
        /// </summary>
        /// <param name="name">The name to hash.</param>
        /// <param name="phf1">PearsonHashFunction to use for the upper
        /// eight bits of the hash.</param>
        /// <param name="phf2">PearsonHashFunction to use for the lower
        /// eight bits of the hash.</param>
        /// <param name="hashMask">The mask value to be applied to the
        /// hash.</param>
        /// <returns>The hash value, masked by hashMask.</returns>
        private static int HashName(string name, PearsonHashFunction phf1, PearsonHashFunction phf2, int hashMask)
        {
            // Get the word name as an array of uppercase ASCII bytes.
            string upperName = name.ToUpperInvariant();

            byte[] upperNameBytes = Encoding.ASCII.GetBytes(upperName);

            // Hash the name.  Use phf1 for the upper eight bits and
            // phf2 for the lower eight bits.  Then mask off the hash
            // value to keep it within range of our hash table.
            return(((phf1.Hash(upperNameBytes) << 8) | phf2.Hash(upperNameBytes)) & hashMask);
        }
예제 #2
0
파일: Program.cs 프로젝트: malyn/MFORTH
        /// <summary>
        /// Hash the given name using the given hash functions.
        /// </summary>
        /// <param name="name">The name to hash.</param>
        /// <param name="phf1">PearsonHashFunction to use for the upper
        /// eight bits of the hash.</param>
        /// <param name="phf2">PearsonHashFunction to use for the lower
        /// eight bits of the hash.</param>
        /// <param name="hashMask">The mask value to be applied to the
        /// hash.</param>
        /// <returns>The hash value, masked by hashMask.</returns>
        private static int HashName(string name, PearsonHashFunction phf1, PearsonHashFunction phf2, int hashMask)
        {
            // Get the word name as an array of uppercase ASCII bytes.
            string upperName = name.ToUpperInvariant();
            byte[] upperNameBytes = Encoding.ASCII.GetBytes(upperName);

            // Hash the name.  Use phf1 for the upper eight bits and
            // phf2 for the lower eight bits.  Then mask off the hash
            // value to keep it within range of our hash table.
            return ((phf1.Hash(upperNameBytes) << 8) | phf2.Hash(upperNameBytes)) & hashMask;
        }
예제 #3
0
파일: Program.cs 프로젝트: malyn/MFORTH
        /// <summary>
        /// Generate the MFORTH hash table.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="phf1">Upon return, will contain the first
        /// PearsonHashFunction used by the hash table.</param>
        /// <param name="phf2">Upon return, will contain the second
        /// PearsonHashFunction used by the hash table.</param>
        /// <returns>The MFORTH hash table.</returns>
        private static CuckooHashTable<Word> GenerateHashTable(ROM rom, out PearsonHashFunction phf1, out PearsonHashFunction phf2)
        {
            // Initialize our random number generator.
            var random = new Random(HashTableRandomSeed);

            // Initialize our hash functions and the hash table.
            var hashFunc1 = phf1 = new PearsonHashFunction(random);
            var hashFunc2 = phf2 = new PearsonHashFunction(random);
            var hashTable = new CuckooHashTable<Word>(
                (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));

            // Generate the hash table.
            #if FINDING_OPTIMAL_HASH_SEED
            int minValuesAtSecondLocation = int.MaxValue;
            #endif
            for (;;)
            {
            #if !FINDING_OPTIMAL_HASH_SEED
                // Display a progress dot.
                Console.Write(".");
            #endif

                // Add all of the words to our hash table; assume that
                // we will be successful.
                bool haveCompleteTable = true;
                foreach (var word in rom.Words)
                {
                    if (!hashTable.TryAddValue(word))
                    {
                        haveCompleteTable = false;
                        break;
                    }
                }

            #if !FINDING_OPTIMAL_HASH_SEED
                // We're done if all of the words were added to the
                // table.
                if (haveCompleteTable)
                {
                    break;
                }

                // We failed to generate a complete hash table; shuffle
                // the hash functions, clear the table, and try again.
                phf1.ShuffleAuxilliaryTable(random);
                phf2.ShuffleAuxilliaryTable(random);
                hashTable.Clear();
            #else
                // Print out the results if this seed produced better
                // results than the previous best seed.
                if (haveCompleteTable
                    && hashTable.NumValuesStoredAtSecondHash < minValuesAtSecondLocation)
                {
                    Console.WriteLine(
                        "Seed: {0}; 1st: {1}; 2nd: {2}",
                        HashTableRandomSeed,
                        hashTable.NumValuesStoredAtFirstHash,
                        hashTable.NumValuesStoredAtSecondHash);
                    minValuesAtSecondLocation = hashTable.NumValuesStoredAtSecondHash;
                }

                // Generate a new seed and re-create all of the hash
                // functions and tables.
                random = new Random(++HashTableRandomSeed);
                hashFunc1 = phf1 = new PearsonHashFunction(random);
                hashFunc2 = phf2 = new PearsonHashFunction(random);
                hashTable = new CuckooHashTable<Word>(
                    (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                    (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));
            #endif
            }

            // Ensure that all of the words in the ROM were added to the
            // hash table.
            if (rom.NumWords != hashTable.Count)
            {
                throw new InvalidDataException(
                    string.Format(
                        "Hash table only has {0} words; expected {1} words.",
                        hashTable.Count,
                        rom.NumWords));
            }

            // Return the hash table.
            return hashTable;
        }
예제 #4
0
파일: Program.cs 프로젝트: wenij/MFORTH
        /// <summary>
        /// Generate the MFORTH hash table.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="phf1">Upon return, will contain the first
        /// PearsonHashFunction used by the hash table.</param>
        /// <param name="phf2">Upon return, will contain the second
        /// PearsonHashFunction used by the hash table.</param>
        /// <returns>The MFORTH hash table.</returns>
        private static CuckooHashTable <Word> GenerateHashTable(ROM rom, out PearsonHashFunction phf1, out PearsonHashFunction phf2)
        {
            // Initialize our random number generator.
            var random = new Random(HashTableRandomSeed);

            // Initialize our hash functions and the hash table.
            var hashFunc1 = phf1 = new PearsonHashFunction(random);
            var hashFunc2 = phf2 = new PearsonHashFunction(random);
            var hashTable = new CuckooHashTable <Word>(
                (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));

            // Generate the hash table.
#if FINDING_OPTIMAL_HASH_SEED
            int minValuesAtSecondLocation = int.MaxValue;
#endif
            for (;;)
            {
#if !FINDING_OPTIMAL_HASH_SEED
                // Display a progress dot.
                Console.Write(".");
#endif

                // Add all of the words to our hash table; assume that
                // we will be successful.
                bool haveCompleteTable = true;
                foreach (var word in rom.Words)
                {
                    if (!hashTable.TryAddValue(word))
                    {
                        haveCompleteTable = false;
                        break;
                    }
                }

#if !FINDING_OPTIMAL_HASH_SEED
                // We're done if all of the words were added to the
                // table.
                if (haveCompleteTable)
                {
                    break;
                }

                // We failed to generate a complete hash table; shuffle
                // the hash functions, clear the table, and try again.
                phf1.ShuffleAuxilliaryTable(random);
                phf2.ShuffleAuxilliaryTable(random);
                hashTable.Clear();
#else
                // Print out the results if this seed produced better
                // results than the previous best seed.
                if (haveCompleteTable &&
                    hashTable.NumValuesStoredAtSecondHash < minValuesAtSecondLocation)
                {
                    Console.WriteLine(
                        "Seed: {0}; 1st: {1}; 2nd: {2}",
                        HashTableRandomSeed,
                        hashTable.NumValuesStoredAtFirstHash,
                        hashTable.NumValuesStoredAtSecondHash);
                    minValuesAtSecondLocation = hashTable.NumValuesStoredAtSecondHash;
                }

                // Generate a new seed and re-create all of the hash
                // functions and tables.
                random    = new Random(++HashTableRandomSeed);
                hashFunc1 = phf1 = new PearsonHashFunction(random);
                hashFunc2 = phf2 = new PearsonHashFunction(random);
                hashTable = new CuckooHashTable <Word>(
                    (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                    (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));
#endif
            }

            // Ensure that all of the words in the ROM were added to the
            // hash table.
            if (rom.NumWords != hashTable.Count)
            {
                throw new InvalidDataException(
                          string.Format(
                              "Hash table only has {0} words; expected {1} words.",
                              hashTable.Count,
                              rom.NumWords));
            }

            // Return the hash table.
            return(hashTable);
        }