/// <summary> /// Write the MFORTH hash table to the given writer. /// </summary> /// <param name="writer">The writer where the hash table should be /// written.</param> /// <param name="hashTable">MFORTH hash table.</param> /// <param name="symbolTable">TASM symbol table for the MFORTH /// ROM.</param> private static void WriteHashTable(TextWriter writer, CuckooHashTable <Word> hashTable, IDictionary <int, string> symbolTable) { // Write out every possible entry in the hash table; not all // hash locations will be filled. for (int i = 0; i < HashTableSize; i++) { // Try to retrieve the word at this hash location; write // out a zero value if no word is stored at this // location. Word word; if (!hashTable.TryGetValue(i, out word)) { writer.WriteLine(" .WORD 0"); continue; } // There is a word stored at this hash location. Find // symbol associated with this word. Symbols point to // the CFA of each word, so we need to offset the word // address by the NFATOCFASZ. That value is different // between standard MFORTH builds and profiled MFORTH // builds. We try the standard value first and then // fall back to the profile value. string label; if (!symbolTable.TryGetValue(word.NFA + 3, out label)) { label = symbolTable[word.NFA + 5]; } // Write out the hash entry, which must point to the NFA // of the word and not the CFA. writer.WriteLine(" .WORD {0}-NFATOCFASZ", label); } }
public static void DoTest() { var cuckooTable = new CuckooHashTable<string, int>(); cuckooTable.Add("Ahmad", 10); cuckooTable.Add("Oliver", 11); cuckooTable.Add("Konstantinos", 12); cuckooTable.Add("Olympos", 13); cuckooTable.Add("Bic", 14); cuckooTable.Add("Carter", 15); cuckooTable.Add("Sameeros", 16); var Ahmad = cuckooTable["Ahmad"]; Debug.Assert(Ahmad == 10); var Oliver = cuckooTable["Oliver"]; Debug.Assert(Oliver == 11); var Konstantinos = cuckooTable["Konstantinos"]; Debug.Assert(Konstantinos == 12); var Olympos = cuckooTable["Olympos"]; Debug.Assert(Olympos == 13); var Bic = cuckooTable["Bic"]; Debug.Assert(Bic == 14); var Carter = cuckooTable["Carter"]; Debug.Assert(Carter == 15); var Sameeros = cuckooTable["Sameeros"]; Debug.Assert(Sameeros == 16); cuckooTable.Clear(); }
public static void DoTest() { var cuckooTable = new CuckooHashTable <string, int>(); cuckooTable.Add("Ahmad", 10); cuckooTable.Add("Oliver", 11); cuckooTable.Add("Konstantinos", 12); cuckooTable.Add("Olympos", 13); cuckooTable.Add("Bic", 14); cuckooTable.Add("Carter", 15); cuckooTable.Add("Sameeros", 16); var Ahmad = cuckooTable["Ahmad"]; Assert.True(Ahmad == 10); var Oliver = cuckooTable["Oliver"]; Assert.True(Oliver == 11); var Konstantinos = cuckooTable["Konstantinos"]; Assert.True(Konstantinos == 12); var Olympos = cuckooTable["Olympos"]; Assert.True(Olympos == 13); var Bic = cuckooTable["Bic"]; Assert.True(Bic == 14); var Carter = cuckooTable["Carter"]; Assert.True(Carter == 15); var Sameeros = cuckooTable["Sameeros"]; Assert.True(Sameeros == 16); cuckooTable.Clear(); }
/// <summary> /// Write the MFORTH hash table to the given writer. /// </summary> /// <param name="writer">The writer where the hash table should be /// written.</param> /// <param name="hashTable">MFORTH hash table.</param> /// <param name="symbolTable">TASM symbol table for the MFORTH /// ROM.</param> private static void WriteHashTable(TextWriter writer, CuckooHashTable<Word> hashTable, IDictionary<int, string> symbolTable) { // Write out every possible entry in the hash table; not all // hash locations will be filled. for (int i = 0; i < HashTableSize; i++) { // Try to retrieve the word at this hash location; write // out a zero value if no word is stored at this // location. Word word; if (!hashTable.TryGetValue(i, out word)) { writer.WriteLine(" .WORD 0"); continue; } // There is a word stored at this hash location. Find // symbol associated with this word. Symbols point to // the CFA of each word, so we need to offset the word // address by the NFATOCFASZ. That value is different // between standard MFORTH builds and profiled MFORTH // builds. We try the standard value first and then // fall back to the profile value. string label; if (!symbolTable.TryGetValue(word.NFA + 3, out label)) { label = symbolTable[word.NFA + 5]; } // Write out the hash entry, which must point to the NFA // of the word and not the CFA. writer.WriteLine(" .WORD {0}-NFATOCFASZ", label); } }
/// <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; }
/// <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); }