diff --git a/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md b/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md
index 600f0d456..8bf86fec8 100644
--- a/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md
+++ b/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md
@@ -12,6 +12,7 @@ search:
- unitary
- multiply
- multiply_constant
+ - canonical_add
- canonical_multiply
- canonical_multiply_constant
diff --git a/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md b/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md
index 6b656c29a..cc2fe43df 100644
--- a/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md
+++ b/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md
@@ -13,7 +13,7 @@ search:
- commuting_paulis_exponent
- suzuki_trotter
- multi_suzuki_trotter
- - unscheduled_suzuki_trotter
+ - sequential_suzuki_trotter
- qdrift
- exponentiate
diff --git a/.internal/docs/qmod-reference/language-reference/expressions.md b/.internal/docs/qmod-reference/language-reference/expressions.md
new file mode 100644
index 000000000..0756194aa
--- /dev/null
+++ b/.internal/docs/qmod-reference/language-reference/expressions.md
@@ -0,0 +1,219 @@
+---
+search:
+ boost: 1.0
+---
+
+# Expressions
+
+Expressions in Qmod have syntax, semantics, and use, similar to expressions in
+conventional programming languages.
+They comprise literal values, variables, and operators applied to them.
+However, Qmod is unique in that variables can be of either [classical](https://docs.classiq.io/latest/qmod-reference/api-reference/classical-types) or
+[quantum](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types) types, and quantum variables have states that can be a
+superposition of values, entangled with the states of other variables.
+Expressions over quantum variables evaluate to a superposition of correlated
+values.
+For example, if `x` is a [classical variable](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables)
+of type `CInt` (an integer), then `x + 1` is a classical expression of type
+`CInt` comprising the operator `+` (plus) applied to `x` and the literal `1`.
+Similarly, if `qarr` is a [quantum variable](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-variables)
+of type `QArray[QNum[3]]`, then `qarr[0] > x` is a quantum expression of type
+`QBit`.
+
+_Unary operators_ are applied to a single operand. For instance, you can apply
+the unary operator `~` (bitwise-invert) to variable `x` and get the expression
+`~x`.
+_Binary operators_ are applied to two operands. For example, the operator `>`
+(greater-than) in the expression `qarr[0] > x` is applied to two operands,
+`qarr[0]` and variable `x`.
+The expression `qarr[0]` comprises the _subscript operator_ `[]` applied to
+variable `qarr` and the literal `0`.
+Applications of subscript (`[]`) and field-access (`.`) operators to classical
+and quantum variables are called _path expressions_, since they point to a
+partial section of the variable along a certain access path.
+In our case, for instance, `qarr[0]` represents the first (0) element of the
+array `qarr`.
+
+## Qmod Operators
+
+You can apply operators to operand expressions to create composite expressions.
+If at least one of the operands is quantum then the expression is quantum as
+well; Otherwise, it is classical.
+
+Qmod supports the following operators:
+
+### Arithmetic operators
+
+You can apply arithmetic operators to classical numbers (`CInt` and `CReal`) and
+quantum scalars (`QBit` and `QNum`) to create numeric expressions.
+
+- Add: +
+- Subtract: - (binary)
+- Negate: - (unary)
+- Multiply: \*
+- Power \*\* (quantum base, positive classical integer exponent)
+- Modulo: % limited for power of 2
+- Max: max (n>=2 arguments)
+- Min: min (n>=2 arguments)
+
+### Bitwise operators
+
+You can apply bitwise operators to classical numbers (`CInt` and `CReal`) and
+quantum scalars (`QBit` and `QNum`) to create numeric expressions.
+
+- Bitwise Or: |
+- Bitwise And: &
+- Bitwise Xor: ^
+- Bitwise Invert: ~
+
+### Relational operators
+
+You can apply relational operators to classical numbers (`CInt` and `CReal`) and
+quantum scalars (`QBit` and `QNum`) to create Boolean expressions (of types
+`CBool` and `QBit`).
+
+- Equal: ==
+- Not Equal: !=
+- Greater Than: >
+- Greater Or Equal: >=
+- Less Than: <
+- Less Or Equal: <=
+
+### Logic operators
+
+You can apply logical operators to Boolean expressions (`CBool`, `QBit`, and
+`QNum[1]`) to create Boolean expressions (of types `CBool` and `QBit`).
+
+- Logical And: `logical_and()` (in Qmod Native: and)
+- Logical Or: `logical_or()` (in Qmod Native: or)
+- Logical Not: `logical_not()` (in Qmod Native: not)
+
+### Path operators
+
+You can use path operators to access parts of classical and quantum variables of
+aggregate types, namely, structs and arrays.
+
+- Field Access: _struct_ **.** _field-name_
+- Array Slice: _array_ **[** _start-index_ **:** _stop-index_ **]**
+ - In Python, _start-index_ and _stop-index_ may be omitted.
+ If _start-index_ is omitted, a `0` will be placed in its stead.
+ If _stop-index_ is omitted, `array.len` will be placed in its stead.
+- Array Subscript: _array_ **[** _index_ **]**
+ - The index of a quantum subscript expression must be an [unsigned quantum integer](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#quantum-scalar-types) variable.
+ - In Python, if _array_ is a Python list and _index_ is a quantum variable, use the alternative syntax: **subscript(** _array_ **,** _index_ **)**
+ - Currently, quantum subscript expressions are not supported in [phase statements](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase/).
+
+## Quantum Expressions
+
+Quantum expressions are expressions that involve one or more quantum variables.
+Quantum expressions can occur in the following contexts:
+
+- The right-value in [assignment](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/assignment) statements
+- The condition in [control](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/control) statements
+- The expression argument in [phase](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase) statements
+
+During computation, the value(s) of an expression are coherently correlated to
+the evaluation of the operators over the computational-basis values of the
+quantum variables it comprises, which may be in any specific superpositions and
+entanglement.
+Quantum expressions may include any combination of operators on any
+classical and quantum variables and literals, with the following exceptions:
+
+- All classical variables must be [compile-time](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables/#semantics).
+- The right-hand side of the division (`/`) and power (`**`) operators must be
+ a classical expression.
+
+### Examples
+
+The following model includes qubit `q` and quantum numeric `n` of size three.
+It uses a `control` statement with a quantum expression `n > 4` to apply
+`X` to `q` only when `n` is greater than four.
+
+=== "Python"
+
+ ```python
+ from classiq import qfunc, Output, QBit, QNum, allocate, control, hadamard_transform
+
+
+ @qfunc
+ def main(n: Output[QNum[3]], q: Output[QBit]):
+ allocate(n)
+ hadamard_transform(n)
+ allocate(q)
+ control(n > 4, lambda: X(q))
+ ```
+
+=== "Native"
+
+ ```
+ qfunc main(output n: qnum<3>, output q: qbit) {
+ allocate(n);
+ hadamard_transform(n);
+ allocate(q);
+ control(n > 4) {
+ X(q);
+ }
+ }
+ ```
+
+After executing this model, you get $q=0$ for $n\in\{0, 1, 2, 3, 4\}$ and
+$q=1$ for $n\in\{5, 6, 7\}$.
+
+See [additional examples](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/assignment/#examples)
+on the Assignment documentation page.
+
+## Classical Expressions
+
+Classical expressions are expressions that involve classical variables and
+constant literals, but no quantum variables.
+Classical variables may have known values at [compile time, link time, or runtime]](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables/#semantics).
+Classical expressions with only compile-time variables are evaluated and
+simplified during compilation.
+This applies sub-expressions of quantum expressions too.
+Qmod supports several built-in classical [constants and functions](https://docs.classiq.io/latest/qmod-reference/api-reference/symbolic-functions/),
+such as `pi` and `sin`.
+
+### Example
+
+In the following model, function `foo` accepts quantum numeric `n` and a
+classical integer `x`, and perform the in-place xor operation `n ^= x + 1`.
+Function `foo` is called twice, once with `x=1` and once with `x=-1`.
+
+=== "Python"
+
+ ```python
+ from classiq import qfunc, CInt, Output, QNum
+
+
+ @qfunc
+ def foo(n: QNum, x: CInt):
+ n ^= x + 1
+
+
+ @qfunc
+ def main(n: Output[QNum]):
+ n |= 1
+ foo(n, 1) # n ^= 2
+ foo(n, -1) # n ^= 0
+ ```
+
+=== "Native"
+
+ ```
+ qfunc foo(n: qnum, x: int) {
+ n ^= x + 1;
+ }
+
+ qfunc main(output n: qnum) {
+ n = 1;
+ foo(n, 1); // n ^= 2;
+ foo(n, -1); // n ^= 0;
+ }
+ ```
+
+On the first call to `foo`, the Qmod compiler assigns `x=1` and simplifies the
+expression `x + 1` into `2`.
+Therefore, the first `foo` call applies a constant-value xor `n ^= 2`.
+On the second call to `foo`, the expression `x + 1` is simplified to `0`.
+Since the assignment `n ^= 0` has no effect, the Qmod compiler removes it from
+the model.
diff --git a/.internal/docs/qmod-reference/language-reference/quantum-variables.md b/.internal/docs/qmod-reference/language-reference/quantum-variables.md
index 13171a0be..6b9304b0b 100644
--- a/.internal/docs/qmod-reference/language-reference/quantum-variables.md
+++ b/.internal/docs/qmod-reference/language-reference/quantum-variables.md
@@ -371,14 +371,14 @@ The _concatenation operator_ is used to combine a sequence of quantum objects
**[** _path-expressions_ **]**
_path-expressions_ is a comma-separated sequence of one or more quantum
- [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/statements/numeric-assignment/?h=path+expression#path-operators).
+ [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/expressions).
=== "Native"
**{** _path-expressions_ **}**
_path-expressions_ is a comma-separated sequence of one or more quantum
- [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/statements/numeric-assignment/?h=path+expression#path-operators).
+ [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/expressions).
For example, the model below uses the concatenation operator to apply
`hadamard_transform` to a specific set of qubits drawn from two quantum
diff --git a/.internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md b/.internal/docs/qmod-reference/language-reference/statements/assignment.md
similarity index 76%
rename from .internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md
rename to .internal/docs/qmod-reference/language-reference/statements/assignment.md
index 875b277c9..40fa4bdd9 100644
--- a/.internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md
+++ b/.internal/docs/qmod-reference/language-reference/statements/assignment.md
@@ -3,10 +3,13 @@ search:
boost: 2.361
---
-# Numeric Assignment
+# Assignment
+
+## Numeric Assignment
Scalar quantum variables (`qnum` and `qbit`) can be assigned the result of arithmetic/logical
-expressions over other scalar variables using computational basis arithmetic. Expressions
+[expressions](https://docs.classiq.io/latest/qmod-reference/language-reference/expressions)
+over other scalar variables using computational basis arithmetic. Expressions
comprise conventional arithmetic operators, numeric constants, and quantum scalar variables.
Numeric assignment statements in the computational basis take two forms - out-of-place
@@ -14,7 +17,7 @@ and in-place. When assigning the result of an expression out-of-place, a new qua
object is allocated to store the result. For in-place assignment, the result
of the operation is stored back in the target variable.
-## Syntax
+### Syntax
=== "Python"
@@ -49,7 +52,7 @@ of the operation is stored back in the target variable.
_target-var_ **+=** _quantum-expression_
-## Semantics
+### Semantics
- _quantum-expression_ consists of quantum scalar variables, numeric constant
literals, and classical scalar variables, composed using arithmetic operators.
@@ -57,7 +60,7 @@ of the operation is stored back in the target variable.
- The quantum variables occurring in the expression can subsequently be used, with their
states unmodified.
-### Out-of-place assignment (`=`/`|=`)
+#### Out-of-place assignment (`=`/`|=`)
- _target-var_ must be uninitialized prior to the assignment and is
subsequently initialized.
@@ -68,7 +71,7 @@ of the operation is stored back in the target variable.
otherwise be compatible with the computed numeric attributes of _quantum-expression_,
that is, fit the entire range of possible expression values.
-### In-place XOR (`^=`)
+#### In-place XOR (`^=`)
- _target-var_ must be initialized prior to the assignment.
- Each bit in _target-var_ is xor-ed with the
@@ -76,7 +79,7 @@ of the operation is stored back in the target variable.
unchanged.
- Bits in the result of _quantum-expression_ with no counterpart in _target-var_ are ignored.
-### In-place add (`+=`)
+#### In-place add (`+=`)
@@ -91,49 +94,63 @@ of the operation is stored back in the target variable.
integer part (including the sign bit) without incurring additional qubits,
following the two's complement method.
-### Supported arithmetic operators
+## Aggregate Type Assignment
+
+A struct or array quantum variable can be assigned to another variable of the
+same type.
+In addition, an array literal can be assigned to a `QArray[QBit]` variable.
+
+### Syntax
+
+=== "Python"
-#### Arithmetic operators
+
-- Add: +
-- Subtract: - (binary)
-- Negate: - (unary)
-- Multiply: \*
-- Power \*\* (quantum base, positive classical integer exponent)
-- Modulo: % limited for power of 2
-- Max: max (n>=2 arguments)
-- Min: min (n>=2 arguments)
+ _target-var_ **|=** _assigned-var_
+ OR
+ **assign(**_assigned-var_**,** _target-var_**)**
-#### Bitwise operators
+ _target-var_ **^=** _assigned-var_
+ OR
+ **inplace_xor(**_assigned-var_**,** _target-var_**)**
-- Bitwise Or: |
-- Bitwise And: &
-- Bitwise Xor: ^
-- Bitwise Invert: ~
+ _array-var_ **|=** _array-literal_
+ OR
+ **assign(**_array-literal_**,** _array-var_**)**
-#### Relational operators
+ _target-var_ **^=** _array-literal_
+ OR
+ **inplace_xor(**_array-literal_**,** _array-var_**)**
-- Equal: ==
-- Not Equal: !=
-- Greater Than: >
-- Greater Or Equal: >=
-- Less Than: <
-- Less Or Equal: <=
+ #### Notes
+
+ * The operator `|=` is used to represent the native `=` since the operator
+ `=` cannot be overloaded in Python.
+ * The operator syntax and the function call syntax are equivalent. The
+ operator syntax is typically easier to read, but it cannot be used
+ directly in lambda expressions, where the function call syntax should be
+ used.
+
+=== "Native"
-#### Logic operators
+ _target-var_ **=** _assigned-var_
-- Logical And: and (in Python `logical_and()`)
-- Logical Or: or (in Python `logical_or()`)
-- Logical Not: not (in Python `logical_not()`)
+ _target-var_ **^=** _assigned-var_
-#### Path operators
+ _array-var_ **=** _array-literal_
-- Field Access: _struct_ **.** _field-name_
-- Array Slice: _array_ **[** _start-index_ **:** _stop-index_ **]**
-- Array Subscript: _array_ **[** _index_ **]**
- - The index of a quantum subscript expression must be an [unsigned quantum integer](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#quantum-scalar-types) variable.
- - In Python, if _array_ is a Python list and _index_ is a quantum variable, use the alternative syntax: **subscript(** _array_ **,** _index_ **)**
- - Currently, quantum subscript expressions are not supported in [phase statements](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase/).
+ _array-var_ **^=** _array-literal_
+
+### Semantics
+
+- As with numeric assignments, _target-var_ must be uninitialized in
+ out-of-place assignments and initialized in in-place assignments.
+ _assigned-var_ must be initialized in both cases.
+- _target-var_ and _assigned-var_ must have the same type. For example,
+ variable of type `QArray[QBit]` can be assigned into a `QArray[QBit]`
+ variable, but a `QArray[QNum]` variable cannot.
+- _array-literal_ is a classical array of 0-s and 1-s. _array-var_ must be
+ a quantum variable of type `QArray[QBit]`.
## Examples
@@ -376,3 +393,35 @@ Overall, the output variable `n` evaluates to 7 (10%), 3 (20%), 6 (30%), or 2
n = [7, 3, 6, 2][index]; // n is 7, 3, 6, or 2 with increasing probability
}
```
+
+### Example 7: Aggregate type assignments
+
+The following model demonstrate different kinds of quantum array assignments.
+First, you assign the array literal `[0, 1, 1, 0]` into variable `qarr1` of type
+`QArray[QBit]`.
+This applies `X` to the second and third bits of the array.
+Next, you initialize `qarr2` by assigning `qarr1` to it.
+This applies `CX` to the qubits of `qarr1` and `qarr2` sequentially.
+
+=== "Python"
+
+ ```python
+ from classiq import qfunc, Output, QArray, QBit, allocate
+
+
+ @qfunc
+ def main(qarr1: Output[QArray], qarr2: Output[QArray]) -> None:
+ allocate(4, qarr1)
+ qarr1 ^= [0, 1, 1, 0]
+ qarr2 |= qarr1
+ ```
+
+=== "Native"
+
+ ```
+ qfunc main(output qarr1: qbit[], output qarr2: qbit[]) {
+ allocate(4, qarr1);
+ qarr1 ^= [0, 1, 1, 0];
+ qarr2 = qarr1;
+ }
+ ```
diff --git a/.internal/docs/support/index.md b/.internal/docs/support/index.md
index e94bf1abe..db5d89159 100644
--- a/.internal/docs/support/index.md
+++ b/.internal/docs/support/index.md
@@ -87,7 +87,7 @@ Welcome to the Classiq Support Center. This page is designed to help you quickly
Using `control`, you can define multi-qubit controls and gates. You can also use `if_` for classical control of quantum gates. See [Classical Control Flow](/latest/qmod-reference/language-reference/statements/classical-control-flow/).
??? note "How do I use controlled operations on multiple qubits instead of QArrays?"
- There are two ways to work around this: either bind the qubits you want to a QArray (see [bind](/latest/qmod-reference/language-reference/statements/bind/)) or slice the QArrays (see [Path Operators](/latest/qmod-reference/language-reference/statements/numeric-assignment/#relational-operators)).
+ There are two ways to work around this: either bind the qubits you want to a QArray (see [bind](/latest/qmod-reference/language-reference/statements/bind/)) or slice the QArrays (see [Path Operators](/latest/qmod-reference/language-reference/expressions/#relational-operators)).
??? note "How do I apply a single-qubit gate to multiple qubits?"
Use the `apply_to_all` function. See [Utility functions](/latest/qmod-reference/api-reference/functions/open_library/utility_functions/).