aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-08-29 04:34:22 +0200
committerhachem <im@hachem.wtf>2026-08-29 04:34:22 +0200
commitcd69b3c1be9a515906954f48f7f1dbc582f8ad83 (patch)
tree9ef61a5c0987742be55f5edc9c42a9fc20f1812b
parent94612a0be0e691d68bcd27a33e529ad30fa3df43 (diff)
add: vectors
-rw-r--r--src/maths/vector.c162
-rw-r--r--src/maths/vector.h48
-rw-r--r--tester/main.c19
3 files changed, 229 insertions, 0 deletions
diff --git a/src/maths/vector.c b/src/maths/vector.c
new file mode 100644
index 0000000..ea85b8e
--- /dev/null
+++ b/src/maths/vector.c
@@ -0,0 +1,162 @@
+#include "maths/vector.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+static enum PsiVectorKind flip_kind(enum PsiVectorKind kind)
+{
+ if (kind == PSI_ROW_VECTOR)
+ return PSI_COLUMN_VECTOR;
+
+ return PSI_ROW_VECTOR;
+}
+
+struct PsiVector psi_new_vector(size_t size, enum PsiVectorKind kind)
+{
+ // all-zero bits == 0.0 for both components
+ struct PsiComplex *data = calloc(size, sizeof(struct PsiComplex));
+ assert(data != NULL || size == 0);
+
+ return (struct PsiVector)
+ {
+ data,
+ size,
+ kind,
+ };
+}
+
+struct PsiVector psi_new_vector_from(const struct PsiComplex *data, size_t size, enum PsiVectorKind kind)
+{
+ struct PsiVector v = psi_new_vector(size, kind);
+ memcpy(v.data, data, size * sizeof(struct PsiComplex));
+
+ return v;
+}
+
+struct PsiVector psi_clone_vector(struct PsiVector v)
+{
+ return psi_new_vector_from(v.data, v.size, v.kind);
+}
+
+void psi_free_vector(struct PsiVector *v)
+{
+ free(v->data);
+ v->data = NULL;
+ v->size = 0;
+}
+
+struct PsiComplex psi_get_vector(struct PsiVector v, size_t index)
+{
+ assert(index < v.size);
+ return v.data[index];
+}
+
+void psi_set_vector(struct PsiVector *v, size_t index, struct PsiComplex value)
+{
+ assert(index < v->size);
+ v->data[index] = value;
+}
+
+struct PsiComplex psi_dot_vector(struct PsiVector a, struct PsiVector b)
+{
+ assert(a.size == b.size);
+
+ struct PsiComplex sum = psi_new_complex(0.0, 0.0);
+ for (size_t i = 0; i < a.size; i++)
+ sum = psi_add_complex(sum, psi_mul_complex(a.data[i], b.data[i]));
+
+ return sum;
+}
+
+struct PsiComplex psi_norm_vector(struct PsiVector v)
+{
+ struct PsiComplex sum = psi_new_complex(0.0, 0.0);
+ for (size_t i = 0; i < v.size; i++)
+ sum = psi_add_complex(sum, psi_mul_complex(v.data[i], v.data[i]));
+
+ return psi_sqrt_complex(sum);
+}
+
+struct PsiComplex psi_sum_vector(struct PsiVector v)
+{
+ struct PsiComplex sum = psi_new_complex(0.0, 0.0);
+ for (size_t i = 0; i < v.size; i++)
+ sum = psi_add_complex(sum, v.data[i]);
+
+ return sum;
+}
+
+// ordering mirrors rust's derived PartialOrd: real first, then imaginary
+static int less_than(struct PsiComplex a, struct PsiComplex b)
+{
+ if (a.real != b.real)
+ return a.real < b.real;
+
+ return a.imaginary < b.imaginary;
+}
+
+struct PsiComplex psi_max_vector(struct PsiVector v)
+{
+ if (v.size == 0)
+ return psi_new_complex(0.0, 0.0);
+
+ struct PsiComplex best = v.data[0];
+ for (size_t i = 1; i < v.size; i++)
+ if (less_than(best, v.data[i]))
+ best = v.data[i];
+
+ return best;
+}
+
+struct PsiComplex psi_min_vector(struct PsiVector v)
+{
+ if (v.size == 0)
+ return psi_new_complex(0.0, 0.0);
+
+ struct PsiComplex best = v.data[0];
+ for (size_t i = 1; i < v.size; i++)
+ if (less_than(v.data[i], best))
+ best = v.data[i];
+
+ return best;
+}
+
+struct PsiVector psi_add_vector(struct PsiVector a, struct PsiVector b)
+{
+ assert(a.size == b.size);
+
+ struct PsiVector result = psi_new_vector(a.size, a.kind);
+ for (size_t i = 0; i < a.size; i++)
+ result.data[i] = psi_add_complex(a.data[i], b.data[i]);
+
+ return result;
+}
+
+struct PsiVector psi_sub_vector(struct PsiVector a, struct PsiVector b)
+{
+ assert(a.size == b.size);
+
+ struct PsiVector result = psi_new_vector(a.size, a.kind);
+ for (size_t i = 0; i < a.size; i++)
+ result.data[i] = psi_sub_complex(a.data[i], b.data[i]);
+
+ return result;
+}
+
+struct PsiVector psi_scale_vector(struct PsiVector v, struct PsiComplex scalar)
+{
+ struct PsiVector result = psi_new_vector(v.size, v.kind);
+ for (size_t i = 0; i < v.size; i++)
+ result.data[i] = psi_mul_complex(v.data[i], scalar);
+
+ return result;
+}
+
+struct PsiVector psi_transpose_vector(struct PsiVector v)
+{
+ struct PsiVector result = psi_clone_vector(v);
+ result.kind = flip_kind(v.kind);
+
+ return result;
+}
diff --git a/src/maths/vector.h b/src/maths/vector.h
new file mode 100644
index 0000000..5c209bb
--- /dev/null
+++ b/src/maths/vector.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <stddef.h>
+
+#include "maths/complex.h"
+
+enum PsiVectorKind
+{
+ PSI_ROW_VECTOR,
+ PSI_COLUMN_VECTOR,
+};
+
+// owns a heap allocation in `data`; release it with psi_free_vector
+struct PsiVector
+{
+ struct PsiComplex *data;
+ size_t size;
+ enum PsiVectorKind kind;
+};
+
+struct PsiVector psi_new_vector(size_t size, enum PsiVectorKind kind);
+struct PsiVector psi_new_vector_from(const struct PsiComplex *data, size_t size, enum PsiVectorKind kind);
+struct PsiVector psi_clone_vector(struct PsiVector v);
+void psi_free_vector(struct PsiVector *v);
+
+// convenience builders, mirroring the row_vector!/column_vector! macros
+#define psi_row_vector(...) \
+ psi_new_vector_from((struct PsiComplex[]){ __VA_ARGS__ }, \
+ sizeof((struct PsiComplex[]){ __VA_ARGS__ }) / sizeof(struct PsiComplex), \
+ PSI_ROW_VECTOR)
+#define psi_column_vector(...) \
+ psi_new_vector_from((struct PsiComplex[]){ __VA_ARGS__ }, \
+ sizeof((struct PsiComplex[]){ __VA_ARGS__ }) / sizeof(struct PsiComplex), \
+ PSI_COLUMN_VECTOR)
+
+struct PsiComplex psi_get_vector(struct PsiVector v, size_t index);
+void psi_set_vector(struct PsiVector *v, size_t index, struct PsiComplex value);
+
+struct PsiComplex psi_dot_vector(struct PsiVector a, struct PsiVector b);
+struct PsiComplex psi_norm_vector(struct PsiVector v);
+struct PsiComplex psi_sum_vector(struct PsiVector v);
+struct PsiComplex psi_max_vector(struct PsiVector v);
+struct PsiComplex psi_min_vector(struct PsiVector v);
+
+struct PsiVector psi_add_vector(struct PsiVector a, struct PsiVector b);
+struct PsiVector psi_sub_vector(struct PsiVector a, struct PsiVector b);
+struct PsiVector psi_scale_vector(struct PsiVector v, struct PsiComplex scalar);
+struct PsiVector psi_transpose_vector(struct PsiVector v);
diff --git a/tester/main.c b/tester/main.c
index eb629fc..bc29bb1 100644
--- a/tester/main.c
+++ b/tester/main.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include "maths/complex.h"
+#include "maths/vector.h"
#include "psi.h"
int main(void)
@@ -19,5 +20,23 @@ int main(void)
printf("a * b = %g + %gi\n", product.real, product.imaginary);
printf("|a| = %g\n", psi_abs_complex(a));
+ struct PsiVector u = psi_column_vector(
+ psi_new_complex(1.0, 0.0),
+ psi_new_complex(2.0, 0.0),
+ psi_new_complex(3.0, 0.0));
+ struct PsiVector v = psi_column_vector(
+ psi_new_complex(4.0, 0.0),
+ psi_new_complex(5.0, 0.0),
+ psi_new_complex(6.0, 0.0));
+
+ struct PsiComplex dot = psi_dot_vector(u, v);
+ struct PsiComplex norm = psi_norm_vector(u);
+
+ printf("u . v = %g + %gi\n", dot.real, dot.imaginary);
+ printf("|u| = %g + %gi\n", norm.real, norm.imaginary);
+
+ psi_free_vector(&u);
+ psi_free_vector(&v);
+
return 0;
}