   void create_input( size_t num_rows, size_t max_value,
                      bool print = false)
   {
-    initialize_tuple(the_columns, num_rows, max_value);
+    initialize_tuple(input_columns, num_rows, max_value);
+    initialize_tuple(output_columns, num_rows, max_value);
 
-    gdf_columns = initialize_gdf_columns(the_columns);
+    gdf_input_columns = initialize_gdf_columns(input_columns);
+    gdf_output_columns = initialize_gdf_columns(output_columns);
 
     // Fill vector of raw pointers to gdf_columns
-    for(auto const& c : gdf_columns){
-      this->raw_gdf_columns.push_back(c.get());
+    for(auto const& c : gdf_input_columns){
+      this->raw_gdf_input_columns.push_back(c.get());
+      this->raw_gdf_output_columns.push_back(c.get());
     }
 
     if(print)
     {
-      std::cout << "Column(s) created. Size: " << std::get<0>(the_columns).size() << std::endl;
-      print_tuple(the_columns);
+      std::cout << "Input column(s) created. Size: " 
+                << std::get<0>(input_columns).size() << std::endl;
+      print_tuple(input_columns);
     }
   }
 
-  void compute_reference_solution(bool print = false, bool sort = true)
-  {
-
-  }
-
-  void compute_gdf_result(bool print = false, bool sort = true)
+  void compute_gdf_result(const int num_partitions, bool print = false)
   {
     const int num_columns = std::tuple_size<multi_column_t>::value;
 
     gdf_error result_error{GDF_SUCCESS};
 
-    gdf_column ** gdf_input_columns = raw_gdf_columns.data();
+    gdf_column ** gdf_input_columns = raw_gdf_input_columns.data();
+    gdf_column ** gdf_output_columns = raw_gdf_output_columns.data();
+
+    std::vector<int> partition_offsets(num_partitions,0);
+
+    result_error = gdf_hash_partition(num_columns, 
+                                      gdf_input_columns,
+                                      this->cols_to_hash.data(),
+                                      this->num_cols_to_hash,
+                                      num_partitions,
+                                      gdf_output_columns,
+                                      partition_offsets.data(),
+                                      GDF_HASH_MURMUR3);
 
     EXPECT_EQ(GDF_SUCCESS, result_error);
 

// TestParameters defined below
// The number and types of columns determined by the number and types of vectors 
// in the VTuple<...> 
typedef ::testing::Types< TestParameters< VTuple<int32_t> > >Implementations;

TYPED_TEST_CASE(HashPartitionTest, Implementations);

TYPED_TEST(HashPartitionTest, ExampleTest)
{
  /*
  this->create_input(10, 2,
                     10, 2);

  std::vector<result_type> reference_result = this->compute_reference_solution();


template <class test_parameters>
struct HashPartitionTest : public testing::Test
{
  const size_t num_cols_to_hash = test_parameters::num_cols_to_hash;
  std::array<int, test_parameters::num_cols_to_hash> cols_to_hash = test_parameters::cols_to_hash;

  // multi_column_t is a tuple of vectors. The number of vectors in the tuple
  // determines the number of columns, and the value_type of each
  // vector determines the data type of the column
  using multi_column_t = typename test_parameters::multi_column_t;
  multi_column_t input_columns;
  multi_column_t output_columns;

  // Containers for unique_ptrs to gdf_columns 
  // unique_ptrs are used to automate freeing device memory
  std::vector<gdf_col_pointer> gdf_input_columns;
  std::vector<gdf_col_pointer> gdf_output_columns;


  // Containers for the raw pointers to the gdf_columns
  std::vector<gdf_column*> raw_gdf_input_columns;
  std::vector<gdf_column*> raw_gdf_output_columns;

  HashPartitionTest()
  {
