Table of Contents

Toffoli gate (cuStateVec)

Toffoli gate implementation using cuStateVec. The example prepares $\lvert 110\rangle$ (both controls $\lvert 1\rangle$, target $\lvert 0\rangle$) and applies the Toffoli gate, flipping the target to produce $\lvert 111\rangle$.

// Compile: nvcc main.cu -o main -lcustatevec
// Run:     ./main
 
#include <stdio.h>
#include <cuda_runtime.h>
#include <custatevec.h>
 
int main() {
    const int nQubits = 3;
    const int dim = 1 << nQubits;
 
    // Prepare |110>: q0=1, q1=1, q2=0 -> index 6 (binary 110)
    cuDoubleComplex h_sv[8] = {0};
    h_sv[6] = make_cuDoubleComplex(1.0, 0.0);
    cuDoubleComplex *d_sv;
    cudaMalloc(&d_sv, dim * sizeof(cuDoubleComplex));
    cudaMemcpy(d_sv, h_sv, dim * sizeof(cuDoubleComplex), cudaMemcpyHostToDevice);
 
    custatevecHandle_t handle;
    custatevecCreate(&handle);
 
    // Toffoli = X gate with two controls (q0=1, q1=1) on target q2
    cuDoubleComplex x_gate[4] = {{0,0},{1,0},{1,0},{0,0}};
    int32_t targets[]   = {2};
    int32_t controls[]  = {0, 1};
    int32_t ctrl_vals[] = {1, 1};
    custatevecApplyMatrix(
        handle, d_sv, CUDA_C_64F, nQubits,
        x_gate, CUDA_C_64F, CUSTATEVEC_MATRIX_LAYOUT_ROW, 0,
        targets, 1, controls, ctrl_vals, 2,
        CUSTATEVEC_COMPUTE_64F, NULL, 0);
 
    cudaMemcpy(h_sv, d_sv, dim * sizeof(cuDoubleComplex), cudaMemcpyDeviceToHost);
    printf("|110>: (%.4f, %.4f)\n", cuCreal(h_sv[6]), cuCimag(h_sv[6]));
    printf("|111>: (%.4f, %.4f)\n", cuCreal(h_sv[7]), cuCimag(h_sv[7]));
    // |110>: (0.0000, 0.0000)
    // |111>: (1.0000, 0.0000)  <- target flipped
 
    custatevecDestroy(handle);
    cudaFree(d_sv);
    return 0;
}