diff options
| author | hachem <im@hachem.wtf> | 2026-09-20 18:37:48 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-20 18:37:48 +0200 |
| commit | a136c80d978841d317a6ad3930b9e608fdba1586 (patch) | |
| tree | 7dde0e0372f60125bd7cb5f851f22efb01be703b /src/core/kernel.c | |
| parent | e1f5c41c35fe26fddf5163ec06f78efd61ad35f4 (diff) | |
Diffstat (limited to 'src/core/kernel.c')
| -rw-r--r-- | src/core/kernel.c | 90 |
1 files changed, 65 insertions, 25 deletions
diff --git a/src/core/kernel.c b/src/core/kernel.c index 377982f..063d47f 100644 --- a/src/core/kernel.c +++ b/src/core/kernel.c @@ -6,6 +6,8 @@ #include <stdlib.h> #include <string.h> +#include "parallel.h" + static char* dup_string(const char* s) { size_t n = strlen(s) + 1; @@ -159,8 +161,49 @@ 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) +struct PsiKernelApply +{ + const struct PsiComplex* state; + struct PsiComplex* new_state; + struct PsiMatrix matrix; + const size_t* target_bits; + size_t g; + size_t gate_dim; + size_t non_target_mask; +}; + +static void kernel_apply_range(size_t start, size_t end, void* vctx) +{ + struct PsiKernelApply* c = vctx; + + for (size_t i = start; i < end; i++) + { + size_t target_idx = 0; + for (size_t k = 0; k < c->g; k++) + if ((i >> c->target_bits[k]) & 1) + target_idx |= (size_t)1 << (c->g - 1 - k); + + struct PsiComplex sum = psi_new_complex(0.0, 0.0); + for (size_t j = 0; j < c->gate_dim; j++) + { + struct PsiComplex gate_elem = c->matrix.data[target_idx * c->gate_dim + j]; + if (fabs(gate_elem.real) < 1e-15 && fabs(gate_elem.imaginary) < 1e-15) + continue; + + size_t source_idx = i & c->non_target_mask; + for (size_t k = 0; k < c->g; k++) + if ((j >> (c->g - 1 - k)) & 1) + source_idx |= (size_t)1 << c->target_bits[k]; + + sum = psi_add_complex(sum, psi_mul_complex(gate_elem, c->state[source_idx])); + } + + c->new_state[i] = sum; + } +} + +static struct PsiComplex* run_kernel(const struct PsiComplex* state, struct PsiKernel kernel, + size_t num_qubits, bool parallel) { size_t dim = (size_t)1 << num_qubits; size_t g = kernel.target_count; @@ -178,35 +221,25 @@ static struct PsiComplex* apply_kernel(const struct PsiComplex* state, struct Ps struct PsiComplex* new_state = malloc(dim * sizeof(struct PsiComplex)); assert(new_state != NULL); - for (size_t i = 0; i < dim; i++) - { - size_t target_idx = 0; - for (size_t k = 0; k < g; k++) - if ((i >> target_bits[k]) & 1) - target_idx |= (size_t)1 << (g - 1 - k); + struct PsiKernelApply ctx = { + state, new_state, kernel.matrix, target_bits, g, gate_dim, non_target_mask, + }; - struct PsiComplex sum = psi_new_complex(0.0, 0.0); - for (size_t j = 0; j < gate_dim; j++) - { - struct PsiComplex gate_elem = kernel.matrix.data[target_idx * gate_dim + j]; - if (fabs(gate_elem.real) < 1e-15 && fabs(gate_elem.imaginary) < 1e-15) - continue; - - size_t source_idx = i & non_target_mask; - for (size_t k = 0; k < g; k++) - if ((j >> (g - 1 - k)) & 1) - source_idx |= (size_t)1 << target_bits[k]; - - sum = psi_add_complex(sum, psi_mul_complex(gate_elem, state[source_idx])); - } - - new_state[i] = sum; - } + if (parallel) + psi_parallel_for(dim, kernel_apply_range, &ctx); + else + kernel_apply_range(0, dim, &ctx); free(target_bits); return new_state; } +static struct PsiComplex* apply_kernel(const struct PsiComplex* state, struct PsiKernel kernel, + size_t num_qubits) +{ + return run_kernel(state, kernel, num_qubits, false); +} + struct PsiKernelBatch psi_new_kernel_batch(size_t num_qubits) { struct PsiKernelBatch batch; @@ -298,6 +331,13 @@ void psi_apply_kernel(struct PsiVector* state, struct PsiKernel kernel, size_t n state->data = next; } +void psi_apply_kernel_parallel(struct PsiVector* state, struct PsiKernel kernel, size_t num_qubits) +{ + struct PsiComplex* next = run_kernel(state->data, kernel, num_qubits, true); + free(state->data); + state->data = next; +} + static void push_kernel(struct PsiKernel** kernels, size_t* count, size_t* capacity, struct PsiKernel kernel) { |
