#ifndef __AMSCU_CUDAFUNCTIONS_HPP__
#define __AMSCU_CUDAFUNCTIONS_HPP__


namespace amscuda
{
    // device memory operations
    // I'm trying to avoid some of the boilerplate mental overhead involved
    // in calling cuda functions and handling errors

    //frees devbuffer if it is not already NULL, and sets devbuffer to NULL
    //wrapper to cudaFree
    template<typename T> int cuda_free(T **devptr);

    //copies hostbuffer to devbuffer
    //initializes devbuffer from NULL if devbuffer is NULL
    //if overwrite is true, deletes and reallocates devbuffer on device (for resizing)
    template<typename T> int buffer_copytodevice(T *hostbuffer, T **devbuffer, long N, bool overwrite);

    //copies info from devbuffer to hostbuffer
    //initialzies hostbuffer from NULL if NULL
    //if overwrite is true, deletes and reallocates hostbuffer on host with new[] (for resizing)
    template<typename T> int buffer_copyfromdevice(T *devbuffer, T **hostbuffer, long N, bool overwrite);

    //wrapper for cudaMemcpy - copies an item or struct (count 1) to the device
    //initializes devptr from NULL if not already initialized
    template<typename T> int cuda_copytodevice(T *hostptr, T **devptr);

    //wrapper for cudaMemcpy - copies an item or struct (count 1) from device
    //initializes hostptr from NULL with new if not already initialized
    template<typename T> int cuda_copyfromdevice(T *devptr, T **hostptr);
    
    int cuda_errortrap(const char *msgheader);

};

#include <amsculib2/amscu_cudafunctions_impl.hpp>

#endif

