Classical Computations in QUA ============================= This section describes standard syntax rules for classical computations in QUA. ********************** Arithmetic expressions ********************** multiplication, addition and subtraction of fixed point varibales is supported. .. note:: division incurs a computational overhead of approximately 400nsec per operation. +--------------+--------+----------+ | Operator | symbol | example | +==============+========+==========+ |multiplication| \* | a*b | +--------------+--------+----------+ |division | \/ | a/b | +--------------+--------+----------+ | addition | \+ | a+b | +--------------+--------+----------+ | subtraction | \- | a-b | +--------------+--------+----------+ |left bitshift | << | a<<2 | +--------------+--------+----------+ |right bitshift| >> | a>>2 | +--------------+--------+----------+ .. code-block:: python with program() as prog: a = declare(fixed) b = declare(int) c = declare(fixed, value=0.3) d = declare(fixed, value=-0.02) e = declare(int, value=3) f = declare(int, value=5) assign(a, c*d-d+c*0.25) assign(b, e+f*123*e-e) assign(c, b/a) save(a, "a") save(b, "b") save(c, "c") The evaluation of each operator takes only a few clock cycles. For example, the addition (\+) and substraction (\-) operations each take 1 clock cycle to evaluate, i.e. 4ns. However, the compiler parallelizes operations, resulting in a much reduced effective calculation time which will often be zero. ****************** Boolean Operations ****************** +----------+--------+----------+ | Operator | symbol | example | +==========+========+==========+ |AND | & | a&b | +----------+--------+----------+ | OR | \| | a\|b | +----------+--------+----------+ | XOR | ^ | a^b | +----------+--------+----------+ |NOT | ~ | ~a | +----------+--------+----------+ compounded boolean expressions are supported. .. note :: it is necessary to wrap the atomic boolean expressions in paranthesis as seen in the example below, due to python operator precedence rules. Example: .. code-block:: python with if_( (~( a > b )) | ( c > d) ): ****** Arrays ****** QUA arrays are defined and accessed as follows. 1. Declare a new array: syntax: `declare(fixed/int/bool, size=N)` `declare(fixed/int/bool, value=[…])` Examples: .. code-block:: python v1 = declare(int, size=3) v2 = declare(int, value=[1,2,3]) 2. Access cell in array .. code-block:: python # syntax and examples assign(v1[0], 5) assign(b, v1[i]+6) assign(v1[i+5], v[i+4]) save(v1[2], "v1_2") 3. Get array length .. code-block:: python # syntax and examples v1.length() assign(length, v1.length()) Use example: .. code-block:: python with program() as arrays_use: v1 = declare(int, value = [1, 2, 4, 8, 16]) v2 = declare(int, size = 5) # will be initialized with zeros v3 = declare(fixed, size = 30) # will be initialized with zeros i = declare(int) assign(v3[0], 16) with for_(i, 0, i < v2.length(), i + 1): assign(v2[i], i*2) with for_(i, 0, i < v1.length(), i + 1): assign(v2[i], v2[i] + v3[i]) with for_(i, 0, i < v1.length(), i + 1): save(v1[i], "v1") save(v2[i], "v2") with for_(i, 0, i < v3.length(), i + 1): save(v3[i], "v3") .. note:: array length is fixed and cannot be changed after declaration. .. note:: No validation is performed for reading/writing out of bounds. This will be added in a future version. ******************************* Computational library functions ******************************* QUA allows the user the real time evaluation of several mathematical operators and functions. Besides the standard mathematical operators (\+, \-, \*, \/) the user can access various libraries including * Math - trigonometric functions, array reduction functions etc. * Random - pseudo-random number generation. * Cast - allows casting between QUA variable types. * Util - Miscellaneous operators, including a hardware optimized conditional expression. Math ^^^^ Trigonometric functions +++++++++++++++++++++++ * ``Math.cos(x)`` : Take the cosine of a fixed in radians * ``Math.sin(x)`` : Take the sine of a fixed in radians * ``Math.cos2pi(x)`` : Take the cosine of a fixed in 2pi radians * ``Math.sin2pi(x)`` : Take the cosine of a fixed in 2pi radians cos2pi(x) and sin2pi(x) are equivalent to cos(2*pi*x) and sin(2*pi*x) but save a few clock cycles as the extra multiplication stage required to calculate 2*pi are removed by simply having 2*pi stored in memory. So whenever working with degrees instead of radians we suggest using the latter. The usage is straightforward, for example: .. code-block:: python amplitude = declare(fixed) time = declare(int)frequency = declare(int) assign(amplitude, 1)assign(frequency, 1e6) with for_(time, 0, time<100, time+1): play('pulse_1' * amp(amplitude*Math.cos2pi(frequency*time)), 'element_1') This program will play `pulse_1` for 100 iterations, where for each iteration the amplitude will be modulated by the envelope function cos(2pi*frequency*time). For evaluation of non-real time mathematical expressions one can always use standard python libraries such as numpy. Array reduction +++++++++++++++ QUA provides several function to reduce arrays. These functions run much more efficiently (with less latency) when compared to a manual implementing in QUA as they use hardware optimizations. * ``Math.sum(x)`` : sums an array. result must of the same type as array * ``Math.max(x)``, ``Math.min(x)`` : max,min an array. result must of the same type as array * ``Math.argmin(x)``/``Math.argmax(x)``: returns the index of the max/min * ``Math.dot(x,y)``: returns the dot product of two QUA arrays of the same size Others ++++++ * ``Math.abs(x)`` : absolute value of a QUA variable Random() ^^^^^^^^ This class generates a pseudo-random number using a the `LCG algorithm `_ with the following parameters: a = 137939405, c = 12345, m = 2**28. The class constructor optionally takes a seed number and can generate `int` or `fixed` values. .. code-block:: python with program() as prog: r = Random() a = declare(int) b = declare(fixed) assign(a, r.rand_int(100)) # a will be a number between 0 and 99 assign(b, r.rand_fixed()) # b will be a number between 0.0 and 1.0 # you can set the seed: r.set_seed(123213) Cast ^^^^ * ``Cast.mul_fixed_by_int(x,y)``: Multiplies a fixed x by an int y, returning a fixed * ``Cast.mul_int_by_fixed(x,y)``: Multiplies an int x by a fixed y, returning an int * ``Cast.to_int(x)``: Casts a variable to int. Supports int, fixed or bool * ``Cast.to_fixed(x)``: Casts a variable to fixed. Supports int, fixed or bool * ``Cast.to_bool(x)``: Casts a variable to bool. Supports int, fixed or bool Util ^^^^ * ``Util.cond(a,b,c)`` : Quick conditional operation. This is equivalent to a ternary operator available in some languages: i.e. a ? b : c, meaning 'b' if 'a' is true, or 'c' if 'a' is false. There is less computation overhead (less latency) when running this operation relative to the if_ conditional .. code-block:: python assign(b, Util.cond(a > b, c, d))