RegisterData

RegisterData contains the actual results of an execution for a partiuclar register (e.g., "ro"). You get a pointer to one by calling get_data.

Definition

typedef struct RegisterData {
    unsigned short number_of_shots;
    unsigned short shot_length;
    struct DataType data;
} RegisterData;

typedef struct DataType {
    DataType_Tag tag;
    union {
        struct {
            char **byte;
        };
        struct {
            double **real;
        };
    };
} DataType;

typedef enum DataType_Tag {
    DataType_Byte,
    DataType_Real,
} DataType_Tag;

Safety

The memory for any RegisterData will be freed when calling free_execution_result for the corresponding ExecutionResult. Make sure not to free the ExecutionResult until after you're done with the data.

Attributes

  1. number_of_shots is the outer dimension of the 2D array of data. This should always be equal to the parameter provided to wrap_in_shots (or 1 if not called).
  2. shot_length is the inner dimension of the data array, corresponding to the dimension of the declared memory. For example, declaring BIT in Quil will result in a shot_length of 1, but declaring BIT[2] in Quil will result in a shot_length of 2.
  3. data is a DataType which contains the actual results as measured from the requested register. This is a 2D array with outer dimension of number_of_shots and inner dimension of shot_length. The type of this data depends on the type of the declared memory. The tag field tells you which type of data is contained within, then byte or real is the 2D array.

Variants

The type of data will depend on how the memory was declared in Quil.

Byte

The result of reading from a BIT or OCTET register is the Byte variant. data.tag will be DataType_Byte, and data.byte will be populated.

Real

The result of reading from a REAL register is the Real variant. data.tag will be DataType_Real, and data.real will be populated.

Example

Here we declare both REAL and OCTET registers which will correspond to Real and Byte variants.

char *REAL_MEMORY_PROGRAM =
        "DECLARE first REAL[1]\n"
        "DECLARE second OCTET[1]\n"
        "MOVE first[0] 3.141\n"
        "MOVE second[0] 2\n";

bool test_real_data_type() {
    const char *TEST_NAME = "test_real_data_type";

    Executable *exe = executable_from_quil(REAL_MEMORY_PROGRAM);
    read_from(exe, "first");
    read_from(exe, "second");
    ExecutionResult *result = execute_on_qvm(exe);

    if (result->tag == ExecutionResult_Error) {
        return fail(
                TEST_NAME,
                result->error,
                exe,
                result
        );
    }

    const RegisterData *first = get_data(result->success.handle, "first");
    const RegisterData *second = get_data(result->success.handle, "second");

    if (first == NULL || first->data.tag != DataType_Real) {
        return fail(
                TEST_NAME,
                "first register did not contain real data",
                exe,
                result
        );
    }
    if (second == NULL || second->data.tag != DataType_Byte) {
        return fail(
                TEST_NAME,
                "second register did not contain byte data",
                exe,
                result
        );
    }

    if (first->data.real[0][0] != 3.141) {
        char message[50];
        sprintf(
                message,
                "Found %f in first, expected 3.141",
                first->data.real[0][0]
        );
        return fail(
                TEST_NAME,
                message,
                exe,
                result
        );
    }
    if (second->data.byte[0][0] != 2) {
        char message[50];
        sprintf(
                message,
                "Found %d in first, expected 2",
                second->data.byte[0][0]
        );
        return fail(
                TEST_NAME,
                message,
                exe,
                result
        );
    }

    return succeed(TEST_NAME, exe, result);
}