cpp : more robust code and added more documentation
This commit is contained in:
186
cpp/data.hpp
186
cpp/data.hpp
@ -4,7 +4,7 @@
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include "config.hpp"
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
@ -19,15 +19,6 @@ typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
typedef long double float128_t;
|
||||
|
||||
__host__ __device__
|
||||
constexpr inline int print(const char* str) noexcept {
|
||||
return printf("%s\n", str);
|
||||
}
|
||||
|
||||
inline int print(const std::string& s) noexcept {
|
||||
return printf("%s\n", s.c_str());
|
||||
}
|
||||
|
||||
namespace np {
|
||||
constexpr const float64_t inf = std::numeric_limits<float64_t>::infinity();
|
||||
|
||||
@ -44,16 +35,16 @@ namespace np {
|
||||
#endif
|
||||
|
||||
__host__ __device__
|
||||
Shape() noexcept {
|
||||
// #if __DEBUG
|
||||
// print("Shape created (default)");
|
||||
// #endif
|
||||
Shape(void) noexcept {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Shape(const size_t& length, size_t* data) noexcept : length(length), data(data), refcount(new size_t(1)) {
|
||||
Shape(const size_t& length, size_t* const data) noexcept : length(length), data(data), refcount(new size_t(1)) {
|
||||
#if __DEBUG
|
||||
//print("Shape created (raw)");
|
||||
printf("Shape created (raw)\n");
|
||||
for(size_t i = 0; i < length; ++i)
|
||||
total *= data[i];
|
||||
#endif
|
||||
@ -64,7 +55,7 @@ namespace np {
|
||||
// #if __DEBUG
|
||||
// print("Shape created (initializer)");
|
||||
// #endif
|
||||
const size_t* begin = dims.begin();
|
||||
const size_t* const begin = dims.begin();
|
||||
for(size_t i = 0; i < length; ++i){
|
||||
data[i] = begin[i];
|
||||
#if __DEBUG
|
||||
@ -76,34 +67,31 @@ namespace np {
|
||||
__host__ __device__
|
||||
Shape(const Shape& shape) noexcept {
|
||||
#if __DEBUG
|
||||
print("Shape created (copy)");
|
||||
printf("Shape created (copy)\n");
|
||||
#endif
|
||||
if (data != nullptr && data != shape.data){
|
||||
#if __DEBUG
|
||||
print("Former shape deleted (copy)");
|
||||
printf("Former shape deleted (copy)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != shape.refcount){
|
||||
#if __DEBUG
|
||||
print("Former shape refcount freed (copy)");
|
||||
printf("Former shape refcount freed (copy)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
length = shape.length;
|
||||
|
||||
//data = new size_t[length];
|
||||
//memcpy(data, shape.data, length * sizeof(size_t));
|
||||
//refcount = new size_t;
|
||||
//memcpy(refcount, shape.refcount, sizeof(size_t));
|
||||
|
||||
data = shape.data;
|
||||
refcount = shape.refcount;
|
||||
|
||||
if (refcount != nullptr)
|
||||
(*refcount)++;
|
||||
#if __DEBUG
|
||||
else
|
||||
print("Moved shape has null refcount");
|
||||
printf("Moved shape has null refcount\n");
|
||||
#endif
|
||||
#if __DEBUG
|
||||
total = shape.total;
|
||||
#endif
|
||||
}
|
||||
@ -115,13 +103,13 @@ namespace np {
|
||||
// #endif
|
||||
if (data != nullptr && data != shape.data){
|
||||
#if __DEBUG
|
||||
print("Former shape deleted (move)");
|
||||
printf("Former shape deleted (move)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != shape.refcount){
|
||||
#if __DEBUG
|
||||
print("Former shape refcount freed (move)");
|
||||
printf("Former shape refcount freed (move)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
@ -139,7 +127,7 @@ namespace np {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
~Shape() noexcept {
|
||||
~Shape(void) noexcept {
|
||||
if(refcount == nullptr){
|
||||
// #if __DEBUG
|
||||
// print("Shape refcount freed more than once");
|
||||
@ -173,34 +161,29 @@ namespace np {
|
||||
__host__ __device__
|
||||
Shape& operator=(const Shape& shape) noexcept {
|
||||
#if __DEBUG
|
||||
print("Shape created (assign copy)");
|
||||
printf("Shape created (assign copy)\n");
|
||||
#endif
|
||||
if (data != nullptr && data != shape.data){
|
||||
#if __DEBUG
|
||||
print("Former shape deleted (assign copy)");
|
||||
printf("Former shape deleted (assign copy)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != shape.refcount){
|
||||
#if __DEBUG
|
||||
print("Former shape refcount freed (assign copy)");
|
||||
printf("Former shape refcount freed (assign copy)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
length = shape.length;
|
||||
|
||||
// data = new size_t[length];
|
||||
// memcpy(data, shape.data, length * sizeof(size_t));
|
||||
// refcount = new size_t;
|
||||
// memcpy(refcount, shape.refcount, sizeof(size_t));
|
||||
|
||||
data = shape.data;
|
||||
refcount = shape.refcount;
|
||||
|
||||
if (refcount != nullptr)
|
||||
(*refcount)++;
|
||||
#if __DEBUG
|
||||
else
|
||||
printf("Assigned copy shape has null refcount");
|
||||
printf("Assigned copy shape has null refcount\n");
|
||||
total = shape.total;
|
||||
#endif
|
||||
return *this;
|
||||
@ -213,13 +196,13 @@ namespace np {
|
||||
// #endif
|
||||
if (data != nullptr && data != shape.data){
|
||||
#if __DEBUG
|
||||
print("Former shape deleted (assign move)");
|
||||
printf("Former shape deleted (assign move)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != shape.refcount){
|
||||
#if __DEBUG
|
||||
print("Former shape refcount freed (assign move)");
|
||||
printf("Former shape refcount freed (assign move)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
@ -228,8 +211,6 @@ namespace np {
|
||||
refcount = shape.refcount;
|
||||
#if __DEBUG
|
||||
total = shape.total;
|
||||
if (refcount == nullptr)
|
||||
print("Assigned copy shape has null refcount");
|
||||
shape.total = 1;
|
||||
#endif
|
||||
shape.length = 0;
|
||||
@ -280,17 +261,16 @@ namespace np {
|
||||
size_t* refcount = nullptr;
|
||||
|
||||
__host__ __device__
|
||||
Array() noexcept {
|
||||
// #if __DEBUG
|
||||
// print("Array created (default)");
|
||||
// #endif
|
||||
Array(void) noexcept {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Array(const Shape& shape, T* data) noexcept : shape(shape), data(data), refcount(new size_t(1)) {
|
||||
// #if __DEBUG
|
||||
// print("Array created (raw, copy shape)");
|
||||
// #endif
|
||||
Array(const Shape& shape, T* const data) noexcept : shape(shape), data(data), refcount(new size_t(1)) {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
@ -301,41 +281,36 @@ namespace np {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Array(Shape&& shape, T* data) noexcept : shape(std::move(shape)), data(data), refcount(new size_t(1)) {
|
||||
// #if __DEBUG
|
||||
// print("Array created (raw, move shape)");
|
||||
// #endif
|
||||
Array(Shape&& shape, T* const data) noexcept : shape(shape), data(data), refcount(new size_t(1)) {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Array(Shape&& shape) noexcept : shape(std::move(shape)), data(new T[np::prod(shape)]), refcount(new size_t(1)) {
|
||||
// #if __DEBUG
|
||||
// print("Array created (raw empty, move shape)");
|
||||
// #endif
|
||||
Array(Shape&& shape) noexcept : shape(shape), data(new T[np::prod(shape)]), refcount(new size_t(1)) {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Array(const Array& array) noexcept : shape(array.shape) {
|
||||
#if __DEBUG
|
||||
print("Array created (copy)");
|
||||
printf("Array created (copy)\n");
|
||||
#endif
|
||||
if (data != nullptr && data != array.data){
|
||||
#ifdef __debug
|
||||
print("Former array deleted (move)");
|
||||
#if __DEBUG
|
||||
printf("Former array deleted (copy)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != array.refcount){
|
||||
#if __DEBUG
|
||||
print("Former array refcount freed (move)");
|
||||
printf("Former array refcount freed (copy)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
// const size_t size = np::prod(shape);
|
||||
// data = new T[size];
|
||||
// memcpy(data, array.data, size);
|
||||
// refcount = new size_t;
|
||||
// memcpy(refcount, array.refcount, sizeof(size_t));
|
||||
|
||||
data = array.data;
|
||||
refcount = array.refcount;
|
||||
@ -343,28 +318,27 @@ namespace np {
|
||||
(*refcount)++;
|
||||
#if __DEBUG
|
||||
else
|
||||
print("Moved array has null refcount");
|
||||
printf("Moved array has null refcount\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
Array(Array&& array) noexcept {
|
||||
// #if __DEBUG
|
||||
// print("Array created (move)");
|
||||
// #endif
|
||||
Array(Array&& array) noexcept : shape(std::move(array.shape)) {
|
||||
if (data != nullptr && data != array.data){
|
||||
#if __DEBUG
|
||||
print("Former array deleted (move)");
|
||||
printf("Former array deleted (move)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != array.refcount){
|
||||
#if __DEBUG
|
||||
print("Former array refcount freed (move)");
|
||||
printf("Former array refcount freed (move)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
shape = std::move(array.shape);
|
||||
data = array.data;
|
||||
refcount = array.refcount;
|
||||
|
||||
@ -373,7 +347,7 @@ namespace np {
|
||||
}
|
||||
|
||||
__host__ __device__
|
||||
~Array() noexcept {
|
||||
~Array(void) noexcept {
|
||||
if(refcount == nullptr){
|
||||
// #if __DEBUG
|
||||
// print("Array refcount freed more than once");
|
||||
@ -404,36 +378,30 @@ namespace np {
|
||||
__host__ __device__
|
||||
Array& operator=(const Array& array) noexcept {
|
||||
#if __DEBUG
|
||||
print("Array created (assign copy)");
|
||||
printf("Array created (assign copy)\n");
|
||||
#endif
|
||||
if (data != nullptr && data != array.data){
|
||||
#if __DEBUG
|
||||
print("Former array deleted (assign copy)");
|
||||
printf("Former array deleted (assign copy)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != array.refcount){
|
||||
#if __DEBUG
|
||||
print("Former array refcount freed (assign copy)");
|
||||
printf("Former array refcount freed (assign copy)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
shape = array.shape;
|
||||
|
||||
// const size_t size = np::prod(shape) * sizeof(T);
|
||||
// data = new T[size];
|
||||
// memcpy(data, array.data, size);
|
||||
// refcount = new size_t;
|
||||
// memcpy(refcount, array.refcount, sizeof(size_t));
|
||||
|
||||
data = array.data;
|
||||
refcount = array.refcount;
|
||||
|
||||
if (refcount != nullptr)
|
||||
(*refcount)++;
|
||||
#if __DEBUG
|
||||
else
|
||||
print("Assigned array has null refcount");
|
||||
#endif
|
||||
printf("Assigned array has null refcount\n");
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -444,13 +412,13 @@ namespace np {
|
||||
// #endif
|
||||
if (data != nullptr && data != array.data){
|
||||
#if __DEBUG
|
||||
print("Former array deleted (assign move)");
|
||||
printf("Former array deleted (assign move)\n");
|
||||
#endif
|
||||
delete[] data;
|
||||
}
|
||||
if (refcount != nullptr && refcount != array.refcount){
|
||||
#if __DEBUG
|
||||
print("Former array refcount freed (assign move)");
|
||||
printf("Former array refcount freed (assign move)\n");
|
||||
#endif
|
||||
delete refcount;
|
||||
}
|
||||
@ -485,35 +453,39 @@ namespace np {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Array<T> empty(Shape&& shape) noexcept {
|
||||
return { std::move(shape), new T[np::prod(shape)] };
|
||||
inline Array<T> empty(Shape&& shape) noexcept {
|
||||
return Array<T>(shape);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> empty(const Shape& shape) noexcept {
|
||||
return { std::move(shape), new T[np::prod(shape)] };
|
||||
inline Array<T> empty(const Shape& shape) noexcept {
|
||||
return Array<T>(shape);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> empty(const std::initializer_list<size_t>& dims) noexcept {
|
||||
const Shape shape(dims);
|
||||
return { std::move(shape), new T[np::prod(shape)] };
|
||||
inline Array<T> empty(const std::initializer_list<size_t>& dims) noexcept {
|
||||
return Array<T>(dims);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> zeros(Shape&& shape) noexcept {
|
||||
return { std::move(shape), new T[np::prod(shape)]{0} };
|
||||
Array<T> res(shape);
|
||||
memset(res.data, 0, sizeof(T) * np::prod(res.shape));
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> zeros(const Shape& shape) noexcept {
|
||||
return { std::move(shape), new T[np::prod(shape)]{0} };
|
||||
Array<T> res(shape);
|
||||
memset(res.data, 0, sizeof(T) * np::prod(res.shape));
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> zeros(const std::initializer_list<size_t>& dims) noexcept {
|
||||
const Shape shape(dims);
|
||||
return { std::move(shape), new T[np::prod(shape)]{0} };
|
||||
Array<T> res(dims);
|
||||
memset(res.data, 0, sizeof(T) * np::prod(res.shape));
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -773,7 +745,7 @@ constexpr np::Array<T>& map(np::Array<T>& a, const std::function<T(const size_t&
|
||||
|
||||
template<typename T>
|
||||
__host__ __device__
|
||||
constexpr inline static void swap(T* a, T* b) noexcept {
|
||||
constexpr inline static void swap(T* const a, T* const b) noexcept {
|
||||
if (a == b) return;
|
||||
const T temp = *a;
|
||||
*a = *b;
|
||||
@ -805,7 +777,7 @@ void quicksort(const np::Array<T>& a) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static size_t as_partition(const T* a, uint16_t* indices, const size_t& l, const size_t& h) noexcept {
|
||||
static size_t as_partition(const T* const a, uint16_t* const indices, const size_t& l, const size_t& h) noexcept {
|
||||
size_t i = l - 1;
|
||||
for (size_t j = l; j <= h; ++j)
|
||||
if (a[indices[j]] < a[indices[h]])
|
||||
@ -815,10 +787,10 @@ static size_t as_partition(const T* a, uint16_t* indices, const size_t& l, const
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void argsort(const T* a, uint16_t* indices, const size_t& l, const size_t& h) noexcept {
|
||||
void argsort(const T* const a, uint16_t* const indices, const size_t& l, const size_t& h) noexcept {
|
||||
const size_t total = h - l + 1;
|
||||
|
||||
size_t* stack = new size_t[total]{l, h};
|
||||
size_t* const stack = new size_t[total]{l, h};
|
||||
size_t top = 1, low = l, high = h;
|
||||
|
||||
while (top <= total) {
|
||||
@ -852,16 +824,16 @@ np::Array<uint16_t> argsort(const np::Array<T>& other, const size_t& l, const si
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
np::Array<uint16_t> argsort(const np::Array<T>* other, const size_t& length) noexcept {
|
||||
np::Array<uint16_t> argsort(const np::Array<T>* const other, const size_t& length) noexcept {
|
||||
return argsort(other, 0, length - 1);
|
||||
}
|
||||
|
||||
std::array<np::Array<uint8_t>, 4> load_datasets(void);
|
||||
void print_error_file(const char*) noexcept;
|
||||
void print_error_file(const char* const) noexcept;
|
||||
|
||||
template<typename T>
|
||||
void save(const np::Array<T>& d, const char* filename) {
|
||||
FILE* output = fopen(filename, "wb");
|
||||
void save(const np::Array<T>& d, const char* const filename) {
|
||||
FILE* const output = fopen(filename, "wb");
|
||||
if (output == NULL) {
|
||||
print_error_file(filename);
|
||||
throw;
|
||||
@ -875,8 +847,8 @@ void save(const np::Array<T>& d, const char* filename) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
np::Array<T> load(const char* filename) {
|
||||
FILE* input = fopen(filename, "rb");
|
||||
np::Array<T> load(const char* const filename) {
|
||||
FILE* const input = fopen(filename, "rb");
|
||||
if (input == NULL) {
|
||||
print_error_file(filename);
|
||||
throw;
|
||||
@ -887,7 +859,7 @@ np::Array<T> load(const char* filename) {
|
||||
fclose(input);
|
||||
throw;
|
||||
}
|
||||
size_t* data = new size_t[length];
|
||||
size_t* const data = new size_t[length];
|
||||
if(!fread(data, sizeof(size_t), length, input)){
|
||||
print_error_file(filename);
|
||||
fclose(input);
|
||||
@ -905,7 +877,7 @@ np::Array<T> load(const char* filename) {
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<typename T>
|
||||
np::Array<T> copyToDevice(const char* name, const np::Array<T>& array) noexcept {
|
||||
np::Array<T> copyToDevice(const char* const name, const np::Array<T>& array) noexcept {
|
||||
const size_t array_size = np::prod(array.shape) * sizeof(T);
|
||||
const size_t shape_size = array.shape.length * sizeof(size_t);
|
||||
np::Array<T> d_array;
|
||||
@ -925,7 +897,7 @@ np::Array<T> copyToDevice(const char* name, const np::Array<T>& array) noexcept
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void cudaFree(const char* name, np::Array<T>& array) noexcept {
|
||||
constexpr void cudaFree(const char* const name, np::Array<T>& array) noexcept {
|
||||
//_print_cuda_error_(name, cudaFree(array.refcount));
|
||||
//array.refcount = nullptr;
|
||||
_print_cuda_error_(name, cudaFree(array.data));
|
||||
@ -936,16 +908,16 @@ constexpr void cudaFree(const char* name, np::Array<T>& array) noexcept {
|
||||
array.shape.data = nullptr;
|
||||
}
|
||||
|
||||
constexpr inline void _print_cuda_error_(const char* name, const cudaError_t& err) noexcept {
|
||||
constexpr inline void _print_cuda_error_(const char* const name, const cudaError_t& err) noexcept {
|
||||
if (err != cudaSuccess) fprintf(stderr, "Error: %s = %d : %s\n", name, err, cudaGetErrorString(err));
|
||||
}
|
||||
#endif
|
||||
|
||||
int print(const np::Shape&) noexcept;
|
||||
int print(const np::Array<uint8_t>&) noexcept;
|
||||
int print(const np::Array<float64_t>&) noexcept;
|
||||
int print(const np::Array<uint8_t>&, const np::Slice&) noexcept;
|
||||
int print(const np::Array<uint32_t>&, const np::Slice&) noexcept;
|
||||
int print(const np::Array<int32_t>&, const np::Slice&) noexcept;
|
||||
int print(const np::Array<uint16_t>&, const np::Slice&) noexcept;
|
||||
int print_feat(const np::Array<uint8_t>&, const np::Slice&) noexcept;
|
||||
int32_t print(const np::Shape&) noexcept;
|
||||
int32_t print(const np::Array<uint8_t>&) noexcept;
|
||||
int32_t print(const np::Array<float64_t>&) noexcept;
|
||||
int32_t print(const np::Array<uint8_t>&, const np::Slice&) noexcept;
|
||||
int32_t print(const np::Array<uint32_t>&, const np::Slice&) noexcept;
|
||||
int32_t print(const np::Array<int32_t>&, const np::Slice&) noexcept;
|
||||
int32_t print(const np::Array<uint16_t>&, const np::Slice&) noexcept;
|
||||
int32_t print_feat(const np::Array<uint8_t>&, const np::Slice&) noexcept;
|
||||
|
Reference in New Issue
Block a user