         return unused_key;
     }
     
+
+    template < typename hash_value_type = typename Hasher::result_type,
+               typename comparison_type = key_equal>
     __forceinline__
-    __host__ __device__ iterator insert(const value_type& x)
+    __device__ iterator insert(const value_type& x,
+                               bool precomputed_hash = false,
+                               hash_value_type precomputed_hash_value = 0,
+                               comparison_type keys_are_equal = key_equal())
+
     {
         const size_type hashtbl_size    = m_hashtbl_size;
         value_type* hashtbl_values      = m_hashtbl_values;
-        const auto key_hash        = m_hf( x.first );
-        size_type hash_tbl_idx          = key_hash%hashtbl_size;
+
+        hash_value_type hash_value{0};
+
+        // If a precomputed hash value has been passed in, then use it to determine
+        // the write location of the new key
+        if(true == precomputed_hash)
+        {
+          hash_value = precomputed_hash_value;
+        }
+        // Otherwise, compute the hash value from the new key
+        else
+        {
+          hash_value = m_hf(x.first);
+        }
+
+        size_type hash_tbl_idx = hash_value % hashtbl_size;
         
         value_type* it = 0;
         
         while (0 == it) {
             value_type* tmp_it = hashtbl_values + hash_tbl_idx;
-#ifdef __CUDA_ARCH__
+
             if ( std::numeric_limits<key_type>::is_integer && std::numeric_limits<mapped_type>::is_integer &&
                  sizeof(unsigned long long int) == sizeof(value_type) )
             {

                    atomicAdd( &m_collisions, 1 );
                }
            }
#else
#ifdef _OPENMP
            #pragma omp critical
#endif
            {
                if ( m_equal( unused_key, tmp_it->first ) ) {
                    hashtbl_values[hash_tbl_idx] = thrust::make_pair( x.first, x.second );
                    it = tmp_it;
                }
            }
#endif
            hash_tbl_idx = (hash_tbl_idx+1)%hashtbl_size;
        }
        

                {
                    atomicAdd( &m_collisions, 1 );
                }
            } 
            else 
            {
                const key_type old_key = atomicCAS( &(tmp_it->first), unused_key, x.first );

                if ( keys_are_equal( unused_key, old_key ) ) 
                {
                    (m_hashtbl_values+hash_tbl_idx)->second = x.second;
                    it = tmp_it;
                }
