mirror of https://github.com/openqasm/openqasm.git
102 lines
4.1 KiB
Plaintext
102 lines
4.1 KiB
Plaintext
OPENQASM 3.0; // Version statement is optional
|
|
|
|
// ==================
|
|
// Array declarations
|
|
// ==================
|
|
|
|
// Declare 'my_ints' to be a 1D array of 8-bit signed integers, where the index
|
|
// runs from 0 to 15.
|
|
array[int[8], 16] my_ints;
|
|
|
|
// Declare 'my_doubles' to be a 2D array of double-precision floating-point
|
|
// values, where the first index runs from 0 to 7 and the second from 0 to 3.
|
|
array[float[64], 8, 4] my_doubles;
|
|
|
|
// Initialise a 1D array with fixed values.
|
|
array[uint[32], 4] my_defined_uints = {5, 6, 7, 8};
|
|
|
|
// Initialise a 2D array with fixed values.
|
|
array[float[32], 4, 2] my_defined_floats = {
|
|
{0.5, 0.5},
|
|
{1.0, 2.0},
|
|
{-0.4, 0.7},
|
|
{1.3, -2.1e-2}
|
|
};
|
|
|
|
// Initialise an array using a row of another array. Note that this copies the
|
|
// data; changes to the values in `my_defined_float_row` will not affect
|
|
// `my_defined_floats`.
|
|
array[float[32], 2] my_defined_float_row = my_defined_floats[0];
|
|
|
|
// Arrays can be defined in terms of compile-time constant dimension sizes, and
|
|
// can use expressions in the slots of their initialisers.
|
|
const uint[8] DIM_SIZE = 2;
|
|
array[int[8], DIM_SIZE, DIM_SIZE] all_ones = {{2+3, 4-1}, {3+8, 12-4}};
|
|
|
|
|
|
// =============================
|
|
// Array indexing and operations
|
|
// =============================
|
|
|
|
// Use `[]` notation to access array elements. The dimensions are
|
|
// comma-separated.
|
|
uint[8] a = my_defined_uints[0];
|
|
float[32] b = my_defined_floats[2, 1];
|
|
|
|
// The same notation is used in simple assignments.
|
|
my_defined_uints[1] = 5;
|
|
my_defined_floats[3, 0] = -0.45;
|
|
|
|
// In both, the indices can be (non-constant) expressions.
|
|
my_defined_uints[a - 1] = a + 1;
|
|
|
|
// Assignments can also be done using an array, or array slice, on the left-hand
|
|
// side, provided the right-hand side evaluates to an array of exactly the same
|
|
// shape. The assignment is done by copy, so subsequent changes to either of
|
|
// the two parts will not affect the other.
|
|
my_defined_floats[2] = my_defined_float_row;
|
|
|
|
// You can also use the slice notation to set elements. Beware that it is
|
|
// generally a logical error to read and write from overlapping slices at the
|
|
// same time, and that OpenQASM 3 makes no guarantees about which order the data
|
|
// will be read from and written to. You might clobber data if you overlap.
|
|
my_defined_floats[0:1] = my_defined_floats[2:3];
|
|
|
|
// The ``sizeof`` operator returns the size of an array's dimension.
|
|
const uint[32] dimension = sizeof(my_defined_uints); // assigns 4.
|
|
|
|
// The ``sizeof`` operator can also be used in two-argument form, where the
|
|
// second argument is the index of the dimension, counting from 0.
|
|
const uint[32] first_dimension = sizeof(my_doubles, 0); // returns 8
|
|
const uint[32] second_dimension = sizeof(my_doubles, 1); // returns 4
|
|
|
|
// If the second argument is omitted from ``sizeof`` and the given array is
|
|
// multi-dimensional, it defaults to returning the first dimension, so
|
|
// ``sizeof(my_array) == sizeof(my_array, 0)`` in all circumstances.
|
|
const uint[32] first_dimension = sizeof(my_doubles); // still 8.
|
|
|
|
|
|
// =====================
|
|
// Arrays in subroutines
|
|
// =====================
|
|
|
|
// Array arguments have a mandatory ``readonly`` or ``mutable`` specifier when
|
|
// defined in a subroutine argument list. This is because arrays are passed to
|
|
// subroutines by reference, not by value, so modifications will propagate back
|
|
// to the original data. Such modifications are only allowed for ``mutable``
|
|
// references, not ``readonly``.
|
|
def copy_3_bytes(readonly array[uint[8], 3] in_array, mutable array[uint[8], 3] out_array) {
|
|
// Within this block, ``in_array`` can be read from, but not written to,
|
|
// whereas ``out_array`` can be both read from and written to.
|
|
}
|
|
|
|
// When specifying array subroutine parameters, there is a second format where
|
|
// the sizes of the dimensions are not given explicitly, only the number of
|
|
// dimensions. This is where the ``sizeof`` operator is most useful. In these
|
|
// cases, `sizeof` is _not_ a compile-time constant.
|
|
def multi_dimensional_input(readonly array[int[32], #dim=3] my_array) {
|
|
uint[32] dimension_0 = sizeof(my_array, 0);
|
|
uint[32] dimension_1 = sizeof(my_array, 1);
|
|
uint[32] dimension_2 = sizeof(my_array, 2);
|
|
}
|