aboutsummaryrefslogtreecommitdiff
path: root/src/core/kernel.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-14 12:20:52 +0200
committerhachem <im@hachem.wtf>2026-09-14 12:20:52 +0200
commitee14ad272e68d9363202d7f668e0b20302827209 (patch)
tree88dd1012ad7f9d6ac7abeb7562dac2194794b823 /src/core/kernel.c
parentae07aab1442a45bbddb79e066f15eaf252a4254a (diff)
feat: simd + testing + formatting
Diffstat (limited to 'src/core/kernel.c')
-rw-r--r--src/core/kernel.c116
1 files changed, 63 insertions, 53 deletions
diff --git a/src/core/kernel.c b/src/core/kernel.c
index f8f7dfd..def0782 100644
--- a/src/core/kernel.c
+++ b/src/core/kernel.c
@@ -6,19 +6,19 @@
#include <stdlib.h>
#include <string.h>
-static char *dup_string(const char *s)
+static char* dup_string(const char* s)
{
size_t n = strlen(s) + 1;
- char *p = malloc(n);
+ char* p = malloc(n);
assert(p != NULL);
memcpy(p, s, n);
return p;
}
-static size_t *dup_targets(const size_t *targets, size_t count)
+static size_t* dup_targets(const size_t* targets, size_t count)
{
- size_t *p = malloc(count * sizeof(size_t));
+ size_t* p = malloc(count * sizeof(size_t));
assert(p != NULL || count == 0);
if (count > 0)
@@ -27,29 +27,30 @@ static size_t *dup_targets(const size_t *targets, size_t count)
return p;
}
-static bool starts_with(const char *s, const char *prefix)
+static bool starts_with(const char* s, const char* prefix)
{
return strncmp(s, prefix, strlen(prefix)) == 0;
}
-static enum PsiGateType detect_gate_type(const char *name, struct PsiMatrix matrix)
+static enum PsiGateType detect_gate_type(const char* name, struct PsiMatrix matrix)
{
- static const char *diagonal[] = { "Z", "S", "T", "Sdg", "Tdg", "Rz", "P", "U1", "CZ", "CP", "CRz" };
+ static const char* diagonal[] = { "Z", "S", "T", "Sdg", "Tdg", "Rz",
+ "P", "U1", "CZ", "CP", "CRz" };
for (size_t i = 0; i < sizeof(diagonal) / sizeof(diagonal[0]); i++)
if (starts_with(name, diagonal[i]))
return PSI_GATE_TYPE_DIAGONAL;
- static const char *controlled[] = { "CNOT", "CZ", "SWAP", "CRx", "CRy", "CRz", "CP", "CCNOT", "CSWAP" };
+ static const char* controlled[] = { "CNOT", "CZ", "SWAP", "CRx", "CRy",
+ "CRz", "CP", "CCNOT", "CSWAP" };
for (size_t i = 0; i < sizeof(controlled) / sizeof(controlled[0]); i++)
if (starts_with(name, controlled[i]))
return PSI_GATE_TYPE_CONTROLLED;
if (matrix.rows == 2 && matrix.cols == 2)
{
- bool is_diag = fabs(matrix.data[1].real) < 1e-10
- && fabs(matrix.data[1].imaginary) < 1e-10
- && fabs(matrix.data[2].real) < 1e-10
- && fabs(matrix.data[2].imaginary) < 1e-10;
+ bool is_diag = fabs(matrix.data[1].real) < 1e-10 &&
+ fabs(matrix.data[1].imaginary) < 1e-10 && fabs(matrix.data[2].real) < 1e-10 &&
+ fabs(matrix.data[2].imaginary) < 1e-10;
if (is_diag)
return PSI_GATE_TYPE_DIAGONAL;
}
@@ -57,7 +58,8 @@ static enum PsiGateType detect_gate_type(const char *name, struct PsiMatrix matr
return PSI_GATE_TYPE_NON_DIAGONAL;
}
-struct PsiKernel psi_new_kernel(const char *name, struct PsiMatrix matrix, const size_t *targets, size_t target_count)
+struct PsiKernel psi_new_kernel(const char* name, struct PsiMatrix matrix, const size_t* targets,
+ size_t target_count)
{
struct PsiKernel kernel;
kernel.matrix = matrix;
@@ -81,7 +83,7 @@ struct PsiKernel psi_clone_kernel(struct PsiKernel kernel)
return copy;
}
-void psi_free_kernel(struct PsiKernel *kernel)
+void psi_free_kernel(struct PsiKernel* kernel)
{
psi_free_matrix(&kernel->matrix);
free(kernel->targets);
@@ -118,7 +120,8 @@ bool psi_kernels_commute(struct PsiKernel a, struct PsiKernel b)
if (!psi_kernels_share_qubits(a, b))
return true;
- if (a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL && targets_equal(a, b))
+ if (a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL &&
+ targets_equal(a, b))
return true;
return false;
@@ -132,17 +135,18 @@ bool psi_kernels_can_fuse(struct PsiKernel a, struct PsiKernel b)
return a.targets[0] == b.targets[0];
}
-bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel *out)
+bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel* out)
{
if (!psi_kernels_can_fuse(a, b))
return false;
- enum PsiGateType new_type = a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL
- ? PSI_GATE_TYPE_DIAGONAL
- : PSI_GATE_TYPE_NON_DIAGONAL;
+ enum PsiGateType new_type =
+ a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL
+ ? PSI_GATE_TYPE_DIAGONAL
+ : PSI_GATE_TYPE_NON_DIAGONAL;
size_t name_len = strlen(a.name) + strlen(b.name) + 2;
- char *fused_name = malloc(name_len);
+ char* fused_name = malloc(name_len);
assert(fused_name != NULL);
snprintf(fused_name, name_len, "%s+%s", a.name, b.name);
@@ -155,13 +159,14 @@ bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel *
return true;
}
-static struct PsiComplex *apply_kernel(const struct PsiComplex *state, struct PsiKernel kernel, size_t num_qubits)
+static struct PsiComplex* apply_kernel(const struct PsiComplex* state, struct PsiKernel kernel,
+ size_t num_qubits)
{
size_t dim = (size_t)1 << num_qubits;
size_t g = kernel.target_count;
size_t gate_dim = (size_t)1 << g;
- size_t *target_bits = malloc(g * sizeof(size_t));
+ size_t* target_bits = malloc(g * sizeof(size_t));
assert(target_bits != NULL || g == 0);
for (size_t k = 0; k < g; k++)
target_bits[k] = num_qubits - 1 - kernel.targets[k];
@@ -170,7 +175,7 @@ static struct PsiComplex *apply_kernel(const struct PsiComplex *state, struct Ps
for (size_t k = 0; k < g; k++)
non_target_mask &= ~((size_t)1 << target_bits[k]);
- struct PsiComplex *new_state = malloc(dim * sizeof(struct PsiComplex));
+ struct PsiComplex* new_state = malloc(dim * sizeof(struct PsiComplex));
assert(new_state != NULL);
for (size_t i = 0; i < dim; i++)
@@ -213,7 +218,7 @@ struct PsiKernelBatch psi_new_kernel_batch(size_t num_qubits)
return batch;
}
-void psi_free_kernel_batch(struct PsiKernelBatch *batch)
+void psi_free_kernel_batch(struct PsiKernelBatch* batch)
{
for (size_t i = 0; i < batch->count; i++)
psi_free_kernel(&batch->kernels[i]);
@@ -224,7 +229,7 @@ void psi_free_kernel_batch(struct PsiKernelBatch *batch)
batch->capacity = 0;
}
-void psi_add_kernel(struct PsiKernelBatch *batch, struct PsiKernel kernel)
+void psi_add_kernel(struct PsiKernelBatch* batch, struct PsiKernel kernel)
{
if (batch->count == batch->capacity)
{
@@ -237,13 +242,13 @@ void psi_add_kernel(struct PsiKernelBatch *batch, struct PsiKernel kernel)
batch->kernels[batch->count++] = kernel;
}
-void psi_optimize_kernel_batch(struct PsiKernelBatch *batch)
+void psi_optimize_kernel_batch(struct PsiKernelBatch* batch)
{
if (batch->count < 2)
return;
size_t original = batch->count;
- struct PsiKernel *out = malloc(original * sizeof(struct PsiKernel));
+ struct PsiKernel* out = malloc(original * sizeof(struct PsiKernel));
assert(out != NULL);
size_t out_count = 0;
@@ -273,27 +278,28 @@ void psi_optimize_kernel_batch(struct PsiKernelBatch *batch)
batch->capacity = original;
}
-void psi_execute_kernel_batch(struct PsiKernelBatch batch, struct PsiVector *state)
+void psi_execute_kernel_batch(struct PsiKernelBatch batch, struct PsiVector* state)
{
size_t dim = (size_t)1 << batch.num_qubits;
assert(state->size == dim);
for (size_t i = 0; i < batch.count; i++)
{
- struct PsiComplex *next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits);
+ struct PsiComplex* next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits);
free(state->data);
state->data = next;
}
}
-void psi_apply_kernel(struct PsiVector *state, struct PsiKernel kernel, size_t num_qubits)
+void psi_apply_kernel(struct PsiVector* state, struct PsiKernel kernel, size_t num_qubits)
{
- struct PsiComplex *next = apply_kernel(state->data, kernel, num_qubits);
+ struct PsiComplex* next = apply_kernel(state->data, kernel, num_qubits);
free(state->data);
state->data = next;
}
-static void push_kernel(struct PsiKernel **kernels, size_t *count, size_t *capacity, struct PsiKernel kernel)
+static void push_kernel(struct PsiKernel** kernels, size_t* count, size_t* capacity,
+ struct PsiKernel kernel)
{
if (*count == *capacity)
{
@@ -315,7 +321,7 @@ static bool layer_can_add(struct PsiExecutionLayer layer, struct PsiKernel kerne
return true;
}
-static void free_layer(struct PsiExecutionLayer *layer)
+static void free_layer(struct PsiExecutionLayer* layer)
{
for (size_t i = 0; i < layer->count; i++)
psi_free_kernel(&layer->kernels[i]);
@@ -341,7 +347,7 @@ struct PsiStructureAwareBatch psi_new_structure_aware_batch(size_t num_qubits)
return batch;
}
-static void clear_layers(struct PsiStructureAwareBatch *batch)
+static void clear_layers(struct PsiStructureAwareBatch* batch)
{
for (size_t i = 0; i < batch->layer_count; i++)
free_layer(&batch->layers[i]);
@@ -352,7 +358,7 @@ static void clear_layers(struct PsiStructureAwareBatch *batch)
batch->layer_capacity = 0;
}
-void psi_free_structure_aware_batch(struct PsiStructureAwareBatch *batch)
+void psi_free_structure_aware_batch(struct PsiStructureAwareBatch* batch)
{
for (size_t i = 0; i < batch->count; i++)
psi_free_kernel(&batch->kernels[i]);
@@ -364,13 +370,13 @@ void psi_free_structure_aware_batch(struct PsiStructureAwareBatch *batch)
clear_layers(batch);
}
-void psi_add_structure_aware_kernel(struct PsiStructureAwareBatch *batch, struct PsiKernel kernel)
+void psi_add_structure_aware_kernel(struct PsiStructureAwareBatch* batch, struct PsiKernel kernel)
{
push_kernel(&batch->kernels, &batch->count, &batch->capacity, kernel);
batch->optimised = false;
}
-static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch *batch, size_t index)
+static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch* batch, size_t index)
{
struct PsiKernel removed = batch->kernels[index];
for (size_t i = index; i + 1 < batch->count; i++)
@@ -380,7 +386,8 @@ static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch *batch, s
return removed;
}
-static void insert_kernel_at(struct PsiStructureAwareBatch *batch, size_t index, struct PsiKernel kernel)
+static void insert_kernel_at(struct PsiStructureAwareBatch* batch, size_t index,
+ struct PsiKernel kernel)
{
if (batch->count == batch->capacity)
{
@@ -397,7 +404,7 @@ static void insert_kernel_at(struct PsiStructureAwareBatch *batch, size_t index,
batch->count++;
}
-static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch)
+static void reorder_commuting_gates(struct PsiStructureAwareBatch* batch)
{
bool changed = true;
size_t iterations = 0;
@@ -413,9 +420,8 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch)
struct PsiKernel current = batch->kernels[i];
struct PsiKernel next = batch->kernels[i + 1];
- if (current.target_count != 1 || next.target_count != 1
- || current.targets[0] == next.targets[0]
- || !psi_kernels_commute(current, next))
+ if (current.target_count != 1 || next.target_count != 1 ||
+ current.targets[0] == next.targets[0] || !psi_kernels_commute(current, next))
continue;
for (size_t j = i + 2; j < batch->count; j++)
@@ -428,7 +434,8 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch)
for (size_t k = i + 1; k < j; k++)
{
struct PsiKernel between = batch->kernels[k];
- if (psi_kernels_share_qubits(between, current) && !psi_kernels_commute(current, between))
+ if (psi_kernels_share_qubits(between, current) &&
+ !psi_kernels_commute(current, between))
{
can_move = false;
break;
@@ -447,7 +454,7 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch)
}
}
-static void multi_pass_fusion(struct PsiStructureAwareBatch *batch)
+static void multi_pass_fusion(struct PsiStructureAwareBatch* batch)
{
bool changed = true;
size_t iterations = 0;
@@ -458,7 +465,7 @@ static void multi_pass_fusion(struct PsiStructureAwareBatch *batch)
changed = false;
iterations++;
- struct PsiKernel *new_kernels = NULL;
+ struct PsiKernel* new_kernels = NULL;
size_t new_count = 0;
size_t new_capacity = 0;
@@ -490,7 +497,7 @@ static void multi_pass_fusion(struct PsiStructureAwareBatch *batch)
}
}
-static void build_execution_layers(struct PsiStructureAwareBatch *batch)
+static void build_execution_layers(struct PsiStructureAwareBatch* batch)
{
clear_layers(batch);
@@ -502,8 +509,9 @@ static void build_execution_layers(struct PsiStructureAwareBatch *batch)
for (size_t l = 0; l < batch->layer_count; l++)
if (layer_can_add(batch->layers[l], kernel))
{
- struct PsiExecutionLayer *layer = &batch->layers[l];
- push_kernel(&layer->kernels, &layer->count, &layer->capacity, psi_clone_kernel(kernel));
+ struct PsiExecutionLayer* layer = &batch->layers[l];
+ push_kernel(&layer->kernels, &layer->count, &layer->capacity,
+ psi_clone_kernel(kernel));
placed = true;
break;
}
@@ -528,7 +536,7 @@ static void build_execution_layers(struct PsiStructureAwareBatch *batch)
}
}
-void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch *batch)
+void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch* batch)
{
if (batch->optimised || batch->count < 2)
return;
@@ -539,20 +547,21 @@ void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch *batch)
batch->optimised = true;
}
-void psi_execute_structure_aware_batch(struct PsiStructureAwareBatch batch, struct PsiVector *state)
+void psi_execute_structure_aware_batch(struct PsiStructureAwareBatch batch, struct PsiVector* state)
{
size_t dim = (size_t)1 << batch.num_qubits;
assert(state->size == dim);
for (size_t i = 0; i < batch.count; i++)
{
- struct PsiComplex *next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits);
+ struct PsiComplex* next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits);
free(state->data);
state->data = next;
}
}
-void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch batch, struct PsiVector *state)
+void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch batch,
+ struct PsiVector* state)
{
size_t dim = (size_t)1 << batch.num_qubits;
assert(state->size == dim);
@@ -560,7 +569,8 @@ void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch bat
for (size_t l = 0; l < batch.layer_count; l++)
for (size_t k = 0; k < batch.layers[l].count; k++)
{
- struct PsiComplex *next = apply_kernel(state->data, batch.layers[l].kernels[k], batch.num_qubits);
+ struct PsiComplex* next =
+ apply_kernel(state->data, batch.layers[l].kernels[k], batch.num_qubits);
free(state->data);
state->data = next;
}