q1tsim 0.5.0

A simple, efficient, quantum computer simulator.
Documentation
import cffi
import os
import os.path

RESULT_ERROR = 0
RESULT_EMPTY = 1
RESULT_STRING = 2
RESULT_HISTOGRAM = 3

def get_q1tsim_lib(ffi):
	if os.name == 'nt':
		paths = (
			'./q1tsim.dll',
			'../target/release/q1tsim.dll',
			'../target/debug/q1tsim.dll'
		)
	else:
		paths = (
			'./libq1tsim.so',
			'../target/release/libq1tsim.so',
			'../target/debug/libq1tsim.so'
		)

	for fname in paths:
		if os.path.exists(fname):
			try:
				return ffi.dlopen(fname)
			except OSError:
				pass

	raise Exception('Failed to open q1tsim library')

ffi = cffi.FFI()
ffi.cdef("""
    typedef struct circuit circuit_t;
    typedef struct
    {
        const char* key;
        size_t count;
    } histelem_t;
    typedef struct
    {
        double value;
        double* value_ptr;
    } parameter_t;
    typedef struct
    {
        void* data;
        size_t length;
        size_t size;
        uint32_t restype;
    } result_t;

    void result_free(result_t res);

    circuit_t *circuit_new(size_t nr_qbits, size_t nr_cbits);
    void circuit_free(circuit_t *ptr);
    size_t circuit_nr_qbits(const circuit_t *ptr);
    size_t circuit_nr_cbits(const circuit_t *ptr);
    result_t circuit_add_gate(circuit_t *ptr, const char* gate,
        const size_t* qbits, size_t nr_qubits,
        const parameter_t* param_ptr, size_t nr_params);
    result_t circuit_add_conditional_gate(circuit_t *ptr,
        const size_t* control_ptr, size_t nr_control, uint64_t target,
        const char* gate,
        const size_t* qbits_ptr, size_t nr_qbits,
        const parameter_t* param_ptr, size_t nr_params);
    result_t circuit_measure(circuit_t *ptr, size_t qbit, size_t cbit, char dir,
        uint8_t collapse);
    result_t circuit_measure_all(circuit_t *ptr, const size_t* cbits, size_t nr_cbits,
        char dir, uint8_t collapse);
    result_t circuit_reset(circuit_t *ptr, size_t qbit);
    result_t circuit_reset_all(circuit_t *ptr);
    result_t circuit_execute(circuit_t *ptr, size_t nr_shots);
    result_t circuit_reexecute(circuit_t *ptr);
    result_t circuit_histogram(const circuit_t *ptr);
    result_t circuit_latex(const circuit_t *ptr);
    result_t circuit_open_qasm(const circuit_t *ptr);
    result_t circuit_c_qasm(const circuit_t *ptr);
""")
qsim_obj = get_q1tsim_lib(ffi)

def unpack_result(res):
    restype = res.restype
    try:
        if restype == RESULT_ERROR:
            msg = ffi.string(ffi.cast("const char*", res.data)).decode('utf-8')
            raise Exception(msg)
        if res.restype == RESULT_EMPTY:
            return None
        elif res.restype == RESULT_STRING:
            msg = ffi.string(ffi.cast("const char*", res.data)).decode('utf-8')
            return msg
        elif res.restype == RESULT_HISTOGRAM:
            elems = ffi.cast("const histelem_t*", res.data)
            hist = dict((ffi.string(elems[i].key).decode('utf-8'), elems[i].count)
                        for i in range(res.length))
            return hist
        else:
            raise Exception("Unknown data type code: {}".format(res.restype))
    finally:
        qsim_obj.result_free(res)

def make_parameters(values):
    res = ffi.new('parameter_t[]', len(values))
    for (i, val) in enumerate(values):
        if type(val) == float:
            res[i].value = val
            res[i].value_ptr = ffi.NULL
        else:
            res[i].value = 0.0
            res[i].value_ptr = val.pointer()
    return res

def q1tsim():
    return qsim_obj