From 427c75f1a65231f5f7bd8ae8ec582ce141e4dc63 Mon Sep 17 00:00:00 2001 From: Elias Kohout Date: Sun, 3 Sep 2023 09:45:20 +0200 Subject: [PATCH] Added comments --- tensor.c | 228 ++++++++++++++++++++++++++++++++++---------- tensor.h | 21 ++-- tests/test_tensor.c | 15 ++- 3 files changed, 193 insertions(+), 71 deletions(-) diff --git a/tensor.c b/tensor.c index 8ae0e48..4ae8c63 100644 --- a/tensor.c +++ b/tensor.c @@ -2,11 +2,19 @@ tensor tensor_new(void) { + /* Creates a new tensor struct and returns it. + * + * @return A tensor (pointer to memory for a _tensor struct) + */ return calloc(1, sizeof(struct _tensor)); } void tensor_destroy(tensor t) { + /* Destroys a tensor struct by free its memory. + * + * @param t The tensor that should be deleted + */ if (!tensor_is_empty(t)) { free(t->size); free(t->elements); @@ -17,11 +25,24 @@ void tensor_destroy(tensor t) bool tensor_is_empty(const tensor t) { + /* Checks whether a tensor is empty. + * + * @param t The tensor to check + * + * @return true when the tensor is empty, false otherwise + */ return t->elements == NULL || t->size == NULL; } bool tensor_is_equal(const tensor t1, const tensor t2) { + /* Checks whether two tensor are equal. + * + * @param t1 The first tensor + * @param t2 The seconds tensor + * + * @return true when the two tensors are equal, false otherwise + */ assert(!tensor_is_empty(t1)); assert(!tensor_is_empty(t2)); @@ -36,19 +57,34 @@ bool tensor_is_equal(const tensor t1, const tensor t2) return true; } -uint8_t _tensor_check_size(const uint32_t *size, uint8_t rank) +bool _tensor_check_size(const uint32_t *size, uint8_t rank) { + /* Checks whether a size array is valid. + * + * @param size A size array + * @param rank The length of the size array + * + * @return true when the size is valid, false otherwise + */ uint8_t i; - if(rank < 0) return 0; + if(rank < 0) return false; for(i = 0; i < rank; i++) { - if(size[i] < 1) return 0; + if(size[i] < 1) return false; } - return 1; + return true; } -uint8_t _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank) +bool _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank) { - /* Sets the size of a Tensor. During this process all data in the tensor t is lost. */ + /* Sets the size of a Tensor. During this process all data in the tensor t + * is lost. + * + * @param t The tensor that should be changed + * @param size The final size of the tensor t + * @param rank The length of size + * + * @return true if the process was successful, false when an error occured + */ uint32_t *temp_size; uint32_t *temp_index_offset; @@ -56,7 +92,7 @@ uint8_t _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank) uint8_t i, j; uint32_t num_elem = 1; - if(!_tensor_check_size(size, rank)) return 0; + if(!_tensor_check_size(size, rank)) return false; /* Try allocating memory for the size/ index_offset array of the tensor */ for(i = 0; i < rank; i++) { @@ -68,7 +104,7 @@ uint8_t _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank) if((temp_size == NULL && rank != 0) || (temp_index_offset == NULL && rank != 0) || temp_elements == NULL) { free(temp_size); free(temp_index_offset); - return 0; + return false; } /* Freeing old memory. */ @@ -92,11 +128,20 @@ uint8_t _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank) t->elements = temp_elements; t->num_elem = num_elem; - return 1; + return true; } -uint8_t tensor_set(tensor t, const uint32_t *index, dtype val) +bool tensor_set(tensor t, const uint32_t *index, dtype val) { + /* Set the value at a index of a tensor. + * + * @param t The tensor to change + * @param index The index of the value that should change, the length of + * this array is defined by the rank of t + * @param val The updated value + * + * @return true if the change was successful, false otherwise + */ assert(!tensor_is_empty(t)); uint8_t i; @@ -104,20 +149,30 @@ uint8_t tensor_set(tensor t, const uint32_t *index, dtype val) if(t->rank == 0) { t->elements[0] = val; - return 1; + return true; } for(i = 0; i < t->rank; i++) { - if(t->size[i] <= index[i]) return 0; + if(t->size[i] <= index[i]) return false; offset += t->index_offsets[i] * index[i]; } t->elements[offset] = val; - return 1; + return true; } -dtype tensor_get(const tensor t, const uint32_t *index, uint8_t *success) +dtype tensor_get(const tensor t, const uint32_t *index, bool *success) { + /* Gets a value at a index from a tensor. + * + * @param t The tensor from which to get the value from + * @param index The index of the value to get, the length of this array is + * defined by the rank of t + * @param success Is set according to the exit status of the function, if it + * is NULL it is ignored + * + * @return The retrieved value, DTYPE_NULL in case of an error + */ assert(!tensor_is_empty(t)); uint8_t i; @@ -127,98 +182,156 @@ dtype tensor_get(const tensor t, const uint32_t *index, uint8_t *success) for(i = 0; i < t->rank; i++) { if(t->size[i] <= index[i]) { - if(success != NULL) *success = 0; - return 0; + if(success != NULL) *success = false; + return DTYPE_ZERO; } offset += t->index_offsets[i] * index[i]; } - if(success != NULL) *success = 1; + if(success != NULL) *success = true; return t->elements[offset]; } -uint8_t tensor_init_one(tensor t, uint8_t rank, const uint32_t *size) +bool tensor_init_one(tensor t, const uint32_t *size, uint8_t rank) { + /* Inits (sets the size) and filles a tensor with ones. + * + * @param t The tensor to fill + * @param size The final size of the tensor t + * @param rank The length of size array + * + * @return true when successful, false otherwise + */ uint32_t i; - if(!_tensor_set_size(t, size, rank)) return 0; + if(!_tensor_set_size(t, size, rank)) return false; for(i = 0; i < t->num_elem; i++) { t->elements[i] = DTYPE_ONE; } - return 1; + return true; } -uint8_t tensor_init_zero(tensor t, uint8_t rank, const uint32_t *size) +bool tensor_init_zero(tensor t, const uint32_t *size, uint8_t rank) { + /* Inits (sets the size) and filles a tensor with zeros. + * + * @param t The tensor to fill + * @param size The final size of the tensor t + * @param rank The length of size array + * + * @return true when successful, false otherwise + */ uint32_t i; - if(!_tensor_set_size(t, size, rank)) return 0; + if(!_tensor_set_size(t, size, rank)) return false; for(i = 0; i < t->num_elem; i++) { t->elements[i] = DTYPE_ZERO; } - return 1; + return true; } -uint8_t tensor_init_rand(tensor t, uint8_t rank, const uint32_t *size, dtype max) +bool tensor_init_rand(tensor t, const uint32_t *size, uint8_t rank, dtype max) { + /* Inits (sets the size) and filles a tensor with random values below or + * equal to the max value. + * + * @param t The tensor to fill + * @param size The final size of the tensor t + * @param rank The length of size array + * @param max The maximal value filled in + * + * @return true when successful, false otherwise + */ uint32_t i; static long last_seed; last_seed += time(NULL) * 200 + rand(); srand(last_seed); - if(!_tensor_set_size(t, size, rank)) return 0; + if(!_tensor_set_size(t, size, rank)) return false; for(i = 0; i < t->num_elem; i++) { t->elements[i] = DTYPE_RAND(max); } - return 1; + return true; } -uint8_t tensor_cpy(tensor t1, const tensor t2) +bool tensor_cpy(tensor t1, const tensor t2) { + /* Copies the contents of t2 into t1. + * + * @param t1 The tensor in which to copy the values + * @param t2 The tensor from which to copy the values + * + * @return true when successful, false otherwise + */ assert(!tensor_is_empty(t2)); uint32_t i; - if(!_tensor_set_size(t1, t2->size, t2->rank)) return 0; + if(!_tensor_set_size(t1, t2->size, t2->rank)) return false; for(i = 0; i < t2->num_elem; i++) { t1->elements[i] = t2->elements[i]; } - return 1; + return true; } -uint8_t tensor_add_inplace(tensor t1, const tensor t2) +bool tensor_add_inplace(tensor t1, const tensor t2) { + /* Adds the values of t2 onto the values of t1. t1 and t2 need to have the + * same size. + * + * @param t1 The tensor on which the values of t2 are added + * @param t2 The tensor whose values are added + * + * @return true when successful, false otherwise + */ assert(!tensor_is_empty(t1)); assert(!tensor_is_empty(t2)); uint32_t i; - if(t1->rank != t2->rank) return 0; + + if(t1->rank != t2->rank) return false; for(i = 0; i < t1->rank; i++) { - if(t1->size[i] != t2->size[i]) return 0; + if(t1->size[i] != t2->size[i]) return false; } for(i = 0; i < t1->num_elem; i++) { t1->elements[i] = DTYPE_ADD(t1->elements[i], t2->elements[i]); } - return 1; + return true; } -uint8_t tensor_sub_inplace(tensor t1, const tensor t2) +bool tensor_sub_inplace(tensor t1, const tensor t2) { + /* Subtracts the values of t2 from the values of t1. t1 and t2 need to have + * the same size. + * + * @param t1 The tensor from which the values of t2 are subtracted + * @param t2 The tensor whose values are subtracted + * + * @return true when successful, false otherwise + */ assert(!tensor_is_empty(t1)); assert(!tensor_is_empty(t2)); uint32_t i; - if(t1->rank != t2->rank) return 0; + + if(t1->rank != t2->rank) return false; for(i = 0; i < t1->rank; i++) { - if(t1->size[i] != t2->size[i]) return 0; + if(t1->size[i] != t2->size[i]) return false; } for(i = 0; i < t1->num_elem; i++) { t1->elements[i] = DTYPE_SUB(t1->elements[i], t2->elements[i]); } - return 1; + return true; } tensor tensor_add(const tensor t1, const tensor t2) { + /* Adds to tensors returning the result as a tensor. + * + * @param t1 The first tensor to add + * @param t2 The second tensor to add + * + * @return The result of the operation, NULL if an error occurs + */ assert(!tensor_is_empty(t1)); assert(!tensor_is_empty(t2)); @@ -231,6 +344,13 @@ tensor tensor_add(const tensor t1, const tensor t2) tensor tensor_sub(const tensor t1, const tensor t2) { + /* Subtracts to tensors returning the result as a tensor. + * + * @param t1 The tensor to subtract from + * @param t2 The tensor that is subtracted + * + * @return The result of the operation, NULL if an error occurs + */ assert(!tensor_is_empty(t1)); assert(!tensor_is_empty(t2)); @@ -244,8 +364,12 @@ tensor tensor_sub(const tensor t1, const tensor t2) void tensor_print(const tensor t) { + /* Prints a tensor to stdout. + * + * @param t The tensor to print + */ uint32_t i, j; - uint32_t *indx; + uint32_t *index; if(tensor_is_empty(t)){ printf("\n"); @@ -285,41 +409,41 @@ void tensor_print(const tensor t) } } else if (t->rank == 2) { /* matix */ - indx = malloc(sizeof(int) * 2); + index = malloc(sizeof(int) * 2); if(t->size[0] == 1) { putchar('('); - indx[0] = 0; + index[0] = 0; for(i = 0; i < t->size[1]; i++) { - indx[1] = i; - DTYPE_PRINT(tensor_get(t, indx, NULL)); + index[1] = i; + DTYPE_PRINT(tensor_get(t, index, NULL)); } printf(")\n"); } else { printf("\n/"); - indx[0] = 0; + index[0] = 0; for(i = 0; i < t->size[1]; i++) { - indx[1] = i; - DTYPE_PRINT(tensor_get(t, indx, NULL)); + index[1] = i; + DTYPE_PRINT(tensor_get(t, index, NULL)); } printf("\\\n"); for(i = 1; i < t->size[0] - 1; i++) { putchar('|'); - indx[0] = i; + index[0] = i; for(j = 0; j < t->size[1]; j++) { - indx[1] = j; - DTYPE_PRINT(tensor_get(t, indx, NULL)); + index[1] = j; + DTYPE_PRINT(tensor_get(t, index, NULL)); } printf("|\n"); } printf("\\"); - indx[0] = t->size[0] - 1; + index[0] = t->size[0] - 1; for(i = 0; i < t->size[1]; i++) { - indx[1] = i; - DTYPE_PRINT(tensor_get(t, indx, NULL)); + index[1] = i; + DTYPE_PRINT(tensor_get(t, index, NULL)); } printf("/\n"); } - free(indx); + free(index); } else { putchar('['); for(i = 0; i < t->num_elem; i++) { diff --git a/tensor.h b/tensor.h index 6331a54..25dcb1b 100644 --- a/tensor.h +++ b/tensor.h @@ -42,23 +42,22 @@ void tensor_destroy(tensor t); bool tensor_is_empty(const tensor t); bool tensor_is_equal(const tensor t1, const tensor t2); -uint8_t _tensor_check_size(const uint32_t *size, uint8_t rank); -uint8_t _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank); +bool _tensor_check_size(const uint32_t *size, uint8_t rank); +bool _tensor_set_size(tensor t, const uint32_t *size, uint8_t rank); -uint8_t tensor_set(tensor t, const uint32_t *index, dtype val); -dtype tensor_get(const tensor t, const uint32_t *index, uint8_t *success); +bool tensor_set(tensor t, const uint32_t *index, dtype val); +dtype tensor_get(const tensor t, const uint32_t *index, bool *success); -uint8_t tensor_init_one(tensor t, uint8_t rank, const uint32_t *size); -uint8_t tensor_init_zero(tensor t, uint8_t rank, const uint32_t *size); -uint8_t tensor_init_rand(tensor t, uint8_t rank, const uint32_t *size, dtype max); -uint8_t tensor_cpy(tensor t1, const tensor t2); +bool tensor_init_one(tensor t, const uint32_t *size, uint8_t rank); +bool tensor_init_zero(tensor t, const uint32_t *size, uint8_t rank); +bool tensor_init_rand(tensor t, const uint32_t *size, uint8_t rank, dtype max); +bool tensor_cpy(tensor t1, const tensor t2); -uint8_t tensor_add_inplace(tensor t1, const tensor t2); -uint8_t tensor_sub_inplace(tensor t1, const tensor t2); +bool tensor_add_inplace(tensor t1, const tensor t2); +bool tensor_sub_inplace(tensor t1, const tensor t2); tensor tensor_add(const tensor t1, const tensor t2); tensor tensor_sub(const tensor t1, const tensor t2); void tensor_print(const tensor t); #endif - diff --git a/tests/test_tensor.c b/tests/test_tensor.c index e43a610..80ddc56 100644 --- a/tests/test_tensor.c +++ b/tests/test_tensor.c @@ -23,12 +23,11 @@ void test_tensor_is_equal(void) uint32_t s[4] = {2, 5, 3, 7}; tensor t1 = tensor_new(); tensor t2 = tensor_new(); - - tensor_init_zero(t1, 4, s); - tensor_init_one(t2, 4, s); + tensor_init_zero(t1, s, 4); + tensor_init_one(t2, s, 4); tensor_assert_ne(t1, t2); - tensor_init_rand(t1, 4, s, 30); + tensor_init_rand(t1, s, 4, 30); tensor_cpy(t2, t1); tensor_assert_eq(t1, t2); @@ -44,8 +43,8 @@ void test_tensor_set(void) tensor t1 = tensor_new(); tensor t2 = tensor_new(); - tensor_init_rand(t1, 4, s, 30); - tensor_init_zero(t2, 4, s); + tensor_init_rand(t1, s, 4, 30); + tensor_init_zero(t2, s, 4); for (index[0] = 0; index[0] < s[0]; ++index[0]) { for (index[1] = 0; index[1] < s[1]; ++index[1]) { @@ -70,8 +69,8 @@ void test_tensor_get(void) tensor t1 = tensor_new(); tensor t2 = tensor_new(); - tensor_init_rand(t1, 4, s, 30); - tensor_init_zero(t2, 4, s); + tensor_init_rand(t1, s, 4, 30); + tensor_init_zero(t2, s, 4); for (index[0] = 0; index[0] < s[0]; ++index[0]) { for (index[1] = 0; index[1] < s[1]; ++index[1]) {