commit 095cc187b28f09a8b73c98f57c2f36c837c16abf
Author: David Sorber <david.sorber@gmail.com>
Date:   Thu Feb 23 15:58:39 2017 -0500

    Adding preliminary code for making random nodes.

diff --git a/software/clustering_proto/make_random_nodes.cc b/software/clustering_proto/make_random_nodes.cc
new file mode 100644
index 0000000..a65158e
--- /dev/null
+++ b/software/clustering_proto/make_random_nodes.cc
@@ -0,0 +1,104 @@
+#include <atomic>
+#include <chrono>
+#include <cmath>
+#include <cstdint>
+#include <cstdlib>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <random>
+#include <set>
+#include <thread>
+#include <vector>
+
+#include "cluster.h"
+
+/**
+ * Generate a good random seed using the x86_64 rdtsc register. See:
+ * http://stackoverflow.com/questions/7617587/is-there-an-alternative-to-using-time-to-seed-a-random-number-generation
+ * for more information about this function.
+ */ 
+unsigned long long rdtsc() 
+{
+    unsigned int lo, hi;
+    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+    return ((unsigned long long)hi << 32) | lo;
+}
+
+
+void usage()
+{
+    std::cout << "\nfoobar <num nodes> <location>\n" << std::endl;
+}
+
+int main(int argc, char** argv)
+{
+    if (argc < 3)
+    {
+        std::cerr << "ERROR: not enough arguments!" << std::endl;
+        usage();
+        return -1;
+    }
+    
+    // Parse arguments
+    uint32_t num_nodes = std::strtoul(argv[1], nullptr, -1);
+    std::string base_path(argv[2]);
+    
+    uint64_t seed = rdtsc();
+    std::cout << "Seed: 0x" << std::hex << seed << std::dec << std::endl;
+    
+    NodeData new_node;
+    
+    // Prime out random number generation
+    std::mt19937_64 generator(rdtsc());
+    std::uniform_real_distribution<double> tf_dist(0, 1);
+    std::uniform_int_distribution<uint32_t> term_dist(0, VECTOR_LEN - 1);
+        
+    // Randomly choose how many terms will have values
+    uint32_t num_terms = term_dist(generator);
+    std::cout << "Num terms: " << num_terms << std::endl;
+    
+    // Create indicies, use a set to guarantee that we end up with unique 
+    // indicies
+    std::set<uint32_t> indicies;
+    std::uniform_int_distribution<uint32_t> slot_dist(0, VECTOR_LEN - 1);
+    while (indicies.size() < num_terms)
+    {
+        indicies.insert(slot_dist(generator));
+    }
+
+    // Create the TF vector be assigning frequencies
+    std::vector<double> tf_freqs(VECTOR_LEN, 0.0);
+    double total = 0.0;
+    for (auto idx : indicies)
+    {
+        tf_freqs[idx] = -std::log(tf_dist(generator));
+        total += tf_freqs[idx];
+    }
+    
+    // Now normalize the frequencies
+    double scaled_total = 0.0;
+    for (auto idx : indicies)
+    {
+        tf_freqs[idx] /= total;
+        scaled_total += tf_freqs[idx];
+    }
+    
+#if 1
+    // Print out the frequencies
+    for (uint32_t idx = 0; idx < VECTOR_LEN; ++idx)
+    {        
+        std::cout << std::setw(3) << idx << " -- " 
+                  << std::setprecision(std::numeric_limits<double>::digits10) 
+                  << tf_freqs[idx] << std::endl;
+    }
+#endif
+
+    // Print out normalized total, which should always be 1.0
+    std::cout << "Scaled total: " 
+              << std::setprecision(std::numeric_limits<double>::digits10) 
+              << scaled_total << std::endl;
+    
+    return 0;
+}
