cpp : more robust code and added more documentation
This commit is contained in:
parent
45f0f6ab8e
commit
c7d21e1014
@ -2,7 +2,6 @@
|
||||
#include "data.hpp"
|
||||
#include "config.hpp"
|
||||
#include "ViolaJonesGPU.hpp"
|
||||
#include "ViolaJonesCPU.hpp"
|
||||
|
||||
static inline void add_empty_feature(const np::Array<uint8_t>& feats, size_t& n) noexcept {
|
||||
memset(&feats[n], 0, 4 * sizeof(uint8_t));
|
||||
@ -110,11 +109,11 @@ np::Array<uint8_t> build_features(const uint16_t& width, const uint16_t& height)
|
||||
return feats;
|
||||
}
|
||||
|
||||
//np::Array<int> select_percentile(const np::Array<uint8_t> X_feat, const np::Array<uint8_t> y) noexcept {
|
||||
//np::Array<int32_t> select_percentile(const np::Array<uint8_t> X_feat, const np::Array<uint8_t> y) noexcept {
|
||||
// std::vector<float64_t> class_0, class_1;
|
||||
//
|
||||
// const int im_size = X_feat.shape[0] / y.shape[0];
|
||||
// int idy = 0, n_samples_per_class_0 = 0, n_samples_per_class_1 = 0;
|
||||
// const int32_t im_size = X_feat.shape[0] / y.shape[0];
|
||||
// int32_t idy = 0, n_samples_per_class_0 = 0, n_samples_per_class_1 = 0;
|
||||
// for (size_t i = 0; i < X_feat.shape[0]; i += im_size) {
|
||||
// if (y[idy] == 0) {
|
||||
// ++n_samples_per_class_0;
|
||||
@ -126,24 +125,24 @@ np::Array<uint8_t> build_features(const uint16_t& width, const uint16_t& height)
|
||||
// }
|
||||
// ++idy;
|
||||
// }
|
||||
// const int n_samples = n_samples_per_class_0 + n_samples_per_class_1;
|
||||
// const int32_t n_samples = n_samples_per_class_0 + n_samples_per_class_1;
|
||||
//
|
||||
// float64_t ss_alldata_0 = 0;
|
||||
// for (int i = 0;i < n_samples_per_class_0;++i)
|
||||
// for (int32_t i = 0;i < n_samples_per_class_0;++i)
|
||||
// ss_alldata_0 += (class_0[i] * class_0[i]);
|
||||
//
|
||||
// float64_t ss_alldata_1 = 0;
|
||||
// for (int i = 0;i < n_samples_per_class_1;++i)
|
||||
// for (int32_t i = 0;i < n_samples_per_class_1;++i)
|
||||
// ss_alldata_1 += (class_1[i] * class_1[i]);
|
||||
//
|
||||
// const float64_t ss_alldata = ss_alldata_0 + ss_alldata_1;
|
||||
//
|
||||
// float64_t sums_classes_0 = 0;
|
||||
// for (int i = 0;i < n_samples_per_class_0;++i)
|
||||
// for (int32_t i = 0;i < n_samples_per_class_0;++i)
|
||||
// sums_classes_0 += class_0[i];
|
||||
//
|
||||
// float64_t sums_classes_1 = 0;
|
||||
// for (int i = 0;i < n_samples_per_class_1;++i)
|
||||
// for (int32_t i = 0;i < n_samples_per_class_1;++i)
|
||||
// sums_classes_1 += class_1[i];
|
||||
//
|
||||
// float64_t sq_of_sums_alldata = sums_classes_0 + sums_classes_1;
|
||||
@ -154,11 +153,11 @@ np::Array<uint8_t> build_features(const uint16_t& width, const uint16_t& height)
|
||||
// const float64_t ss_tot = ss_alldata - sq_of_sums_alldata / n_samples;
|
||||
// const float64_t sqd_sum_bw_n = sq_of_sums_args_0 / n_samples_per_class_0 + sq_of_sums_args_1 / n_samples_per_class_1 - sq_of_sums_alldata / n_samples;
|
||||
// const float64_t ss_wn = ss_tot - sqd_sum_bw_n;
|
||||
// const int df_wn = n_samples - 2;
|
||||
// const int32_t df_wn = n_samples - 2;
|
||||
// const float64_t msw = ss_wn / df_wn;
|
||||
// const float64_t f_values = sqd_sum_bw_n / msw;
|
||||
//
|
||||
// const np::Array<int> res = np::empty<int>({ static_cast<size_t>(std::ceil(static_cast<float64_t>(im_size) / 10.0)) });
|
||||
// const np::Array<int32_t> res = np::empty<int32_t>({ static_cast<size_t>(std::ceil(static_cast<float64_t>(im_size) / 10.0)) });
|
||||
// // TODO Complete code
|
||||
// return res;
|
||||
//}
|
||||
@ -293,4 +292,3 @@ std::tuple<uint16_t, uint16_t, uint16_t, uint16_t> confusion_matrix(const np::Ar
|
||||
++false_positive;
|
||||
return std::make_tuple(true_negative, false_positive, false_negative, true_positive);
|
||||
}
|
||||
|
||||
|
@ -112,9 +112,9 @@ template <typename T, size_t N, typename F, typename... Args>
|
||||
std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32_t& column_width, const std::vector<const char*>& filenames, const bool& force_redo, const bool& save_state, const char* const out_dir, const F& fnc, Args &&...args) noexcept {
|
||||
char filepath[BUFFER_SIZE] = { 0 };
|
||||
bool abs = false;
|
||||
for (const char* filename : filenames){
|
||||
sprintf(filepath, "%s/%s.bin", out_dir, filename);
|
||||
if (!fs::exists(filepath)) {
|
||||
for (const char* const filename : filenames){
|
||||
snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
|
||||
if (!std::filesystem::exists(filepath)) {
|
||||
abs = true;
|
||||
break;
|
||||
}
|
||||
@ -130,8 +130,8 @@ std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32
|
||||
fflush(stderr);
|
||||
#endif
|
||||
size_t i = 0;
|
||||
for (const char* filename : filenames){
|
||||
sprintf(filepath, "%s/%s.bin", out_dir, filename);
|
||||
for (const char* const filename : filenames){
|
||||
snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
|
||||
save<T>(bin[i++], filepath);
|
||||
}
|
||||
#if __DEBUG == false
|
||||
@ -145,8 +145,8 @@ std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32
|
||||
fflush(stderr);
|
||||
#endif
|
||||
size_t i = 0;
|
||||
for (const char* filename : filenames){
|
||||
bin[i++] = std::move(load<T>(filepath));
|
||||
for (const char* const filename : filenames){
|
||||
snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
|
||||
}
|
||||
formatted_row<3>({ column_width, -18, 29 }, { step_name, "None", "loaded saved state" });
|
||||
@ -156,7 +156,7 @@ std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32
|
||||
|
||||
np::Array<uint16_t> argsort_2d_cpu(const np::Array<int32_t>&) noexcept;
|
||||
np::Array<uint8_t> build_features(const uint16_t&, const uint16_t&) noexcept;
|
||||
np::Array<int> select_percentile(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
|
||||
np::Array<int32_t> select_percentile(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
|
||||
np::Array<uint8_t> classify_viola_jones(const np::Array<float64_t>&, const np::Array<float64_t>&, const np::Array<int32_t>&) noexcept;
|
||||
np::Array<float64_t> init_weights(const np::Array<uint8_t>&) noexcept;
|
||||
std::tuple<int32_t, float64_t, np::Array<float64_t>> select_best(const np::Array<float64_t>&, const np::Array<float64_t>&, const np::Array<int32_t>&,
|
||||
|
@ -180,7 +180,7 @@ static __global__ void __apply_feature_kernel__(int32_t* d_X_feat, const np::Arr
|
||||
|
||||
np::Array<int32_t> apply_features_gpu(const np::Array<uint8_t>& feats, const np::Array<uint32_t>& X_ii) noexcept {
|
||||
const np::Array<int32_t> X_feat = np::empty<int32_t>({ feats.shape[0], X_ii.shape[0] });
|
||||
int32_t* d_X_feat;
|
||||
int32_t* d_X_feat = nullptr;
|
||||
|
||||
_print_cuda_error_("malloc d_X_feat", cudaMalloc(&d_X_feat, np::prod(X_feat.shape) * sizeof(int32_t)));
|
||||
np::Array<uint32_t> d_X_ii = copyToDevice<uint32_t>("X_ii", X_ii);
|
||||
@ -268,7 +268,7 @@ np::Array<float64_t> train_weak_clf_gpu(const np::Array<int32_t>& X_feat, const
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__device__ inline static int32_t as_partition_gpu(const T* a, uint16_t* indices, const size_t l, const size_t h) noexcept {
|
||||
__device__ inline static int32_t as_partition_gpu(const T* a, uint16_t* const indices, const size_t l, const size_t h) noexcept {
|
||||
int32_t i = l - 1;
|
||||
for (int32_t j = l; j <= h; ++j)
|
||||
if (a[indices[j]] < a[indices[h]])
|
||||
@ -278,7 +278,7 @@ __device__ inline static int32_t as_partition_gpu(const T* a, uint16_t* indices,
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__device__ void argsort_gpu(const T* a, uint16_t* indices, const size_t l, const size_t h) noexcept {
|
||||
__device__ void argsort_gpu(const T* a, uint16_t* const indices, const size_t l, const size_t h) noexcept {
|
||||
const size_t total = h - l + 1;
|
||||
|
||||
//int32_t* stack = new int32_t[total]{l, h};
|
||||
@ -312,7 +312,7 @@ __device__ void argsort_gpu(const T* a, uint16_t* indices, const size_t l, const
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__global__ void argsort_bounded_gpu(const np::Array<T> a, uint16_t* indices){
|
||||
__global__ void argsort_bounded_gpu(const np::Array<T> a, uint16_t* const indices){
|
||||
const size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx >= a.shape[0])
|
||||
return;
|
||||
@ -324,7 +324,7 @@ __global__ void argsort_bounded_gpu(const np::Array<T> a, uint16_t* indices){
|
||||
np::Array<uint16_t> argsort_2d_gpu(const np::Array<int32_t>& X_feat) noexcept {
|
||||
const np::Array<uint16_t> indices = np::empty<uint16_t>(X_feat.shape);
|
||||
|
||||
uint16_t* d_indices;
|
||||
uint16_t* d_indices = nullptr;
|
||||
const size_t indices_size = np::prod(indices.shape) * sizeof(uint16_t);
|
||||
|
||||
np::Array<int32_t> d_X_feat = copyToDevice<int32_t>("X_feat", X_feat);
|
||||
|
58
cpp/data.cpp
58
cpp/data.cpp
@ -1,9 +1,7 @@
|
||||
#include "data.hpp"
|
||||
//#include "toolbox.hpp"
|
||||
//#include <cstring>
|
||||
|
||||
int print(const np::Shape& shape) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print(const np::Shape& shape) noexcept {
|
||||
int32_t num_written = 0;
|
||||
num_written += printf("(");
|
||||
if (shape.length > 1) {
|
||||
const size_t length = shape.length - 1;
|
||||
@ -17,7 +15,7 @@ int print(const np::Shape& shape) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int print(const np::Array<T>& array, const char* format) noexcept {
|
||||
int32_t print(const np::Array<T>& array, const char* const format) noexcept {
|
||||
//printf("[");
|
||||
//const size_t length = np::prod(array.shape);
|
||||
//for(size_t i = 0; i < length - 1; ++i)
|
||||
@ -27,10 +25,10 @@ int print(const np::Array<T>& array, const char* format) noexcept {
|
||||
//printf("%f]\n", array[length - 1]);
|
||||
|
||||
char format_space[BUFFER_SIZE] = { 0 };
|
||||
sprintf(format_space, "%s ", format);
|
||||
snprintf(format_space, BUFFER_SIZE,"%s ", format);
|
||||
char format_close[BUFFER_SIZE] = { 0 };
|
||||
sprintf(format_close, "%s]\n", format);
|
||||
int num_written = 0;
|
||||
snprintf(format_close, BUFFER_SIZE,"%s]\n", format);
|
||||
int32_t num_written = 0;
|
||||
|
||||
if (array.shape.length == 1) {
|
||||
const size_t max = array.shape[0] - 1;
|
||||
@ -53,16 +51,16 @@ int print(const np::Array<T>& array, const char* format) noexcept {
|
||||
return num_written;
|
||||
}
|
||||
|
||||
int print(const np::Array<uint8_t>& array) noexcept {
|
||||
int32_t print(const np::Array<uint8_t>& array) noexcept {
|
||||
return print(array, "%hu");
|
||||
}
|
||||
|
||||
int print(const np::Array<float64_t>& array) noexcept {
|
||||
int32_t print(const np::Array<float64_t>& array) noexcept {
|
||||
return print(array, "%f");
|
||||
}
|
||||
|
||||
int print_feat(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print_feat(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept {
|
||||
int32_t num_written = 0;
|
||||
num_written += printf("[");
|
||||
const size_t feat_size = np::prod(array.shape, 1);
|
||||
const size_t offset = slice.x * feat_size;
|
||||
@ -74,8 +72,8 @@ int print_feat(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept
|
||||
return num_written;
|
||||
}
|
||||
|
||||
int print(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept {
|
||||
int32_t num_written = 0;
|
||||
if (array.shape.length == 1) {
|
||||
const size_t max = slice.y - 1; //std::min(slice.y, array.shape[0] - 1);
|
||||
num_written += printf("[");
|
||||
@ -97,8 +95,8 @@ int print(const np::Array<uint8_t>& array, const np::Slice& slice) noexcept {
|
||||
return num_written;
|
||||
}
|
||||
|
||||
int print(const np::Array<uint32_t>& array, const np::Slice& slice) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print(const np::Array<uint32_t>& array, const np::Slice& slice) noexcept {
|
||||
int32_t num_written = 0;
|
||||
if (array.shape.length == 1) {
|
||||
const size_t max = slice.y - 1; //std::min(slice.y, array.shape[0] - 1);
|
||||
num_written += printf("[");
|
||||
@ -115,37 +113,37 @@ int print(const np::Array<uint32_t>& array, const np::Slice& slice) noexcept {
|
||||
num_written += printf("%5i ", array[k + i * array.shape[1] + j]);
|
||||
num_written += printf("]\n");
|
||||
}
|
||||
num_written += print("]");
|
||||
num_written += printf("]");
|
||||
}
|
||||
return num_written;
|
||||
}
|
||||
|
||||
int print(const np::Array<int32_t>& array, const np::Slice& slice) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print(const np::Array<int32_t>& array, const np::Slice& slice) noexcept {
|
||||
int32_t num_written = 0;
|
||||
num_written += printf("[");
|
||||
//size_t k = slice.x * array.shape[1] * array.shape[2] + slice.y * array.shape[2] + slice.z;
|
||||
size_t k = slice.x * array.shape[1];
|
||||
for (size_t i = k; i < k + (slice.y - slice.x); ++i) {
|
||||
num_written += printf("%5i ", array[i]);
|
||||
}
|
||||
num_written += print("]");
|
||||
num_written += printf("]");
|
||||
return num_written;
|
||||
}
|
||||
|
||||
int print(const np::Array<uint16_t>& array, const np::Slice& slice) noexcept {
|
||||
int num_written = 0;
|
||||
int32_t print(const np::Array<uint16_t>& array, const np::Slice& slice) noexcept {
|
||||
int32_t num_written = 0;
|
||||
num_written += printf("[");
|
||||
//size_t k = slice.x * array.shape[1] * array.shape[2] + slice.y * array.shape[2] + slice.z;
|
||||
size_t k = slice.x * array.shape[1];
|
||||
for (size_t i = k; i < k + (slice.y - slice.x); ++i) {
|
||||
num_written += printf("%5hu ", array[i]);
|
||||
}
|
||||
num_written += print("]");
|
||||
num_written += printf("]");
|
||||
return num_written;
|
||||
}
|
||||
|
||||
static inline np::Array<uint8_t> load_set(const char* set_name) {
|
||||
FILE* file = fopen(set_name, "rb");
|
||||
static inline np::Array<uint8_t> load_set(const char* const set_name) {
|
||||
FILE* const file = fopen(set_name, "rb");
|
||||
if (file == NULL) {
|
||||
print_error_file(set_name);
|
||||
throw;
|
||||
@ -156,7 +154,7 @@ static inline np::Array<uint8_t> load_set(const char* set_name) {
|
||||
fclose(file);
|
||||
throw;
|
||||
}
|
||||
size_t* dims = new size_t[3]();
|
||||
size_t* const dims = new size_t[3]();
|
||||
if (!sscanf(meta, "%lu %lu %lu", &dims[0], &dims[1], &dims[2])) {
|
||||
print_error_file(set_name);
|
||||
fclose(file);
|
||||
@ -167,7 +165,7 @@ static inline np::Array<uint8_t> load_set(const char* set_name) {
|
||||
|
||||
const size_t size = np::prod(a.shape);
|
||||
size_t i = 0, j = 0;
|
||||
int c;
|
||||
int32_t c;
|
||||
char buff[STRING_INT_SIZE] = { 0 };
|
||||
while ((c = fgetc(file)) != EOF && i < size) {
|
||||
if (c == ' ' || c == '\n') {
|
||||
@ -191,15 +189,15 @@ static inline np::Array<uint8_t> load_set(const char* set_name) {
|
||||
return a;
|
||||
}
|
||||
|
||||
std::array<np::Array<uint8_t>, 4> load_datasets() {
|
||||
std::array<np::Array<uint8_t>, 4> load_datasets(void) {
|
||||
return {
|
||||
load_set(DATA_DIR "/X_train.bin"), load_set(DATA_DIR "/y_train.bin"),
|
||||
load_set(DATA_DIR "/X_test.bin"), load_set(DATA_DIR "/y_test.bin")
|
||||
};
|
||||
}
|
||||
|
||||
void print_error_file(const char* file_dir) noexcept {
|
||||
const char* buff = strerror(errno);
|
||||
void print_error_file(const char* const file_dir) noexcept {
|
||||
const char* const buff = strerror(errno);
|
||||
fprintf(stderr, "Can't open %s, error code = %d : %s\n", file_dir, errno, buff);
|
||||
// delete buff;
|
||||
}
|
||||
|
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;
|
||||
|
@ -11,7 +11,7 @@ void test_working(const size_t& length) noexcept {
|
||||
const size_t size = length * sizeof(size_t);
|
||||
|
||||
#if __DEBUG
|
||||
print("Estimating memory footprint at : " + format_byte_size(2 * size));
|
||||
printf("Estimating memory footprint at : %s\n", format_byte_size(2 * size).c_str());
|
||||
#endif
|
||||
|
||||
np::Array<size_t> x = np::empty<size_t>({ length }), y = np::empty<size_t>({ length });
|
||||
@ -53,7 +53,7 @@ void test_working_2d(const size_t& N1, const size_t& N2) noexcept {
|
||||
const size_t size = length * sizeof(size_t);
|
||||
|
||||
#if __DEBUG
|
||||
print("Estimating memory footprint at : " + format_byte_size(2 * size));
|
||||
printf("Estimating memory footprint at : %s\n", format_byte_size(2 * size).c_str());
|
||||
#endif
|
||||
|
||||
np::Array<size_t> x = np::empty<size_t>({ length }), y = np::empty<size_t>({ length });
|
||||
@ -96,7 +96,7 @@ void test_working_3d(const size_t& N1, const size_t& N2, const size_t& N3) noexc
|
||||
const size_t size = length * sizeof(size_t);
|
||||
|
||||
#if __DEBUG
|
||||
print("Estimating memory footprint at : " + format_byte_size(2 * size));
|
||||
printf("Estimating memory footprint at : %s\n", format_byte_size(2 * size).c_str());
|
||||
#endif
|
||||
|
||||
np::Array<size_t> x = np::empty<size_t>({ length }), y = np::empty<size_t>({ length });
|
||||
|
177
cpp/projet.cpp
177
cpp/projet.cpp
@ -1,50 +1,61 @@
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#include "data.hpp"
|
||||
#include "toolbox.hpp"
|
||||
#include "config.hpp"
|
||||
#include "gpu_unit_test.hpp"
|
||||
#include "toolbox_unit_test.hpp"
|
||||
#include "ViolaJones.hpp"
|
||||
#include "ViolaJonesGPU.hpp"
|
||||
#include "ViolaJonesCPU.hpp"
|
||||
|
||||
#if GPU_BOOSTED
|
||||
#include "ViolaJonesGPU.hpp"
|
||||
#include "gpu_unit_test.hpp"
|
||||
#define LABEL "GPU"
|
||||
#define apply_features apply_features_gpu
|
||||
#define set_integral_image set_integral_image_gpu
|
||||
#define argsort_2d argsort_2d_gpu
|
||||
#else
|
||||
#include "ViolaJonesCPU.hpp"
|
||||
#define LABEL "CPU"
|
||||
#define apply_features apply_features_cpu
|
||||
#define set_integral_image set_integral_image_cpu
|
||||
#define argsort_2d argsort_2d_cpu
|
||||
#endif
|
||||
|
||||
std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Array<int32_t>, np::Array<uint8_t>> preprocessing() {
|
||||
/**
|
||||
* @brief Execute the preprocessing phase
|
||||
*
|
||||
* The preprocessing phase consist of the following steps :
|
||||
* - Load the dataset
|
||||
* - Calculate features
|
||||
* - Calculate integral images
|
||||
* - Apply features to images
|
||||
* - Calculate argsort of the featured images.
|
||||
*
|
||||
* @return std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Array<int32_t>, np::Array<uint8_t>> Tuple containing in order : training features, training features sorted indexes, training labels, testing features, testing labels
|
||||
*/
|
||||
std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Array<int32_t>, np::Array<uint8_t>> preprocessing(void) {
|
||||
// Creating state saver folders if they don't exist already
|
||||
if (SAVE_STATE)
|
||||
for (const char* const folder_name : { "models", "out" })
|
||||
fs::create_directory(folder_name);
|
||||
std::filesystem::create_directory(folder_name);
|
||||
|
||||
const std::chrono::system_clock::time_point preproc_timestamp = perf_counter_ns();
|
||||
const std::array<int32_t, 3> preproc_gaps = { 49, -18, 29 };
|
||||
header({ "Preprocessing", "Time spent (ns)", "Formatted time spent" }, preproc_gaps);
|
||||
|
||||
const auto [ X_train, y_train, X_test, y_test ] = state_saver<uint8_t, 4>("Loading sets", preproc_gaps[0], {"X_train", "y_train", "X_test", "y_test"},
|
||||
const auto [ X_train, y_train, X_test, y_test ] = state_saver<uint8_t, 4>("Loading sets", preproc_gaps[0], { "X_train", "y_train", "X_test", "y_test" },
|
||||
FORCE_REDO, SAVE_STATE, OUT_DIR, load_datasets);
|
||||
|
||||
#if __DEBUG
|
||||
print("X_train");
|
||||
printf("X_train\n");
|
||||
print(X_train.shape);
|
||||
print(X_train, { IDX_INSPECT });
|
||||
print("X_test");
|
||||
printf("X_test\n");
|
||||
print(X_test.shape);
|
||||
print(X_test, { IDX_INSPECT });
|
||||
print("y_train");
|
||||
printf("y_train\n");
|
||||
print(y_train.shape);
|
||||
print(y_train, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET });
|
||||
print("y_test");
|
||||
printf("y_test\n");
|
||||
print(y_test.shape);
|
||||
print(y_test, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET });
|
||||
#endif
|
||||
@ -53,7 +64,7 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra
|
||||
FORCE_REDO, SAVE_STATE, OUT_DIR, build_features, X_train.shape[1], X_train.shape[2]);
|
||||
|
||||
#if __DEBUG
|
||||
print("feats");
|
||||
printf("feats\n");
|
||||
print(feats.shape);
|
||||
print_feat(feats, { IDX_INSPECT });
|
||||
#endif
|
||||
@ -64,10 +75,10 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra
|
||||
FORCE_REDO, SAVE_STATE, OUT_DIR, set_integral_image, X_test);
|
||||
|
||||
#if __DEBUG
|
||||
print("X_train_ii");
|
||||
printf("X_train_ii\n");
|
||||
print(X_train_ii.shape);
|
||||
print(X_train_ii, { IDX_INSPECT });
|
||||
print("X_test_ii");
|
||||
printf("X_test_ii\n");
|
||||
print(X_test_ii.shape);
|
||||
print(X_test_ii, { IDX_INSPECT });
|
||||
#endif
|
||||
@ -78,16 +89,16 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra
|
||||
FORCE_REDO, SAVE_STATE, OUT_DIR, apply_features, feats, X_test_ii);
|
||||
|
||||
#if __DEBUG
|
||||
print("X_train_feat");
|
||||
printf("X_train_feat\n");
|
||||
print(X_train_feat.shape);
|
||||
print(X_train_feat, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET });
|
||||
print("X_test_feat");
|
||||
printf("X_test_feat\n");
|
||||
print(X_test_feat.shape);
|
||||
print(X_test_feat, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET });
|
||||
#endif
|
||||
|
||||
// const Array<int> indices = measure_time_save<Array<int>>("Selecting best features", "indices", select_percentile, X_train_feat, d.y_train);
|
||||
// const Array<int> indices = measure_time<Array<int>>("Selecting best features", select_percentile, X_train_feat, d.y_train);
|
||||
// const np::Array<int32_t> indices = measure_time_save<Array<int>>("Selecting best features", preproc_gaps[0], "indices", select_percentile, X_train_feat, d.y_train);
|
||||
// const np::Array<int32_t> indices = measure_time<Array<int>>("Selecting best features", preproc_gaps[0], select_percentile, X_train_feat, d.y_train);
|
||||
|
||||
#if __DEBUG
|
||||
// print_feature(indices);
|
||||
@ -97,7 +108,7 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra
|
||||
FORCE_REDO, SAVE_STATE, OUT_DIR, argsort_2d, X_train_feat);
|
||||
|
||||
#if __DEBUG
|
||||
print("X_train_feat_argsort");
|
||||
printf("X_train_feat_argsort\n");
|
||||
print(X_train_feat_argsort.shape);
|
||||
print(X_train_feat_argsort, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET });
|
||||
#endif
|
||||
@ -117,6 +128,14 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra
|
||||
return { X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Train the weak classifiers.
|
||||
*
|
||||
* @param X_train_feat Training images.
|
||||
* @param X_train_feat_argsort Sorted indexes of the training images features.
|
||||
* @param y_train Training labels.
|
||||
* @return Trained models
|
||||
*/
|
||||
std::array<std::array<np::Array<float64_t>, 2>, TS.size()> train(const np::Array<int32_t>& X_train_feat, const np::Array<uint16_t>& X_train_feat_argsort, const np::Array<uint8_t>& y_train) noexcept {
|
||||
const std::chrono::system_clock::time_point training_timestamp = perf_counter_ns();
|
||||
const std::array<int32_t, 3> training_gaps = { 26, -18, 29 };
|
||||
@ -136,9 +155,9 @@ std::array<std::array<np::Array<float64_t>, 2>, TS.size()> train(const np::Array
|
||||
const auto [ alphas, final_classifiers ] = state_saver<float64_t, 2>(title, training_gaps[0], { alphas_title, final_classifiers_title },
|
||||
FORCE_REDO, SAVE_STATE, MODEL_DIR, train_viola_jones, T, X_train_feat, X_train_feat_argsort, y_train);
|
||||
#if __DEBUG
|
||||
print("alphas");
|
||||
printf("alphas\n");
|
||||
print(alphas);
|
||||
print("final_classifiers");
|
||||
printf("final_classifiers\n");
|
||||
print(final_classifiers);
|
||||
#endif
|
||||
models[i++] = { alphas, final_classifiers };
|
||||
@ -151,6 +170,14 @@ std::array<std::array<np::Array<float64_t>, 2>, TS.size()> train(const np::Array
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Benchmark the trained classifiers on the training and testing sets.
|
||||
*
|
||||
* @param X_train_feat Training features.
|
||||
* @param y_train Training labels.
|
||||
* @param X_test_feat Testing features.
|
||||
* @param y_test Testing labels.
|
||||
*/
|
||||
void testing_and_evaluating(const std::array<std::array<np::Array<float64_t>, 2>, TS.size()>& models, const np::Array<int32_t>& X_train_feat, const np::Array<uint8_t>& y_train, const np::Array<int32_t>& X_test_feat, const np::Array<uint8_t>& y_test) {
|
||||
const std::array<int32_t, 5> testing_gaps = { 26, -19, 24, -19, 24 };
|
||||
header({ "Testing", "Time spent (ns) (E)", "Formatted time spent (E)", "Time spent (ns) (T)", "Formatted time spent (T)" }, testing_gaps);
|
||||
@ -201,6 +228,13 @@ void testing_and_evaluating(const std::array<std::array<np::Array<float64_t>, 2>
|
||||
footer(evaluating_gaps);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test if the each result is equals to other devices.
|
||||
*
|
||||
* Given ViolaJones is a fully deterministic algorithm.
|
||||
* The results, regardless the device, should be the same.
|
||||
* This function check this assertion.
|
||||
*/
|
||||
void unit_test(void) {
|
||||
const std::chrono::system_clock::time_point unit_timestamp = perf_counter_ns();
|
||||
const std::array<int32_t, 4> unit_gaps = { 37, -10, -18, 29};
|
||||
@ -224,76 +258,99 @@ void unit_test(void) {
|
||||
formatted_row(unit_gaps, { title, "Failed", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() });
|
||||
};
|
||||
|
||||
for (const char* label : { "train", "test" }) {
|
||||
sprintf(file_cpu, OUT_DIR "/X_%s_ii_CPU.bin", label);
|
||||
sprintf(file_gpu, OUT_DIR "/X_%s_ii_GPU.bin", label);
|
||||
if (fs::exists(file_cpu) && fs::exists(file_gpu)) {
|
||||
for (const char* const label : { "train", "test" }) {
|
||||
snprintf(file_cpu, BUFFER_SIZE, OUT_DIR "/X_%s_ii_CPU.bin", label);
|
||||
snprintf(file_gpu, BUFFER_SIZE, OUT_DIR "/X_%s_ii_GPU.bin", label);
|
||||
if (std::filesystem::exists(file_cpu) && std::filesystem::exists(file_gpu)) {
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "X_%s_ii", label);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&file_cpu, &file_gpu]{
|
||||
const np::Array<uint32_t> X_train_ii_cpu = load<uint32_t>(file_cpu);
|
||||
const np::Array<uint32_t> X_train_ii_gpu = load<uint32_t>(file_gpu);
|
||||
sprintf(tmp_title, "X_%s_ii", label);
|
||||
sprintf(title, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&X_train_ii_cpu, &X_train_ii_gpu]{ return unit_test_cpu_vs_gpu<uint32_t>(X_train_ii_cpu, X_train_ii_gpu); });
|
||||
return unit_test_cpu_vs_gpu<uint32_t>(X_train_ii_cpu, X_train_ii_gpu);
|
||||
});
|
||||
}
|
||||
snprintf(file_cpu, BUFFER_SIZE, OUT_DIR "/X_%s_feat_CPU.bin", label);
|
||||
snprintf(file_gpu, BUFFER_SIZE, OUT_DIR "/X_%s_feat_GPU.bin", label);
|
||||
uint8_t feat = 0;
|
||||
char file_feat[BUFFER_SIZE] = { 0 };
|
||||
sprintf(file_feat, OUT_DIR "/X_%s_feat_CPU.bin", label);
|
||||
if (fs::exists(file_feat)) {
|
||||
const np::Array<int32_t> X_feat = load<int32_t>(file_feat);
|
||||
sprintf(file_gpu, OUT_DIR "/X_%s_feat_GPU.bin", label);
|
||||
if (fs::exists(file_gpu)) {
|
||||
const np::Array<int32_t> X_feat_gpu = load<int32_t>(file_gpu);
|
||||
sprintf(tmp_title, "X_%s_feat", label);
|
||||
sprintf(title, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&X_feat, &X_feat_gpu]{ return unit_test_cpu_vs_gpu<int32_t>(X_feat, X_feat_gpu); });
|
||||
if (std::filesystem::exists(file_cpu)) {
|
||||
strncpy(file_feat, file_cpu, BUFFER_SIZE);
|
||||
feat = 1;
|
||||
} else if (std::filesystem::exists(file_gpu)) {
|
||||
strncpy(file_feat, file_gpu, BUFFER_SIZE);
|
||||
feat = 2;
|
||||
}
|
||||
sprintf(file_cpu, OUT_DIR "/X_%s_feat_argsort_CPU.bin", label);
|
||||
if (feat != 0) {
|
||||
const np::Array<int32_t> X_feat = load<int32_t>(file_feat);
|
||||
snprintf(file_gpu, BUFFER_SIZE, feat == 1 ? OUT_DIR "/X_%s_feat_GPU.bin" : OUT_DIR "/X_%s_feat_CPU.bin", label);
|
||||
if (std::filesystem::exists(file_gpu)) {
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "X_%s_feat", label);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&X_feat, &file_gpu]{
|
||||
const np::Array<int32_t> X_feat_aux = load<int32_t>(file_gpu);
|
||||
return unit_test_cpu_vs_gpu<int32_t>(X_feat, X_feat_aux);
|
||||
});
|
||||
}
|
||||
snprintf(file_cpu, BUFFER_SIZE, OUT_DIR "/X_%s_feat_argsort_CPU.bin", label);
|
||||
np::Array<uint16_t> X_feat_argsort_cpu;
|
||||
uint8_t loaded = 0;
|
||||
if (fs::exists(file_cpu)) {
|
||||
if (std::filesystem::exists(file_cpu)) {
|
||||
++loaded;
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "X_%s_feat_argsort", label);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - CPU argsort", tmp_title);
|
||||
test_fnc(title, [&X_feat, &X_feat_argsort_cpu, &file_cpu]{
|
||||
X_feat_argsort_cpu = std::move(load<uint16_t>(file_cpu));
|
||||
++loaded;
|
||||
sprintf(tmp_title, "X_%s_feat_argsort", label);
|
||||
sprintf(title, "%-22s - CPU argsort", tmp_title);
|
||||
test_fnc(title, [&X_feat, &X_feat_argsort_cpu]{ return unit_test_argsort_2d<int32_t>(X_feat, X_feat_argsort_cpu); });
|
||||
return unit_test_argsort_2d<int32_t>(X_feat, X_feat_argsort_cpu);
|
||||
});
|
||||
}
|
||||
sprintf(file_gpu, OUT_DIR "/X_%s_feat_argsort_GPU.bin", label);
|
||||
snprintf(file_gpu, BUFFER_SIZE, OUT_DIR "/X_%s_feat_argsort_GPU.bin", label);
|
||||
np::Array<uint16_t> X_feat_argsort_gpu;
|
||||
if (fs::exists(file_gpu)) {
|
||||
X_feat_argsort_gpu = std::move(load<uint16_t>(file_gpu));
|
||||
if (std::filesystem::exists(file_gpu)) {
|
||||
++loaded;
|
||||
sprintf(tmp_title, "X_%s_feat_argsort", label);
|
||||
sprintf(title, "%-22s - GPU argsort", tmp_title);
|
||||
test_fnc(title, [&X_feat, &X_feat_argsort_gpu]{ return unit_test_argsort_2d<int32_t>(X_feat, X_feat_argsort_gpu); });
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "X_%s_feat_argsort", label);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - GPU argsort", tmp_title);
|
||||
test_fnc(title, [&X_feat, &X_feat_argsort_gpu, &file_gpu]{
|
||||
X_feat_argsort_gpu = std::move(load<uint16_t>(file_gpu));
|
||||
return unit_test_argsort_2d<int32_t>(X_feat, X_feat_argsort_gpu);
|
||||
});
|
||||
}
|
||||
if (loaded == 2){
|
||||
sprintf(tmp_title, "X_%s_feat_argsort", label);
|
||||
sprintf(title, "%-22s - CPU vs GPU", tmp_title);
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "X_%s_feat_argsort", label);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&X_feat_argsort_cpu, &X_feat_argsort_gpu]{ return unit_test_cpu_vs_gpu<uint16_t>(X_feat_argsort_cpu, X_feat_argsort_gpu); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const size_t T : TS)
|
||||
for (const char* label : { "alphas", "final_classifiers" }) {
|
||||
sprintf(file_cpu, MODEL_DIR "/%s_%lu_CPU.bin", label, T);
|
||||
sprintf(file_gpu, MODEL_DIR "/%s_%lu_GPU.bin", label, T);
|
||||
if (fs::exists(file_cpu) && fs::exists(file_gpu)){
|
||||
for (const char* const label : { "alphas", "final_classifiers" }) {
|
||||
snprintf(file_cpu, BUFFER_SIZE, MODEL_DIR "/%s_%lu_CPU.bin", label, T);
|
||||
snprintf(file_gpu, BUFFER_SIZE, MODEL_DIR "/%s_%lu_GPU.bin", label, T);
|
||||
if (std::filesystem::exists(file_cpu) && std::filesystem::exists(file_gpu)){
|
||||
snprintf(tmp_title, BUFFER_SIZE / 2, "%s_%ld", label, T);
|
||||
snprintf(title, BUFFER_SIZE, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&file_cpu, &file_gpu]{
|
||||
const np::Array<float64_t> cpu = load<float64_t>(file_cpu);
|
||||
const np::Array<float64_t> gpu = load<float64_t>(file_gpu);
|
||||
sprintf(tmp_title, "%s_%ld", label, T);
|
||||
sprintf(title, "%-22s - CPU vs GPU", tmp_title);
|
||||
test_fnc(title, [&cpu, &gpu]{ return unit_test_cpu_vs_gpu<float64_t>(cpu, gpu); });
|
||||
return unit_test_cpu_vs_gpu<float64_t>(cpu, gpu);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const long long time_spent = duration_ns(perf_counter_ns() - unit_timestamp);
|
||||
snprintf(title, BUFFER_SIZE, "%ld/%ld", n_success, n_total);
|
||||
|
||||
if (n_total == 0)
|
||||
formatted_row(unit_gaps, { "Unit testing summary", "No files", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() });
|
||||
else {
|
||||
snprintf(title, BUFFER_SIZE, "%ld/%ld", n_success, n_total);
|
||||
formatted_line(unit_gaps, "├", "┼", "─", "┤");
|
||||
formatted_row(unit_gaps, { "Unit testing summary", title, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() });
|
||||
}
|
||||
footer(unit_gaps);
|
||||
}
|
||||
|
||||
int main(){
|
||||
int32_t main(void){
|
||||
setlocale(LC_NUMERIC, ""); // Allow proper number display
|
||||
|
||||
const std::chrono::system_clock::time_point unit_timestamp = perf_counter_ns();
|
||||
|
17
cpp/test.cpp
17
cpp/test.cpp
@ -8,22 +8,22 @@
|
||||
|
||||
void printProgress(const float64_t& percentage) noexcept {
|
||||
const uint64_t val = static_cast<uint64_t>(percentage * 100);
|
||||
const int lpad = static_cast<int>(percentage * PBWIDTH);
|
||||
const int rpad = PBWIDTH - lpad;
|
||||
printf("%3lu%% [%.*s%*s]\r", val, lpad, PBSTR, rpad, "");
|
||||
fflush(stdout);
|
||||
const int32_t lpad = static_cast<int32_t>(percentage * PBWIDTH);
|
||||
const int32_t rpad = PBWIDTH - lpad;
|
||||
fprintf(stderr, "%3lu%% [%.*s%*s]\r", val, lpad, PBSTR, rpad, "");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void clearProgress() noexcept {
|
||||
void clearProgress(void) noexcept {
|
||||
// Progress bar width + space before + num space + space after
|
||||
printf("%*c\r", PBWIDTH + 1 + 3 + 3, ' ');
|
||||
fprintf(stderr, "%*c\r", PBWIDTH + 1 + 3 + 3, ' ');
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void test(const uint64_t& N) noexcept {
|
||||
#if __DEBUG
|
||||
printf("DETERMINISTIC for N=%s of %s sized %s\n", thousand_sep(N).c_str(), typeid(T).name(), format_byte_size(sizeof(T)).c_str());
|
||||
print("Estimating memory footprint at : " + format_byte_size(3 * N * sizeof(T)));
|
||||
printf("Estimating memory footprint at : %s\n", format_byte_size(3 * N * sizeof(T)).c_str());
|
||||
#endif
|
||||
|
||||
T *a = new T[N], *b = new T[N], *c = new T[N];
|
||||
@ -45,7 +45,7 @@ void test(const uint64_t& N) noexcept {
|
||||
delete[] a, delete[] b, delete[] c;
|
||||
}
|
||||
|
||||
void test_float() noexcept {
|
||||
void test_float(void) noexcept {
|
||||
std::cout << std::setprecision(1<<8);
|
||||
const uint64_t N = static_cast<uint64_t>(1)<<28;
|
||||
test<float128_t>(N);
|
||||
@ -60,4 +60,3 @@ void test_float() noexcept {
|
||||
//printf("%.128lf\n", static_cast<float64_t>(1) / 3);
|
||||
//printf("%.128f\n", static_cast<float>(1) / 3);
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,17 @@
|
||||
#include "toolbox.hpp"
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
static constexpr uint64_t u64(const double& n) noexcept { return static_cast<uint64_t>(n); }
|
||||
inline static constexpr uint64_t u64(const double& n) noexcept { return static_cast<uint64_t>(n); }
|
||||
|
||||
static const constexpr size_t N_TIMES = 11;
|
||||
static const constexpr std::array<const char*, N_TIMES> time_formats = { "ns", "µs", "ms", "s", "m", "h", "j", "w", "M", "y", "c" };
|
||||
static const constexpr std::array<const char*, N_TIMES> time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y", "c" };
|
||||
static const constexpr std::array<uint64_t, N_TIMES> time_numbers = { 1, u64(1e3), u64(1e6), u64(1e9), u64(6e10), u64(36e11), u64(864e11),
|
||||
u64(6048e11), u64(26784e11), u64(31536e12), u64(31536e14) };
|
||||
|
||||
/**
|
||||
* @brief Format the time in seconds in human readable format.
|
||||
*
|
||||
* @param time Time in seconds
|
||||
* @return std::string The formatted human readable string.
|
||||
* @param time number of seconds
|
||||
* @return The formatted human readable string.
|
||||
*/
|
||||
std::string format_time(uint64_t time) noexcept {
|
||||
if (time == 0)
|
||||
@ -21,8 +19,8 @@ std::string format_time(uint64_t time) noexcept {
|
||||
|
||||
std::string s = "";
|
||||
uint64_t res;
|
||||
for (int i = N_TIMES - 1; i >= 3; --i) {
|
||||
const uint64_t time_number = time_numbers[i] / 1e9; // Converting nanosecond timestamp to second
|
||||
for (int32_t i = N_TIMES - 1; i >= 3; --i) {
|
||||
const uint64_t time_number = time_numbers[i] / u64(1e9); // Converting nanosecond timestamp to second
|
||||
if (time >= time_number) {
|
||||
res = time / time_number;
|
||||
time %= time_number;
|
||||
@ -30,7 +28,7 @@ std::string format_time(uint64_t time) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
if (s.back() == ' ')
|
||||
// Remove trailing character
|
||||
s.pop_back();
|
||||
|
||||
return s;
|
||||
@ -48,7 +46,7 @@ std::string format_time_ns(uint64_t time) noexcept {
|
||||
|
||||
std::string s = "";
|
||||
uint64_t res;
|
||||
for (int i = N_TIMES - 1; i >= 0; --i) {
|
||||
for (int32_t i = N_TIMES - 1; i >= 0; --i) {
|
||||
if (time >= time_numbers[i]) {
|
||||
res = time / time_numbers[i];
|
||||
time %= time_numbers[i];
|
||||
@ -56,7 +54,7 @@ std::string format_time_ns(uint64_t time) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
if (s.back() == ' ')
|
||||
// Remove trailing character
|
||||
s.pop_back();
|
||||
|
||||
return s;
|
||||
@ -71,7 +69,7 @@ static const constexpr uint64_t total_bytes = u64(1)<<(10 * (N_BYTES - 1));
|
||||
* See more : https://en.wikipedia.org/wiki/JEDEC_memory_standards
|
||||
*
|
||||
* @param bytes Number of bytes
|
||||
* @return std::string JEDEC compliant formatted number of bytes
|
||||
* @return JEDEC compliant formatted number of bytes
|
||||
*/
|
||||
std::string format_byte_size(uint64_t bytes) noexcept {
|
||||
if (bytes == 0)
|
||||
@ -95,6 +93,13 @@ std::string format_byte_size(uint64_t bytes) noexcept {
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a number with a separator (i.e. 1000 as 1,000)
|
||||
*
|
||||
* @param k number to format
|
||||
* @param separator used between each thouand
|
||||
* @return Formatted number
|
||||
*/
|
||||
std::string thousand_sep(uint64_t k, const char& separator) noexcept {
|
||||
const std::string n = std::to_string(k);
|
||||
const uint64_t st_size = n.length() + (n.length() - 1) / 3;
|
||||
@ -110,5 +115,13 @@ std::string thousand_sep(uint64_t k, const char& separator) noexcept {
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//uint64_t len = n.length(), dlen = 3;
|
||||
|
||||
//while (len > dlen) {
|
||||
// n.insert(len - dlen, 1, separator);
|
||||
// dlen += 4;
|
||||
// len += 1;
|
||||
//}
|
||||
//return n;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
template<typename T>
|
||||
void Assert(const char* name, const T& expected, const T& result) noexcept {
|
||||
void Assert(const char* const name, const T& expected, const T& result) noexcept {
|
||||
if(expected != result){
|
||||
std::cerr << "For test named " << name << " Expected '" << expected << "' but got '" << result << "' instead\n";
|
||||
assert(false);
|
||||
@ -85,7 +85,7 @@ void format_time_ns_test(void) noexcept {
|
||||
Assert("format_time_ns null", std::string("0ns"), format_time_ns(static_cast<uint64_t>(0)));
|
||||
Assert("format_time_ns nanosecond", std::string("1ns"), format_time_ns(static_cast<uint64_t>(1)));
|
||||
Assert("format_time_ns shake", std::string("10ns"), format_time_ns(static_cast<uint64_t>(10)));
|
||||
Assert("format_time_ns microsecond", std::string("1µs"), format_time_ns(static_cast<uint64_t>(1e3)));
|
||||
Assert("format_time_ns microsecond", std::string("1us"), format_time_ns(static_cast<uint64_t>(1e3)));
|
||||
Assert("format_time_ns millisecond", std::string("1ms"), format_time_ns(static_cast<uint64_t>(1e6)));
|
||||
Assert("format_time_ns centisecond", std::string("10ms"), format_time_ns(static_cast<uint64_t>(1e7)));
|
||||
Assert("format_time_ns decisecond", std::string("100ms"), format_time_ns(static_cast<uint64_t>(1e8)));
|
||||
@ -112,7 +112,7 @@ void format_time_ns_test(void) noexcept {
|
||||
Assert("format_time_ns year", std::string("1y"), format_time_ns(static_cast<uint64_t>(31536e12)));
|
||||
Assert("format_time_ns tropical year", std::string("1y 5h 48m 45s 216ms"), format_time_ns(static_cast<uint64_t>(31556925216e6)));
|
||||
Assert("format_time_ns gregorian year", std::string("1y 5h 49m 12s"), format_time_ns(static_cast<uint64_t>(31556952e9)));
|
||||
Assert("format_time_ns sidereal year", std::string("1y 6h 9m 9s 763ms 545µs 600ns"), format_time_ns(static_cast<uint64_t>(315581497635456e2)));
|
||||
Assert("format_time_ns sidereal year", std::string("1y 6h 9m 9s 763ms 545us 600ns"), format_time_ns(static_cast<uint64_t>(315581497635456e2)));
|
||||
Assert("format_time_ns leap year", std::string("1y 1j"), format_time_ns(static_cast<uint64_t>(316224e11)));
|
||||
Assert("format_time_ns olympiad", std::string("4y"), format_time_ns(static_cast<uint64_t>(126144e12)));
|
||||
Assert("format_time_ns lusturm", std::string("5y"), format_time_ns(static_cast<uint64_t>(15768e13)));
|
||||
@ -137,7 +137,7 @@ void format_time_ns_test(void) noexcept {
|
||||
//Assert("format_time_ns ronnasecond", std::string(""), format_time_ns(static_cast<uint64_t>(1e36)));
|
||||
//Assert("format_time_ns quettasecond", std::string(""), format_time_ns(static_cast<uint64_t>(1e39)));
|
||||
// uint64_t_MAX == 2**64 == 18446744073709551615I64u == -1
|
||||
Assert("format_time_ns max", std::string("5c 84y 11M 2j 23h 34m 33s 709ms 551µs 615ns"), format_time_ns(static_cast<uint64_t>(-1)));
|
||||
Assert("format_time_ns max", std::string("5c 84y 11M 2j 23h 34m 33s 709ms 551us 615ns"), format_time_ns(static_cast<uint64_t>(-1)));
|
||||
}
|
||||
|
||||
void thousand_sep_test(void) noexcept {
|
||||
@ -182,4 +182,3 @@ void thousand_sep_test(void) noexcept {
|
||||
// uint64_t_MAX == 2**64 == 18446744073709551615I64u == -1
|
||||
Assert("thousand_sep max", std::string("18,446,744,073,709,551,615"), thousand_sep(static_cast<uint64_t>(-1)));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user