From 7cce34a3e11c6d63a019743e01f0e23db5d0dd12 Mon Sep 17 00:00:00 2001 From: Elias Kohout Date: Fri, 24 Feb 2023 19:10:32 +0100 Subject: [PATCH] Init, Implementation of Create, Destroy, Init and basic get and set functions. --- tensor.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tensor.h | 40 ++++++++++ 2 files changed, 266 insertions(+) create mode 100644 tensor.c create mode 100644 tensor.h diff --git a/tensor.c b/tensor.c new file mode 100644 index 0000000..ac4f2fd --- /dev/null +++ b/tensor.c @@ -0,0 +1,226 @@ +#include "tensor.h" +#include +#include + +tensor tensor_new(void) +{ + return calloc(1, sizeof(struct _tensor)); +} + +void tensor_destroy(tensor t) +{ + if (!tensor_is_empty(t)) { + free(t->size); + free(t->elements); + } +} + +int tensor_is_empty(tensor t){ + return t->elements == NULL || t->size == NULL; +} + +int _tensor_check_size(const int *size, int dim) +{ + int i; + if(dim < 0) return 0; + for(i = 0; i < dim; i++) { + if(size[i] < 1) return 0; + } + return 1; +} + +int _tensor_set_size(tensor t, const int *size, int dim) +{ + int *temp; + t_type *t_temp; + int i, num_elem = 1; + + for(i = 0; i < dim; i++) { + num_elem *= size[i]; + } + + if(!_tensor_check_size(size, dim)) return 0; + /* Try allocating memory for the size array of the Tensor */ + temp = realloc(t->size, dim * sizeof(int)); + if(temp == NULL && dim != 0) return 0; + /* Try allocating memory for the Tensor */ + t_temp = realloc(t->elements, num_elem * sizeof(t_type)); + if(t_temp == NULL) { + /* Revert to before the function call and return */ + t->size = realloc(temp, t->dimension * sizeof(int)); + if(t->size == NULL && t->dimension != 0) { + printf("Fatal error in _tensor_set_size when reallocating memory."); + exit(-1); + } + return 0; + } + + /* Setting the size array */ + t->size = temp; + if(dim != 0) memcpy(t->size, size, dim * sizeof(int)); + t->dimension = dim; + /* Setting the elements pointer and memory usage */ + t->elements = t_temp; + t->num_elem = num_elem; + + return 1; +} + +int tensor_set(tensor t, const int *index, t_type val) +{ + int i, offset = 0; + if(tensor_is_empty(t)) return 0; + + for(i = 0; i < t->dimension - 1; i++) { + if(t->size[i] >= index[i]) return 0; + offset += t->size[i] * index[i]; + } + offset += index[t->dimension - 1]; + t->elements[offset] = val; + return 1; +} + +t_type tensor_get(tensor t, const int *index, int *success) +{ + int i, offset = 0; + if(tensor_is_empty(t)) return 0; + + for(i = 0; i < t->dimension - 1; i++) { + if(t->size[i] <= index[i]) { + if(success != NULL) *success = 0; + return 0; + } + offset += t->size[i] * index[i]; + } + offset += index[t->dimension - 1]; + if(success != NULL) *success = 1; + return t->elements[offset]; +} + +int tensor_init_one(tensor t, int dimension, const int *size) +{ + int i; + + if(!_tensor_set_size(t, size, dimension)) return 0; + for(i = 0; i < t->num_elem; i++) { + t->elements[i] = (t_type) 1; + } + return 1; +} + +int tensor_init_zero(tensor t, int dimension, const int *size) +{ + int i; + + if(!_tensor_set_size(t, size, dimension)) return 0; + for(i = 0; i < t->num_elem; i++) { + t->elements[i] = (t_type) 0; + } + return 1; +} + +int tensor_init_rand(tensor t, int dimension, const int *size) +{ + int i; + srand(time(NULL)); + + if(!_tensor_set_size(t, size, dimension)) return 0; + for(i = 0; i < t->num_elem; i++) { + t->elements[i] = (t_type) rand(); + } + return 1; +} + +void tensor_for_each_elem(tensor t, t_type (*func)(t_type)) +{ + int i; + srand(time(NULL)); + + for(i = 0; i < t->num_elem; i++) { + t->elements[i] = func(t->elements[i]); + } +} + +void tensor_print(tensor t) +{ + int i, j; + int *indx; + + if(tensor_is_empty(t)){ + printf("\n"); + return; + } + + printf("Tensor of dimension %i and size (", t->dimension); + for(i = 0; i < t->dimension - 1; i++) { + printf("%i, ", t->size[i]); + } + if(t->dimension == 0) printf("): "); + else printf("%i): ", t->size[t->dimension - 1]); + + + if(t->dimension == 0) { + /* Skalar */ + printf(PRINT_STRING, t->elements[0]); + putchar('\n'); + } else if (t->dimension == 1) { + /* Spaltenvektor */ + if(t->size[0] == 1) { + putchar('('); + printf(PRINT_STRING, t->elements[0]); + printf(")\n"); + } else { + printf("\n/"); + printf(PRINT_STRING, t->elements[0]); + printf("\\\n"); + for(i = 1; i < t->size[0] - 1; i++) { + putchar('|'); + printf(PRINT_STRING, t->elements[i]); + printf("|\n"); + } + printf("\\"); + printf(PRINT_STRING, t->elements[t->size[0] - 1]); + printf("/\n"); + } + } else if (t->dimension == 2) { + /* Matix */ + indx = malloc(sizeof(int) * 2); + if(t->size[0] == 1) { + putchar('('); + indx[1] = 0; + for(i = 0; i < t->size[1]; i++) { + indx[0] = i; + printf(PRINT_STRING, tensor_get(t, indx, NULL)); + } + printf(")\n"); + } else { + printf("\n/"); + indx[1] = 0; + for(i = 0; i < t->size[1]; i++) { + indx[0] = i; + printf(PRINT_STRING, tensor_get(t, indx, NULL)); + } + printf("\\\n"); + for(i = 1; i < t->size[0] - 1; i++) { + putchar('|'); + indx[1] = i; + for(j = 0; j < t->size[1]; j++) { + indx[0] = j; + printf(PRINT_STRING, tensor_get(t, indx, NULL)); + } + printf("|\n"); + } + printf("\\"); + indx[t->size[1] - 1] = 0; + for(i = 0; i < t->size[1]; i++) { + indx[0] = i; + printf(PRINT_STRING, tensor_get(t, indx, NULL)); + } + printf("/\n"); + } + free(indx); + } else { + printf(" print function not yet implemented for dim > 2."); + } +} + diff --git a/tensor.h b/tensor.h new file mode 100644 index 0000000..00ecde1 --- /dev/null +++ b/tensor.h @@ -0,0 +1,40 @@ +#ifndef TENSOR_H_INCLUDED +#define TENSOR_H_INCLUDED + +#include +#include +#include +#include + +#define PRINT_STRING " %4.1f " + +typedef float t_type; + +typedef struct _tensor { + t_type *elements; + int dimension; + int *size; + int num_elem; +} *tensor; + + +tensor tensor_new(void); +void tensor_destroy(tensor t); + +int tensor_is_empty(tensor t); + +int _tensor_check_size(const int *size, int dim); +int _tensor_set_size(tensor t, const int *size, int dim); + +int tensor_set(tensor t, const int *index, t_type val); +t_type tensor_get(tensor t, const int *index, int *success); + +int tensor_init_one(tensor t, int dimension, const int *size); +int tensor_init_zero(tensor t, int dimension, const int *size); +int tensor_init_rand(tensor t, int dimension, const int *size); + +void tensor_for_each_elem(tensor t, t_type (*func)(t_type)); +void tensor_print(tensor t); + +#endif +