‘qc’ Dialect¶
The QC (reference semantics) dialect for quantum computing.
The QC dialect uses reference semantics where quantum operations modify qubits in place, similar to how hardware physically transforms quantum states. This model provides:
Natural mapping to hardware execution models
Intuitive representation for circuit descriptions
Direct compatibility with imperative quantum programming languages
Straightforward backend code generation
The name “QC” stands for “Quantum Circuit.”
Example:
qc.h %q // Applies Hadamard to qubit %q in place
qc.swap %q0, %q1 // Applies SWAP using %q0, %q1 as targets
Operations¶
qc.alloc (qc::AllocOp)¶
Allocate a qubit dynamically
Syntax:
operation ::= `qc.alloc` attr-dict `:` type($result)
Allocates a new qubit dynamically and returns a reference to it. The qubit is initialized to the |0⟩ state.
Example:
%q = qc.alloc : !qc.qubit
Interfaces: InferTypeOpInterface, MemoryEffectOpInterface (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{MemoryEffects::Allocate on ::mlir::SideEffects::DefaultResource}
Results:¶
Result |
Description |
|---|---|
|
QC qubit reference type |
qc.barrier (qc::BarrierOp)¶
Apply a barrier gate to a set of qubits
Syntax:
operation ::= `qc.barrier` $qubits attr-dict `:` type($qubits)
Applies a barrier gate to a set of qubits, modifying them in place.
Example:
qc.barrier %q : !qc.qubit
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QC qubit reference type |
qc.ctrl (qc::CtrlOp)¶
Add control qubits to a unitary operation
Syntax:
operation ::= `qc.ctrl` `(` $controls `)`
`targets`
custom<TargetAliasing>($region, $targets)
attr-dict `:`
`{` type($controls) `}` ( `,` `{` type($targets)^ `}` )?
A modifier operation that adds control qubits to the unitary operation defined in its body region. The controlled operation applies the underlying unitary only when all control qubits are in the \(|1\rangle\) state.
Note that control qubits are logically unmodified by this operation in that their quantum state remains unchanged.
However, the controls argument is marked with MemWrite to ensure correct dependency tracking in MLIR.
The body region may contain an arbitrary amount of unitary and classical operations.
Non-unitary operations, such as AllocOp and MeasureOp, are not allowed.
Example:
qc.ctrl(%q0) targets(%a0 = %q1) {
qc.x %a0 : !qc.qubit
} : !qc.qubit
Traits: AttrSizedOperandSegments, RecursiveMemoryEffects, SingleBlockImplicitTerminator<::mlir::qc::YieldOp>, SingleBlock
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QC qubit reference type |
|
variadic of QC qubit reference type |
qc.dcx (qc::DCXOp)¶
Apply a DCX gate to two qubits
Syntax:
operation ::= `qc.dcx` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies a DCX gate to two qubits, modifying them in place.
Example:
qc.dcx %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
qc.dealloc (qc::DeallocOp)¶
Deallocate a qubit
Syntax:
operation ::= `qc.dealloc` $qubit attr-dict `:` type($qubit)
Deallocates a qubit, releasing its resources.
Example:
qc.dealloc %q : !qc.qubit
Interfaces: MemoryEffectOpInterface (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{MemoryEffects::Free on ::mlir::SideEffects::DefaultResource}
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.ecr (qc::ECROp)¶
Apply an ECR gate to two qubits
Syntax:
operation ::= `qc.ecr` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an ECR gate to two qubits, modifying them in place.
Example:
qc.ecr %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
qc.gphase (qc::GPhaseOp)¶
Apply a global phase to the state
Syntax:
operation ::= `qc.gphase` `(` $theta `)` attr-dict
Applies a global phase to the state.
Example:
qc.gphase(%theta)
Traits: ZeroTargetOneParameter
Interfaces: MemoryEffectOpInterface (MemoryEffectOpInterface), UnitaryOpInterface
Effects: MemoryEffects::Effect{MemoryEffects::Write on ::mlir::SideEffects::DefaultResource}
Operands:¶
Operand |
Description |
|---|---|
|
64-bit float |
qc.h (qc::HOp)¶
Apply an H gate to a qubit
Syntax:
operation ::= `qc.h` $qubit_in attr-dict `:` type($qubit_in)
Applies an H gate to a qubit, modifying it in place.
Example:
qc.h %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.id (qc::IdOp)¶
Apply an Id gate to a qubit
Syntax:
operation ::= `qc.id` $qubit_in attr-dict `:` type($qubit_in)
Applies an Id gate to a qubit, modifying it in place.
Example:
qc.id %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.inv (qc::InvOp)¶
Invert a unitary operation
Syntax:
operation ::= `qc.inv` custom<TargetAliasing>($region, $qubits)
attr-dict `:`
type($qubits)
A modifier operation that inverts the unitary operation defined in its body region.
The body region may contain an arbitrary amount of unitary and classical operations.
Non-unitary operations, such as AllocOp and MeasureOp, are not allowed.
Example:
qc.inv (%a0 = %q0) {
qc.s %a0 : !qc.qubit
}
Traits: RecursiveMemoryEffects, SingleBlockImplicitTerminator<::mlir::qc::YieldOp>, SingleBlock
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
variadic of QC qubit reference type |
qc.iswap (qc::iSWAPOp)¶
Apply a iSWAP gate to two qubits
Syntax:
operation ::= `qc.iswap` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies a iSWAP gate to two qubits, modifying them in place.
Example:
qc.iswap %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
qc.measure (qc::MeasureOp)¶
Measure a qubit in the computational basis
Syntax:
operation ::= `qc.measure` (`(` $register_name^ `,` $register_size `,` $register_index `)`)?
$qubit `:` type($qubit) `->` type($result) attr-dict
Measures a qubit in the computational (Z) basis, collapsing the state and returning a classical bit result.
Optionally, the measurement can be recorded to an output register by specifying:
register_name: Name of the classical register (e.g., “c”)register_size: Total size of the registerregister_index: Index within the register for this measurement
Example (simple measurement):
%result = qc.measure %q : !qc.qubit -> i1
Example (measurement with output recording):
%result = qc.measure("c", 2, 0) %q : !qc.qubit -> i1
Interfaces: InferTypeOpInterface
Attributes:¶
| Attribute | MLIR Type | Description |
|---|---|---|
register_name | ::mlir::StringAttr | string attribute |
register_size | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is positive |
register_index | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is non-negative |
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
Results:¶
Result |
Description |
|---|---|
|
1-bit signless integer |
qc.p (qc::POp)¶
Apply a P gate to a qubit
Syntax:
operation ::= `qc.p` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in)
Applies a P gate to a qubit, modifying it in place.
Example:
qc.p(%theta) %q : !qc.qubit
Traits: OneTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
qc.r (qc::ROp)¶
Apply an R gate to a qubit
Syntax:
operation ::= `qc.r` `(` $theta `,` $phi `)` $qubit_in attr-dict `:` type($qubit_in)
Applies an R gate to a qubit, modifying it in place.
Example:
qc.r(%theta, %phi) %q : !qc.qubit
Traits: OneTargetTwoParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
|
64-bit float |
qc.reset (qc::ResetOp)¶
Reset a qubit to |0⟩ state
Syntax:
operation ::= `qc.reset` $qubit attr-dict `:` type($qubit)
Resets a qubit to the |0⟩ state, regardless of its current state.
Example:
qc.reset %q : !qc.qubit
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.rx (qc::RXOp)¶
Apply an RX gate to a qubit
Syntax:
operation ::= `qc.rx` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in)
Applies an RX gate to a qubit, modifying it in place.
Example:
qc.rx(%theta) %q : !qc.qubit
Traits: OneTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
qc.rxx (qc::RXXOp)¶
Apply an RXX gate to two qubits
Syntax:
operation ::= `qc.rxx` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an RXX gate to two qubits, modifying them in place.
Example:
qc.rxx(%theta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
qc.ry (qc::RYOp)¶
Apply an RY gate to a qubit
Syntax:
operation ::= `qc.ry` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in)
Applies an RY gate to a qubit, modifying it in place.
Example:
qc.ry(%theta) %q : !qc.qubit
Traits: OneTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
qc.ryy (qc::RYYOp)¶
Apply an RYY gate to two qubits
Syntax:
operation ::= `qc.ryy` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an RYY gate to two qubits, modifying them in place.
Example:
qc.ryy(%theta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
qc.rz (qc::RZOp)¶
Apply an RZ gate to a qubit
Syntax:
operation ::= `qc.rz` `(` $theta `)` $qubit_in attr-dict `:` type($qubit_in)
Applies an RZ gate to a qubit, modifying it in place.
Example:
qc.rz(%theta) %q : !qc.qubit
Traits: OneTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
qc.rzx (qc::RZXOp)¶
Apply an RZX gate to two qubits
Syntax:
operation ::= `qc.rzx` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an RZX gate to two qubits, modifying them in place.
Example:
qc.rzx(%theta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
qc.rzz (qc::RZZOp)¶
Apply an RZZ gate to two qubits
Syntax:
operation ::= `qc.rzz` `(` $theta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an RZZ gate to two qubits, modifying them in place.
Example:
qc.rzz(%theta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetOneParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
qc.s (qc::SOp)¶
Apply an S gate to a qubit
Syntax:
operation ::= `qc.s` $qubit_in attr-dict `:` type($qubit_in)
Applies an S gate to a qubit, modifying it in place.
Example:
qc.s %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.sdg (qc::SdgOp)¶
Apply an Sdg gate to a qubit
Syntax:
operation ::= `qc.sdg` $qubit_in attr-dict `:` type($qubit_in)
Applies an Sdg gate to a qubit, modifying it in place.
Example:
qc.sdg %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.static (qc::StaticOp)¶
Retrieve a static qubit by index
Syntax:
operation ::= `qc.static` $index attr-dict `:` type($qubit)
The qc.static operation produces an SSA value representing a qubit
identified by a static index. This is useful for referring to fixed
qubits in a quantum program or to hardware-mapped qubits.
Example:
%q = qc.static 0 : !qc.qubit
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes:¶
| Attribute | MLIR Type | Description |
|---|---|---|
index | ::mlir::IntegerAttr | 64-bit signless integer attribute whose value is non-negative |
Results:¶
Result |
Description |
|---|---|
|
QC qubit reference type |
qc.swap (qc::SWAPOp)¶
Apply a SWAP gate to two qubits
Syntax:
operation ::= `qc.swap` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies a SWAP gate to two qubits, modifying them in place.
Example:
qc.swap %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
qc.sx (qc::SXOp)¶
Apply an SX gate to a qubit
Syntax:
operation ::= `qc.sx` $qubit_in attr-dict `:` type($qubit_in)
Applies an SX gate to a qubit, modifying it in place.
Example:
qc.sx %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.sxdg (qc::SXdgOp)¶
Apply an SXdg gate to a qubit
Syntax:
operation ::= `qc.sxdg` $qubit_in attr-dict `:` type($qubit_in)
Applies an SXdg gate to a qubit, modifying it in place.
Example:
qc.sxdg %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.t (qc::TOp)¶
Apply a T gate to a qubit
Syntax:
operation ::= `qc.t` $qubit_in attr-dict `:` type($qubit_in)
Applies a T gate to a qubit, modifying it in place.
Example:
qc.t %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.tdg (qc::TdgOp)¶
Apply a Tdg gate to a qubit
Syntax:
operation ::= `qc.tdg` $qubit_in attr-dict `:` type($qubit_in)
Applies a Tdg gate to a qubit, modifying it in place.
Example:
qc.tdg %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.u (qc::UOp)¶
Apply a U gate to a qubit
Syntax:
operation ::= `qc.u` `(` $theta `,` $phi `,` $lambda `)` $qubit_in attr-dict `:` type($qubit_in)
Applies a U gate to a qubit, modifying it in place.
Example:
qc.u(%theta, %phi, %lambda) %q : !qc.qubit
Traits: OneTargetThreeParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
|
64-bit float |
|
64-bit float |
qc.u2 (qc::U2Op)¶
Apply a U2 gate to a qubit
Syntax:
operation ::= `qc.u2` `(` $phi `,` $lambda `)` $qubit_in attr-dict `:` type($qubit_in)
Applies a U2 gate to a qubit, modifying it in place.
Example:
qc.u2(%phi, %lambda) %q : !qc.qubit
Traits: OneTargetTwoParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
64-bit float |
|
64-bit float |
qc.x (qc::XOp)¶
Apply an X gate to a qubit
Syntax:
operation ::= `qc.x` $qubit_in attr-dict `:` type($qubit_in)
Applies an X gate to a qubit, modifying it in place.
Example:
qc.x %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.xx_minus_yy (qc::XXMinusYYOp)¶
Apply an XX-YY gate to two qubits
Syntax:
operation ::= `qc.xx_minus_yy` `(` $theta `,` $beta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an XX-YY gate to two qubits, modifying them in place.
Example:
qc.xx_minus_yy(%theta, %beta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetTwoParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
|
64-bit float |
qc.xx_plus_yy (qc::XXPlusYYOp)¶
Apply an XX+YY gate to two qubits
Syntax:
operation ::= `qc.xx_plus_yy` `(` $theta `,` $beta `)` $qubit0_in `,` $qubit1_in attr-dict `:` type($qubit0_in) `,` type($qubit1_in)
Applies an XX+YY gate to two qubits, modifying them in place.
Example:
qc.xx_plus_yy(%theta, %beta) %q0, %q1 : !qc.qubit, !qc.qubit
Traits: TwoTargetTwoParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
|
QC qubit reference type |
|
64-bit float |
|
64-bit float |
qc.y (qc::YOp)¶
Apply a Y gate to a qubit
Syntax:
operation ::= `qc.y` $qubit_in attr-dict `:` type($qubit_in)
Applies a Y gate to a qubit, modifying it in place.
Example:
qc.y %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
qc.yield (qc::YieldOp)¶
Yield from a modifier region
Syntax:
operation ::= `qc.yield` attr-dict
Terminates a modifier region, yielding control back to the enclosing operation.
Traits: Terminator
qc.z (qc::ZOp)¶
Apply a Z gate to a qubit
Syntax:
operation ::= `qc.z` $qubit_in attr-dict `:` type($qubit_in)
Applies a Z gate to a qubit, modifying it in place.
Example:
qc.z %q : !qc.qubit
Traits: OneTargetZeroParameter
Interfaces: UnitaryOpInterface
Operands:¶
Operand |
Description |
|---|---|
|
QC qubit reference type |
Types¶
QubitType¶
QC qubit reference type
Syntax: !qc.qubit
The !qc.qubit type represents a reference to a quantum bit in the QC dialect.
Operations using this type modify qubits in place using reference semantics, similar to how classical imperative languages handle mutable references.
OpInterface definitions¶
UnitaryOpInterface (UnitaryOpInterface)¶
This interface provides a unified API for all operations that apply or produce a unitary transformation. This includes base gates, user-defined gates, modifier operations (control, inverse, power), and sequences.
The interface enables uniform introspection and composition capabilities across all unitary operations in the QC dialect.
Methods:¶
getNumQubits¶
size_t getNumQubits();
Returns the number of qubits acted on by the unitary operation.
NOTE: This method must be implemented by the user.
getNumTargets¶
size_t getNumTargets();
Returns the number of target qubits (excluding control qubits).
NOTE: This method must be implemented by the user.
getNumControls¶
size_t getNumControls();
Returns the number of control qubits (both positive and negative).
NOTE: This method must be implemented by the user.
getQubit¶
Value getQubit(size_t i);
Returns the i-th qubit (targets + controls combined).
NOTE: This method must be implemented by the user.
getTarget¶
Value getTarget(size_t i);
Returns the i-th target qubit.
NOTE: This method must be implemented by the user.
getControl¶
Value getControl(size_t i);
Returns the i-th control qubit.
NOTE: This method must be implemented by the user.
getQubits¶
OperandRange getQubits();
Returns a range of all qubits (targets + controls combined).
NOTE: This method must be implemented by the user.
getTargets¶
OperandRange getTargets();
Returns a range of all target qubits.
NOTE: This method must be implemented by the user.
getControls¶
OperandRange getControls();
Returns a range of all control qubits.
NOTE: This method must be implemented by the user.
getNumParams¶
size_t getNumParams();
Returns the number of parameters.
NOTE: This method must be implemented by the user.
getParameter¶
Value getParameter(size_t i);
Returns the i-th parameter.
NOTE: This method must be implemented by the user.
getParameters¶
OperandRange getParameters();
Returns a range of all parameters.
NOTE: This method must be implemented by the user.
isControlled¶
bool isControlled();
Returns true if the operation has any control qubits, otherwise false.
isSingleQubit¶
bool isSingleQubit();
Returns true if the operation only acts on a single qubit.
isTwoQubit¶
bool isTwoQubit();
Returns true if the operation acts on two qubits.
getBaseSymbol¶
StringRef getBaseSymbol();
Returns the base symbol/mnemonic of the operation.
NOTE: This method must be implemented by the user.
Passes¶
-qc-shrink-qubit-registers¶
Shrink static qc::QubitType MemRef registers to accessed indices.
Shrinks one-dimensional static MemRef registers with element type !qc.qubit by removing never-read indices and remapping memref.load users accordingly.