diff options
| author | hachem <im@hachem.wtf> | 2026-09-14 12:20:52 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-14 12:20:52 +0200 |
| commit | ee14ad272e68d9363202d7f668e0b20302827209 (patch) | |
| tree | 88dd1012ad7f9d6ac7abeb7562dac2194794b823 /src/core/kernel.c | |
| parent | ae07aab1442a45bbddb79e066f15eaf252a4254a (diff) | |
feat: simd + testing + formatting
Diffstat (limited to 'src/core/kernel.c')
| -rw-r--r-- | src/core/kernel.c | 116 |
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; } |
