From 590f7c388cc0e55b77890f5dbe3b568457ea96ae Mon Sep 17 00:00:00 2001 From: Benjamin Brock Date: Thu, 24 Oct 2024 14:46:04 -0700 Subject: [PATCH 1/5] Change functions in `array.h` and `array.hpp` to inline. --- include/binsparse/array.h | 14 +++++++------- include/binsparse/detail/cpp/array.hpp | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/binsparse/array.h b/include/binsparse/array.h index 1df73c5..193ae7e 100644 --- a/include/binsparse/array.h +++ b/include/binsparse/array.h @@ -20,7 +20,7 @@ typedef struct bsp_array_t { bsp_allocator_t allocator; } bsp_array_t; -bsp_array_t bsp_construct_default_array_t() { +inline bsp_array_t bsp_construct_default_array_t() { bsp_array_t array; array.data = NULL; array.size = 0; @@ -28,7 +28,7 @@ bsp_array_t bsp_construct_default_array_t() { return array; } -bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { +inline bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { size_t byte_size = size * bsp_type_size(type); bsp_array_t array; @@ -41,14 +41,14 @@ bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { return array; } -bsp_array_t bsp_copy_construct_array_t(bsp_array_t other) { +inline bsp_array_t bsp_copy_construct_array_t(bsp_array_t other) { bsp_array_t array = bsp_construct_array_t(other.size, other.type); memcpy(array.data, other.data, other.size * bsp_type_size(other.type)); return array; } -bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { +inline bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { assert(other.type == BSP_COMPLEX_FLOAT32 || other.type == BSP_COMPLEX_FLOAT64); @@ -66,7 +66,7 @@ bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { return array; } -bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { +inline bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { assert(other.type == BSP_FLOAT32 || other.type == BSP_FLOAT64); bsp_array_t array; @@ -83,11 +83,11 @@ bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { return array; } -void bsp_destroy_array_t(bsp_array_t array) { +inline void bsp_destroy_array_t(bsp_array_t array) { array.allocator.free(array.data); } -bool bsp_array_equal(bsp_array_t x, bsp_array_t y) { +inline bool bsp_array_equal(bsp_array_t x, bsp_array_t y) { if (x.size != y.size) { return false; } diff --git a/include/binsparse/detail/cpp/array.hpp b/include/binsparse/detail/cpp/array.hpp index 1b5ff7d..dfcac33 100644 --- a/include/binsparse/detail/cpp/array.hpp +++ b/include/binsparse/detail/cpp/array.hpp @@ -19,7 +19,7 @@ using array_ptr_variant_t = int32_t*, int64_t*, float*, double*, float _Complex*, double _Complex*>; -array_ptr_variant_t get_typed_ptr(bsp_array_t array) { +inline array_ptr_variant_t get_typed_ptr(bsp_array_t array) { if (array.type == BSP_UINT8) { uint8_t* data = (uint8_t*) array.data; return data; @@ -69,7 +69,7 @@ array_ptr_variant_t get_typed_ptr(bsp_array_t array) { // value = array[index] template -void bsp_array_read(bsp_array_t array, size_t index, T& value) { +inline void bsp_array_read(bsp_array_t array, size_t index, T& value) { auto variant_ptr = binsparse::__detail::get_typed_ptr(array); std::visit( @@ -85,7 +85,7 @@ void bsp_array_read(bsp_array_t array, size_t index, T& value) { // array[index] = value template -void bsp_array_write(bsp_array_t array, size_t index, U value) { +inline void bsp_array_write(bsp_array_t array, size_t index, U value) { auto variant_ptr = binsparse::__detail::get_typed_ptr(array); std::visit( @@ -100,8 +100,8 @@ void bsp_array_write(bsp_array_t array, size_t index, U value) { } // array_0[index_0] = array_1[index_1] -void bsp_array_awrite(bsp_array_t array_0, size_t index_0, bsp_array_t array_1, - size_t index_1) { +inline void bsp_array_awrite(bsp_array_t array_0, size_t index_0, + bsp_array_t array_1, size_t index_1) { auto variant_ptr_0 = binsparse::__detail::get_typed_ptr(array_0); auto variant_ptr_1 = binsparse::__detail::get_typed_ptr(array_1); From 1c870ce1d101d6d23b444aca8e3d260b6cbb29f5 Mon Sep 17 00:00:00 2001 From: Benjamin Brock Date: Thu, 24 Oct 2024 14:52:32 -0700 Subject: [PATCH 2/5] Much more inline --- include/binsparse/detail/declamp_values.h | 4 ++-- include/binsparse/detail/parse_dataset.h | 4 ++-- include/binsparse/detail/shm_tools.h | 12 ++++++------ include/binsparse/generate.h | 7 ++++--- include/binsparse/matrix.h | 8 ++++---- include/binsparse/matrix_formats.h | 4 ++-- include/binsparse/minimize_values.h | 2 +- include/binsparse/structure.h | 4 ++-- include/binsparse/types.h | 12 ++++++------ 9 files changed, 29 insertions(+), 28 deletions(-) diff --git a/include/binsparse/detail/declamp_values.h b/include/binsparse/detail/declamp_values.h index fad2ce3..8bc3381 100644 --- a/include/binsparse/detail/declamp_values.h +++ b/include/binsparse/detail/declamp_values.h @@ -9,7 +9,7 @@ #include #include -double bsp_suitesparse_declamp_impl_(double value) { +inline double bsp_suitesparse_declamp_impl_(double value) { const double HUGE_DOUBLE = 1e308; if (value >= HUGE_DOUBLE) { return INFINITY; @@ -26,7 +26,7 @@ double bsp_suitesparse_declamp_impl_(double value) { // Here, we "declamp" these values to restore them to infinity. // This allows the `bsp_matrix_minimize_values` to properly minimize // matrices that have infinity values. -void bsp_matrix_declamp_values(bsp_matrix_t matrix) { +inline void bsp_matrix_declamp_values(bsp_matrix_t matrix) { if (matrix.values.type == BSP_FLOAT64) { double* values = (double*) matrix.values.data; diff --git a/include/binsparse/detail/parse_dataset.h b/include/binsparse/detail/parse_dataset.h index c40f6cd..0810fdb 100644 --- a/include/binsparse/detail/parse_dataset.h +++ b/include/binsparse/detail/parse_dataset.h @@ -13,7 +13,7 @@ typedef struct { char* dataset; } bsp_fdataset_info_t; -bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { +inline bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { size_t len = strlen(str); int split = -1; @@ -41,7 +41,7 @@ bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { } } -const char* bsp_get_file_extension(const char* file_name) { +inline const char* bsp_get_file_extension(const char* file_name) { int64_t len = strlen(file_name); for (int64_t i = len - 1; i >= 0; i--) { if (file_name[i] == '.') { diff --git a/include/binsparse/detail/shm_tools.h b/include/binsparse/detail/shm_tools.h index d552c69..09fe618 100644 --- a/include/binsparse/detail/shm_tools.h +++ b/include/binsparse/detail/shm_tools.h @@ -20,7 +20,7 @@ typedef struct { size_t size; } bsp_shm_t; -bsp_shm_t bsp_shm_new(size_t size) { +inline bsp_shm_t bsp_shm_new(size_t size) { bsp_shm_t shm; shm.size = size; @@ -32,11 +32,11 @@ bsp_shm_t bsp_shm_new(size_t size) { return shm; } -void bsp_shm_delete(bsp_shm_t shm) { +inline void bsp_shm_delete(bsp_shm_t shm) { shmctl(shm.id, IPC_RMID, 0); } -void* bsp_shm_attach(bsp_shm_t shm) { +inline void* bsp_shm_attach(bsp_shm_t shm) { void* data; if ((data = shmat(shm.id, NULL, 0)) == (void*) -1) { @@ -46,11 +46,11 @@ void* bsp_shm_attach(bsp_shm_t shm) { return data; } -void bsp_shm_detach(void* data) { +inline void bsp_shm_detach(void* data) { shmdt(data); } -void* bsp_shm_malloc(size_t size) { +inline void* bsp_shm_malloc(size_t size) { bsp_shm_t shm_id = bsp_shm_new(size); void* ptr = bsp_shm_attach(shm_id); @@ -60,7 +60,7 @@ void* bsp_shm_malloc(size_t size) { return ptr; } -void bsp_shm_free(void* ptr) { +inline void bsp_shm_free(void* ptr) { bsp_shm_detach(ptr); } diff --git a/include/binsparse/generate.h b/include/binsparse/generate.h index 2ea8fd8..844de04 100644 --- a/include/binsparse/generate.h +++ b/include/binsparse/generate.h @@ -8,7 +8,7 @@ #include -void bsp_array_fill_random(bsp_array_t array, size_t bound) { +inline void bsp_array_fill_random(bsp_array_t array, size_t bound) { if (array.type == BSP_UINT8) { uint8_t* values = (uint8_t*) array.data; for (size_t i = 0; i < array.size; i++) { @@ -67,8 +67,9 @@ void bsp_array_fill_random(bsp_array_t array, size_t bound) { } } -bsp_matrix_t bsp_generate_coo(size_t m, size_t n, size_t nnz, - bsp_type_t value_type, bsp_type_t index_type) { +inline bsp_matrix_t bsp_generate_coo(size_t m, size_t n, size_t nnz, + bsp_type_t value_type, + bsp_type_t index_type) { bsp_matrix_t matrix = bsp_construct_default_matrix_t(); matrix.nrows = m; matrix.ncols = n; diff --git a/include/binsparse/matrix.h b/include/binsparse/matrix.h index fcfc6e5..73bfbf0 100644 --- a/include/binsparse/matrix.h +++ b/include/binsparse/matrix.h @@ -26,7 +26,7 @@ typedef struct bsp_matrix_t { bsp_structure_t structure; } bsp_matrix_t; -bsp_matrix_t bsp_construct_default_matrix_t() { +inline bsp_matrix_t bsp_construct_default_matrix_t() { bsp_matrix_t mat; mat.values = bsp_construct_default_array_t(); mat.indices_0 = bsp_construct_default_array_t(); @@ -38,14 +38,14 @@ bsp_matrix_t bsp_construct_default_matrix_t() { return mat; } -void bsp_destroy_matrix_t(bsp_matrix_t matrix) { +inline void bsp_destroy_matrix_t(bsp_matrix_t matrix) { bsp_destroy_array_t(matrix.values); bsp_destroy_array_t(matrix.indices_0); bsp_destroy_array_t(matrix.indices_1); bsp_destroy_array_t(matrix.pointers_to_1); } -size_t bsp_matrix_nbytes(bsp_matrix_t mat) { +inline size_t bsp_matrix_nbytes(bsp_matrix_t mat) { size_t nbytes = 0; if (mat.values.size > 0) { nbytes += mat.values.size * bsp_type_size(mat.values.type); @@ -66,7 +66,7 @@ size_t bsp_matrix_nbytes(bsp_matrix_t mat) { return nbytes; } -void bsp_print_matrix_info(bsp_matrix_t matrix) { +inline void bsp_print_matrix_info(bsp_matrix_t matrix) { printf("%lu x %lu matrix with %lu nnz.\n", matrix.nrows, matrix.ncols, matrix.nnz); printf("%s format with %s structure\n", diff --git a/include/binsparse/matrix_formats.h b/include/binsparse/matrix_formats.h index 691097a..1748d00 100644 --- a/include/binsparse/matrix_formats.h +++ b/include/binsparse/matrix_formats.h @@ -24,7 +24,7 @@ typedef enum bsp_matrix_format_t { BSP_INVALID_FORMAT = 21 } bsp_matrix_format_t; -char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { +inline char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { if (format == BSP_DVEC) { return (char*) "DVEC"; } else if (format == BSP_DMAT) { @@ -48,7 +48,7 @@ char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { } } -bsp_matrix_format_t bsp_get_matrix_format(char* format) { +inline bsp_matrix_format_t bsp_get_matrix_format(char* format) { if (strcmp("DVEC", format) == 0) { return BSP_DVEC; } else if (strcmp("DMAT", format) == 0) { diff --git a/include/binsparse/minimize_values.h b/include/binsparse/minimize_values.h index 8764e91..6cbbec8 100644 --- a/include/binsparse/minimize_values.h +++ b/include/binsparse/minimize_values.h @@ -11,7 +11,7 @@ // Given a matrix `matrix`, store its values using the smallest type possible // without losing precision. -bsp_matrix_t bsp_matrix_minimize_values(bsp_matrix_t matrix) { +inline bsp_matrix_t bsp_matrix_minimize_values(bsp_matrix_t matrix) { if (matrix.values.type == BSP_FLOAT64) { bool float32_representable = true; diff --git a/include/binsparse/structure.h b/include/binsparse/structure.h index 62e2ddd..1a10351 100644 --- a/include/binsparse/structure.h +++ b/include/binsparse/structure.h @@ -22,7 +22,7 @@ typedef enum bsp_structure_t { BSP_INVALID_STRUCTURE = 106 } bsp_structure_t; -char* bsp_get_structure_string(bsp_structure_t structure) { +inline char* bsp_get_structure_string(bsp_structure_t structure) { if (structure == BSP_GENERAL) { return (char*) "general"; } else if (structure == BSP_SYMMETRIC_LOWER) { @@ -42,7 +42,7 @@ char* bsp_get_structure_string(bsp_structure_t structure) { } } -bsp_structure_t bsp_get_structure(char* structure) { +inline bsp_structure_t bsp_get_structure(char* structure) { if (strcmp(structure, "symmetric_lower") == 0) { return BSP_SYMMETRIC_LOWER; } else if (strcmp(structure, "symmetric_upper") == 0) { diff --git a/include/binsparse/types.h b/include/binsparse/types.h index 9ce6dea..0945458 100644 --- a/include/binsparse/types.h +++ b/include/binsparse/types.h @@ -26,7 +26,7 @@ typedef enum bsp_type_t { BSP_INVALID_TYPE = 13 } bsp_type_t; -char* bsp_get_type_string(bsp_type_t type) { +inline char* bsp_get_type_string(bsp_type_t type) { if (type == BSP_UINT8) { return (char*) "uint8"; } else if (type == BSP_UINT16) { @@ -58,7 +58,7 @@ char* bsp_get_type_string(bsp_type_t type) { } } -size_t bsp_type_size(bsp_type_t type) { +inline size_t bsp_type_size(bsp_type_t type) { if (type == BSP_UINT8) { return sizeof(uint8_t); } else if (type == BSP_UINT16) { @@ -90,7 +90,7 @@ size_t bsp_type_size(bsp_type_t type) { } } -hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { +inline hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { if (type == BSP_UINT8) { return H5T_STD_U8LE; } else if (type == BSP_UINT16) { @@ -118,7 +118,7 @@ hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { } } -bsp_type_t bsp_get_bsp_type(hid_t type) { +inline bsp_type_t bsp_get_bsp_type(hid_t type) { H5T_class_t cl = H5Tget_class(type); H5T_order_t order = H5Tget_order(type); H5T_sign_t sign = H5Tget_sign(type); @@ -166,7 +166,7 @@ bsp_type_t bsp_get_bsp_type(hid_t type) { // NOTE: This code is a bit silly, but it seems to be the only // way to generically determine the HDF5 native types for // stdint's fixed width integer types. -hid_t bsp_get_hdf5_native_type(bsp_type_t type) { +inline hid_t bsp_get_hdf5_native_type(bsp_type_t type) { if (type == BSP_INT8 || type == BSP_BINT8) { if (sizeof(int8_t) == sizeof(char)) { return H5T_NATIVE_CHAR; @@ -290,7 +290,7 @@ hid_t bsp_get_hdf5_native_type(bsp_type_t type) { // Given the maximum value `max_value` that must be stored, // pick an unsigned integer type for indices. -bsp_type_t bsp_pick_integer_type(size_t max_value) { +inline bsp_type_t bsp_pick_integer_type(size_t max_value) { if (max_value < (size_t) UINT8_MAX) { return BSP_UINT8; } else if (max_value < (size_t) UINT16_MAX) { From 3ea3cb39c0b3c76f8a6ab61ee67d5d0f9516dfb6 Mon Sep 17 00:00:00 2001 From: Benjamin Brock Date: Thu, 24 Oct 2024 15:03:48 -0700 Subject: [PATCH 3/5] Update---`static inline` --- include/binsparse/array.h | 14 +++++++------- include/binsparse/detail/declamp_values.h | 4 ++-- include/binsparse/detail/parse_dataset.h | 4 ++-- include/binsparse/detail/shm_tools.h | 12 ++++++------ include/binsparse/generate.h | 8 ++++---- include/binsparse/matrix.h | 8 ++++---- include/binsparse/matrix_formats.h | 4 ++-- include/binsparse/minimize_values.h | 2 +- include/binsparse/structure.h | 4 ++-- include/binsparse/types.h | 12 ++++++------ 10 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/binsparse/array.h b/include/binsparse/array.h index 193ae7e..8ac69af 100644 --- a/include/binsparse/array.h +++ b/include/binsparse/array.h @@ -20,7 +20,7 @@ typedef struct bsp_array_t { bsp_allocator_t allocator; } bsp_array_t; -inline bsp_array_t bsp_construct_default_array_t() { +static inline bsp_array_t bsp_construct_default_array_t() { bsp_array_t array; array.data = NULL; array.size = 0; @@ -28,7 +28,7 @@ inline bsp_array_t bsp_construct_default_array_t() { return array; } -inline bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { +static inline bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { size_t byte_size = size * bsp_type_size(type); bsp_array_t array; @@ -41,14 +41,14 @@ inline bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) { return array; } -inline bsp_array_t bsp_copy_construct_array_t(bsp_array_t other) { +static inline bsp_array_t bsp_copy_construct_array_t(bsp_array_t other) { bsp_array_t array = bsp_construct_array_t(other.size, other.type); memcpy(array.data, other.data, other.size * bsp_type_size(other.type)); return array; } -inline bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { +static inline bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { assert(other.type == BSP_COMPLEX_FLOAT32 || other.type == BSP_COMPLEX_FLOAT64); @@ -66,7 +66,7 @@ inline bsp_array_t bsp_complex_array_to_fp(bsp_array_t other) { return array; } -inline bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { +static inline bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { assert(other.type == BSP_FLOAT32 || other.type == BSP_FLOAT64); bsp_array_t array; @@ -83,11 +83,11 @@ inline bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) { return array; } -inline void bsp_destroy_array_t(bsp_array_t array) { +static inline void bsp_destroy_array_t(bsp_array_t array) { array.allocator.free(array.data); } -inline bool bsp_array_equal(bsp_array_t x, bsp_array_t y) { +static inline bool bsp_array_equal(bsp_array_t x, bsp_array_t y) { if (x.size != y.size) { return false; } diff --git a/include/binsparse/detail/declamp_values.h b/include/binsparse/detail/declamp_values.h index 8bc3381..fb52d6f 100644 --- a/include/binsparse/detail/declamp_values.h +++ b/include/binsparse/detail/declamp_values.h @@ -9,7 +9,7 @@ #include #include -inline double bsp_suitesparse_declamp_impl_(double value) { +static inline double bsp_suitesparse_declamp_impl_(double value) { const double HUGE_DOUBLE = 1e308; if (value >= HUGE_DOUBLE) { return INFINITY; @@ -26,7 +26,7 @@ inline double bsp_suitesparse_declamp_impl_(double value) { // Here, we "declamp" these values to restore them to infinity. // This allows the `bsp_matrix_minimize_values` to properly minimize // matrices that have infinity values. -inline void bsp_matrix_declamp_values(bsp_matrix_t matrix) { +static inline void bsp_matrix_declamp_values(bsp_matrix_t matrix) { if (matrix.values.type == BSP_FLOAT64) { double* values = (double*) matrix.values.data; diff --git a/include/binsparse/detail/parse_dataset.h b/include/binsparse/detail/parse_dataset.h index 0810fdb..4facff7 100644 --- a/include/binsparse/detail/parse_dataset.h +++ b/include/binsparse/detail/parse_dataset.h @@ -13,7 +13,7 @@ typedef struct { char* dataset; } bsp_fdataset_info_t; -inline bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { +static inline bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { size_t len = strlen(str); int split = -1; @@ -41,7 +41,7 @@ inline bsp_fdataset_info_t bsp_parse_fdataset_string(char* str) { } } -inline const char* bsp_get_file_extension(const char* file_name) { +static inline const char* bsp_get_file_extension(const char* file_name) { int64_t len = strlen(file_name); for (int64_t i = len - 1; i >= 0; i--) { if (file_name[i] == '.') { diff --git a/include/binsparse/detail/shm_tools.h b/include/binsparse/detail/shm_tools.h index 09fe618..2d53553 100644 --- a/include/binsparse/detail/shm_tools.h +++ b/include/binsparse/detail/shm_tools.h @@ -20,7 +20,7 @@ typedef struct { size_t size; } bsp_shm_t; -inline bsp_shm_t bsp_shm_new(size_t size) { +static inline bsp_shm_t bsp_shm_new(size_t size) { bsp_shm_t shm; shm.size = size; @@ -32,11 +32,11 @@ inline bsp_shm_t bsp_shm_new(size_t size) { return shm; } -inline void bsp_shm_delete(bsp_shm_t shm) { +static inline void bsp_shm_delete(bsp_shm_t shm) { shmctl(shm.id, IPC_RMID, 0); } -inline void* bsp_shm_attach(bsp_shm_t shm) { +static inline void* bsp_shm_attach(bsp_shm_t shm) { void* data; if ((data = shmat(shm.id, NULL, 0)) == (void*) -1) { @@ -46,11 +46,11 @@ inline void* bsp_shm_attach(bsp_shm_t shm) { return data; } -inline void bsp_shm_detach(void* data) { +static inline void bsp_shm_detach(void* data) { shmdt(data); } -inline void* bsp_shm_malloc(size_t size) { +static inline void* bsp_shm_malloc(size_t size) { bsp_shm_t shm_id = bsp_shm_new(size); void* ptr = bsp_shm_attach(shm_id); @@ -60,7 +60,7 @@ inline void* bsp_shm_malloc(size_t size) { return ptr; } -inline void bsp_shm_free(void* ptr) { +static inline void bsp_shm_free(void* ptr) { bsp_shm_detach(ptr); } diff --git a/include/binsparse/generate.h b/include/binsparse/generate.h index 844de04..93205a1 100644 --- a/include/binsparse/generate.h +++ b/include/binsparse/generate.h @@ -8,7 +8,7 @@ #include -inline void bsp_array_fill_random(bsp_array_t array, size_t bound) { +static inline void bsp_array_fill_random(bsp_array_t array, size_t bound) { if (array.type == BSP_UINT8) { uint8_t* values = (uint8_t*) array.data; for (size_t i = 0; i < array.size; i++) { @@ -67,9 +67,9 @@ inline void bsp_array_fill_random(bsp_array_t array, size_t bound) { } } -inline bsp_matrix_t bsp_generate_coo(size_t m, size_t n, size_t nnz, - bsp_type_t value_type, - bsp_type_t index_type) { +static inline bsp_matrix_t bsp_generate_coo(size_t m, size_t n, size_t nnz, + bsp_type_t value_type, + bsp_type_t index_type) { bsp_matrix_t matrix = bsp_construct_default_matrix_t(); matrix.nrows = m; matrix.ncols = n; diff --git a/include/binsparse/matrix.h b/include/binsparse/matrix.h index 73bfbf0..db858c7 100644 --- a/include/binsparse/matrix.h +++ b/include/binsparse/matrix.h @@ -26,7 +26,7 @@ typedef struct bsp_matrix_t { bsp_structure_t structure; } bsp_matrix_t; -inline bsp_matrix_t bsp_construct_default_matrix_t() { +static inline bsp_matrix_t bsp_construct_default_matrix_t() { bsp_matrix_t mat; mat.values = bsp_construct_default_array_t(); mat.indices_0 = bsp_construct_default_array_t(); @@ -38,14 +38,14 @@ inline bsp_matrix_t bsp_construct_default_matrix_t() { return mat; } -inline void bsp_destroy_matrix_t(bsp_matrix_t matrix) { +static inline void bsp_destroy_matrix_t(bsp_matrix_t matrix) { bsp_destroy_array_t(matrix.values); bsp_destroy_array_t(matrix.indices_0); bsp_destroy_array_t(matrix.indices_1); bsp_destroy_array_t(matrix.pointers_to_1); } -inline size_t bsp_matrix_nbytes(bsp_matrix_t mat) { +static inline size_t bsp_matrix_nbytes(bsp_matrix_t mat) { size_t nbytes = 0; if (mat.values.size > 0) { nbytes += mat.values.size * bsp_type_size(mat.values.type); @@ -66,7 +66,7 @@ inline size_t bsp_matrix_nbytes(bsp_matrix_t mat) { return nbytes; } -inline void bsp_print_matrix_info(bsp_matrix_t matrix) { +static inline void bsp_print_matrix_info(bsp_matrix_t matrix) { printf("%lu x %lu matrix with %lu nnz.\n", matrix.nrows, matrix.ncols, matrix.nnz); printf("%s format with %s structure\n", diff --git a/include/binsparse/matrix_formats.h b/include/binsparse/matrix_formats.h index 1748d00..2804e02 100644 --- a/include/binsparse/matrix_formats.h +++ b/include/binsparse/matrix_formats.h @@ -24,7 +24,7 @@ typedef enum bsp_matrix_format_t { BSP_INVALID_FORMAT = 21 } bsp_matrix_format_t; -inline char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { +static inline char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { if (format == BSP_DVEC) { return (char*) "DVEC"; } else if (format == BSP_DMAT) { @@ -48,7 +48,7 @@ inline char* bsp_get_matrix_format_string(bsp_matrix_format_t format) { } } -inline bsp_matrix_format_t bsp_get_matrix_format(char* format) { +static inline bsp_matrix_format_t bsp_get_matrix_format(char* format) { if (strcmp("DVEC", format) == 0) { return BSP_DVEC; } else if (strcmp("DMAT", format) == 0) { diff --git a/include/binsparse/minimize_values.h b/include/binsparse/minimize_values.h index 6cbbec8..4969000 100644 --- a/include/binsparse/minimize_values.h +++ b/include/binsparse/minimize_values.h @@ -11,7 +11,7 @@ // Given a matrix `matrix`, store its values using the smallest type possible // without losing precision. -inline bsp_matrix_t bsp_matrix_minimize_values(bsp_matrix_t matrix) { +static inline bsp_matrix_t bsp_matrix_minimize_values(bsp_matrix_t matrix) { if (matrix.values.type == BSP_FLOAT64) { bool float32_representable = true; diff --git a/include/binsparse/structure.h b/include/binsparse/structure.h index 1a10351..537aff7 100644 --- a/include/binsparse/structure.h +++ b/include/binsparse/structure.h @@ -22,7 +22,7 @@ typedef enum bsp_structure_t { BSP_INVALID_STRUCTURE = 106 } bsp_structure_t; -inline char* bsp_get_structure_string(bsp_structure_t structure) { +static inline char* bsp_get_structure_string(bsp_structure_t structure) { if (structure == BSP_GENERAL) { return (char*) "general"; } else if (structure == BSP_SYMMETRIC_LOWER) { @@ -42,7 +42,7 @@ inline char* bsp_get_structure_string(bsp_structure_t structure) { } } -inline bsp_structure_t bsp_get_structure(char* structure) { +static inline bsp_structure_t bsp_get_structure(char* structure) { if (strcmp(structure, "symmetric_lower") == 0) { return BSP_SYMMETRIC_LOWER; } else if (strcmp(structure, "symmetric_upper") == 0) { diff --git a/include/binsparse/types.h b/include/binsparse/types.h index 0945458..e3c9e53 100644 --- a/include/binsparse/types.h +++ b/include/binsparse/types.h @@ -26,7 +26,7 @@ typedef enum bsp_type_t { BSP_INVALID_TYPE = 13 } bsp_type_t; -inline char* bsp_get_type_string(bsp_type_t type) { +static inline char* bsp_get_type_string(bsp_type_t type) { if (type == BSP_UINT8) { return (char*) "uint8"; } else if (type == BSP_UINT16) { @@ -58,7 +58,7 @@ inline char* bsp_get_type_string(bsp_type_t type) { } } -inline size_t bsp_type_size(bsp_type_t type) { +static inline size_t bsp_type_size(bsp_type_t type) { if (type == BSP_UINT8) { return sizeof(uint8_t); } else if (type == BSP_UINT16) { @@ -90,7 +90,7 @@ inline size_t bsp_type_size(bsp_type_t type) { } } -inline hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { +static inline hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { if (type == BSP_UINT8) { return H5T_STD_U8LE; } else if (type == BSP_UINT16) { @@ -118,7 +118,7 @@ inline hid_t bsp_get_hdf5_standard_type(bsp_type_t type) { } } -inline bsp_type_t bsp_get_bsp_type(hid_t type) { +static inline bsp_type_t bsp_get_bsp_type(hid_t type) { H5T_class_t cl = H5Tget_class(type); H5T_order_t order = H5Tget_order(type); H5T_sign_t sign = H5Tget_sign(type); @@ -166,7 +166,7 @@ inline bsp_type_t bsp_get_bsp_type(hid_t type) { // NOTE: This code is a bit silly, but it seems to be the only // way to generically determine the HDF5 native types for // stdint's fixed width integer types. -inline hid_t bsp_get_hdf5_native_type(bsp_type_t type) { +static inline hid_t bsp_get_hdf5_native_type(bsp_type_t type) { if (type == BSP_INT8 || type == BSP_BINT8) { if (sizeof(int8_t) == sizeof(char)) { return H5T_NATIVE_CHAR; @@ -290,7 +290,7 @@ inline hid_t bsp_get_hdf5_native_type(bsp_type_t type) { // Given the maximum value `max_value` that must be stored, // pick an unsigned integer type for indices. -inline bsp_type_t bsp_pick_integer_type(size_t max_value) { +static inline bsp_type_t bsp_pick_integer_type(size_t max_value) { if (max_value < (size_t) UINT8_MAX) { return BSP_UINT8; } else if (max_value < (size_t) UINT16_MAX) { From e83e90e033301241fce0cb3e4706d1101956ed1c Mon Sep 17 00:00:00 2001 From: Benjamin Brock Date: Thu, 24 Oct 2024 16:05:48 -0700 Subject: [PATCH 4/5] Make `bsp_read_matrix` statically linked instead of header-only. --- CMakeLists.txt | 15 +- include/CMakeLists.txt | 3 +- include/binsparse/hdf5_wrapper.h | 15 +- .../matrix_market/matrix_market_inspector.h | 2 +- .../matrix_market/matrix_market_read.h | 20 +- .../matrix_market/matrix_market_write.h | 2 +- include/binsparse/read_matrix.h | 275 +---------------- src/CMakeLists.txt | 7 + src/read_matrix.c | 279 ++++++++++++++++++ 9 files changed, 333 insertions(+), 285 deletions(-) create mode 100644 src/CMakeLists.txt create mode 100644 src/read_matrix.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad2478..a0c78b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,11 +13,18 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_FLAGS "-O3 -march=native") +add_library(binsparse-rc STATIC) + add_subdirectory(include) +add_subdirectory(src) + +# NOTE: For now, both HDF5 and cJSON are `PUBLIC`, meaning that anything that +# depends on `binsparse-rc` will also link/include HDF5 and cJSON. We can change +# these to `PRIVATE` to use them only when building binsparse-rc. find_package(HDF5 REQUIRED COMPONENTS C) -target_link_libraries(binsparse-rc INTERFACE ${HDF5_C_LIBRARIES}) -target_include_directories(binsparse-rc INTERFACE . ${HDF5_INCLUDE_DIRS}) +target_link_libraries(binsparse-rc PUBLIC ${HDF5_C_LIBRARIES}) +target_include_directories(binsparse-rc PUBLIC . ${HDF5_INCLUDE_DIRS}) include(FetchContent) FetchContent_Declare( @@ -28,8 +35,8 @@ FetchContent_Declare( FetchContent_MakeAvailable(cJSON) configure_file(${cJSON_SOURCE_DIR}/cJSON.h ${CMAKE_BINARY_DIR}/include/cJSON/cJSON.h) -target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_BINARY_DIR}/include) -target_link_libraries(${PROJECT_NAME} INTERFACE cjson) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR}/include) +target_link_libraries(${PROJECT_NAME} PUBLIC cjson) if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) add_subdirectory(examples) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index a423da1..f8ebad3 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -2,5 +2,4 @@ # # SPDX-License-Identifier: BSD-3-Clause -add_library(binsparse-rc INTERFACE) -target_include_directories(binsparse-rc INTERFACE .) +target_include_directories(binsparse-rc PUBLIC .) diff --git a/include/binsparse/hdf5_wrapper.h b/include/binsparse/hdf5_wrapper.h index f3f6763..5aded28 100644 --- a/include/binsparse/hdf5_wrapper.h +++ b/include/binsparse/hdf5_wrapper.h @@ -21,8 +21,8 @@ // Write an array to a dataset / file // Returns 0 on success, nonzero on error. -int bsp_write_array(hid_t f, const char* label, bsp_array_t array, - int compression_level) { +static inline int bsp_write_array(hid_t f, const char* label, bsp_array_t array, + int compression_level) { if (array.type == BSP_COMPLEX_FLOAT32 || array.type == BSP_COMPLEX_FLOAT64) { array = bsp_complex_array_to_fp(array); } @@ -76,8 +76,8 @@ int bsp_write_array(hid_t f, const char* label, bsp_array_t array, } #if __STDC_VERSION__ >= 201112L -bsp_array_t bsp_read_array_parallel(hid_t f, const char* label, - int num_threads) { +static inline bsp_array_t bsp_read_array_parallel(hid_t f, const char* label, + int num_threads) { hid_t dset = H5Dopen2(f, label, H5P_DEFAULT); if (dset == H5I_INVALID_HID) { @@ -173,7 +173,7 @@ bsp_array_t bsp_read_array_parallel(hid_t f, const char* label, } #endif -bsp_array_t bsp_read_array(hid_t f, const char* label) { +static inline bsp_array_t bsp_read_array(hid_t f, const char* label) { hid_t dset = H5Dopen2(f, label, H5P_DEFAULT); if (dset == H5I_INVALID_HID) { @@ -212,7 +212,8 @@ bsp_array_t bsp_read_array(hid_t f, const char* label) { return array; } -void bsp_write_attribute(hid_t f, const char* label, const char* string) { +static inline void bsp_write_attribute(hid_t f, const char* label, + const char* string) { hid_t strtype = H5Tcopy(H5T_C_S1); H5Tset_size(strtype, strlen(string)); H5Tset_cset(strtype, H5T_CSET_UTF8); @@ -228,7 +229,7 @@ void bsp_write_attribute(hid_t f, const char* label, const char* string) { H5Sclose(dataspace); } -char* bsp_read_attribute(hid_t f, const char* label) { +static inline char* bsp_read_attribute(hid_t f, const char* label) { hid_t attribute = H5Aopen(f, label, H5P_DEFAULT); hid_t strtype = H5Aget_type(attribute); diff --git a/include/binsparse/matrix_market/matrix_market_inspector.h b/include/binsparse/matrix_market/matrix_market_inspector.h index 3bae696..8811a89 100644 --- a/include/binsparse/matrix_market/matrix_market_inspector.h +++ b/include/binsparse/matrix_market/matrix_market_inspector.h @@ -32,7 +32,7 @@ typedef struct bsp_mm_metadata { char* comments; } bsp_mm_metadata; -bsp_mm_metadata bsp_mmread_metadata(const char* file_path) { +static inline bsp_mm_metadata bsp_mmread_metadata(const char* file_path) { FILE* f = fopen(file_path, "r"); assert(f != NULL); diff --git a/include/binsparse/matrix_market/matrix_market_read.h b/include/binsparse/matrix_market/matrix_market_read.h index 5013ab9..c3eb8a0 100644 --- a/include/binsparse/matrix_market/matrix_market_read.h +++ b/include/binsparse/matrix_market/matrix_market_read.h @@ -11,13 +11,14 @@ #include #include +#include #include #include #include -bsp_matrix_t bsp_mmread_explicit_array(const char* file_path, - bsp_type_t value_type, - bsp_type_t index_type) { +static inline bsp_matrix_t bsp_mmread_explicit_array(const char* file_path, + bsp_type_t value_type, + bsp_type_t index_type) { bsp_mm_metadata metadata = bsp_mmread_metadata(file_path); bsp_matrix_market_type_t mm_type; @@ -103,9 +104,9 @@ bsp_matrix_t bsp_mmread_explicit_array(const char* file_path, return matrix; } -bsp_matrix_t bsp_mmread_explicit_coordinate(const char* file_path, - bsp_type_t value_type, - bsp_type_t index_type) { +static inline bsp_matrix_t +bsp_mmread_explicit_coordinate(const char* file_path, bsp_type_t value_type, + bsp_type_t index_type) { bsp_mm_metadata metadata = bsp_mmread_metadata(file_path); bsp_matrix_market_type_t mm_type; @@ -261,8 +262,9 @@ bsp_matrix_t bsp_mmread_explicit_coordinate(const char* file_path, return matrix; } -bsp_matrix_t bsp_mmread_explicit(const char* file_path, bsp_type_t value_type, - bsp_type_t index_type) { +static inline bsp_matrix_t bsp_mmread_explicit(const char* file_path, + bsp_type_t value_type, + bsp_type_t index_type) { bsp_mm_metadata metadata = bsp_mmread_metadata(file_path); if (strcmp(metadata.format, "array") == 0) { @@ -274,7 +276,7 @@ bsp_matrix_t bsp_mmread_explicit(const char* file_path, bsp_type_t value_type, } } -bsp_matrix_t bsp_mmread(const char* file_path) { +static inline bsp_matrix_t bsp_mmread(const char* file_path) { bsp_mm_metadata metadata = bsp_mmread_metadata(file_path); bsp_type_t value_type; diff --git a/include/binsparse/matrix_market/matrix_market_write.h b/include/binsparse/matrix_market/matrix_market_write.h index 1a4a5e2..afb4706 100644 --- a/include/binsparse/matrix_market/matrix_market_write.h +++ b/include/binsparse/matrix_market/matrix_market_write.h @@ -12,7 +12,7 @@ #include -void bsp_mmwrite(const char* file_path, bsp_matrix_t matrix) { +static inline void bsp_mmwrite(const char* file_path, bsp_matrix_t matrix) { FILE* f = fopen(file_path, "w"); assert(f != NULL); diff --git a/include/binsparse/read_matrix.h b/include/binsparse/read_matrix.h index 0730bb9..948ffba 100644 --- a/include/binsparse/read_matrix.h +++ b/include/binsparse/read_matrix.h @@ -6,274 +6,27 @@ #pragma once -#include -#include -#include - -#if __STDC_VERSION__ >= 201112L -bsp_matrix_t bsp_read_matrix_from_group_parallel(hid_t f, int num_threads) { - bsp_matrix_t matrix = bsp_construct_default_matrix_t(); - - char* json_string = bsp_read_attribute(f, (char*) "binsparse"); - - cJSON* j = cJSON_Parse(json_string); - - assert(j != NULL); - assert(cJSON_IsObject(j)); - - cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); - assert(cJSON_IsObject(binsparse)); - - cJSON* version_ = cJSON_GetObjectItemCaseSensitive(binsparse, "version"); - - assert(version_ != NULL); - - assert(cJSON_IsString(version_)); - - // TODO: check version. - - cJSON* format_ = cJSON_GetObjectItemCaseSensitive(binsparse, "format"); - assert(format_ != NULL); - char* format_string = cJSON_GetStringValue(format_); - - bsp_matrix_format_t format = bsp_get_matrix_format(format_string); - - assert(format != 0); - - matrix.format = format; - - cJSON* nnz_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); - assert(nnz_ != NULL); - size_t nnz = cJSON_GetNumberValue(nnz_); - - cJSON* shape_ = cJSON_GetObjectItemCaseSensitive(binsparse, "shape"); - assert(shape_ != NULL); - - assert(cJSON_GetArraySize(shape_) == 2); - - cJSON* nrows_ = cJSON_GetArrayItem(shape_, 0); - assert(nrows_ != NULL); - - size_t nrows = cJSON_GetNumberValue(nrows_); - - cJSON* ncols_ = cJSON_GetArrayItem(shape_, 1); - assert(ncols_ != NULL); - - size_t ncols = cJSON_GetNumberValue(ncols_); - - matrix.nrows = nrows; - matrix.ncols = ncols; - matrix.nnz = nnz; - matrix.format = format; - - cJSON* data_types_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); - assert(data_types_ != NULL); - - if (cJSON_HasObjectItem(data_types_, "values")) { - matrix.values = bsp_read_array_parallel(f, (char*) "values", num_threads); - - cJSON* value_type = cJSON_GetObjectItemCaseSensitive(data_types_, "values"); - char* type_string = cJSON_GetStringValue(value_type); - - if (strlen(type_string) >= 4 && strncmp(type_string, "iso[", 4) == 0) { - matrix.is_iso = true; - type_string += 4; - } - - if (strlen(type_string) >= 8 && strncmp(type_string, "complex[", 8) == 0) { - matrix.values = bsp_fp_array_to_complex(matrix.values); - } - } - - if (cJSON_HasObjectItem(data_types_, "indices_0")) { - matrix.indices_0 = - bsp_read_array_parallel(f, (char*) "indices_0", num_threads); - } - - if (cJSON_HasObjectItem(data_types_, "indices_1")) { - matrix.indices_1 = - bsp_read_array_parallel(f, (char*) "indices_1", num_threads); - } - - if (cJSON_HasObjectItem(data_types_, "pointers_to_1")) { - matrix.pointers_to_1 = - bsp_read_array_parallel(f, (char*) "pointers_to_1", num_threads); - } - - if (cJSON_HasObjectItem(binsparse, "structure")) { - cJSON* structure_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "structure"); - char* structure = cJSON_GetStringValue(structure_); - matrix.structure = bsp_get_structure(structure); - } - - cJSON_Delete(j); - free(json_string); - - return matrix; -} +#ifdef __cplusplus +extern "C" { #endif -bsp_matrix_t bsp_read_matrix_from_group(hid_t f) { - bsp_matrix_t matrix = bsp_construct_default_matrix_t(); - - char* json_string = bsp_read_attribute(f, (char*) "binsparse"); - - cJSON* j = cJSON_Parse(json_string); +#ifdef BSP_USE_HDF5 +#include - assert(j != NULL); - assert(cJSON_IsObject(j)); - - cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); - assert(cJSON_IsObject(binsparse)); - - cJSON* version_ = cJSON_GetObjectItemCaseSensitive(binsparse, "version"); - - assert(version_ != NULL); - - assert(cJSON_IsString(version_)); - - // TODO: check version. - - cJSON* format_ = cJSON_GetObjectItemCaseSensitive(binsparse, "format"); - assert(format_ != NULL); - char* format_string = cJSON_GetStringValue(format_); - - bsp_matrix_format_t format = bsp_get_matrix_format(format_string); - - assert(format != 0); - - matrix.format = format; - - cJSON* nnz_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); - assert(nnz_ != NULL); - size_t nnz = cJSON_GetNumberValue(nnz_); - - cJSON* shape_ = cJSON_GetObjectItemCaseSensitive(binsparse, "shape"); - assert(shape_ != NULL); - - assert(cJSON_GetArraySize(shape_) == 2); - - cJSON* nrows_ = cJSON_GetArrayItem(shape_, 0); - assert(nrows_ != NULL); - - size_t nrows = cJSON_GetNumberValue(nrows_); - - cJSON* ncols_ = cJSON_GetArrayItem(shape_, 1); - assert(ncols_ != NULL); - - size_t ncols = cJSON_GetNumberValue(ncols_); - - matrix.nrows = nrows; - matrix.ncols = ncols; - matrix.nnz = nnz; - matrix.format = format; - - cJSON* data_types_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); - assert(data_types_ != NULL); - - if (cJSON_HasObjectItem(data_types_, "values")) { - matrix.values = bsp_read_array(f, (char*) "values"); - - cJSON* value_type = cJSON_GetObjectItemCaseSensitive(data_types_, "values"); - char* type_string = cJSON_GetStringValue(value_type); - - if (strlen(type_string) >= 4 && strncmp(type_string, "iso[", 4) == 0) { - matrix.is_iso = true; - type_string += 4; - } - - if (strlen(type_string) >= 8 && strncmp(type_string, "complex[", 8) == 0) { - matrix.values = bsp_fp_array_to_complex(matrix.values); - } - } - - if (cJSON_HasObjectItem(data_types_, "indices_0")) { - matrix.indices_0 = bsp_read_array(f, (char*) "indices_0"); - } - - if (cJSON_HasObjectItem(data_types_, "indices_1")) { - matrix.indices_1 = bsp_read_array(f, (char*) "indices_1"); - } - - if (cJSON_HasObjectItem(data_types_, "pointers_to_1")) { - matrix.pointers_to_1 = bsp_read_array(f, (char*) "pointers_to_1"); - } - - if (cJSON_HasObjectItem(binsparse, "structure")) { - cJSON* structure_ = - cJSON_GetObjectItemCaseSensitive(binsparse, "structure"); - char* structure = cJSON_GetStringValue(structure_); - matrix.structure = bsp_get_structure(structure); - } - - cJSON_Delete(j); - free(json_string); - - return matrix; -} +#if __STDC_VERSION__ >= 201112L +bsp_matrix_t bsp_read_matrix_from_group_parallel(hid_t f, int num_threads); +#endif -size_t bsp_final_dot(const char* str) { - size_t dot_idx = 0; - for (size_t i = 0; str[i] != '\0'; i++) { - if (str[i] == '.') { - dot_idx = i; - } - } - return dot_idx; -} +bsp_matrix_t bsp_read_matrix_from_group(hid_t f); +#endif #if __STDC_VERSION__ >= 201112L bsp_matrix_t bsp_read_matrix_parallel(const char* file_name, const char* group, - int num_threads) { - if (group == NULL) { - size_t idx = bsp_final_dot(file_name); - if (strcmp(file_name + idx, ".hdf5") == 0 || - strcmp(file_name + idx, ".h5") == 0) { - hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); - bsp_matrix_t matrix = bsp_read_matrix_from_group_parallel(f, num_threads); - H5Fclose(f); - return matrix; - } else if (strcmp(file_name + idx, ".mtx") == 0) { - return bsp_mmread(file_name); - } else { - assert(false); - } - } else { - hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); - hid_t g = H5Gopen1(f, group); - bsp_matrix_t matrix = bsp_read_matrix_from_group_parallel(g, num_threads); - H5Gclose(g); - H5Fclose(f); - return matrix; - } -} + int num_threads); #endif -bsp_matrix_t bsp_read_matrix(const char* file_name, const char* group) { - if (group == NULL) { - size_t idx = bsp_final_dot(file_name); - if (strcmp(file_name + idx, ".hdf5") == 0 || - strcmp(file_name + idx, ".h5") == 0) { - hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); - bsp_matrix_t matrix = bsp_read_matrix_from_group(f); - H5Fclose(f); - return matrix; - } else if (strcmp(file_name + idx, ".mtx") == 0) { - return bsp_mmread(file_name); - } else { - assert(false); - } - } else { - hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); - hid_t g = H5Gopen1(f, group); - bsp_matrix_t matrix = bsp_read_matrix_from_group(g); - H5Gclose(g); - H5Fclose(f); - return matrix; - } +bsp_matrix_t bsp_read_matrix(const char* file_name, const char* group); + +#ifdef __cplusplus } +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..7f0bbcb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2024 Binsparse Developers +# +# SPDX-License-Identifier: BSD-3-Clause + +target_sources(binsparse-rc PRIVATE + src/read_matrix.c +) diff --git a/src/read_matrix.c b/src/read_matrix.c new file mode 100644 index 0000000..464210c --- /dev/null +++ b/src/read_matrix.c @@ -0,0 +1,279 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#if __STDC_VERSION__ >= 201112L +bsp_matrix_t bsp_read_matrix_from_group_parallel(hid_t f, int num_threads) { + bsp_matrix_t matrix = bsp_construct_default_matrix_t(); + + char* json_string = bsp_read_attribute(f, (char*) "binsparse"); + + cJSON* j = cJSON_Parse(json_string); + + assert(j != NULL); + assert(cJSON_IsObject(j)); + + cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); + assert(cJSON_IsObject(binsparse)); + + cJSON* version_ = cJSON_GetObjectItemCaseSensitive(binsparse, "version"); + + assert(version_ != NULL); + + assert(cJSON_IsString(version_)); + + // TODO: check version. + + cJSON* format_ = cJSON_GetObjectItemCaseSensitive(binsparse, "format"); + assert(format_ != NULL); + char* format_string = cJSON_GetStringValue(format_); + + bsp_matrix_format_t format = bsp_get_matrix_format(format_string); + + assert(format != 0); + + matrix.format = format; + + cJSON* nnz_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); + assert(nnz_ != NULL); + size_t nnz = cJSON_GetNumberValue(nnz_); + + cJSON* shape_ = cJSON_GetObjectItemCaseSensitive(binsparse, "shape"); + assert(shape_ != NULL); + + assert(cJSON_GetArraySize(shape_) == 2); + + cJSON* nrows_ = cJSON_GetArrayItem(shape_, 0); + assert(nrows_ != NULL); + + size_t nrows = cJSON_GetNumberValue(nrows_); + + cJSON* ncols_ = cJSON_GetArrayItem(shape_, 1); + assert(ncols_ != NULL); + + size_t ncols = cJSON_GetNumberValue(ncols_); + + matrix.nrows = nrows; + matrix.ncols = ncols; + matrix.nnz = nnz; + matrix.format = format; + + cJSON* data_types_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); + assert(data_types_ != NULL); + + if (cJSON_HasObjectItem(data_types_, "values")) { + matrix.values = bsp_read_array_parallel(f, (char*) "values", num_threads); + + cJSON* value_type = cJSON_GetObjectItemCaseSensitive(data_types_, "values"); + char* type_string = cJSON_GetStringValue(value_type); + + if (strlen(type_string) >= 4 && strncmp(type_string, "iso[", 4) == 0) { + matrix.is_iso = true; + type_string += 4; + } + + if (strlen(type_string) >= 8 && strncmp(type_string, "complex[", 8) == 0) { + matrix.values = bsp_fp_array_to_complex(matrix.values); + } + } + + if (cJSON_HasObjectItem(data_types_, "indices_0")) { + matrix.indices_0 = + bsp_read_array_parallel(f, (char*) "indices_0", num_threads); + } + + if (cJSON_HasObjectItem(data_types_, "indices_1")) { + matrix.indices_1 = + bsp_read_array_parallel(f, (char*) "indices_1", num_threads); + } + + if (cJSON_HasObjectItem(data_types_, "pointers_to_1")) { + matrix.pointers_to_1 = + bsp_read_array_parallel(f, (char*) "pointers_to_1", num_threads); + } + + if (cJSON_HasObjectItem(binsparse, "structure")) { + cJSON* structure_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "structure"); + char* structure = cJSON_GetStringValue(structure_); + matrix.structure = bsp_get_structure(structure); + } + + cJSON_Delete(j); + free(json_string); + + return matrix; +} +#endif + +bsp_matrix_t bsp_read_matrix_from_group(hid_t f) { + bsp_matrix_t matrix = bsp_construct_default_matrix_t(); + + char* json_string = bsp_read_attribute(f, (char*) "binsparse"); + + cJSON* j = cJSON_Parse(json_string); + + assert(j != NULL); + assert(cJSON_IsObject(j)); + + cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); + assert(cJSON_IsObject(binsparse)); + + cJSON* version_ = cJSON_GetObjectItemCaseSensitive(binsparse, "version"); + + assert(version_ != NULL); + + assert(cJSON_IsString(version_)); + + // TODO: check version. + + cJSON* format_ = cJSON_GetObjectItemCaseSensitive(binsparse, "format"); + assert(format_ != NULL); + char* format_string = cJSON_GetStringValue(format_); + + bsp_matrix_format_t format = bsp_get_matrix_format(format_string); + + assert(format != 0); + + matrix.format = format; + + cJSON* nnz_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); + assert(nnz_ != NULL); + size_t nnz = cJSON_GetNumberValue(nnz_); + + cJSON* shape_ = cJSON_GetObjectItemCaseSensitive(binsparse, "shape"); + assert(shape_ != NULL); + + assert(cJSON_GetArraySize(shape_) == 2); + + cJSON* nrows_ = cJSON_GetArrayItem(shape_, 0); + assert(nrows_ != NULL); + + size_t nrows = cJSON_GetNumberValue(nrows_); + + cJSON* ncols_ = cJSON_GetArrayItem(shape_, 1); + assert(ncols_ != NULL); + + size_t ncols = cJSON_GetNumberValue(ncols_); + + matrix.nrows = nrows; + matrix.ncols = ncols; + matrix.nnz = nnz; + matrix.format = format; + + cJSON* data_types_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); + assert(data_types_ != NULL); + + if (cJSON_HasObjectItem(data_types_, "values")) { + matrix.values = bsp_read_array(f, (char*) "values"); + + cJSON* value_type = cJSON_GetObjectItemCaseSensitive(data_types_, "values"); + char* type_string = cJSON_GetStringValue(value_type); + + if (strlen(type_string) >= 4 && strncmp(type_string, "iso[", 4) == 0) { + matrix.is_iso = true; + type_string += 4; + } + + if (strlen(type_string) >= 8 && strncmp(type_string, "complex[", 8) == 0) { + matrix.values = bsp_fp_array_to_complex(matrix.values); + } + } + + if (cJSON_HasObjectItem(data_types_, "indices_0")) { + matrix.indices_0 = bsp_read_array(f, (char*) "indices_0"); + } + + if (cJSON_HasObjectItem(data_types_, "indices_1")) { + matrix.indices_1 = bsp_read_array(f, (char*) "indices_1"); + } + + if (cJSON_HasObjectItem(data_types_, "pointers_to_1")) { + matrix.pointers_to_1 = bsp_read_array(f, (char*) "pointers_to_1"); + } + + if (cJSON_HasObjectItem(binsparse, "structure")) { + cJSON* structure_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "structure"); + char* structure = cJSON_GetStringValue(structure_); + matrix.structure = bsp_get_structure(structure); + } + + cJSON_Delete(j); + free(json_string); + + return matrix; +} + +static inline size_t bsp_final_dot(const char* str) { + size_t dot_idx = 0; + for (size_t i = 0; str[i] != '\0'; i++) { + if (str[i] == '.') { + dot_idx = i; + } + } + return dot_idx; +} + +#if __STDC_VERSION__ >= 201112L +bsp_matrix_t bsp_read_matrix_parallel(const char* file_name, const char* group, + int num_threads) { + if (group == NULL) { + size_t idx = bsp_final_dot(file_name); + if (strcmp(file_name + idx, ".hdf5") == 0 || + strcmp(file_name + idx, ".h5") == 0) { + hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); + bsp_matrix_t matrix = bsp_read_matrix_from_group_parallel(f, num_threads); + H5Fclose(f); + return matrix; + } else if (strcmp(file_name + idx, ".mtx") == 0) { + return bsp_mmread(file_name); + } else { + assert(false); + } + } else { + hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); + hid_t g = H5Gopen1(f, group); + bsp_matrix_t matrix = bsp_read_matrix_from_group_parallel(g, num_threads); + H5Gclose(g); + H5Fclose(f); + return matrix; + } +} +#endif + +bsp_matrix_t bsp_read_matrix(const char* file_name, const char* group) { + if (group == NULL) { + size_t idx = bsp_final_dot(file_name); + if (strcmp(file_name + idx, ".hdf5") == 0 || + strcmp(file_name + idx, ".h5") == 0) { + hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); + bsp_matrix_t matrix = bsp_read_matrix_from_group(f); + H5Fclose(f); + return matrix; + } else if (strcmp(file_name + idx, ".mtx") == 0) { + return bsp_mmread(file_name); + } else { + assert(false); + } + } else { + hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); + hid_t g = H5Gopen1(f, group); + bsp_matrix_t matrix = bsp_read_matrix_from_group(g); + H5Gclose(g); + H5Fclose(f); + return matrix; + } +} From d9f61bf94fdfed2cd800e7559f0869a7f955497c Mon Sep 17 00:00:00 2001 From: Benjamin Brock Date: Thu, 24 Oct 2024 16:55:28 -0700 Subject: [PATCH 5/5] Make `write_matrix` separately compiled --- include/binsparse/convert_matrix.h | 4 +- include/binsparse/write_matrix.h | 147 +++------------------------- src/CMakeLists.txt | 1 + src/write_matrix.c | 148 +++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 135 deletions(-) create mode 100644 src/write_matrix.c diff --git a/include/binsparse/convert_matrix.h b/include/binsparse/convert_matrix.h index d7b2e6f..2f6c332 100644 --- a/include/binsparse/convert_matrix.h +++ b/include/binsparse/convert_matrix.h @@ -9,8 +9,8 @@ #include #include -bsp_matrix_t bsp_convert_matrix(bsp_matrix_t matrix, - bsp_matrix_format_t format) { +static inline bsp_matrix_t bsp_convert_matrix(bsp_matrix_t matrix, + bsp_matrix_format_t format) { // Throw an error if matrix already in desired format. if (matrix.format == format) { assert(false); diff --git a/include/binsparse/write_matrix.h b/include/binsparse/write_matrix.h index e07cedd..53b89f5 100644 --- a/include/binsparse/write_matrix.h +++ b/include/binsparse/write_matrix.h @@ -6,144 +6,25 @@ #pragma once -#include -#include -#include -#include - -char* bsp_generate_json(bsp_matrix_t matrix, cJSON* user_json) { - cJSON* j = cJSON_CreateObject(); - assert(j != NULL); - - cJSON* binsparse = cJSON_CreateObject(); - - assert(binsparse != NULL); - - cJSON_AddItemToObject(j, "binsparse", binsparse); - - cJSON* item; - cJSON_ArrayForEach(item, user_json) { - cJSON_AddItemToObject(j, item->string, item); - } - - cJSON_AddStringToObject(binsparse, "version", BINSPARSE_VERSION); - - cJSON_AddStringToObject(binsparse, "format", - bsp_get_matrix_format_string(matrix.format)); - - cJSON* shape = cJSON_AddArrayToObject(binsparse, "shape"); - - cJSON* nrows = cJSON_CreateNumber(matrix.nrows); - cJSON* ncols = cJSON_CreateNumber(matrix.ncols); - - cJSON_AddItemToArray(shape, nrows); - cJSON_AddItemToArray(shape, ncols); - - cJSON_AddNumberToObject(binsparse, "number_of_stored_values", matrix.nnz); - - cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); - - if (!matrix.is_iso) { - cJSON_AddStringToObject(data_types, "values", - bsp_get_type_string(matrix.values.type)); - } else { - char* base_type_string = bsp_get_type_string(matrix.values.type); - size_t len = strlen(base_type_string) + 6; - char* type_string = (char*) malloc(sizeof(char) * len); - - strncpy(type_string, "iso[", len); - strncpy(type_string + 4, base_type_string, len - 4); - strncpy(type_string + len - 2, "]", 2); - - cJSON_AddStringToObject(data_types, "values", type_string); +#ifdef __cplusplus +extern "C" { +#endif - free(type_string); - } +// TODO: make cJSON optional. - if (matrix.indices_0.data != NULL) { - cJSON_AddStringToObject(data_types, "indices_0", - bsp_get_type_string(matrix.indices_0.type)); - } - - if (matrix.indices_1.data != NULL) { - cJSON_AddStringToObject(data_types, "indices_1", - bsp_get_type_string(matrix.indices_1.type)); - } - - if (matrix.pointers_to_1.data != NULL) { - cJSON_AddStringToObject(data_types, "pointers_to_1", - bsp_get_type_string(matrix.pointers_to_1.type)); - } - - if (matrix.structure != BSP_GENERAL) { - cJSON_AddStringToObject(binsparse, "structure", - bsp_get_structure_string(matrix.structure)); - } - - char* string = cJSON_Print(j); - - cJSON_Delete(j); +#include +#include - return string; -} +#ifdef BSP_USE_HDF5 +#include int bsp_write_matrix_to_group(hid_t f, bsp_matrix_t matrix, cJSON* user_json, - int compression_level) { - int result = - bsp_write_array(f, (char*) "values", matrix.values, compression_level); - - if (result != 0) - return result; - - if (matrix.indices_0.size > 0) { - result = bsp_write_array(f, (char*) "indices_0", matrix.indices_0, - compression_level); - if (result != 0) { - return result; - } - } - - if (matrix.indices_1.size > 0) { - result = bsp_write_array(f, (char*) "indices_1", matrix.indices_1, - compression_level); - if (result != 0) { - return result; - } - } - - if (matrix.pointers_to_1.size > 0) { - result = bsp_write_array(f, (char*) "pointers_to_1", matrix.pointers_to_1, - compression_level); - if (result != 0) { - return result; - } - } - - char* json_string = bsp_generate_json(matrix, user_json); - - bsp_write_attribute(f, (char*) "binsparse", json_string); - free(json_string); - - return 0; -} + int compression_level); +#endif int bsp_write_matrix(const char* fname, bsp_matrix_t matrix, const char* group, - cJSON* user_json, int compression_level) { - if (group == NULL) { - hid_t f = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - bsp_write_matrix_to_group(f, matrix, user_json, compression_level); - H5Fclose(f); - } else { - hid_t f; - if (access(fname, F_OK) == 0) { - f = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT); - } else { - f = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - } - hid_t g = H5Gcreate1(f, group, H5P_DEFAULT); - bsp_write_matrix_to_group(g, matrix, user_json, compression_level); - H5Gclose(g); - H5Fclose(f); - } - return 0; + cJSON* user_json, int compression_level); + +#ifdef __cplusplus } +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f0bbcb..50ffb26 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,4 +4,5 @@ target_sources(binsparse-rc PRIVATE src/read_matrix.c + src/write_matrix.c ) diff --git a/src/write_matrix.c b/src/write_matrix.c new file mode 100644 index 0000000..7c012b0 --- /dev/null +++ b/src/write_matrix.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +char* bsp_generate_json(bsp_matrix_t matrix, cJSON* user_json) { + cJSON* j = cJSON_CreateObject(); + assert(j != NULL); + + cJSON* binsparse = cJSON_CreateObject(); + + assert(binsparse != NULL); + + cJSON_AddItemToObject(j, "binsparse", binsparse); + + cJSON* item; + cJSON_ArrayForEach(item, user_json) { + cJSON_AddItemToObject(j, item->string, item); + } + + cJSON_AddStringToObject(binsparse, "version", BINSPARSE_VERSION); + + cJSON_AddStringToObject(binsparse, "format", + bsp_get_matrix_format_string(matrix.format)); + + cJSON* shape = cJSON_AddArrayToObject(binsparse, "shape"); + + cJSON* nrows = cJSON_CreateNumber(matrix.nrows); + cJSON* ncols = cJSON_CreateNumber(matrix.ncols); + + cJSON_AddItemToArray(shape, nrows); + cJSON_AddItemToArray(shape, ncols); + + cJSON_AddNumberToObject(binsparse, "number_of_stored_values", matrix.nnz); + + cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); + + if (!matrix.is_iso) { + cJSON_AddStringToObject(data_types, "values", + bsp_get_type_string(matrix.values.type)); + } else { + char* base_type_string = bsp_get_type_string(matrix.values.type); + size_t len = strlen(base_type_string) + 6; + char* type_string = (char*) malloc(sizeof(char) * len); + + strncpy(type_string, "iso[", len); + strncpy(type_string + 4, base_type_string, len - 4); + strncpy(type_string + len - 2, "]", 2); + + cJSON_AddStringToObject(data_types, "values", type_string); + + free(type_string); + } + + if (matrix.indices_0.data != NULL) { + cJSON_AddStringToObject(data_types, "indices_0", + bsp_get_type_string(matrix.indices_0.type)); + } + + if (matrix.indices_1.data != NULL) { + cJSON_AddStringToObject(data_types, "indices_1", + bsp_get_type_string(matrix.indices_1.type)); + } + + if (matrix.pointers_to_1.data != NULL) { + cJSON_AddStringToObject(data_types, "pointers_to_1", + bsp_get_type_string(matrix.pointers_to_1.type)); + } + + if (matrix.structure != BSP_GENERAL) { + cJSON_AddStringToObject(binsparse, "structure", + bsp_get_structure_string(matrix.structure)); + } + + char* string = cJSON_Print(j); + + cJSON_Delete(j); + + return string; +} + +int bsp_write_matrix_to_group(hid_t f, bsp_matrix_t matrix, cJSON* user_json, + int compression_level) { + int result = + bsp_write_array(f, (char*) "values", matrix.values, compression_level); + + if (result != 0) + return result; + + if (matrix.indices_0.size > 0) { + result = bsp_write_array(f, (char*) "indices_0", matrix.indices_0, + compression_level); + if (result != 0) { + return result; + } + } + + if (matrix.indices_1.size > 0) { + result = bsp_write_array(f, (char*) "indices_1", matrix.indices_1, + compression_level); + if (result != 0) { + return result; + } + } + + if (matrix.pointers_to_1.size > 0) { + result = bsp_write_array(f, (char*) "pointers_to_1", matrix.pointers_to_1, + compression_level); + if (result != 0) { + return result; + } + } + + char* json_string = bsp_generate_json(matrix, user_json); + + bsp_write_attribute(f, (char*) "binsparse", json_string); + free(json_string); + + return 0; +} + +int bsp_write_matrix(const char* fname, bsp_matrix_t matrix, const char* group, + cJSON* user_json, int compression_level) { + if (group == NULL) { + hid_t f = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + bsp_write_matrix_to_group(f, matrix, user_json, compression_level); + H5Fclose(f); + } else { + hid_t f; + if (access(fname, F_OK) == 0) { + f = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT); + } else { + f = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + } + hid_t g = H5Gcreate1(f, group, H5P_DEFAULT); + bsp_write_matrix_to_group(g, matrix, user_json, compression_level); + H5Gclose(g); + H5Fclose(f); + } + return 0; +}