The classic data-types of QCL are the arithmetic types int, real and complex and the general types boolean and string.
The QCL type int is based on the C data type singed long. On a 32bit computer, this typically allows values form to . While this is more than enough for any standard programming task, the implementation of certain combinatoric functions can require some attention.
However, the word-length limitation has no effect on the number of qubits which can be simulated or on the maximum size of quantum registers. 2.1
The QCL type real is based on C data type double, which is typically 64bit. To improve readability, output of real numbers is truncated to a reasonable number of digits.
Real numbers are written in decimal notation and must include the decimal point.
QCL complex numbers are internally represented as two double floats. This holds for variables of type complex as well as the internal representation of the machine state. Complex numbers are given as (real,imag)-pairs:
Unlike C, logical values have their own data type in QCL. Literals for boolean are true and false:
String literals are quoted with "character string" and may contain any printable character except `"'.
Arithmetic operators generally work on all arithmetic data types and return the most general type (operator overloading), e.g.
qcl> print 2+2; // evaluates to int : 4 qcl> print 2+2.0; // evaluates to real : 4.000000 qcl> print 2+(2,0); // evaluates to complex : (4.000000,0.000000) |
^
for integer bases is only
defined for non-negative, integer exponents.
For real exponents, the base must be non-negative.
table 2.3 shows all arithmetic operators ordered from high to low precedence. All binary operators are left associative, thus . Explicit grouping can be achieved by using parentheses.
Table 2.4 shows all comparison and logic operators with their argument types. The return type of all operators is boolean.
QCL defines two more operators, which are mainly used with quantum expressions. They are described in section 2.3.3 and mentioned her only for completeness.
Unlike user defined functions (see section 2.5.2), most of QCL's built-in functions are overloaded. Like arithmetic operators, they often accept more then one argument type and evaluate to different return types.
Trigonometric functions (table 2.5) are defined for int, real and complex arguments. There return type is real or complex, depending on the argument type.
qcl> print sin(0); // integer or real arguments : 0.000000 // evaluate to real, even if the qcl> print sin(pi); // result is an integer number : 0.000000 qcl> print tanh((0,1)*pi); // complex arguments evaluate : (0.000000,-0.000000) // to complex |
exp, log and sqrt also work on all arithmetic types (table 2.6). Square roots of negative real numbers trigger an error, as do non positive real logarithms.
qcl> print sqrt(-1); ! math error: real square root of negative number qcl> print log(-1.0); ! math error: real logarithm of non positive number qcl> print sqrt((-1,0)),log((-1,0)); : (0.000000,1.000000) (0.000000,3.141593) |
For handling and conversion of complex expressions, the functions Re, Im, abs and conj are defined (table 2.7). abs also works on real and int arguments.
ceil(x) and floor(x) round the real value up- or downwards to the nearest integer. The rounded value is returned as int.
The functions max and min take an arbitrary number of int or real arguments and return the maximum or minimum value. The return type is int, if all arguments are integer, and real otherwise.
qcl> print max(3,pi,4); : 4.000000 |
The greatest common divisor and the least common multiple of a list of integers can be determined by gcd and lcm.
qcl> print gcd(48,72,180),lcm(48,72,180); : 12 720 |
The pseudo function random() returns a random value from the interval . The generation of random numbers can be determined by providing a seed value with the option -seed. Random numbers cannot be used in the definition of functions and quantum operators.
Identifiers are restricted to alphanumeric characters (no underscores) and must begin with a letter. As in C, there is no limit in length and case is significant. Names must not collide with internal keywords.
Frequently used values can be defined as symbolic constants. The syntax of a constant declaration is
const pi=3.141592653589793238462643383279502884197; |
qcl> const seed=random(); qcl> print seed; : 0.378990 qcl> print seed; : 0.378990 |
The definition of variables in QCL is analogous to C:
The value of a variable can be changed by an assignment, as well as several other statements (see section 2.4):
qcl> complex z; // declare complex variable z qcl> print z; // z was initialised with 0 : (0.000000,0.000000) qcl> z=(0,1); // setting z to i qcl> print z; : (0.000000,1.000000) qcl> z=exp(z*pi); // assignment to z may contain z qcl> print z; : (-1.000000,0.000000) qcl> input z; // ask for user input ? complex z [(Re,Im)] ? (0.8,0.6) qcl> print z; : (0.800000,0.600000) |
All Symbols share the same namespace, therefore all global identifiers have to be unique, even if they designate different objects. To guarantee consistent behaviour of defined functions and operators, there is no way to undefine a once declared global symbol.
qcl> int f; qcl> int f(int n) { return f^2; } ! illegal scope: Global symbol f already defined |
qufunct flip(qureg q) { /* define my own version of flip */ } set allow-redefines true; include "dft"; // flip-version in dft.qcl is ignored set allow-redefines false; |
When using qcl interactively (see section 2.1.3.3), the shell command can be used to open a subshell with a temporal scope. This means, that new definitions are only valid within the current subshell.2.2 All temporal symbols are destroyed again, when the subshell is left with exit.
qcl> list x; : symbol x is undefined. qcl> shell; : shell escape qcl1> int x; qcl1> list x; : global symbol x = 0: int x; qcl1> exit qcl> list x; : symbol x is undefined. |