summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper2025-09-08 10:35:14 +0200
committerJasper2025-09-08 10:35:14 +0200
commit1386f6dc5024937c8c9c741efed9274d4861b76f (patch)
tree50c27e867e3551a820e90ac2bd0d43ca087625ef
parentbd39c6ab8b87a90944afe271ce847ed0ce090c92 (diff)
Added vector struct
It's completely based on the existing matrix struct and its functions.
-rwxr-xr-xbuild.sh2
-rw-r--r--vector.c186
-rw-r--r--vector.h67
3 files changed, 254 insertions, 1 deletions
diff --git a/build.sh b/build.sh
index 6ec6b63..82d4c4c 100755
--- a/build.sh
+++ b/build.sh
@@ -2,4 +2,4 @@ if [ ! -d "bin" ]; then
mkdir bin
fi
-gcc -Wall -Wextra -pedantic -lm -o bin/linalg_debug debug.c tests.c utils.c matrix.c
+gcc -Wall -Wextra -pedantic -lm -o bin/linalg_debug debug.c tests.c utils.c matrix.c vector.c
diff --git a/vector.c b/vector.c
new file mode 100644
index 0000000..e5bf717
--- /dev/null
+++ b/vector.c
@@ -0,0 +1,186 @@
+#include <math.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "utils.h"
+#include "vector.h"
+
+Vector *vector_alloc(size_t m)
+{
+ Vector *v = malloc(sizeof(Vector));
+ assert(v != NULL && "Allocation of vector failed");
+ v->mat = matrix_alloc(m, 1);
+ v->xs = v->mat->xs;
+ v->m = v->mat->m;
+ v->is_colvec = true;
+ return v;
+}
+
+Vector *vector_alloc1(Matrix *mat)
+{
+ assert(matrix_is_colvec(mat) && "Matrix as column vector expected");
+ Vector *v = malloc(sizeof(Vector));
+ v->mat = mat;
+ v->m = mat->m;
+ v->xs = mat->xs;
+ v->is_colvec = true;
+ return v;
+}
+
+void vector_free(Vector *v)
+{
+ matrix_free(v->mat);
+ free(v);
+}
+
+void vector_print(const Vector *v)
+{
+ if (v->is_colvec) matrix_print(v->mat);
+ else matrix_print(matrix_transpose(v->mat));
+}
+
+Vector *vector_from_str(char *str)
+{
+ return vector_alloc1(matrix_from_str(str));
+}
+
+Vector *vector_from_arr(double arr[], size_t m)
+{
+ return vector_alloc1(matrix_from_arr(arr, m, 1));
+}
+
+Vector *vector_unit(size_t m, size_t i)
+{
+ Vector *v = vector_alloc(m);
+
+ vector_foreach_idx(v, it, idx)
+ {
+ if (i != idx) *it = 0;
+ else *it = 1;
+ }
+
+ return v;
+}
+
+Vector *vector_const(size_t m, double x)
+{
+ return vector_alloc1(matrix_const(m, 1, x));
+}
+
+void vector_const1(Vector *v, double x)
+{
+ matrix_const1(v->mat, x);
+}
+
+Vector *vector_slice(const Vector *v, size_t i, size_t j)
+{
+ assert(j < v->m && i < j && "Valid start and end positions expected");
+
+ Vector *w = vector_alloc(j - i);
+
+ vector_foreach_idx(w, it, idx)
+ *it = vector_at(v, i + idx);
+
+ return w;
+}
+
+Vector *vector_copy(const Vector *v)
+{
+ return vector_alloc1(matrix_copy(v->mat));
+}
+
+void vector_copy1(Vector *u, const Vector *v)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ matrix_copy1(u->mat, v->mat);
+}
+
+Vector *vector_transpose(const Vector *v)
+{
+ Vector *w = vector_copy(v);
+ w->is_colvec = false;
+
+ return w;
+}
+
+void vector_transpose1(Vector *v)
+{
+ v->is_colvec = false;
+}
+
+Vector *vector_add(const Vector *u, const Vector *v)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ return vector_alloc1(matrix_add(u->mat, v->mat));
+}
+
+void vector_add1(Vector *u, const Vector *v)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ matrix_add1(u->mat, v->mat);
+}
+
+Vector *vector_scale(const Vector *v, double x)
+{
+ return vector_alloc1(matrix_scale(v->mat, x));
+}
+
+void vector_scale1(Vector *v, double x)
+{
+ matrix_scale1(v->mat, x);
+}
+
+Vector *vector_sub(const Vector *u, const Vector *v)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ return vector_alloc1(matrix_sub(u->mat, v->mat));
+}
+
+void vector_sub1(Vector *u, const Vector *v)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ matrix_sub1(u->mat, v->mat);
+}
+
+Vector *vector_rand(size_t m, int bound_l, int bound_u)
+{
+ return vector_alloc1(matrix_rand(m, 1, bound_l, bound_u, MATRIX_NONE));
+}
+
+void vector_rand1(Vector *v, int bound_l, int bound_u)
+{
+ matrix_rand1(v->mat, bound_l, bound_u, MATRIX_NONE);
+}
+
+bool vector_eq(const Vector *u, const Vector *v, double tol)
+{
+ assert(VECTOR_DIM_MATCH(u, v) && "Dimension mismatch");
+
+ return matrix_eq(u->mat, v->mat, tol);
+}
+
+double vector_norm_p(const Vector *v, size_t p)
+{
+ assert(p >= 1 && "Nonzero p expected");
+
+ double tmp = 0;
+ vector_foreach(v, it)
+ tmp += pow(ABS(*it), p);
+ return pow(tmp, 1.0/p);
+}
+
+double vector_norm_max(const Vector *v)
+{
+ double tmp = ABS(v->xs[0]);
+ vector_foreach(v, it)
+ if (ABS(*it) > tmp) tmp = ABS(*it);
+
+ return tmp;
+}
diff --git a/vector.h b/vector.h
new file mode 100644
index 0000000..c10a765
--- /dev/null
+++ b/vector.h
@@ -0,0 +1,67 @@
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include <stddef.h>
+
+#include "matrix.h"
+
+#define vector_at(v, i) ((v)->xs[(i)])
+
+#define vector_loop(v, i) matrix_loop((v)->mat, i)
+
+#define vector_foreach(v, it) matrix_foreach((v)->mat, it)
+
+#define vector_foreach_idx(v, it, i) matrix_foreach_idx((v)->mat, it, i, _)
+
+#define VECTOR_DIM_MATCH(v1, v2) ((v1)->m == (v2)->m)
+
+typedef struct {
+ double *xs;
+ size_t m;
+ Matrix *mat;
+ bool is_colvec;
+} Vector;
+
+Vector *vector_alloc(size_t m);
+Vector *vector_alloc1(Matrix *mat);
+
+void vector_free(Vector *v);
+
+void vector_print(const Vector *v);
+
+Vector *vector_from_str(char *str);
+Vector *vector_from_arr(double arr[], size_t m);
+
+Vector *vector_unit(size_t m, size_t i);
+
+Vector *vector_const(size_t m, double x);
+void vector_const1(Vector *v, double x);
+
+Vector *vector_slice(const Vector *v, size_t i, size_t j);
+
+Vector *vector_copy(const Vector *v);
+void vector_copy1(Vector *u, const Vector *v);
+
+Vector *vector_transpose(const Vector *v);
+void vector_transpose1(Vector *v);
+
+Vector *vector_add(const Vector *u, const Vector *v);
+void vector_add1(Vector *u, const Vector *v);
+
+Vector *vector_scale(const Vector *v, double x);
+void vector_scale1(Vector *v, double x);
+
+double vector_norm_p(const Vector *x, size_t p);
+
+Vector *vector_sub(const Vector *u, const Vector *v);
+void vector_sub1(Vector *u, const Vector *v);
+
+Vector *vector_rand(size_t m, int bound_l, int bound_u);
+void vector_rand1(Vector *v, int bound_l, int bound_u);
+
+bool vector_eq(const Vector *u, const Vector *v, double tol);
+
+double vector_norm_p(const Vector *v, size_t p);
+double vector_norm_max(const Vector *v);
+
+#endif