#include <cstdlib>
#include <cstdio>
#include <cuda.h>
#include <cub/cub.cuh>
template <typename T>
static __global__ void d_lorenzo_encode_1d(const T* const in, T* const out, const long long size_in_T)
{
const long long tid = threadIdx.x + (long long)blockIdx.x * TPB;
__shared__ T shared_buf [TPB + 1];
if (threadIdx.x == 0) shared_buf[0] = (tid == 0) ? 0 : in[tid - 1];
if (tid < size_in_T) {
shared_buf[threadIdx.x + 1] = in[tid];
}
__syncthreads();
if (tid < size_in_T) {
out[tid] = shared_buf[threadIdx.x + 1] - shared_buf[threadIdx.x];
}
}
static inline void d_LOR1D_i32(long long& size, byte*& data, const int paramc, const double paramv [])
{
using type = int;
type* in_t = (type*)data;
if (size % sizeof(type) != 0) {
fprintf(stderr, "ERROR: size %lld is not evenly divisible by type size %ld\n", size, sizeof(type));
throw std::runtime_error("LC error");
}
type* d_encoded;
if (cudaSuccess != cudaMalloc((void **)&d_encoded, size)) fprintf(stderr, "CUDA ERROR: could not allocate d_encoded\n");
long long insize = size / sizeof(type);
const int blocks = (insize + TPB - 1) / TPB;
d_lorenzo_encode_1d<<<blocks, TPB>>>(in_t, d_encoded, insize);
cudaDeviceSynchronize();
data = (byte*)d_encoded;
cudaFree(in_t);
return;
}
static inline void d_iLOR1D_i32(long long& size, byte*& data, const int paramc, const double paramv [])
{
using type = int;
type* in_t = (type*)data;
if (size % sizeof(type) != 0) {
fprintf(stderr, "ERROR: size %lld is not evenly divisible by type size %ld\n", size, sizeof(type));
throw std::runtime_error("LC error");
}
type* d_decoded;
if (cudaSuccess != cudaMalloc((void **)&d_decoded, size)) fprintf(stderr, "CUDA ERROR: could not allocate d_decoded\n");
long long insize = size / sizeof(type);
void* d_temp_storage = NULL;
size_t temp_storage_bytes = 0;
cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_t, d_decoded, insize);
if (cudaSuccess != cudaMalloc(&d_temp_storage, temp_storage_bytes)) fprintf(stderr, "CUDA ERROR: could not allocate d_temp_storage\n");
cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_t, d_decoded, insize);
cudaDeviceSynchronize();
data = (byte*)d_decoded;
cudaFree(in_t);
return;
}