From e6ffb126a539e80207ff48b3499bc51843023902 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Wed, 12 Feb 2025 21:10:22 -0500 Subject: [PATCH 01/24] dev environment --- compile_flags.txt | 2 ++ dev.sh | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 compile_flags.txt create mode 100755 dev.sh diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..449b102 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,2 @@ +-I./include +-I./build/include diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..a86d79b --- /dev/null +++ b/dev.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env sh + +CONTAINER='binsparse-reference-c' +IMAGE='docker.io/junikimm717/nvim2025:finch' +DIR="$(realpath "$(dirname "$0")")" + +case "$1" in + pull|p) + podman pull "$IMAGE" + (podman container ls | grep "$CONTAINER" > /dev/null 2>&1) && podman container rm -fv "$CONTAINER" + ;; + clear|c) + (podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1)\ + && { + podman container kill "$CONTAINER" > /dev/null 2>&1; + podman container rm "$CONTAINER" + } + ;; + *) + set +x + if ! (podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1); then + podman run\ + -dt\ + --name "$CONTAINER"\ + --group-add keep-groups\ + -v "$DIR:/workspace"\ + --privileged\ + --rm\ + "$IMAGE" + fi || exit 1 + podman exec\ + -e ENV=/root/.profile\ + -it "$CONTAINER" /bin/bash + ;; +esac From 388acbdd896989364f25fe8ffd3d76072c803140 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Sat, 15 Feb 2025 18:20:25 -0500 Subject: [PATCH 02/24] read tensor implemented --- compile_flags.txt | 2 + include/binsparse/read_tensor.h | 17 +++ include/binsparse/tensor.h | 84 ++++++++++++++ src/CMakeLists.txt | 1 + src/read_matrix.c | 1 + src/read_tensor.c | 194 ++++++++++++++++++++++++++++++++ 6 files changed, 299 insertions(+) create mode 100644 include/binsparse/read_tensor.h create mode 100644 include/binsparse/tensor.h create mode 100644 src/read_tensor.c diff --git a/compile_flags.txt b/compile_flags.txt index 449b102..ba24856 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,2 +1,4 @@ -I./include -I./build/include +-DBSP_USE_HDF5 +-I/usr/include/hdf5/serial diff --git a/include/binsparse/read_tensor.h b/include/binsparse/read_tensor.h new file mode 100644 index 0000000..0e9a2f9 --- /dev/null +++ b/include/binsparse/read_tensor.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef BSP_USE_HDF5 +#include <hdf5.h> + +bsp_tensor_t bsp_read_tensor_from_group(hid_t f); +#endif + +bsp_tensor_t bsp_read_tensor(const char* file_name, const char* group); + +#ifdef __cplusplus +} +#endif diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h new file mode 100644 index 0000000..e70ef04 --- /dev/null +++ b/include/binsparse/tensor.h @@ -0,0 +1,84 @@ +#pragma once + +#include <binsparse/array.h> +#include <binsparse/structure.h> + +typedef enum { + BSP_TENSOR_SPARSE = 0, + BSP_TENSOR_DENSE = 1, + BSP_TENSOR_ELEMENT = 2, +} bsp_level_kind_t; + +typedef struct { + bsp_level_kind_t kind; + // data here should be bsp_element_t*, bsp_sparse_t*, or bsp_dense_t* + void* data; +} bsp_level_t; + +// corresponds to BSP_TENSOR_ELEMENT +typedef struct { + bsp_array_t values; +} bsp_element_t; + +// corresponds to BSP_TENSOR_DENSE +typedef struct { + int rank; + bsp_array_t pointers_to; + bsp_array_t* indices; + bsp_level_t* child; +} bsp_sparse_t; + +typedef struct { + int rank; + bsp_level_t* child; +} bsp_dense_t; + +typedef struct { + int rank; + size_t* dims; + size_t nnz; + bool is_iso; + + bsp_level_t* level; + // don't think too much about this at the moment. + bsp_structure_t structure; +} bsp_tensor_t; + +static inline bsp_tensor_t bsp_construct_default_tensor_t() { + bsp_tensor_t tensor; + tensor.structure = BSP_GENERAL; + tensor.is_iso = false; + tensor.nnz = tensor.rank = 0; + tensor.dims = NULL; + + tensor.level = NULL; + return tensor; +} + +static void bsp_destroy_level_t(bsp_level_t* level) { + switch (level->kind) { + case BSP_TENSOR_ELEMENT:; + bsp_element_t* element = level->data; + bsp_destroy_array_t(element->values); + free(element); + break; + case BSP_TENSOR_DENSE:; + bsp_dense_t* dense = level->data; + bsp_destroy_level_t(dense->child); + free(dense); + break; + case BSP_TENSOR_SPARSE:; + bsp_sparse_t* sparse = level->data; + bsp_destroy_array_t(*sparse->indices); + bsp_destroy_array_t(*sparse->pointers_to); + bsp_destroy_level_t(sparse->child); + free(sparse); + break; + default:; + } +} + +static inline void bsp_destroy_tensor_t(bsp_tensor_t tensor) { + bsp_destroy_level_t(tensor.level); + free(tensor.dims); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50ffb26..22a19ff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,5 +4,6 @@ target_sources(binsparse-rc PRIVATE src/read_matrix.c + src/read_tensor.c src/write_matrix.c ) diff --git a/src/read_matrix.c b/src/read_matrix.c index 464210c..bf2b96d 100644 --- a/src/read_matrix.c +++ b/src/read_matrix.c @@ -143,6 +143,7 @@ bsp_matrix_t bsp_read_matrix_from_group(hid_t f) { bsp_matrix_format_t format = bsp_get_matrix_format(format_string); + // isn't this never true? assert(format != 0); matrix.format = format; diff --git a/src/read_tensor.c b/src/read_tensor.c new file mode 100644 index 0000000..5ee7dea --- /dev/null +++ b/src/read_tensor.c @@ -0,0 +1,194 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <binsparse/hdf5_wrapper.h> +#include <binsparse/matrix.h> +#include <binsparse/matrix_market/matrix_market_read.h> +#include <binsparse/tensor.h> +#include <cJSON/cJSON.h> +#include <math.h> +#include <string.h> + +static char* key_with_index(const char* key, size_t index) { + int keylen = strlen(key); + int strsize = keylen * sizeof(char) + + (int) ((ceil(log10(index + 1)) + 1) * sizeof(char)); + char* res = (char*) malloc(strsize); + for (int i = 0; i < keylen; i++) { + res[i] = key[i]; + } + sprintf(res + keylen, "%ld", index); + res[strsize] = '\0'; + return res; +} + +bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { + bsp_tensor_t tensor = bsp_construct_default_tensor_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_); + + // nnz computation + cJSON* nnz_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); + assert(nnz_ != NULL); + size_t nnz = cJSON_GetNumberValue(nnz_); + tensor.nnz = nnz; + + // check tensor shape. + cJSON* shape_ = cJSON_GetObjectItemCaseSensitive(binsparse, "shape"); + assert(shape_ != NULL); + tensor.rank = cJSON_GetArraySize(shape_); + size_t* dims = (size_t*) malloc(tensor.rank * sizeof(size_t)); + for (int idx = 0; idx < tensor.rank; idx++) { + dims[idx] = cJSON_GetNumberValue(cJSON_GetArrayItem(shape_, idx)); + } + tensor.dims = dims; + assert(tensor.rank > 0); + + cJSON* data_types_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); + assert(data_types_ != NULL); + + cJSON* binsparse_tensor = + cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); + assert(binsparse_tensor != NULL); + cJSON* json_level = + cJSON_GetObjectItemCaseSensitive(binsparse_tensor, "level"); + assert(json_level != NULL); + + bsp_level_t* cur_level = malloc(sizeof(bsp_level_t)); + tensor.level = cur_level; + + // this is effectively a pointer on dims. + size_t depth = 0; + + while (depth < tensor.rank + 1) { + cJSON* type_object = + cJSON_GetObjectItemCaseSensitive(json_level, "level_kind"); + char* type = type_object ? cJSON_GetStringValue(type_object) : NULL; + assert(type != NULL); + + // base case: working with an element. + if (strcmp(type, "element") == 0) { + bsp_array_t values = bsp_read_array(f, (char*) "values"); + cur_level->kind = BSP_TENSOR_ELEMENT; + bsp_element_t* data = malloc(sizeof(bsp_element_t)); + data->values = values; + cur_level->data = data; + depth++; + break; + } + + // compute what the rank of our current level is, and update our pointer + // accordingly. + cJSON* rank_obj = cJSON_GetObjectItemCaseSensitive(json_level, "rank"); + int rank = cJSON_GetNumberValue(rank_obj); + + if (strcmp(type, "dense") == 0) { + cur_level->kind = BSP_TENSOR_DENSE; + + bsp_dense_t* data = malloc(sizeof(bsp_dense_t)); + data->rank = rank; + data->child = malloc(sizeof(bsp_level_t)); + + cur_level->data = data; + cur_level = data->child; + } else if (strcmp(type, "sparse") == 0) { + cur_level->kind = BSP_TENSOR_SPARSE; + + bsp_sparse_t* data = malloc(sizeof(bsp_sparse_t)); + + // initialize pointers_to. + { + char* pointers_key = key_with_index("pointers_to_", depth); + data->pointers_to = bsp_read_array(f, pointers_key); + free(pointers_key); + } + + // initialize indices + data->indices = malloc(rank * sizeof(bsp_array_t)); + for (int idx = 0; idx < rank; idx++) { + char* indices_key = key_with_index("indices_", depth + rank); + data->indices[idx] = bsp_read_array(f, indices_key); + free(indices_key); + } + + data->rank = rank; + data->child = malloc(sizeof(bsp_level_t)); + cur_level->data = data; + cur_level = data->child; + + } else { + assert(false); + } + // update the depth here. + depth += rank; + } + if (cJSON_HasObjectItem(binsparse, "structure")) { + cJSON* structure_ = + cJSON_GetObjectItemCaseSensitive(binsparse, "structure"); + char* structure = cJSON_GetStringValue(structure_); + tensor.structure = bsp_get_structure(structure); + } + + cJSON_Delete(j); + free(json_string); + + return tensor; +} + +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; +} + +bsp_tensor_t bsp_read_tensor(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_tensor_t tensor = bsp_read_tensor_from_group(f); + H5Fclose(f); + return tensor; + } else { + assert(false); + } + } else { + hid_t f = H5Fopen(file_name, H5F_ACC_RDONLY, H5P_DEFAULT); + hid_t g = H5Gopen1(f, group); + bsp_tensor_t matrix = bsp_read_tensor_from_group(g); + H5Gclose(g); + H5Fclose(f); + return matrix; + } +} From 29a58e72511759908139513435ddf8c1c3e9d2e7 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Wed, 19 Feb 2025 17:58:33 -0500 Subject: [PATCH 03/24] segfault debugging --- examples/CMakeLists.txt | 1 + examples/tensor_test.c | 19 +++++++++++++++++++ include/binsparse/read_tensor.h | 2 ++ include/binsparse/tensor.h | 14 +++++++++++--- src/read_tensor.c | 27 +++++++++++++++------------ 5 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 examples/tensor_test.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7e5bbd1..1df709c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -19,5 +19,6 @@ add_example(bsp-ls) add_example(benchmark_read) add_example(benchmark_read_parallel) add_example(benchmark_write) +add_example(tensor_test) add_subdirectory(cpp) diff --git a/examples/tensor_test.c b/examples/tensor_test.c new file mode 100644 index 0000000..091367f --- /dev/null +++ b/examples/tensor_test.c @@ -0,0 +1,19 @@ +#include<binsparse/tensor.h> +#include<binsparse/read_tensor.h> + +int main(int argc, char **argv) { + if (argc < 2) { + fprintf(stderr, "usage: ./tensor_test [file_name.h5]\n"); + return 1; + } + char* file_name = argv[1]; + bsp_tensor_t tensor = bsp_read_tensor(file_name, NULL); + printf("rank: %d\n", tensor.rank); + printf("dims:"); + for (int i = 0; i < tensor.rank; i++) { + printf("%ld, ", tensor.dims[i]); + } + printf("\n"); + bsp_destroy_tensor_t(tensor); + return 0; +} diff --git a/include/binsparse/read_tensor.h b/include/binsparse/read_tensor.h index 0e9a2f9..9d419ec 100644 --- a/include/binsparse/read_tensor.h +++ b/include/binsparse/read_tensor.h @@ -4,6 +4,8 @@ extern "C" { #endif +char* key_with_index(const char* key, size_t index); + #ifdef BSP_USE_HDF5 #include <hdf5.h> diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index e70ef04..9fa577e 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -23,7 +23,7 @@ typedef struct { // corresponds to BSP_TENSOR_DENSE typedef struct { int rank; - bsp_array_t pointers_to; + bsp_array_t* pointers_to; bsp_array_t* indices; bsp_level_t* child; } bsp_sparse_t; @@ -56,6 +56,8 @@ static inline bsp_tensor_t bsp_construct_default_tensor_t() { } static void bsp_destroy_level_t(bsp_level_t* level) { + if (level == NULL) + return; switch (level->kind) { case BSP_TENSOR_ELEMENT:; bsp_element_t* element = level->data; @@ -69,8 +71,14 @@ static void bsp_destroy_level_t(bsp_level_t* level) { break; case BSP_TENSOR_SPARSE:; bsp_sparse_t* sparse = level->data; - bsp_destroy_array_t(*sparse->indices); - bsp_destroy_array_t(*sparse->pointers_to); + + if (sparse->pointers_to != NULL) + bsp_destroy_array_t(*sparse->pointers_to); + if (sparse->indices != NULL) { + for (int i = 0; i < sparse->rank; i++) { + bsp_destroy_array_t(sparse->indices[i]); + } + } bsp_destroy_level_t(sparse->child); free(sparse); break; diff --git a/src/read_tensor.c b/src/read_tensor.c index 5ee7dea..48996d5 100644 --- a/src/read_tensor.c +++ b/src/read_tensor.c @@ -13,10 +13,13 @@ #include <math.h> #include <string.h> -static char* key_with_index(const char* key, size_t index) { +/* +Returns "{key}-{index}" +*/ +char* key_with_index(const char* key, size_t index) { int keylen = strlen(key); int strsize = keylen * sizeof(char) + - (int) ((ceil(log10(index + 1)) + 1) * sizeof(char)); + (int) ((ceil(log10(index + 1)) + 1) * sizeof(char)) + 1; char* res = (char*) malloc(strsize); for (int i = 0; i < keylen; i++) { res[i] = key[i]; @@ -45,12 +48,6 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { assert(cJSON_IsString(version_)); - // TODO: check version. - - cJSON* format_ = cJSON_GetObjectItemCaseSensitive(binsparse, "format"); - assert(format_ != NULL); - char* format_string = cJSON_GetStringValue(format_); - // nnz computation cJSON* nnz_ = cJSON_GetObjectItemCaseSensitive(binsparse, "number_of_stored_values"); @@ -117,22 +114,26 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { cur_level->data = data; cur_level = data->child; + } else if (strcmp(type, "sparse") == 0) { cur_level->kind = BSP_TENSOR_SPARSE; bsp_sparse_t* data = malloc(sizeof(bsp_sparse_t)); - // initialize pointers_to. - { + // initialize pointers_to, but only if the depth is not zero. + if (depth != 0) { char* pointers_key = key_with_index("pointers_to_", depth); - data->pointers_to = bsp_read_array(f, pointers_key); + data->pointers_to = malloc(sizeof(bsp_array_t)); + *data->pointers_to = bsp_read_array(f, pointers_key); free(pointers_key); + } else { + data->pointers_to = NULL; } // initialize indices data->indices = malloc(rank * sizeof(bsp_array_t)); for (int idx = 0; idx < rank; idx++) { - char* indices_key = key_with_index("indices_", depth + rank); + char* indices_key = key_with_index("indices_", depth + idx); data->indices[idx] = bsp_read_array(f, indices_key); free(indices_key); } @@ -146,6 +147,8 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { assert(false); } // update the depth here. + json_level = cJSON_GetObjectItemCaseSensitive(json_level, "level"); + assert(json_level != NULL); depth += rank; } if (cJSON_HasObjectItem(binsparse, "structure")) { From 436863e6e527a1aa9f615593acd18c061c231d3f Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Wed, 19 Feb 2025 21:51:08 -0500 Subject: [PATCH 04/24] tensor writer implemented TODO: you need to apparently set the format key. --- examples/tensor_test.c | 14 +-- include/binsparse/tensor.h | 23 +++++ include/binsparse/write_tensor.h | 30 +++++++ src/CMakeLists.txt | 1 + src/write_tensor.c | 143 +++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 include/binsparse/write_tensor.h create mode 100644 src/write_tensor.c diff --git a/examples/tensor_test.c b/examples/tensor_test.c index 091367f..bfa0bfc 100644 --- a/examples/tensor_test.c +++ b/examples/tensor_test.c @@ -1,19 +1,21 @@ -#include<binsparse/tensor.h> -#include<binsparse/read_tensor.h> +#include <binsparse/tensor.h> +#include <binsparse/read_tensor.h> +#include <binsparse/write_tensor.h> -int main(int argc, char **argv) { - if (argc < 2) { - fprintf(stderr, "usage: ./tensor_test [file_name.h5]\n"); +int main(int argc, char** argv) { + if (argc < 3) { + fprintf(stderr, "usage: ./tensor_test [file_name.h5] [output_file_name.h5]\n"); return 1; } char* file_name = argv[1]; - bsp_tensor_t tensor = bsp_read_tensor(file_name, NULL); + bsp_tensor_t tensor = bsp_read_tensor(argv[1], NULL); printf("rank: %d\n", tensor.rank); printf("dims:"); for (int i = 0; i < tensor.rank; i++) { printf("%ld, ", tensor.dims[i]); } printf("\n"); + bsp_write_tensor(argv[2], tensor, NULL, NULL, 9); bsp_destroy_tensor_t(tensor); return 0; } diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 9fa577e..32e16a3 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -86,6 +86,29 @@ static void bsp_destroy_level_t(bsp_level_t* level) { } } +static bsp_array_t bsp_get_tensor_values(bsp_tensor_t tensor) { + bsp_level_t* level = tensor.level; + while (level != NULL) { + switch (level->kind) { + case BSP_TENSOR_ELEMENT:; + bsp_element_t* element = level->data; + return element->values; + break; + case BSP_TENSOR_SPARSE:; + bsp_sparse_t* sparse = level->data; + level = sparse->child; + break; + case BSP_TENSOR_DENSE:; + bsp_dense_t* dense = level->data; + level = dense->child; + break; + default:; + } + } + // this should never happen! + assert(false); +} + static inline void bsp_destroy_tensor_t(bsp_tensor_t tensor) { bsp_destroy_level_t(tensor.level); free(tensor.dims); diff --git a/include/binsparse/write_tensor.h b/include/binsparse/write_tensor.h new file mode 100644 index 0000000..64497c2 --- /dev/null +++ b/include/binsparse/write_tensor.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// TODO: make cJSON optional. + +#include<binsparse/tensor.h> +#include <cJSON/cJSON.h> + +#ifdef BSP_USE_HDF5 +#include <hdf5.h> + +int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, + int compression_level); +#endif + +int bsp_write_tensor(const char* fname, bsp_tensor_t tensor, const char* group, + cJSON* user_json, int compression_level); + +#ifdef __cplusplus +} +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22a19ff..4f52770 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,4 +6,5 @@ target_sources(binsparse-rc PRIVATE src/read_matrix.c src/read_tensor.c src/write_matrix.c + src/write_tensor.c ) diff --git a/src/write_tensor.c b/src/write_tensor.c new file mode 100644 index 0000000..2c1a983 --- /dev/null +++ b/src/write_tensor.c @@ -0,0 +1,143 @@ +#include <assert.h> +#include <binsparse/tensor.h> +#include <unistd.h> + +#include <binsparse/binsparse.h> +#include <binsparse/read_tensor.h> +#include <cJSON/cJSON.h> + +static cJSON* init_tensor_json(bsp_tensor_t tensor, cJSON* user_json) { + cJSON* j = cJSON_CreateObject(); + assert(j != NULL); + + cJSON* binsparse = cJSON_CreateObject(); + + assert(binsparse != NULL); + + cJSON_AddItemToObject(j, "binsparse", binsparse); + + cJSON* userJsonItem; + + cJSON_ArrayForEach(userJsonItem, user_json) { + cJSON_AddItemToObject(j, userJsonItem->string, userJsonItem); + } + + cJSON_AddStringToObject(binsparse, "version", BINSPARSE_VERSION); + + cJSON* shape = cJSON_AddArrayToObject(binsparse, "shape"); + for (int i = 0; i < tensor.rank; i++) { + cJSON_AddItemToArray(shape, cJSON_CreateNumber(tensor.dims[i])); + } + + cJSON_AddNumberToObject(binsparse, "number_of_stored_values", tensor.nnz); + + if (tensor.structure != BSP_GENERAL) { + cJSON_AddStringToObject(binsparse, "structure", + bsp_get_structure_string(tensor.structure)); + } + + return j; +} + +int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, + int compression_level) { + // bsp_matrix_t matrix; + cJSON* j = init_tensor_json(tensor, user_json); + cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); + assert(binsparse != NULL); + cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); + bsp_array_t values = bsp_get_tensor_values(tensor); + + if (!tensor.is_iso) { + cJSON_AddStringToObject(data_types, "values", + bsp_get_type_string(values.type)); + } else { + char* base_type_string = bsp_get_type_string(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); + } + + // attempt to write an array. + int result = bsp_write_array(f, (char*) "values", values, compression_level); + if (result != 0) { + cJSON_Delete(j); + return result; + } + + int rank = 0; + bsp_level_t* level = tensor.level; + while (level->kind != BSP_TENSOR_ELEMENT) { + switch (level->kind) { + case BSP_TENSOR_SPARSE:; + bsp_sparse_t* sparse = level->data; + size_t layer_rank = sparse->rank; + if (sparse->pointers_to != NULL) { + cJSON_AddStringToObject(data_types, + key_with_index("pointers_to_", rank), + bsp_get_type_string(sparse->pointers_to->type)); + result = bsp_write_array(f, key_with_index("pointers_to_", rank), + *sparse->pointers_to, compression_level); + if (result != 0) { + cJSON_Delete(j); + return result; + } + } + + for (int i = 0; i < layer_rank; i++) { + cJSON_AddStringToObject(data_types, + key_with_index("indices_", rank + i), + bsp_get_type_string(sparse->indices[i].type)); + result = bsp_write_array(f, key_with_index("indices_", rank + i), + sparse->indices[i], compression_level); + if (result != 0) { + cJSON_Delete(j); + return result; + } + } + + rank += layer_rank; + level = sparse->child; + break; + case BSP_TENSOR_DENSE:; + rank += ((bsp_dense_t*) level->data)->rank; + level = ((bsp_dense_t*) level->data)->child; + break; + default:; + } + } + + char* json_string = cJSON_Print(j); + bsp_write_attribute(f, (char*) "binsparse", json_string); + free(json_string); + + return 0; +} + +int bsp_write_tensor(const char* fname, bsp_tensor_t tensor, 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_tensor_to_group(f, tensor, 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_tensor_to_group(g, tensor, user_json, compression_level); + H5Gclose(g); + H5Fclose(f); + } + return 0; +} From 7150a6ef23b8913070ee341271952100dbbefa85 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Wed, 19 Feb 2025 23:40:52 -0500 Subject: [PATCH 05/24] tensor reader/writer successfully bootstrapped --- src/write_tensor.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/write_tensor.c b/src/write_tensor.c index 2c1a983..7a2ccc7 100644 --- a/src/write_tensor.c +++ b/src/write_tensor.c @@ -11,9 +11,12 @@ static cJSON* init_tensor_json(bsp_tensor_t tensor, cJSON* user_json) { assert(j != NULL); cJSON* binsparse = cJSON_CreateObject(); - assert(binsparse != NULL); + cJSON* binsparse_tensor = cJSON_CreateObject(); + assert(binsparse_tensor != NULL); + + cJSON_AddItemToObject(binsparse, "tensor", binsparse_tensor); cJSON_AddItemToObject(j, "binsparse", binsparse); cJSON* userJsonItem; @@ -43,8 +46,13 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, int compression_level) { // bsp_matrix_t matrix; cJSON* j = init_tensor_json(tensor, user_json); + // tensor: cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); assert(binsparse != NULL); + cJSON* binsparse_tensor = + cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); + assert(binsparse_tensor != NULL); + cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); bsp_array_t values = bsp_get_tensor_values(tensor); @@ -74,11 +82,16 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, int rank = 0; bsp_level_t* level = tensor.level; - while (level->kind != BSP_TENSOR_ELEMENT) { + cJSON* json_level = cJSON_AddObjectToObject(binsparse_tensor, "level"); + while (true) { + int reached_end = 0; switch (level->kind) { case BSP_TENSOR_SPARSE:; bsp_sparse_t* sparse = level->data; size_t layer_rank = sparse->rank; + cJSON_AddStringToObject(json_level, "level_kind", "sparse"); + cJSON_AddNumberToObject(json_level, "rank", layer_rank); + if (sparse->pointers_to != NULL) { cJSON_AddStringToObject(data_types, key_with_index("pointers_to_", rank), @@ -107,11 +120,22 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, level = sparse->child; break; case BSP_TENSOR_DENSE:; + cJSON_AddStringToObject(json_level, "level_kind", "dense"); + cJSON_AddNumberToObject(json_level, "rank", + ((bsp_dense_t*) level->data)->rank); rank += ((bsp_dense_t*) level->data)->rank; level = ((bsp_dense_t*) level->data)->child; break; + case BSP_TENSOR_ELEMENT:; + cJSON_AddStringToObject(json_level, "level_kind", "element"); + reached_end = 1; + break; default:; } + + if (reached_end) + break; + json_level = cJSON_AddObjectToObject(json_level, "level"); } char* json_string = cJSON_Print(j); From b1e6d12357719046d916ad11fe9f078396d96c51 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Thu, 20 Feb 2025 17:40:10 -0500 Subject: [PATCH 06/24] testing framework for tensor read/write implemented --- .gitignore | 1 + examples/cpp/CMakeLists.txt | 1 + examples/cpp/tensor_test.cpp | 1 + examples/simple_read.c | 2 +- include/binsparse/tensor.h | 30 ++++++++++------- src/write_tensor.c | 9 ++++-- test/CMakeLists.txt | 1 + test/julia/CMakeLists.txt | 13 ++++++++ test/julia/tensor_test.jl | 62 ++++++++++++++++++++++++++++++++++++ 9 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 examples/cpp/tensor_test.cpp create mode 100644 test/julia/CMakeLists.txt create mode 100644 test/julia/tensor_test.jl diff --git a/.gitignore b/.gitignore index a1e6811..bfb11fb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ scripts venv build ._* +tensor_test_files diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 2b8dcdf..d6ad9e1 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -15,5 +15,6 @@ add_example(mtx2bsp) add_example(bsp2mtx) add_example(check_equivalence) add_example(bsp-ls) +add_example(tensor_test) add_example(benchmark_read) add_example(benchmark_write) diff --git a/examples/cpp/tensor_test.cpp b/examples/cpp/tensor_test.cpp new file mode 100644 index 0000000..677d71e --- /dev/null +++ b/examples/cpp/tensor_test.cpp @@ -0,0 +1 @@ +#include "../tensor_test.c" diff --git a/examples/simple_read.c b/examples/simple_read.c index f2a1184..a4ba9bb 100644 --- a/examples/simple_read.c +++ b/examples/simple_read.c @@ -7,7 +7,7 @@ #include <binsparse/binsparse.h> int main(int argc, char** argv) { - char* file_name = "test.hdf5"; + char* file_name = (char*) "test.hdf5"; hid_t f = H5Fopen(file_name, H5F_ACC_RDWR, H5P_DEFAULT); diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 32e16a3..87c1b54 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -59,18 +59,20 @@ static void bsp_destroy_level_t(bsp_level_t* level) { if (level == NULL) return; switch (level->kind) { - case BSP_TENSOR_ELEMENT:; - bsp_element_t* element = level->data; + case BSP_TENSOR_ELEMENT: { + bsp_element_t* element = (bsp_element_t*) level->data; bsp_destroy_array_t(element->values); free(element); break; - case BSP_TENSOR_DENSE:; - bsp_dense_t* dense = level->data; + } + case BSP_TENSOR_DENSE: { + bsp_dense_t* dense = (bsp_dense_t*) level->data; bsp_destroy_level_t(dense->child); free(dense); break; - case BSP_TENSOR_SPARSE:; - bsp_sparse_t* sparse = level->data; + } + case BSP_TENSOR_SPARSE: { + bsp_sparse_t* sparse = (bsp_sparse_t*) level->data; if (sparse->pointers_to != NULL) bsp_destroy_array_t(*sparse->pointers_to); @@ -82,6 +84,7 @@ static void bsp_destroy_level_t(bsp_level_t* level) { bsp_destroy_level_t(sparse->child); free(sparse); break; + } default:; } } @@ -90,18 +93,21 @@ static bsp_array_t bsp_get_tensor_values(bsp_tensor_t tensor) { bsp_level_t* level = tensor.level; while (level != NULL) { switch (level->kind) { - case BSP_TENSOR_ELEMENT:; - bsp_element_t* element = level->data; + case BSP_TENSOR_ELEMENT: { + bsp_element_t* element = (bsp_element_t*) level->data; return element->values; break; - case BSP_TENSOR_SPARSE:; - bsp_sparse_t* sparse = level->data; + } + case BSP_TENSOR_SPARSE: { + bsp_sparse_t* sparse = (bsp_sparse_t*) level->data; level = sparse->child; break; - case BSP_TENSOR_DENSE:; - bsp_dense_t* dense = level->data; + } + case BSP_TENSOR_DENSE: { + bsp_dense_t* dense = (bsp_dense_t*) level->data; level = dense->child; break; + } default:; } } diff --git a/src/write_tensor.c b/src/write_tensor.c index 7a2ccc7..1d468a7 100644 --- a/src/write_tensor.c +++ b/src/write_tensor.c @@ -86,7 +86,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, while (true) { int reached_end = 0; switch (level->kind) { - case BSP_TENSOR_SPARSE:; + case BSP_TENSOR_SPARSE: { bsp_sparse_t* sparse = level->data; size_t layer_rank = sparse->rank; cJSON_AddStringToObject(json_level, "level_kind", "sparse"); @@ -119,17 +119,20 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, rank += layer_rank; level = sparse->child; break; - case BSP_TENSOR_DENSE:; + } + case BSP_TENSOR_DENSE: { cJSON_AddStringToObject(json_level, "level_kind", "dense"); cJSON_AddNumberToObject(json_level, "rank", ((bsp_dense_t*) level->data)->rank); rank += ((bsp_dense_t*) level->data)->rank; level = ((bsp_dense_t*) level->data)->child; break; - case BSP_TENSOR_ELEMENT:; + } + case BSP_TENSOR_ELEMENT: { cJSON_AddStringToObject(json_level, "level_kind", "element"); reached_end = 1; break; + } default:; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0dd7ef0..45ff378 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,3 +3,4 @@ # SPDX-License-Identifier: BSD-3-Clause add_subdirectory(bash) +add_subdirectory(julia) diff --git a/test/julia/CMakeLists.txt b/test/julia/CMakeLists.txt new file mode 100644 index 0000000..4c2c9d8 --- /dev/null +++ b/test/julia/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2024 Binsparse Developers +# +# SPDX-License-Identifier: BSD-3-Clause + +find_program(JULIA_PROGRAM julia) + +enable_testing() + +if(JULIA_PROGRAM) + add_test(NAME tensors.tensor_test COMMAND ${JULIA_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/tensor_test.jl) + + add_test(NAME tensors.cpp.tensor_test COMMAND ${JULIA_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/tensor_test.jl cpp) +endif() diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl new file mode 100644 index 0000000..04cb1d2 --- /dev/null +++ b/test/julia/tensor_test.jl @@ -0,0 +1,62 @@ +using Finch; +using HDF5; + +# dir = @__DIR__(); +dir = pwd(); + +print("Args:", ARGS, "\n"); + +if length(ARGS) == 0 + tensor_test = joinpath(dir, "../../examples/tensor_test") + test_files = joinpath(dir, "../../tensor_test_files") +else + tensor_test = joinpath(dir, "../../examples/cpp/tensor_test-cpp") + test_files = joinpath(dir, "../../tensor_test_files/cpp") +end + +mkpath(test_files) + +function tensortest(tensor::Tensor, input::AbstractString, output::AbstractString) + print("tensor_test ", input, " -> ", output, "\n") + fwrite(input, tensor) + run(`$tensor_test $input $output`) + new_tensor = fread(output) + # @assert new_tensor == tensor +end + +tensortest( + Tensor( + Dense(SparseList(SparseList(Element(0.0)))), + fsprand(10, 10, 10, 0.1) + ), + joinpath(test_files, "input1.bsp.h5"), + joinpath(test_files, "output1.bsp.h5") +) + + +tensortest( + Tensor( + Dense(SparseCOO{2}(Element(0.0))), + fsprand(10, 10, 10, 0.1) + ), + joinpath(test_files, "input2.bsp.h5"), + joinpath(test_files, "output2.bsp.h5") +) + +tensortest( + Tensor( + Dense(Dense(Dense(Element(0.0)))), + fsprand(10, 10, 10, 0.1) + ), + joinpath(test_files, "input3.bsp.h5"), + joinpath(test_files, "output3.bsp.h5") +) + +tensortest( + Tensor( + SparseCOO{2}(Element(0.0)), + fsprand(10, 10, 0.1) + ), + joinpath(test_files, "input4.bsp.h5"), + joinpath(test_files, "output4.bsp.h5") +) From 138647f3ba585f87532e64f5dc059b4fa19aae56 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Fri, 21 Feb 2025 08:27:43 -0500 Subject: [PATCH 07/24] tests fixed --- test/julia/tensor_test.jl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl index 04cb1d2..216a0ec 100644 --- a/test/julia/tensor_test.jl +++ b/test/julia/tensor_test.jl @@ -1,11 +1,8 @@ using Finch; using HDF5; -# dir = @__DIR__(); dir = pwd(); -print("Args:", ARGS, "\n"); - if length(ARGS) == 0 tensor_test = joinpath(dir, "../../examples/tensor_test") test_files = joinpath(dir, "../../tensor_test_files") @@ -20,8 +17,9 @@ function tensortest(tensor::Tensor, input::AbstractString, output::AbstractStrin print("tensor_test ", input, " -> ", output, "\n") fwrite(input, tensor) run(`$tensor_test $input $output`) - new_tensor = fread(output) - # @assert new_tensor == tensor + # for whatever reason, fread returns a swizzlearray + new_tensor = fread(output).body + @assert new_tensor == tensor end tensortest( From 3309097e4f7228e09cc6931704fd33058c2edeca Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Sat, 22 Feb 2025 11:50:49 -0500 Subject: [PATCH 08/24] parse transposes too --- include/binsparse/tensor.h | 5 ++++- src/read_tensor.c | 18 +++++++++++++++--- src/write_tensor.c | 17 +++++++++++------ test/julia/tensor_test.jl | 5 ++--- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 87c1b54..60dad01 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -36,6 +36,7 @@ typedef struct { typedef struct { int rank; size_t* dims; + size_t* transpose; size_t nnz; bool is_iso; @@ -50,6 +51,7 @@ static inline bsp_tensor_t bsp_construct_default_tensor_t() { tensor.is_iso = false; tensor.nnz = tensor.rank = 0; tensor.dims = NULL; + tensor.transpose = NULL; tensor.level = NULL; return tensor; @@ -117,5 +119,6 @@ static bsp_array_t bsp_get_tensor_values(bsp_tensor_t tensor) { static inline void bsp_destroy_tensor_t(bsp_tensor_t tensor) { bsp_destroy_level_t(tensor.level); - free(tensor.dims); + if (tensor.dims != NULL) free(tensor.dims); + if (tensor.transpose != NULL) free(tensor.transpose); } diff --git a/src/read_tensor.c b/src/read_tensor.c index 48996d5..ec552a2 100644 --- a/src/read_tensor.c +++ b/src/read_tensor.c @@ -70,11 +70,23 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { cJSON_GetObjectItemCaseSensitive(binsparse, "data_types"); assert(data_types_ != NULL); - cJSON* binsparse_tensor = + cJSON* binsparse_custom = cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); - assert(binsparse_tensor != NULL); + assert(binsparse_custom != NULL); + + cJSON* transpose_ = + cJSON_GetObjectItemCaseSensitive(binsparse_custom, "transpose"); + if (transpose_ != NULL) { + size_t* transpose = (size_t*) malloc(tensor.rank * sizeof(size_t)); + for (int idx = 0; idx < tensor.rank; idx++) { + transpose[idx] = + cJSON_GetNumberValue((cJSON_GetArrayItem(transpose_, idx))); + } + tensor.transpose = transpose; + } + cJSON* json_level = - cJSON_GetObjectItemCaseSensitive(binsparse_tensor, "level"); + cJSON_GetObjectItemCaseSensitive(binsparse_custom, "level"); assert(json_level != NULL); bsp_level_t* cur_level = malloc(sizeof(bsp_level_t)); diff --git a/src/write_tensor.c b/src/write_tensor.c index 1d468a7..d1f272e 100644 --- a/src/write_tensor.c +++ b/src/write_tensor.c @@ -13,10 +13,10 @@ static cJSON* init_tensor_json(bsp_tensor_t tensor, cJSON* user_json) { cJSON* binsparse = cJSON_CreateObject(); assert(binsparse != NULL); - cJSON* binsparse_tensor = cJSON_CreateObject(); - assert(binsparse_tensor != NULL); + cJSON* binsparse_custom = cJSON_CreateObject(); + assert(binsparse_custom != NULL); - cJSON_AddItemToObject(binsparse, "tensor", binsparse_tensor); + cJSON_AddItemToObject(binsparse, "tensor", binsparse_custom); cJSON_AddItemToObject(j, "binsparse", binsparse); cJSON* userJsonItem; @@ -32,6 +32,11 @@ static cJSON* init_tensor_json(bsp_tensor_t tensor, cJSON* user_json) { cJSON_AddItemToArray(shape, cJSON_CreateNumber(tensor.dims[i])); } + cJSON* transpose = cJSON_AddArrayToObject(binsparse_custom, "transpose"); + for (int i = 0; i < tensor.rank; i++) { + cJSON_AddItemToArray(transpose, cJSON_CreateNumber(tensor.transpose[i])); + } + cJSON_AddNumberToObject(binsparse, "number_of_stored_values", tensor.nnz); if (tensor.structure != BSP_GENERAL) { @@ -49,9 +54,9 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, // tensor: cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); assert(binsparse != NULL); - cJSON* binsparse_tensor = + cJSON* binsparse_custom = cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); - assert(binsparse_tensor != NULL); + assert(binsparse_custom != NULL); cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); bsp_array_t values = bsp_get_tensor_values(tensor); @@ -82,7 +87,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, int rank = 0; bsp_level_t* level = tensor.level; - cJSON* json_level = cJSON_AddObjectToObject(binsparse_tensor, "level"); + cJSON* json_level = cJSON_AddObjectToObject(binsparse_custom, "level"); while (true) { int reached_end = 0; switch (level->kind) { diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl index 216a0ec..844c758 100644 --- a/test/julia/tensor_test.jl +++ b/test/julia/tensor_test.jl @@ -17,9 +17,8 @@ function tensortest(tensor::Tensor, input::AbstractString, output::AbstractStrin print("tensor_test ", input, " -> ", output, "\n") fwrite(input, tensor) run(`$tensor_test $input $output`) - # for whatever reason, fread returns a swizzlearray - new_tensor = fread(output).body - @assert new_tensor == tensor + output_tensor = fread(output) + @assert tensor == output_tensor end tensortest( From 4e50d1486a88283cc8cff5eb607584046268408b Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Thu, 27 Feb 2025 21:15:41 -0500 Subject: [PATCH 09/24] json reading/writing adjusted for binsparse compliance --- src/read_tensor.c | 4 ++-- src/write_tensor.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/read_tensor.c b/src/read_tensor.c index ec552a2..01453ac 100644 --- a/src/read_tensor.c +++ b/src/read_tensor.c @@ -71,7 +71,7 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { assert(data_types_ != NULL); cJSON* binsparse_custom = - cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); + cJSON_GetObjectItemCaseSensitive(binsparse, "custom"); assert(binsparse_custom != NULL); cJSON* transpose_ = @@ -97,7 +97,7 @@ bsp_tensor_t bsp_read_tensor_from_group(hid_t f) { while (depth < tensor.rank + 1) { cJSON* type_object = - cJSON_GetObjectItemCaseSensitive(json_level, "level_kind"); + cJSON_GetObjectItemCaseSensitive(json_level, "level_desc"); char* type = type_object ? cJSON_GetStringValue(type_object) : NULL; assert(type != NULL); diff --git a/src/write_tensor.c b/src/write_tensor.c index d1f272e..52a4877 100644 --- a/src/write_tensor.c +++ b/src/write_tensor.c @@ -16,7 +16,7 @@ static cJSON* init_tensor_json(bsp_tensor_t tensor, cJSON* user_json) { cJSON* binsparse_custom = cJSON_CreateObject(); assert(binsparse_custom != NULL); - cJSON_AddItemToObject(binsparse, "tensor", binsparse_custom); + cJSON_AddItemToObject(binsparse, "custom", binsparse_custom); cJSON_AddItemToObject(j, "binsparse", binsparse); cJSON* userJsonItem; @@ -55,7 +55,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, cJSON* binsparse = cJSON_GetObjectItemCaseSensitive(j, "binsparse"); assert(binsparse != NULL); cJSON* binsparse_custom = - cJSON_GetObjectItemCaseSensitive(binsparse, "tensor"); + cJSON_GetObjectItemCaseSensitive(binsparse, "custom"); assert(binsparse_custom != NULL); cJSON* data_types = cJSON_AddObjectToObject(binsparse, "data_types"); @@ -94,7 +94,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, case BSP_TENSOR_SPARSE: { bsp_sparse_t* sparse = level->data; size_t layer_rank = sparse->rank; - cJSON_AddStringToObject(json_level, "level_kind", "sparse"); + cJSON_AddStringToObject(json_level, "level_desc", "sparse"); cJSON_AddNumberToObject(json_level, "rank", layer_rank); if (sparse->pointers_to != NULL) { @@ -126,7 +126,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, break; } case BSP_TENSOR_DENSE: { - cJSON_AddStringToObject(json_level, "level_kind", "dense"); + cJSON_AddStringToObject(json_level, "level_desc", "dense"); cJSON_AddNumberToObject(json_level, "rank", ((bsp_dense_t*) level->data)->rank); rank += ((bsp_dense_t*) level->data)->rank; @@ -134,7 +134,7 @@ int bsp_write_tensor_to_group(hid_t f, bsp_tensor_t tensor, cJSON* user_json, break; } case BSP_TENSOR_ELEMENT: { - cJSON_AddStringToObject(json_level, "level_kind", "element"); + cJSON_AddStringToObject(json_level, "level_desc", "element"); reached_end = 1; break; } From 1683216a4b961ec61c8a8880b70927d79940950f Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Sun, 16 Mar 2025 14:21:24 -0400 Subject: [PATCH 10/24] change to shared library --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0c78b7..231146d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_FLAGS "-O3 -march=native") -add_library(binsparse-rc STATIC) +add_library(binsparse-rc SHARED) add_subdirectory(include) add_subdirectory(src) From c6dcbb42da7cd506f77a741a6dc2c5b28ace9fe3 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Mon, 31 Mar 2025 12:32:30 -0400 Subject: [PATCH 11/24] so it turns out that we need int32 indices --- include/binsparse/tensor.h | 4 ++++ test/julia/tensor_test.jl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 60dad01..3909318 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -23,7 +23,11 @@ typedef struct { // corresponds to BSP_TENSOR_DENSE typedef struct { int rank; + // pointers_to, while it will only ever point to one bsp_array_t, must be kept + // as a pointer (rather than a struct) because there are cases where it MUST + // be null. bsp_array_t* pointers_to; + // indices is supposed to be an array of bsp_array_t's. bsp_array_t* indices; bsp_level_t* child; } bsp_sparse_t; diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl index 844c758..3f9812f 100644 --- a/test/julia/tensor_test.jl +++ b/test/julia/tensor_test.jl @@ -57,3 +57,35 @@ tensortest( joinpath(test_files, "input4.bsp.h5"), joinpath(test_files, "output4.bsp.h5") ) + +tensortest( + Tensor( + Dense(SparseList{Int32}(Element{0.0,Float64,Int32}())), + [ + 0 1 0 3; + 1 0 0 4; + ] + ), + joinpath(test_files, "inputcsr.bsp.h5"), + joinpath(test_files, "outputcsr.bsp.h5") +) +tensortest( + Tensor( + Dense(SparseList{Int32}(Element{0.0,Float64,Int32}())), + fsprand(10, 10, 0.1) + ), + joinpath(test_files, "inputcsr2.bsp.h5"), + joinpath(test_files, "outputcsr2.bsp.h5") +) + +tensortest( + Tensor( + Dense(Dense(Element(0.0))), + [ + 1 1 2 3; + 6 1 5 4; + ] + ), + joinpath(test_files, "inputdense.bsp.h5"), + joinpath(test_files, "outputdense.bsp.h5") +) From 467e819436bd8351ed66963b32e4cf185326eacf Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Mon, 31 Mar 2025 15:23:03 -0400 Subject: [PATCH 12/24] change everything to int32 --- test/julia/tensor_test.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl index 3f9812f..7671ffa 100644 --- a/test/julia/tensor_test.jl +++ b/test/julia/tensor_test.jl @@ -23,7 +23,7 @@ end tensortest( Tensor( - Dense(SparseList(SparseList(Element(0.0)))), + Dense(SparseList{Int32}(SparseList{Int32}(Element{0.0,Float64,Int32}()))), fsprand(10, 10, 10, 0.1) ), joinpath(test_files, "input1.bsp.h5"), @@ -42,7 +42,7 @@ tensortest( tensortest( Tensor( - Dense(Dense(Dense(Element(0.0)))), + Dense(Dense(Dense(Element{0.0,Float64,Int32}()))), fsprand(10, 10, 10, 0.1) ), joinpath(test_files, "input3.bsp.h5"), From 054253842acf88612ceb24516a4e0310da2556c4 Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Mon, 7 Apr 2025 11:59:09 -0400 Subject: [PATCH 13/24] make ready for pr --- CMakeLists.txt | 44 -------------------------------------------- dev.sh | 35 ----------------------------------- src/read_matrix.c | 1 - 3 files changed, 80 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100755 dev.sh diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 231146d..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Binsparse Developers -# -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.5) -project(binsparse-rc) - -cmake_policy(SET CMP0079 NEW) - -set(CMAKE_C_STANDARD 11) - -set(CMAKE_CXX_STANDARD 20) - -set(CMAKE_C_FLAGS "-O3 -march=native") - -add_library(binsparse-rc SHARED) - -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 PUBLIC ${HDF5_C_LIBRARIES}) -target_include_directories(binsparse-rc PUBLIC . ${HDF5_INCLUDE_DIRS}) - -include(FetchContent) -FetchContent_Declare( - cJSON - GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git - GIT_TAG v1.7.17 -) -FetchContent_MakeAvailable(cJSON) - -configure_file(${cJSON_SOURCE_DIR}/cJSON.h ${CMAKE_BINARY_DIR}/include/cJSON/cJSON.h) -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) - add_subdirectory(test) -endif() diff --git a/dev.sh b/dev.sh deleted file mode 100755 index a86d79b..0000000 --- a/dev.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env sh - -CONTAINER='binsparse-reference-c' -IMAGE='docker.io/junikimm717/nvim2025:finch' -DIR="$(realpath "$(dirname "$0")")" - -case "$1" in - pull|p) - podman pull "$IMAGE" - (podman container ls | grep "$CONTAINER" > /dev/null 2>&1) && podman container rm -fv "$CONTAINER" - ;; - clear|c) - (podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1)\ - && { - podman container kill "$CONTAINER" > /dev/null 2>&1; - podman container rm "$CONTAINER" - } - ;; - *) - set +x - if ! (podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1); then - podman run\ - -dt\ - --name "$CONTAINER"\ - --group-add keep-groups\ - -v "$DIR:/workspace"\ - --privileged\ - --rm\ - "$IMAGE" - fi || exit 1 - podman exec\ - -e ENV=/root/.profile\ - -it "$CONTAINER" /bin/bash - ;; -esac diff --git a/src/read_matrix.c b/src/read_matrix.c index bf2b96d..464210c 100644 --- a/src/read_matrix.c +++ b/src/read_matrix.c @@ -143,7 +143,6 @@ bsp_matrix_t bsp_read_matrix_from_group(hid_t f) { bsp_matrix_format_t format = bsp_get_matrix_format(format_string); - // isn't this never true? assert(format != 0); matrix.format = format; From 25126850e4d6da8b2d8f689c1fa8c66dff15c521 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Mon, 7 Apr 2025 13:33:58 -0700 Subject: [PATCH 14/24] Fix formatting --- examples/tensor_test.c | 5 +++-- include/binsparse/tensor.h | 6 ++++-- include/binsparse/write_tensor.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/tensor_test.c b/examples/tensor_test.c index bfa0bfc..cd30060 100644 --- a/examples/tensor_test.c +++ b/examples/tensor_test.c @@ -1,10 +1,11 @@ -#include <binsparse/tensor.h> #include <binsparse/read_tensor.h> +#include <binsparse/tensor.h> #include <binsparse/write_tensor.h> int main(int argc, char** argv) { if (argc < 3) { - fprintf(stderr, "usage: ./tensor_test [file_name.h5] [output_file_name.h5]\n"); + fprintf(stderr, + "usage: ./tensor_test [file_name.h5] [output_file_name.h5]\n"); return 1; } char* file_name = argv[1]; diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 3909318..8201e67 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -123,6 +123,8 @@ static bsp_array_t bsp_get_tensor_values(bsp_tensor_t tensor) { static inline void bsp_destroy_tensor_t(bsp_tensor_t tensor) { bsp_destroy_level_t(tensor.level); - if (tensor.dims != NULL) free(tensor.dims); - if (tensor.transpose != NULL) free(tensor.transpose); + if (tensor.dims != NULL) + free(tensor.dims); + if (tensor.transpose != NULL) + free(tensor.transpose); } diff --git a/include/binsparse/write_tensor.h b/include/binsparse/write_tensor.h index 64497c2..27e1f29 100644 --- a/include/binsparse/write_tensor.h +++ b/include/binsparse/write_tensor.h @@ -12,7 +12,7 @@ extern "C" { // TODO: make cJSON optional. -#include<binsparse/tensor.h> +#include <binsparse/tensor.h> #include <cJSON/cJSON.h> #ifdef BSP_USE_HDF5 From 5ac75e6da0696f341b71e8d2cb49459df8087deb Mon Sep 17 00:00:00 2001 From: Juni Kim <junikimm717@gmail.com> Date: Sun, 20 Apr 2025 17:14:52 -0400 Subject: [PATCH 15/24] add cmakelists back in --- CMakeLists.txt | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..231146d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2024 Binsparse Developers +# +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.5) +project(binsparse-rc) + +cmake_policy(SET CMP0079 NEW) + +set(CMAKE_C_STANDARD 11) + +set(CMAKE_CXX_STANDARD 20) + +set(CMAKE_C_FLAGS "-O3 -march=native") + +add_library(binsparse-rc SHARED) + +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 PUBLIC ${HDF5_C_LIBRARIES}) +target_include_directories(binsparse-rc PUBLIC . ${HDF5_INCLUDE_DIRS}) + +include(FetchContent) +FetchContent_Declare( + cJSON + GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git + GIT_TAG v1.7.17 +) +FetchContent_MakeAvailable(cJSON) + +configure_file(${cJSON_SOURCE_DIR}/cJSON.h ${CMAKE_BINARY_DIR}/include/cJSON/cJSON.h) +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) + add_subdirectory(test) +endif() From 093add15ee37969643a0b4218f68a2692e1b16c9 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 15:29:08 -0700 Subject: [PATCH 16/24] Add SPDX headers, remove `compile_flags.txt`. (Use `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to generate automatically.) --- .gitignore | 1 + CMakeLists.txt | 10 +++++----- compile_flags.txt | 4 ---- examples/cpp/tensor_test.cpp | 6 ++++++ examples/tensor_test.c | 6 ++++++ include/binsparse/read_tensor.h | 6 ++++++ include/binsparse/tensor.h | 6 ++++++ src/CMakeLists.txt | 4 ++-- src/write_tensor.c | 6 ++++++ test/julia/tensor_test.jl | 4 ++++ 10 files changed, 42 insertions(+), 11 deletions(-) delete mode 100644 compile_flags.txt diff --git a/.gitignore b/.gitignore index 8fc2fe2..8dddad7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ scripts venv build* +compile_flags.txt ._* tensor_test_files diff --git a/CMakeLists.txt b/CMakeLists.txt index 349bbe8..6ea7531 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,11 +46,6 @@ target_include_directories(${PROJECT_NAME} $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ${HDF5_INCLUDE_DIRS}) -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - add_subdirectory(examples) - add_subdirectory(test) -endif() - # Installation rules - these are always needed when the library is built install(TARGETS binsparse EXPORT binsparse-targets @@ -87,3 +82,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/binsparse-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/binsparse-config-version.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/binsparse) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + add_subdirectory(examples) + add_subdirectory(test) +endif() diff --git a/compile_flags.txt b/compile_flags.txt deleted file mode 100644 index ba24856..0000000 --- a/compile_flags.txt +++ /dev/null @@ -1,4 +0,0 @@ --I./include --I./build/include --DBSP_USE_HDF5 --I/usr/include/hdf5/serial diff --git a/examples/cpp/tensor_test.cpp b/examples/cpp/tensor_test.cpp index 677d71e..893c334 100644 --- a/examples/cpp/tensor_test.cpp +++ b/examples/cpp/tensor_test.cpp @@ -1 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include "../tensor_test.c" diff --git a/examples/tensor_test.c b/examples/tensor_test.c index cd30060..5d3ba6e 100644 --- a/examples/tensor_test.c +++ b/examples/tensor_test.c @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include <binsparse/read_tensor.h> #include <binsparse/tensor.h> #include <binsparse/write_tensor.h> diff --git a/include/binsparse/read_tensor.h b/include/binsparse/read_tensor.h index 9d419ec..579c5c7 100644 --- a/include/binsparse/read_tensor.h +++ b/include/binsparse/read_tensor.h @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #pragma once #ifdef __cplusplus diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 8201e67..74863b2 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #pragma once #include <binsparse/array.h> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee41ab5..0b82bd2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ target_sources(binsparse PRIVATE read_matrix.c - src/read_tensor.c + read_tensor.c write_matrix.c - src/write_tensor.c + write_tensor.c ) diff --git a/src/write_tensor.c b/src/write_tensor.c index 52a4877..11a84ef 100644 --- a/src/write_tensor.c +++ b/src/write_tensor.c @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2024 Binsparse Developers + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include <assert.h> #include <binsparse/tensor.h> #include <unistd.h> diff --git a/test/julia/tensor_test.jl b/test/julia/tensor_test.jl index 7671ffa..cbba45f 100644 --- a/test/julia/tensor_test.jl +++ b/test/julia/tensor_test.jl @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2024 Binsparse Developers +# +# SPDX-License-Identifier: BSD-3-Clause + using Finch; using HDF5; From 0e75d8fb729c351ef28f8097a8c28175e94d1c44 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 15:35:10 -0700 Subject: [PATCH 17/24] Add missing includes. --- include/binsparse/read_tensor.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/binsparse/read_tensor.h b/include/binsparse/read_tensor.h index 579c5c7..bcf3145 100644 --- a/include/binsparse/read_tensor.h +++ b/include/binsparse/read_tensor.h @@ -6,6 +6,14 @@ #pragma once +#include <binsparse/tensor.h> + +#ifndef __cplusplus +#include <stddef.h> +#else +#include <cstddef> +#endif + #ifdef __cplusplus extern "C" { #endif From 35435891beaf99d725b3e90175cf78488acffbc9 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:00:36 -0700 Subject: [PATCH 18/24] Add Tensor tests. --- .github/workflows/ci.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 365a69d..0ae2e73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,8 +38,14 @@ jobs: cmake -B build - name: Build run: VERBOSE=true make -C build -j `nproc` - - name: Test + - name: Test-Matrix run: ctest --test-dir ./build/test/bash + - name: Install-Julia + run: curl -fsSL https://install.julialang.org | sh + - name: Install-Finch + run: julia -e 'using Pkg; Pkg.add("Finch")' + - name: Test-Tensor + run: ctest --test-dir ./build/test/julia clang: runs-on: 'ubuntu-latest' @@ -55,5 +61,11 @@ jobs: cmake -B build - name: Build run: VERBOSE=true make -C build -j `nproc` - - name: Test + - name: Test-Matrix run: ctest --test-dir ./build/test/bash + - name: Install-Julia + run: curl -fsSL https://install.julialang.org | sh + - name: Install-Finch + run: julia -e 'using Pkg; Pkg.add("Finch")' + - name: Test-Tensor + run: ctest --test-dir ./build/test/julia From 3abac30bd130f1e9eeabde66f374262c989de958 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:15:22 -0700 Subject: [PATCH 19/24] Fix Julia install --- .github/workflows/ci.yml | 41 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ae2e73..ef207c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,12 +23,20 @@ jobs: - run: pip install -r requirements.txt - name: Checks uses: pre-commit/action@v3.0.0 - - gcc: + + build: runs-on: 'ubuntu-latest' + strategy: + matrix: + include: + - cc: gcc-12 + cxx: g++-12 + - cc: clang + cxx: clang++ + name: ${{ matrix.cc }} env: - CXX: g++-12 - CC: gcc-12 + CC: ${{ matrix.cc }} + CXX: ${{ matrix.cxx }} steps: - uses: actions/checkout@v4 - name: CMake @@ -41,30 +49,7 @@ jobs: - name: Test-Matrix run: ctest --test-dir ./build/test/bash - name: Install-Julia - run: curl -fsSL https://install.julialang.org | sh - - name: Install-Finch - run: julia -e 'using Pkg; Pkg.add("Finch")' - - name: Test-Tensor - run: ctest --test-dir ./build/test/julia - - clang: - runs-on: 'ubuntu-latest' - env: - CXX: clang++ - CC: clang - steps: - - uses: actions/checkout@v4 - - name: CMake - run: | - sudo apt-get update - sudo apt-get install libhdf5-dev clang - cmake -B build - - name: Build - run: VERBOSE=true make -C build -j `nproc` - - name: Test-Matrix - run: ctest --test-dir ./build/test/bash - - name: Install-Julia - run: curl -fsSL https://install.julialang.org | sh + run: curl -fsSL https://install.julialang.org | sh -s -- -y - name: Install-Finch run: julia -e 'using Pkg; Pkg.add("Finch")' - name: Test-Tensor From 53f2a76573681ce0f31298d674a47e3c68dbad50 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:18:10 -0700 Subject: [PATCH 20/24] Fix whitespace --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef207c3..86769f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - run: pip install -r requirements.txt - name: Checks uses: pre-commit/action@v3.0.0 - + build: runs-on: 'ubuntu-latest' strategy: From 79b7f955a96c9a837440a2b18c996dfd703ab939 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:33:18 -0700 Subject: [PATCH 21/24] Turn off Julia pre-compilation, install HDF5. --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86769f5..938bf93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,15 +42,17 @@ jobs: - name: CMake run: | sudo apt-get update - sudo apt-get install libhdf5-dev $CXX $CC + sudo apt-get install libhdf5-dev gcc-12 g++-12 clang cmake -B build - name: Build run: VERBOSE=true make -C build -j `nproc` - - name: Test-Matrix + - name: Matrix Tests run: ctest --test-dir ./build/test/bash - - name: Install-Julia + - name: Install Julia run: curl -fsSL https://install.julialang.org | sh -s -- -y - - name: Install-Finch - run: julia -e 'using Pkg; Pkg.add("Finch")' - - name: Test-Tensor + - name: Disable Julia precompilation + run: julia -e 'using PrecompileTools, Preferences; set_preferences!(PrecompileTools, "precompile_workloads" => false; force=true)' + - name: Install Julia Packages + run: julia -e 'using Pkg; Pkg.add(["Finch", "HDF5"])' + - name: Tensor Tests run: ctest --test-dir ./build/test/julia From 8980791a1316684eb6b5fda850ee7efa6e5b0df6 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:39:49 -0700 Subject: [PATCH 22/24] Add missing package. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 938bf93..3d8680c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: - name: Install Julia run: curl -fsSL https://install.julialang.org | sh -s -- -y - name: Disable Julia precompilation - run: julia -e 'using PrecompileTools, Preferences; set_preferences!(PrecompileTools, "precompile_workloads" => false; force=true)' + run: julia -e 'using Pkg; Pkg.add("PrecompileTools"); using PrecompileTools, Preferences; set_preferences!(PrecompileTools, "precompile_workloads" => false; force=true)' - name: Install Julia Packages run: julia -e 'using Pkg; Pkg.add(["Finch", "HDF5"])' - name: Tensor Tests From 0c3f3f83b8d1afbe14a4556014262d1f06e94ef4 Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 16:41:42 -0700 Subject: [PATCH 23/24] Add missing Julia package. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d8680c..516614f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: - name: Install Julia run: curl -fsSL https://install.julialang.org | sh -s -- -y - name: Disable Julia precompilation - run: julia -e 'using Pkg; Pkg.add("PrecompileTools"); using PrecompileTools, Preferences; set_preferences!(PrecompileTools, "precompile_workloads" => false; force=true)' + run: julia -e 'using Pkg; Pkg.add(["PrecompileTools", "Preferences"]); using PrecompileTools, Preferences; set_preferences!(PrecompileTools, "precompile_workloads" => false; force=true)' - name: Install Julia Packages run: julia -e 'using Pkg; Pkg.add(["Finch", "HDF5"])' - name: Tensor Tests From e2c21a0cd59a5c9ac46a2057418cd4835a54d71a Mon Sep 17 00:00:00 2001 From: Benjamin Brock <benjamin.brock@intel.com> Date: Wed, 6 Aug 2025 17:44:51 -0700 Subject: [PATCH 24/24] Correct comment. --- include/binsparse/tensor.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/binsparse/tensor.h b/include/binsparse/tensor.h index 74863b2..4d63512 100644 --- a/include/binsparse/tensor.h +++ b/include/binsparse/tensor.h @@ -26,7 +26,7 @@ typedef struct { bsp_array_t values; } bsp_element_t; -// corresponds to BSP_TENSOR_DENSE +// corresponds to BSP_TENSOR_SPARSE typedef struct { int rank; // pointers_to, while it will only ever point to one bsp_array_t, must be kept @@ -38,6 +38,7 @@ typedef struct { bsp_level_t* child; } bsp_sparse_t; +// corresponds to BSP_TENSOR_DENSE typedef struct { int rank; bsp_level_t* child;