 int nfft_of_plan;
 int size_of_plan;
 
+void cufft_check_error(const char* file_name, const int line_number, cufftResult result)
+{
+    if (result == CUFFT_SUCCESS) return;
+    
+    printf("CUFFT error at line %i of file %s: ", line_number, file_name);
+    switch (result)
+    {
+        case CUFFT_INVALID_PLAN:
+        {
+            printf("CUFFT_INVALID_PLAN\n");
+            break;
+        }
+        case CUFFT_ALLOC_FAILED:
+        {
+            printf("CUFFT_ALLOC_FAILED\n");
+            break;
+        }
+        case CUFFT_INVALID_VALUE:
+        {
+            printf("CUFFT_INVALID_VALUE\n");
+            break;
+        }
+        case CUFFT_INTERNAL_ERROR:
+        {
+            printf("CUFFT_INTERNAL_ERROR\n");
+            break;
+        }
+        case CUFFT_SETUP_FAILED:
+        {
+            printf("CUFFT_SETUP_FAILED\n");
+            break;
+        }
+        case CUFFT_INVALID_SIZE:
+        {
+            printf("CUFFT_INVALID_SIZE\n");
+            break;
+        }
+        default:
+        {
+            printf("unknown error code %i\n", result);
+            break;
+        }
+    }
+    exit(-100);
+}
+
 extern "C" void cufft_create_plan_handle(void)
 {
-    if (cufftCreate(&plan) != CUFFT_SUCCESS)
-    {
-        printf("failed to execute cufftCreate()\n");
-        exit(0);
-    }
+    cufftResult result = cufftCreate(&plan);
+    cufft_check_error(__FILE__, __LINE__, result);
 }
 
 extern "C" size_t cufft_get_size(int nx, int ny, int nz, int nfft)

// CUDA functions
//================

extern "C" void cuda_initialize()
{
    if (cudaSetDeviceFlags(cudaDeviceMapHost) != cudaSuccess)
    {
        printf("failed to execute cudaSetDeviceFlags()\n");
        exit(0);
    }
}

extern "C" void cuda_malloc(void** ptr, size_t size)
{
    if (cudaMalloc(ptr, size) != cudaSuccess)
    {
        printf("failed to execute cudaMalloc() \n");
        exit(0);
    }
}

extern "C" void cuda_free(void* ptr)
{
    if (cudaFree(ptr) != cudaSuccess)
    {
        printf("failed to execute cudaFree() \n");
        exit(0);
    }
}

extern "C" void cuda_malloc_host(void** ptr, size_t size)
{
    if (cudaMallocHost(ptr, size) != cudaSuccess)
    {  
        printf("cudaMallocHost failed\n");
        exit(-1);
    }
}

extern "C" void cuda_free_host(void** ptr)
{
    if (cudaFreeHost(*ptr) != cudaSuccess)
    {
        printf("cudaFreeHost failed\n");
        exit(-1);
    }
}

extern "C" void cuda_copy_to_device(void* target, void* source, size_t size)
{
    if (cudaMemcpy(target, source, size, cudaMemcpyHostToDevice) != cudaSuccess)
    {
        printf("failed to execute cudaMemcpy(cudaMemcpyHostToDevice)\n");
        exit(0);
    }
}

extern "C" void cuda_copy_to_host(void* target, void* source, size_t size)
{
    if (cudaMemcpy(target, source, size, cudaMemcpyDeviceToHost) != cudaSuccess)
    {
        printf("failed to execute cudaMemcpy(cudaMemcpyDeviceToHost)\n");
        exit(0);
    }
}

extern "C" void cuda_device_synchronize()
{
    if (cudaDeviceSynchronize() != cudaSuccess)
    {
        printf("failed to execute cudaDeviceSynchronize()\n");
        exit(0);
    }
}

extern "C" void cuda_device_reset()
{
    if (cudaDeviceReset() != cudaSuccess)
    {
        printf("faile to execute cudaDeviceReset()\n");
        exit(0);
    }
}

cudaStream_t* streams;


    cudaDeviceProp devprop;
     
    cudaGetDeviceProperties(&devprop, 0);
    cuda_check_last_error(__FILE__, __LINE__);
    
    printf("name                        : %s \n", devprop.name);
    printf("major                       : %i \n", devprop.major);
