From 17598056a69a14e0390a07251d383f413ded9eea Mon Sep 17 00:00:00 2001 From: hachem Date: Fri, 18 Sep 2026 12:25:32 +0200 Subject: feat: add matrix, vector, and circuit display + fmt --- tester/clifford.c | 108 +++++++++++++++++++++++++------------------------- tester/custom_gates.c | 54 ++++++++++++------------- tester/kernels.c | 76 +++++++++++++++++------------------ tester/main.c | 56 +++++++++++++------------- tester/noise.c | 74 +++++++++++++++++----------------- tester/non_clifford.c | 58 +++++++++++++-------------- tester/simd.c | 108 +++++++++++++++++++++++++------------------------- tester/test.c | 84 +++++++++++++++++++-------------------- 8 files changed, 309 insertions(+), 309 deletions(-) (limited to 'tester') diff --git a/tester/clifford.c b/tester/clifford.c index 3be9234..4bed17e 100644 --- a/tester/clifford.c +++ b/tester/clifford.c @@ -4,72 +4,72 @@ static const double R2 = 0.7071067811865476; static void build_bell(struct PsiQuantumCircuit* c) { - psi_apply_h(c, 0); - psi_apply_cnot(c, 0, 1); + psi_apply_h(c, 0); + psi_apply_cnot(c, 0, 1); } static void build_ghz(struct PsiQuantumCircuit* c) { - psi_apply_h(c, 0); - psi_apply_cnot(c, 0, 1); - psi_apply_cnot(c, 0, 2); + psi_apply_h(c, 0); + psi_apply_cnot(c, 0, 1); + psi_apply_cnot(c, 0, 2); } void run_clifford_tests(void) { - psi_test_section("Clifford gates"); + psi_test_section("Clifford gates"); - struct PsiQuantumCircuit x = psi_new_quantum_circuit(1); - psi_apply_x(&x, 0); - struct PsiComplex x_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; - psi_check_circuit("X|0> = |1>", &x, x_exp, 2); - psi_free_quantum_circuit(&x); + struct PsiQuantumCircuit x = psi_new_quantum_circuit(1); + psi_apply_x(&x, 0); + struct PsiComplex x_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; + psi_check_circuit("X|0> = |1>", &x, x_exp, 2); + psi_free_quantum_circuit(&x); - struct PsiQuantumCircuit bell = psi_new_quantum_circuit(2); - build_bell(&bell); - struct PsiComplex bell_exp[] = { - psi_new_complex(R2, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(R2, 0.0), - }; - psi_check_circuit("Bell = (|00>+|11>)/sqrt2", &bell, bell_exp, 4); - psi_free_quantum_circuit(&bell); + struct PsiQuantumCircuit bell = psi_new_quantum_circuit(2); + build_bell(&bell); + struct PsiComplex bell_exp[] = { + psi_new_complex(R2, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(R2, 0.0), + }; + psi_check_circuit("Bell = (|00>+|11>)/sqrt2", &bell, bell_exp, 4); + psi_free_quantum_circuit(&bell); - struct PsiQuantumCircuit ghz = psi_new_quantum_circuit(3); - build_ghz(&ghz); - struct PsiComplex ghz_exp[] = { - psi_new_complex(R2, 0.0), psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(R2, 0.0), - }; - psi_check_circuit("GHZ = (|000>+|111>)/sqrt2", &ghz, ghz_exp, 8); - psi_free_quantum_circuit(&ghz); + struct PsiQuantumCircuit ghz = psi_new_quantum_circuit(3); + build_ghz(&ghz); + struct PsiComplex ghz_exp[] = { + psi_new_complex(R2, 0.0), psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(R2, 0.0), + }; + psi_check_circuit("GHZ = (|000>+|111>)/sqrt2", &ghz, ghz_exp, 8); + psi_free_quantum_circuit(&ghz); - struct PsiQuantumCircuit swap = psi_new_quantum_circuit(2); - psi_apply_x(&swap, 0); - psi_apply_cnot(&swap, 0, 1); - psi_apply_cnot(&swap, 1, 0); - psi_apply_cnot(&swap, 0, 1); - struct PsiComplex swap_exp[] = { - psi_new_complex(0.0, 0.0), - psi_new_complex(1.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - }; - psi_check_circuit("SWAP via 3 CNOTs: |10> -> |01>", &swap, swap_exp, 4); - psi_free_quantum_circuit(&swap); + struct PsiQuantumCircuit swap = psi_new_quantum_circuit(2); + psi_apply_x(&swap, 0); + psi_apply_cnot(&swap, 0, 1); + psi_apply_cnot(&swap, 1, 0); + psi_apply_cnot(&swap, 0, 1); + struct PsiComplex swap_exp[] = { + psi_new_complex(0.0, 0.0), + psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + }; + psi_check_circuit("SWAP via 3 CNOTs: |10> -> |01>", &swap, swap_exp, 4); + psi_free_quantum_circuit(&swap); - struct PsiQuantumCircuit toffoli = psi_new_quantum_circuit(3); - psi_apply_x(&toffoli, 0); - psi_apply_x(&toffoli, 1); - psi_apply_ccnot(&toffoli, 0, 1, 2); - struct PsiComplex toffoli_exp[8]; - for (size_t i = 0; i < 8; i++) - toffoli_exp[i] = psi_new_complex(0.0, 0.0); - toffoli_exp[7] = psi_new_complex(1.0, 0.0); - psi_check_circuit("Toffoli: |110> -> |111>", &toffoli, toffoli_exp, 8); - psi_free_quantum_circuit(&toffoli); + struct PsiQuantumCircuit toffoli = psi_new_quantum_circuit(3); + psi_apply_x(&toffoli, 0); + psi_apply_x(&toffoli, 1); + psi_apply_ccnot(&toffoli, 0, 1, 2); + struct PsiComplex toffoli_exp[8]; + for (size_t i = 0; i < 8; i++) + toffoli_exp[i] = psi_new_complex(0.0, 0.0); + toffoli_exp[7] = psi_new_complex(1.0, 0.0); + psi_check_circuit("Toffoli: |110> -> |111>", &toffoli, toffoli_exp, 8); + psi_free_quantum_circuit(&toffoli); - psi_check_runtimes_agree("Runtimes agree on GHZ", 3, build_ghz); + psi_check_runtimes_agree("Runtimes agree on GHZ", 3, build_ghz); } diff --git a/tester/custom_gates.c b/tester/custom_gates.c index df2d9ae..8831e8c 100644 --- a/tester/custom_gates.c +++ b/tester/custom_gates.c @@ -4,33 +4,33 @@ static const double R2 = 0.7071067811865476; void run_custom_tests(void) { - psi_test_section("Custom gates"); + psi_test_section("Custom gates"); - struct PsiCompositeGateOp bell_ops[] = { - { PSI_OP_H, { 0 }, 1 }, - { PSI_OP_CNOT, { 0, 1 }, 2 }, - }; - struct PsiCustomGate bell = psi_new_custom_gate_from_composite("BELL", 2, bell_ops, 2); - struct PsiQuantumCircuit c = psi_new_quantum_circuit(2); - size_t bell_targets[] = { 0, 1 }; - psi_apply_custom(&c, bell, bell_targets, 2); - struct PsiComplex bell_exp[] = { - psi_new_complex(R2, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(R2, 0.0), - }; - psi_check_circuit("composite BELL gate -> Bell state", &c, bell_exp, 4); - psi_free_quantum_circuit(&c); + struct PsiCompositeGateOp bell_ops[] = { + { PSI_OP_H, { 0 }, 1 }, + { PSI_OP_CNOT, { 0, 1 }, 2 }, + }; + struct PsiCustomGate bell = psi_new_custom_gate_from_composite("BELL", 2, bell_ops, 2); + struct PsiQuantumCircuit c = psi_new_quantum_circuit(2); + size_t bell_targets[] = { 0, 1 }; + psi_apply_custom(&c, bell, bell_targets, 2); + struct PsiComplex bell_exp[] = { + psi_new_complex(R2, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(R2, 0.0), + }; + psi_check_circuit("composite BELL gate -> Bell state", &c, bell_exp, 4); + psi_free_quantum_circuit(&c); - struct PsiCustomGate custom_x = psi_new_custom_gate_from_matrix( - "MYX", - psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0), - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0))); - struct PsiQuantumCircuit c2 = psi_new_quantum_circuit(1); - size_t x_targets[] = { 0 }; - psi_apply_custom(&c2, custom_x, x_targets, 1); - struct PsiComplex x_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; - psi_check_circuit("from_matrix X custom gate: |0> -> |1>", &c2, x_exp, 2); - psi_free_quantum_circuit(&c2); + struct PsiCustomGate custom_x = psi_new_custom_gate_from_matrix( + "MYX", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0), + psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0))); + struct PsiQuantumCircuit c2 = psi_new_quantum_circuit(1); + size_t x_targets[] = { 0 }; + psi_apply_custom(&c2, custom_x, x_targets, 1); + struct PsiComplex x_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; + psi_check_circuit("from_matrix X custom gate: |0> -> |1>", &c2, x_exp, 2); + psi_free_quantum_circuit(&c2); } diff --git a/tester/kernels.c b/tester/kernels.c index 91a5cba..f3e4e46 100644 --- a/tester/kernels.c +++ b/tester/kernels.c @@ -4,50 +4,50 @@ static const double R2 = 0.7071067811865476; static void build_fusion(struct PsiQuantumCircuit* c) { - psi_apply_h(c, 0); - psi_apply_z(c, 0); - psi_apply_h(c, 0); - psi_apply_x(c, 1); - psi_apply_x(c, 1); + psi_apply_h(c, 0); + psi_apply_z(c, 0); + psi_apply_h(c, 0); + psi_apply_x(c, 1); + psi_apply_x(c, 1); } void run_kernel_tests(void) { - psi_test_section("Kernel batching and fusion"); + psi_test_section("Kernel batching and fusion"); - struct PsiQuantumCircuit hh = psi_new_quantum_circuit(1); - psi_apply_h(&hh, 0); - psi_apply_h(&hh, 0); - struct PsiComplex hh_exp[] = { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }; - psi_check_circuit("H then H = identity", &hh, hh_exp, 2); - psi_free_quantum_circuit(&hh); + struct PsiQuantumCircuit hh = psi_new_quantum_circuit(1); + psi_apply_h(&hh, 0); + psi_apply_h(&hh, 0); + struct PsiComplex hh_exp[] = { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }; + psi_check_circuit("H then H = identity", &hh, hh_exp, 2); + psi_free_quantum_circuit(&hh); - struct PsiKernel a = - psi_new_kernel("H", - psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), - psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), - (size_t[]){ 0 }, 1); - struct PsiKernel b = psi_clone_kernel(a); - psi_test_check(psi_kernels_can_fuse(a, b), "adjacent single-qubit kernels fuse"); - psi_free_kernel(&a); - psi_free_kernel(&b); + struct PsiKernel a = + psi_new_kernel("H", + psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), + psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), + (size_t[]){ 0 }, 1); + struct PsiKernel b = psi_clone_kernel(a); + psi_test_check(psi_kernels_can_fuse(a, b), "adjacent single-qubit kernels fuse"); + psi_free_kernel(&a); + psi_free_kernel(&b); - struct PsiKernelBatch batch = psi_new_kernel_batch(1); - psi_add_kernel( - &batch, - psi_new_kernel("H", - psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), - psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), - (size_t[]){ 0 }, 1)); - psi_add_kernel( - &batch, - psi_new_kernel("H", - psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), - psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), - (size_t[]){ 0 }, 1)); - psi_optimize_kernel_batch(&batch); - psi_test_check(batch.count == 1, "batch fuses two H kernels into one"); - psi_free_kernel_batch(&batch); + struct PsiKernelBatch batch = psi_new_kernel_batch(1); + psi_add_kernel( + &batch, + psi_new_kernel("H", + psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), + psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), + (size_t[]){ 0 }, 1)); + psi_add_kernel( + &batch, + psi_new_kernel("H", + psi_matrix(2, 2, psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0), + psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0)), + (size_t[]){ 0 }, 1)); + psi_optimize_kernel_batch(&batch); + psi_test_check(batch.count == 1, "batch fuses two H kernels into one"); + psi_free_kernel_batch(&batch); - psi_check_runtimes_agree("Runtimes agree on fusion circuit", 2, build_fusion); + psi_check_runtimes_agree("Runtimes agree on fusion circuit", 2, build_fusion); } diff --git a/tester/main.c b/tester/main.c index c516568..a17e8f5 100644 --- a/tester/main.c +++ b/tester/main.c @@ -5,37 +5,37 @@ static bool has_arg(int argc, char** argv, const char* name) { - for (int i = 1; i < argc; i++) - if (strcmp(argv[i], name) == 0) - return true; + for (int i = 1; i < argc; i++) + if (strcmp(argv[i], name) == 0) + return true; - return false; + return false; } int main(int argc, char** argv) { - if (has_arg(argc, argv, "help") || has_arg(argc, argv, "--help") || has_arg(argc, argv, "-h")) - { - printf("Usage: tester [clifford|non-clifford|custom|kernels|simd|noise|all]\n"); - return 0; - } - - bool all = argc < 2 || has_arg(argc, argv, "all"); - - printf("psi %s test suite\n", psi_version()); - - if (all || has_arg(argc, argv, "clifford")) - run_clifford_tests(); - if (all || has_arg(argc, argv, "non-clifford")) - run_non_clifford_tests(); - if (all || has_arg(argc, argv, "custom")) - run_custom_tests(); - if (all || has_arg(argc, argv, "kernels")) - run_kernel_tests(); - if (all || has_arg(argc, argv, "simd")) - run_simd_tests(); - if (all || has_arg(argc, argv, "noise")) - run_noise_tests(); - - return psi_test_summary(); + if (has_arg(argc, argv, "help") || has_arg(argc, argv, "--help") || has_arg(argc, argv, "-h")) + { + printf("Usage: tester [clifford|non-clifford|custom|kernels|simd|noise|all]\n"); + return 0; + } + + bool all = argc < 2 || has_arg(argc, argv, "all"); + + printf("psi %s test suite\n", psi_version()); + + if (all || has_arg(argc, argv, "clifford")) + run_clifford_tests(); + if (all || has_arg(argc, argv, "non-clifford")) + run_non_clifford_tests(); + if (all || has_arg(argc, argv, "custom")) + run_custom_tests(); + if (all || has_arg(argc, argv, "kernels")) + run_kernel_tests(); + if (all || has_arg(argc, argv, "simd")) + run_simd_tests(); + if (all || has_arg(argc, argv, "noise")) + run_noise_tests(); + + return psi_test_summary(); } diff --git a/tester/noise.c b/tester/noise.c index df791ae..184537c 100644 --- a/tester/noise.c +++ b/tester/noise.c @@ -4,46 +4,46 @@ void run_noise_tests(void) { - psi_test_section("Noise channels"); + psi_test_section("Noise channels"); - struct PsiDensityMatrix pure = psi_new_density_matrix(1); - psi_test_check(psi_is_pure_density_matrix(pure, 1e-10), "fresh density matrix is pure"); - psi_test_check(fabs(psi_trace_density_matrix(pure).real - 1.0) < 1e-10, "trace = 1"); - psi_free_density_matrix(&pure); + struct PsiDensityMatrix pure = psi_new_density_matrix(1); + psi_test_check(psi_is_pure_density_matrix(pure, 1e-10), "fresh density matrix is pure"); + psi_test_check(fabs(psi_trace_density_matrix(pure).real - 1.0) < 1e-10, "trace = 1"); + psi_free_density_matrix(&pure); - struct PsiDensityMatrix bf = psi_new_density_matrix(1); - struct PsiNoiseChannel flip = psi_bit_flip_channel(0.25); - psi_apply_noise_channel(&bf, flip, 0); - double probs[2]; - psi_density_matrix_probabilities(bf, probs); - psi_test_check(fabs(probs[0] - 0.75) < 1e-10 && fabs(probs[1] - 0.25) < 1e-10, - "bit_flip(0.25) on |0>: p = [0.75, 0.25]"); - psi_test_check(fabs(psi_purity_density_matrix(bf) - 0.625) < 1e-10, - "bit_flip(0.25) purity = 0.625"); - psi_free_noise_channel(&flip); - psi_free_density_matrix(&bf); + struct PsiDensityMatrix bf = psi_new_density_matrix(1); + struct PsiNoiseChannel flip = psi_bit_flip_channel(0.25); + psi_apply_noise_channel(&bf, flip, 0); + double probs[2]; + psi_density_matrix_probabilities(bf, probs); + psi_test_check(fabs(probs[0] - 0.75) < 1e-10 && fabs(probs[1] - 0.25) < 1e-10, + "bit_flip(0.25) on |0>: p = [0.75, 0.25]"); + psi_test_check(fabs(psi_purity_density_matrix(bf) - 0.625) < 1e-10, + "bit_flip(0.25) purity = 0.625"); + psi_free_noise_channel(&flip); + psi_free_density_matrix(&bf); - struct PsiComplex one[2] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; - struct PsiDensityMatrix damp = psi_new_density_matrix_from_state(one, 2); - struct PsiNoiseChannel ad = psi_amplitude_damping_channel(1.0); - psi_apply_noise_channel(&damp, ad, 0); - double dprobs[2]; - psi_density_matrix_probabilities(damp, dprobs); - psi_test_check(fabs(dprobs[0] - 1.0) < 1e-10, "amplitude_damping(1.0) fully decays |1> -> |0>"); - psi_free_noise_channel(&ad); - psi_free_density_matrix(&damp); + struct PsiComplex one[2] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; + struct PsiDensityMatrix damp = psi_new_density_matrix_from_state(one, 2); + struct PsiNoiseChannel ad = psi_amplitude_damping_channel(1.0); + psi_apply_noise_channel(&damp, ad, 0); + double dprobs[2]; + psi_density_matrix_probabilities(damp, dprobs); + psi_test_check(fabs(dprobs[0] - 1.0) < 1e-10, "amplitude_damping(1.0) fully decays |1> -> |0>"); + psi_free_noise_channel(&ad); + psi_free_density_matrix(&damp); - struct PsiComplex zero[2] = { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }; - struct PsiDensityMatrix fid = psi_new_density_matrix_from_state(zero, 2); - psi_test_check(fabs(psi_fidelity_density_matrix(fid, zero) - 1.0) < 1e-10, - "fidelity(|0><0|, |0>) = 1"); - psi_free_density_matrix(&fid); + struct PsiComplex zero[2] = { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }; + struct PsiDensityMatrix fid = psi_new_density_matrix_from_state(zero, 2); + psi_test_check(fabs(psi_fidelity_density_matrix(fid, zero) - 1.0) < 1e-10, + "fidelity(|0><0|, |0>) = 1"); + psi_free_density_matrix(&fid); - struct PsiDensityMatrix depo = psi_new_density_matrix(1); - struct PsiNoiseChannel dc = psi_depolarising_channel(0.3); - psi_apply_noise_channel(&depo, dc, 0); - psi_test_check(fabs(psi_trace_density_matrix(depo).real - 1.0) < 1e-10, - "depolarising preserves trace"); - psi_free_noise_channel(&dc); - psi_free_density_matrix(&depo); + struct PsiDensityMatrix depo = psi_new_density_matrix(1); + struct PsiNoiseChannel dc = psi_depolarising_channel(0.3); + psi_apply_noise_channel(&depo, dc, 0); + psi_test_check(fabs(psi_trace_density_matrix(depo).real - 1.0) < 1e-10, + "depolarising preserves trace"); + psi_free_noise_channel(&dc); + psi_free_density_matrix(&depo); } diff --git a/tester/non_clifford.c b/tester/non_clifford.c index c361fb5..e82c86d 100644 --- a/tester/non_clifford.c +++ b/tester/non_clifford.c @@ -5,38 +5,38 @@ static const double PI = 3.141592653589793; void run_non_clifford_tests(void) { - psi_test_section("Non-Clifford gates"); + psi_test_section("Non-Clifford gates"); - struct PsiQuantumCircuit t = psi_new_quantum_circuit(1); - psi_apply_x(&t, 0); - psi_apply_t(&t, 0); - struct PsiComplex t_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(R2, R2) }; - psi_check_circuit("T|1> = e^{i pi/4}|1>", &t, t_exp, 2); - psi_free_quantum_circuit(&t); + struct PsiQuantumCircuit t = psi_new_quantum_circuit(1); + psi_apply_x(&t, 0); + psi_apply_t(&t, 0); + struct PsiComplex t_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(R2, R2) }; + psi_check_circuit("T|1> = e^{i pi/4}|1>", &t, t_exp, 2); + psi_free_quantum_circuit(&t); - struct PsiQuantumCircuit rx = psi_new_quantum_circuit(1); - psi_apply_rx(&rx, 0, PI); - struct PsiComplex rx_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0) }; - psi_check_circuit("Rx(pi)|0> = -i|1>", &rx, rx_exp, 2); - psi_free_quantum_circuit(&rx); + struct PsiQuantumCircuit rx = psi_new_quantum_circuit(1); + psi_apply_rx(&rx, 0, PI); + struct PsiComplex rx_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0) }; + psi_check_circuit("Rx(pi)|0> = -i|1>", &rx, rx_exp, 2); + psi_free_quantum_circuit(&rx); - struct PsiQuantumCircuit ry = psi_new_quantum_circuit(1); - psi_apply_ry(&ry, 0, PI); - struct PsiComplex ry_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; - psi_check_circuit("Ry(pi)|0> = |1>", &ry, ry_exp, 2); - psi_free_quantum_circuit(&ry); + struct PsiQuantumCircuit ry = psi_new_quantum_circuit(1); + psi_apply_ry(&ry, 0, PI); + struct PsiComplex ry_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; + psi_check_circuit("Ry(pi)|0> = |1>", &ry, ry_exp, 2); + psi_free_quantum_circuit(&ry); - struct PsiQuantumCircuit p = psi_new_quantum_circuit(1); - psi_apply_x(&p, 0); - psi_apply_p(&p, 0, PI / 2.0); - struct PsiComplex p_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 1.0) }; - psi_check_circuit("P(pi/2)|1> = i|1>", &p, p_exp, 2); - psi_free_quantum_circuit(&p); + struct PsiQuantumCircuit p = psi_new_quantum_circuit(1); + psi_apply_x(&p, 0); + psi_apply_p(&p, 0, PI / 2.0); + struct PsiComplex p_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 1.0) }; + psi_check_circuit("P(pi/2)|1> = i|1>", &p, p_exp, 2); + psi_free_quantum_circuit(&p); - struct PsiQuantumCircuit sx = psi_new_quantum_circuit(1); - psi_apply_sx(&sx, 0); - psi_apply_sx(&sx, 0); - struct PsiComplex sx_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; - psi_check_circuit("sqrt(X) applied twice = X", &sx, sx_exp, 2); - psi_free_quantum_circuit(&sx); + struct PsiQuantumCircuit sx = psi_new_quantum_circuit(1); + psi_apply_sx(&sx, 0); + psi_apply_sx(&sx, 0); + struct PsiComplex sx_exp[] = { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }; + psi_check_circuit("sqrt(X) applied twice = X", &sx, sx_exp, 2); + psi_free_quantum_circuit(&sx); } diff --git a/tester/simd.c b/tester/simd.c index bea2f06..cfc38e2 100644 --- a/tester/simd.c +++ b/tester/simd.c @@ -6,58 +6,58 @@ static const double R2 = 0.7071067811865476; void run_simd_tests(void) { - psi_test_section("SIMD single-qubit kernels"); - - printf(" detected: %s\n", psi_simd_name(psi_detect_simd())); - - struct PsiComplex h[2][2] = { - { psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0) }, - { psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0) }, - }; - - struct PsiComplex two[4] = { - psi_new_complex(1.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - }; - psi_apply_single_qubit_gate_simd(two, h, 0, 2); - struct PsiComplex two_exp[] = { - psi_new_complex(R2, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(R2, 0.0), - psi_new_complex(0.0, 0.0), - }; - psi_test_check(psi_amps_match(two, two_exp, 4), "SIMD H on q0 of |00>"); - - struct PsiComplex three[8]; - for (size_t i = 0; i < 8; i++) - three[i] = psi_new_complex(0.0, 0.0); - three[0] = psi_new_complex(1.0, 0.0); - psi_apply_single_qubit_gate_simd(three, h, 0, 3); - struct PsiComplex three_exp[8]; - for (size_t i = 0; i < 8; i++) - three_exp[i] = psi_new_complex(0.0, 0.0); - three_exp[0] = psi_new_complex(R2, 0.0); - three_exp[4] = psi_new_complex(R2, 0.0); - psi_test_check(psi_amps_match(three, three_exp, 8), "SIMD H on q0 of |000> (chunked)"); - - struct PsiComplex x[2][2] = { - { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }, - { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }, - }; - struct PsiComplex flip[4] = { - psi_new_complex(1.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - }; - psi_apply_single_qubit_gate_simd(flip, x, 1, 2); - struct PsiComplex flip_exp[] = { - psi_new_complex(0.0, 0.0), - psi_new_complex(1.0, 0.0), - psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), - }; - psi_test_check(psi_amps_match(flip, flip_exp, 4), "SIMD X on q1 of |00> = |01>"); + psi_test_section("SIMD single-qubit kernels"); + + printf(" detected: %s\n", psi_simd_name(psi_detect_simd())); + + struct PsiComplex h[2][2] = { + { psi_new_complex(R2, 0.0), psi_new_complex(R2, 0.0) }, + { psi_new_complex(R2, 0.0), psi_new_complex(-R2, 0.0) }, + }; + + struct PsiComplex two[4] = { + psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + }; + psi_apply_single_qubit_gate_simd(two, h, 0, 2); + struct PsiComplex two_exp[] = { + psi_new_complex(R2, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(R2, 0.0), + psi_new_complex(0.0, 0.0), + }; + psi_test_check(psi_amps_match(two, two_exp, 4), "SIMD H on q0 of |00>"); + + struct PsiComplex three[8]; + for (size_t i = 0; i < 8; i++) + three[i] = psi_new_complex(0.0, 0.0); + three[0] = psi_new_complex(1.0, 0.0); + psi_apply_single_qubit_gate_simd(three, h, 0, 3); + struct PsiComplex three_exp[8]; + for (size_t i = 0; i < 8; i++) + three_exp[i] = psi_new_complex(0.0, 0.0); + three_exp[0] = psi_new_complex(R2, 0.0); + three_exp[4] = psi_new_complex(R2, 0.0); + psi_test_check(psi_amps_match(three, three_exp, 8), "SIMD H on q0 of |000> (chunked)"); + + struct PsiComplex x[2][2] = { + { psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0) }, + { psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0) }, + }; + struct PsiComplex flip[4] = { + psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + }; + psi_apply_single_qubit_gate_simd(flip, x, 1, 2); + struct PsiComplex flip_exp[] = { + psi_new_complex(0.0, 0.0), + psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), + }; + psi_test_check(psi_amps_match(flip, flip_exp, 4), "SIMD X on q1 of |00> = |01>"); } diff --git a/tester/test.c b/tester/test.c index 9e11d8c..2c3532f 100644 --- a/tester/test.c +++ b/tester/test.c @@ -8,74 +8,74 @@ static int tests_passed = 0; void psi_test_section(const char* name) { - printf("\n── %s ──\n", name); + printf("\n── %s ──\n", name); } void psi_test_check(bool ok, const char* name) { - tests_run++; - if (ok) - tests_passed++; + tests_run++; + if (ok) + tests_passed++; - printf(" [%s] %s\n", ok ? "PASS" : "FAIL", name); + printf(" [%s] %s\n", ok ? "PASS" : "FAIL", name); } bool psi_amps_match(const struct PsiComplex* actual, const struct PsiComplex* expected, size_t n) { - for (size_t i = 0; i < n; i++) - { - if (fabs(actual[i].real - expected[i].real) > 1e-9) - return false; - if (fabs(actual[i].imaginary - expected[i].imaginary) > 1e-9) - return false; - } + for (size_t i = 0; i < n; i++) + { + if (fabs(actual[i].real - expected[i].real) > 1e-9) + return false; + if (fabs(actual[i].imaginary - expected[i].imaginary) > 1e-9) + return false; + } - return true; + return true; } void psi_check_circuit(const char* name, struct PsiQuantumCircuit* circuit, const struct PsiComplex* expected, size_t n) { - const struct PsiVector* state = psi_compute_circuit(circuit); - bool ok = state->size == n && psi_amps_match(state->data, expected, n); - psi_test_check(ok, name); + const struct PsiVector* state = psi_compute_circuit(circuit); + bool ok = state->size == n && psi_amps_match(state->data, expected, n); + psi_test_check(ok, name); } void psi_check_runtimes_agree(const char* name, size_t num_qubits, void (*build)(struct PsiQuantumCircuit*)) { - enum PsiRuntime runtimes[] = { - PSI_RUNTIME_BASIC, - PSI_RUNTIME_BATCHED, - PSI_RUNTIME_SIMD, - PSI_RUNTIME_STRUCTURE_AWARE, - }; + enum PsiRuntime runtimes[] = { + PSI_RUNTIME_BASIC, + PSI_RUNTIME_BATCHED, + PSI_RUNTIME_SIMD, + PSI_RUNTIME_STRUCTURE_AWARE, + }; - struct PsiQuantumCircuit base = psi_new_quantum_circuit(num_qubits); - build(&base); - const struct PsiVector* base_state = psi_compute_circuit_with(&base, PSI_RUNTIME_BASIC); - struct PsiVector reference = psi_clone_vector(*base_state); + struct PsiQuantumCircuit base = psi_new_quantum_circuit(num_qubits); + build(&base); + const struct PsiVector* base_state = psi_compute_circuit_with(&base, PSI_RUNTIME_BASIC); + struct PsiVector reference = psi_clone_vector(*base_state); - bool ok = true; - for (size_t i = 1; i < sizeof runtimes / sizeof runtimes[0]; i++) - { - struct PsiQuantumCircuit circuit = psi_new_quantum_circuit(num_qubits); - build(&circuit); - const struct PsiVector* state = psi_compute_circuit_with(&circuit, runtimes[i]); - if (state->size != reference.size || - !psi_amps_match(state->data, reference.data, reference.size)) - ok = false; + bool ok = true; + for (size_t i = 1; i < sizeof runtimes / sizeof runtimes[0]; i++) + { + struct PsiQuantumCircuit circuit = psi_new_quantum_circuit(num_qubits); + build(&circuit); + const struct PsiVector* state = psi_compute_circuit_with(&circuit, runtimes[i]); + if (state->size != reference.size || + !psi_amps_match(state->data, reference.data, reference.size)) + ok = false; - psi_free_quantum_circuit(&circuit); - } + psi_free_quantum_circuit(&circuit); + } - psi_free_vector(&reference); - psi_free_quantum_circuit(&base); - psi_test_check(ok, name); + psi_free_vector(&reference); + psi_free_quantum_circuit(&base); + psi_test_check(ok, name); } int psi_test_summary(void) { - printf("\n%d/%d checks passed\n", tests_passed, tests_run); - return tests_passed == tests_run ? 0 : 1; + printf("\n%d/%d checks passed\n", tests_passed, tests_run); + return tests_passed == tests_run ? 0 : 1; } -- cgit v1.3