# Quellcode für qiskit.circuit.library.arithmetic.multipliers.hrs_cumulative_multiplier

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2021.
#
# obtain a copy of this license in the LICENSE.txt file in the root directory
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Compute the product of two qubit registers using classical multiplication approach."""

from typing import Optional
from qiskit.circuit import QuantumRegister, AncillaRegister, QuantumCircuit

from .multiplier import Multiplier

[Doku]class HRSCumulativeMultiplier(Multiplier):
r"""A multiplication circuit to store product of two input registers out-of-place.

Circuit uses the approach from . As an example, a multiplier circuit that
performs a non-modular multiplication on two 3-qubit sized registers with
the default adder is as follows (where Adder denotes the
CDKMRippleCarryAdder):

.. parsed-literal::

a_0: ────■─────────────────────────
│
a_1: ────┼─────────■───────────────
│         │
a_2: ────┼─────────┼─────────■─────
┌───┴────┐┌───┴────┐┌───┴────┐
b_0: ┤0       ├┤0       ├┤0       ├
│        ││        ││        │
b_1: ┤1       ├┤1       ├┤1       ├
│        ││        ││        │
b_2: ┤2       ├┤2       ├┤2       ├
│        ││        ││        │
out_0: ┤3       ├┤        ├┤        ├
│        ││        ││        │
out_1: ┤4       ├┤3       ├┤        ├
out_2: ┤5       ├┤4       ├┤3       ├
│        ││        ││        │
out_3: ┤6       ├┤5       ├┤4       ├
│        ││        ││        │
out_4: ┤        ├┤6       ├┤5       ├
│        ││        ││        │
out_5: ┤        ├┤        ├┤6       ├
│        ││        ││        │
aux_0: ┤7       ├┤7       ├┤7       ├
└────────┘└────────┘└────────┘

Multiplication in this circuit is implemented in a classical approach by performing
a series of shifted additions using one of the input registers while the qubits
from the other input register act as control qubits for the adders.

**References:**

 Häner et al., Optimizing Quantum Circuits for Arithmetic, 2018.
arXiv:1805.12445 <https://arxiv.org/pdf/1805.12445.pdf>_

"""

def __init__(
self,
num_state_qubits: int,
num_result_qubits: Optional[int] = None,
name: str = "HRSCumulativeMultiplier",
) -> None:
r"""
Args:
num_state_qubits: The number of qubits in either input register for
state :math:|a\rangle or :math:|b\rangle. The two input
registers must have the same number of qubits.
num_result_qubits: The number of result qubits to limit the output to.
If number of result qubits is :math:n, multiplication modulo :math:2^n is performed
to limit the output to the specified number of qubits. Default
value is 2 * num_state_qubits to represent any possible
result from the multiplication of the two inputs.
name: The name of the circuit object.
Raises:
NotImplementedError: If num_result_qubits is not default and a custom adder is provided.
"""
super().__init__(num_state_qubits, num_result_qubits, name=name)

if self.num_result_qubits != 2 * num_state_qubits and adder is not None:
raise NotImplementedError("Only default adder is supported for modular multiplication.")

# define the registers
qr_a = QuantumRegister(num_state_qubits, name="a")
qr_b = QuantumRegister(num_state_qubits, name="b")
qr_out = QuantumRegister(self.num_result_qubits, name="out")

# prepare adder as controlled gate

# get the number of helper qubits needed

# add helper qubits if required
if num_helper_qubits > 0:
qr_h = AncillaRegister(num_helper_qubits, name="helper")  # helper/ancilla qubits

# build multiplication circuit
circuit = QuantumCircuit(*self.qregs, name=name)

for i in range(num_state_qubits):
excess_qubits = max(0, num_state_qubits + i + 1 - self.num_result_qubits)
if excess_qubits == 0:
else:
num_adder_qubits = num_state_qubits - excess_qubits + 1