wai-quantum 0.5.0

A deterministic quantum stack in pure Rust: byte-exact circuit simulation (statevector / stabilizer / tensor-network MPS / sparse-Pauli backends), sparse Pauli dynamics at utility scale (arbitrary angles, 1024 qubits), belief-propagation tensor networks on the hardware graph, error mitigation, qLDPC decoding, noise learning, circuit-equivalence proofs, a phasor interference-ML layer, information-theoretic limits, noisy channels and state tomography, and signed energy-accounted receipts. No QPU, no cloud, no system libraries in the default features — identical results native, in the browser, and as a WASI component at the edge; the opt-in WebGPU member reaches the platform's GPU interface.
Documentation
// wai-quantum fabric: the host harness for the gate datapath's simulation.
//
// Drives the Verilator model of `wq_lanes64` (lanes64.v) over a binary
// protocol on stdin and stdout, little-endian, one request at a time:
//
//   op 0                      quit
//   op 1, u64 count, count x (i32 a, i32 b)
//                             probe: count x (u32 prod_hi, prod_lo, fx_hi, fx_lo)
//   op 2, u32 n, u32 gates, 2^n x (i32 re, i32 im),
//         gates x (u32 m0..m7, tbit, ctrl, index)
//                             run: u32 report, 2^n x (i32 re, i32 im), u64 cycles
//
// The harness only moves bytes and toggles the clock: the arithmetic, the pair
// addressing, the control test and the report are the model's. A request it
// cannot serve (a state wider than the model's RAM, a short read) ends the
// process with a nonzero status, which the member reports.

#include "Vwq_lanes64.h"
#include "verilated.h"

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <vector>

static Vwq_lanes64* top = nullptr;
static uint64_t cycles = 0;

static void tick() {
    top->clk = 0;
    top->eval();
    top->clk = 1;
    top->eval();
    cycles++;
}

static void need(void* buf, size_t n) {
    if (fread(buf, 1, n, stdin) != n) {
        std::exit(3);
    }
}

template <class T> static T get() {
    T v;
    need(&v, sizeof v);
    return v;
}

static void put(const void* buf, size_t n) {
    if (fwrite(buf, 1, n, stdout) != n) {
        std::exit(4);
    }
}

int main(int argc, char** argv) {
    Verilated::commandArgs(argc, argv);
    top = new Vwq_lanes64;
    top->clk = 0;
    top->host_we = 0;
    top->start = 0;
    top->report_reset = 0;
    top->eval();
    for (;;) {
        uint8_t op;
        if (fread(&op, 1, 1, stdin) != 1 || op == 0) {
            break;
        }
        if (op == 1) {
            uint64_t count = get<uint64_t>();
            std::vector<uint32_t> out;
            out.reserve(count * 4);
            for (uint64_t k = 0; k < count; k++) {
                int32_t a = get<int32_t>();
                int32_t b = get<int32_t>();
                top->probe_a = (uint32_t)a;
                top->probe_b = (uint32_t)b;
                top->eval();
                uint64_t prod = top->probe_prod;
                uint64_t fx = top->probe_fx;
                out.push_back((uint32_t)(prod >> 32));
                out.push_back((uint32_t)prod);
                out.push_back((uint32_t)(fx >> 32));
                out.push_back((uint32_t)fx);
            }
            put(out.data(), out.size() * 4);
        } else if (op == 2) {
            uint32_t n = get<uint32_t>();
            uint32_t gates = get<uint32_t>();
            if (n < 1 || n > WQ_AW) {
                std::exit(5);
            }
            uint64_t len = 1ull << n;
            cycles = 0;
            for (uint64_t x = 0; x < len; x++) {
                uint32_t re = (uint32_t)get<int32_t>();
                uint32_t im = (uint32_t)get<int32_t>();
                top->host_addr = (uint32_t)x;
                top->host_wdata = ((uint64_t)im << 32) | re;
                top->host_we = 1;
                tick();
            }
            top->host_we = 0;
            top->report_reset = 1;
            tick();
            top->report_reset = 0;
            for (uint32_t g = 0; g < gates; g++) {
                uint32_t w[11];
                need(w, sizeof w);
                top->m0 = w[0];
                top->m1 = w[1];
                top->m2 = w[2];
                top->m3 = w[3];
                top->m4 = w[4];
                top->m5 = w[5];
                top->m6 = w[6];
                top->m7 = w[7];
                top->tbit = w[8];
                top->ctrl = w[9];
                top->index = w[10];
                top->pairs = (uint32_t)(len / 2);
                top->start = 1;
                tick();
                top->start = 0;
                while (top->busy) {
                    tick();
                }
            }
            uint32_t report = top->report;
            put(&report, 4);
            std::vector<int32_t> state;
            state.reserve(len * 2);
            for (uint64_t x = 0; x < len; x++) {
                top->host_addr = (uint32_t)x;
                top->eval();
                uint64_t v = top->host_rdata;
                state.push_back((int32_t)(uint32_t)v);
                state.push_back((int32_t)(uint32_t)(v >> 32));
            }
            put(state.data(), state.size() * 4);
            put(&cycles, 8);
        } else {
            std::exit(2);
        }
        fflush(stdout);
    }
    top->final();
    delete top;
    return 0;
}