  * The grid of data that will be worked on is divided into blocks
  */
 #define BLOCK_SIZE 32
+
+#define gpuErrchk(ans)                                                         \
+  { gpuAssert((ans), __FILE__, __LINE__); }
+inline void gpuAssert(cudaError_t code, const char *file, int line,
+                      bool abort = true) {
+  if (code != cudaSuccess) {
+    fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file,
+            line);
+    if (abort)
+      exit(code);
+  }
+}
 
 __global__ void cu_dotProduct(long long *distance_array_d,
                               long long *force_array_d,

  dim3 dimgrid(ceil((long double)num_vectors / BLOCK_SIZE));

  cu_gen_force_array<<<dimgrid, dimblock>>>(force_array_d, num_vectors);
  cu_gen_distance_array<<<dimgrid, dimblock>>>(distance_array_d, num_vectors);
  cu_dotProduct<<<dimgrid, dimblock>>>(distance_array_d, force_array_d,
                                       result_array_d, num_vectors);

  cudaError_t err = cudaGetLastError();
  if (err != cudaSuccess) {
    printf("CUDA errors: %s\n", cudaGetErrorString(err));
  }
  // transfer results back to host
  cudaMemcpy(result_array, result_array_d, sizeof(long long) * num_vectors,
             cudaMemcpyDeviceToHost);
  // release the memory on the GPU
  cudaFree(distance_array_d);
  cudaFree(force_array_d);

  long long *result_array_d;

  // allocate space in the device
  gpuErrchk(
      cudaMalloc((void **)&distance_array_d, sizeof(long long) * num_vectors));
  gpuErrchk(
      cudaMalloc((void **)&force_array_d, sizeof(long long) * num_vectors));
  gpuErrchk(
      cudaMalloc((void **)&result_array_d, sizeof(long long) * num_vectors));

  // cudaMemcpy(result_array_d, result_array, sizeof(long long) * num_vectors,
  //           cudaMemcpyHostToDevice);

  // set execution configuration
