classiq 0.100.0__py3-none-any.whl → 0.104.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +63 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/__init__.py +11 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +3 -0
- classiq/execution/functions/_logging.py +19 -0
- classiq/execution/functions/constants.py +9 -0
- classiq/execution/functions/parse_provider_backend.py +90 -0
- classiq/execution/functions/sample.py +257 -0
- classiq/execution/jobs.py +122 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +15 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +3 -0
- classiq/interface/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +38 -2
- classiq/interface/generator/function_param_list.py +4 -2
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +45 -0
- classiq/interface/generator/functions/type_name.py +23 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +62 -2
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +15 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_function_call.py +17 -5
- classiq/interface/model/quantum_type.py +21 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +12 -10
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -47
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +34 -4
- classiq/qmod/builtins/operations.py +30 -41
- classiq/qmod/native/pretty_printer.py +12 -12
- classiq/qmod/pretty_print/pretty_printer.py +11 -15
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +45 -8
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- classiq/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
from collections.abc import Mapping, Sequence
|
|
2
|
-
from typing import Literal
|
|
3
|
-
|
|
4
|
-
import pydantic
|
|
5
|
-
|
|
6
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
7
|
-
from classiq.interface.generator.amplitude_loading import (
|
|
8
|
-
AMPLITUDE_IO_NAME,
|
|
9
|
-
TARGET_OUTPUT_NAME,
|
|
10
|
-
)
|
|
11
|
-
from classiq.interface.model.handle_binding import (
|
|
12
|
-
ConcreteHandleBinding,
|
|
13
|
-
HandleBinding,
|
|
14
|
-
)
|
|
15
|
-
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
16
|
-
QuantumAssignmentOperation,
|
|
17
|
-
)
|
|
18
|
-
from classiq.interface.model.quantum_statement import HandleMetadata
|
|
19
|
-
from classiq.interface.model.quantum_type import QuantumBit, QuantumNumeric, QuantumType
|
|
20
|
-
|
|
21
|
-
MULTI_VARS_UNSUPPORTED_ERROR = (
|
|
22
|
-
"Amplitude Loading with more than one input variable is unsupported."
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
VAR_TYPE_ILLEGAL = "Amplitude Loading input variable should be a quantum numeric"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
|
29
|
-
kind: Literal["AmplitudeLoadingOperation"]
|
|
30
|
-
|
|
31
|
-
_result_type: QuantumType = pydantic.PrivateAttr(default_factory=QuantumBit)
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def wiring_inouts(
|
|
35
|
-
self,
|
|
36
|
-
) -> Mapping[str, ConcreteHandleBinding]:
|
|
37
|
-
inouts = {self.result_name(): self.result_var}
|
|
38
|
-
if len(self.var_handles) == 1:
|
|
39
|
-
inouts[AMPLITUDE_IO_NAME] = self.var_handles[0]
|
|
40
|
-
return inouts
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def readable_inouts(self) -> Sequence[HandleMetadata]:
|
|
44
|
-
inouts = [
|
|
45
|
-
HandleMetadata(
|
|
46
|
-
handle=self.result_var,
|
|
47
|
-
readable_location="on the left-hand side of an in-place assignment",
|
|
48
|
-
)
|
|
49
|
-
]
|
|
50
|
-
if len(self.var_handles) == 1:
|
|
51
|
-
inouts.append(
|
|
52
|
-
HandleMetadata(
|
|
53
|
-
handle=self.var_handles[0],
|
|
54
|
-
readable_location="in an expression",
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
return inouts
|
|
58
|
-
|
|
59
|
-
@property
|
|
60
|
-
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
|
61
|
-
return {}
|
|
62
|
-
|
|
63
|
-
def initialize_var_types(
|
|
64
|
-
self,
|
|
65
|
-
var_types: dict[str, QuantumType],
|
|
66
|
-
machine_precision: int,
|
|
67
|
-
) -> None:
|
|
68
|
-
if len(var_types) != 1:
|
|
69
|
-
raise ClassiqValueError(MULTI_VARS_UNSUPPORTED_ERROR)
|
|
70
|
-
var_type = list(var_types.values())[0]
|
|
71
|
-
if not isinstance(var_type, QuantumNumeric):
|
|
72
|
-
raise ClassiqValueError(VAR_TYPE_ILLEGAL)
|
|
73
|
-
super().initialize_var_types(var_types, machine_precision)
|
|
74
|
-
|
|
75
|
-
@classmethod
|
|
76
|
-
def result_name(cls) -> str:
|
|
77
|
-
return TARGET_OUTPUT_NAME
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
from classiq.open_library.functions.qft_functions import qft, qft_no_swap
|
|
2
|
-
from classiq.qmod.builtins.classical_functions import qft_const_adder_phase
|
|
3
|
-
from classiq.qmod.builtins.functions.allocation import free
|
|
4
|
-
from classiq.qmod.builtins.functions.standard_gates import PHASE, SWAP, X
|
|
5
|
-
from classiq.qmod.builtins.operations import (
|
|
6
|
-
allocate,
|
|
7
|
-
bind,
|
|
8
|
-
control,
|
|
9
|
-
invert,
|
|
10
|
-
repeat,
|
|
11
|
-
skip_control,
|
|
12
|
-
within_apply,
|
|
13
|
-
)
|
|
14
|
-
from classiq.qmod.cparam import CInt
|
|
15
|
-
from classiq.qmod.qfunc import qfunc, qperm
|
|
16
|
-
from classiq.qmod.qmod_variable import Const, QArray, QBit
|
|
17
|
-
from classiq.qmod.symbolic import min, mod_inverse
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@qfunc
|
|
21
|
-
def _check_msb(ref: CInt, x: QArray[QBit], aux: QBit) -> None:
|
|
22
|
-
within_apply(
|
|
23
|
-
lambda: invert(lambda: qft_no_swap(x)),
|
|
24
|
-
lambda: control(x[0] == ref, lambda: X(aux)),
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@qfunc
|
|
29
|
-
def qft_space_add_const(value: CInt, phi_b: QArray[QBit]) -> None:
|
|
30
|
-
"""
|
|
31
|
-
[Qmod Classiq-library function]
|
|
32
|
-
|
|
33
|
-
Adds a constant to a quantum number (in the Fourier space) using the Quantum Fourier Transform (QFT) Adder algorithm.
|
|
34
|
-
Assuming that the input `phi_b` has `n` qubits, the result will be $\\phi_b+=value \\mod 2^n$.
|
|
35
|
-
|
|
36
|
-
To perform the full algorithm, use:
|
|
37
|
-
within_apply(lambda: QFT(phi_b), qft_space_add_const(value, phi_b))
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
value: The constant to add to the quantum number.
|
|
41
|
-
phi_b: The quantum number (at the aft space) to which the constant is added.
|
|
42
|
-
|
|
43
|
-
"""
|
|
44
|
-
repeat(
|
|
45
|
-
count=phi_b.len,
|
|
46
|
-
iteration=lambda index: PHASE(
|
|
47
|
-
theta=qft_const_adder_phase(
|
|
48
|
-
index, value, phi_b.len # type:ignore[arg-type]
|
|
49
|
-
),
|
|
50
|
-
target=phi_b[index],
|
|
51
|
-
),
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@qperm(disable_perm_check=True)
|
|
56
|
-
def cc_modular_add(
|
|
57
|
-
n: CInt, a: CInt, phi_b: QArray[QBit], c1: Const[QBit], c2: Const[QBit]
|
|
58
|
-
) -> None:
|
|
59
|
-
"""
|
|
60
|
-
[Qmod Classiq-library function]
|
|
61
|
-
|
|
62
|
-
Adds a constant `a` to a quantum number `phi_b` modulo the constant `n`, controlled by 2 qubits.
|
|
63
|
-
The quantum number `phi_b` and the constant `a` are assumed to be in the QFT space.
|
|
64
|
-
|
|
65
|
-
Args:
|
|
66
|
-
n: The modulo number.
|
|
67
|
-
a: The constant to add to the quantum number.
|
|
68
|
-
phi_b: The quantum number to which the constant is added.
|
|
69
|
-
c1: a control qubit.
|
|
70
|
-
c2: a control qubit.
|
|
71
|
-
|
|
72
|
-
"""
|
|
73
|
-
ctrl: QArray[QBit] = QArray()
|
|
74
|
-
aux = QBit()
|
|
75
|
-
|
|
76
|
-
allocate(aux)
|
|
77
|
-
within_apply(
|
|
78
|
-
lambda: bind([c1, c2], ctrl),
|
|
79
|
-
lambda: (
|
|
80
|
-
control(ctrl, lambda: qft_space_add_const(a, phi_b)),
|
|
81
|
-
invert(lambda: qft_space_add_const(n, phi_b)),
|
|
82
|
-
_check_msb(1, phi_b, aux),
|
|
83
|
-
control(aux, lambda: qft_space_add_const(n, phi_b)),
|
|
84
|
-
within_apply(
|
|
85
|
-
lambda: invert(
|
|
86
|
-
lambda: control(ctrl, lambda: qft_space_add_const(a, phi_b))
|
|
87
|
-
),
|
|
88
|
-
lambda: _check_msb(0, phi_b, aux),
|
|
89
|
-
),
|
|
90
|
-
),
|
|
91
|
-
)
|
|
92
|
-
free(aux)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@qperm(disable_perm_check=True)
|
|
96
|
-
def c_modular_multiply(
|
|
97
|
-
n: CInt,
|
|
98
|
-
a: CInt,
|
|
99
|
-
b: QArray[QBit],
|
|
100
|
-
x: Const[QArray[QBit]],
|
|
101
|
-
ctrl: Const[QBit],
|
|
102
|
-
) -> None:
|
|
103
|
-
"""
|
|
104
|
-
[Qmod Classiq-library function]
|
|
105
|
-
|
|
106
|
-
Performs out-of-place multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`,
|
|
107
|
-
controlled by a quantum bit `ctrl` and adds the result to a quantum array `b`. Applies $b += xa \\mod n$ if `ctrl=1`, and the identity otherwise.
|
|
108
|
-
|
|
109
|
-
Args:
|
|
110
|
-
n: The modulo number. Should be non-negative.
|
|
111
|
-
a: The classical factor. Should be non-negative.
|
|
112
|
-
b: The quantum number added to the multiplication result. Stores the result of the multiplication.
|
|
113
|
-
x: The quantum factor.
|
|
114
|
-
ctrl: The control bit.
|
|
115
|
-
"""
|
|
116
|
-
within_apply(
|
|
117
|
-
lambda: qft(b),
|
|
118
|
-
lambda: repeat(
|
|
119
|
-
count=x.len,
|
|
120
|
-
iteration=lambda index: cc_modular_add(
|
|
121
|
-
n, (a * (2**index)) % n, b, x[index], ctrl
|
|
122
|
-
),
|
|
123
|
-
),
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
@qperm
|
|
128
|
-
def multiswap(x: QArray[QBit], y: QArray[QBit]) -> None:
|
|
129
|
-
"""
|
|
130
|
-
[Qmod Classiq-library function]
|
|
131
|
-
|
|
132
|
-
Swaps the qubit states between two arrays.
|
|
133
|
-
Qubits of respective indices are swapped, and additional qubits in the longer array are left unchanged.
|
|
134
|
-
|
|
135
|
-
Args:
|
|
136
|
-
x: The first array
|
|
137
|
-
y: The second array
|
|
138
|
-
|
|
139
|
-
"""
|
|
140
|
-
repeat(
|
|
141
|
-
count=min(x.len, y.len),
|
|
142
|
-
iteration=lambda index: SWAP(x[index], y[index]),
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@qfunc
|
|
147
|
-
def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) -> None:
|
|
148
|
-
"""
|
|
149
|
-
[Qmod Classiq-library function]
|
|
150
|
-
|
|
151
|
-
Performs multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`,
|
|
152
|
-
controlled by a quantum bit `ctrl`. Applies $x=xa \\mod n$ if `ctrl=1`, and the identity otherwise.
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
n: The modulo number. Should be non-negative.
|
|
156
|
-
a: The classical factor. Should be non-negative.
|
|
157
|
-
x: The quantum factor.
|
|
158
|
-
ctrl: The control bit.
|
|
159
|
-
"""
|
|
160
|
-
b: QArray[QBit] = QArray(length=x.len + 1)
|
|
161
|
-
allocate(b)
|
|
162
|
-
c_modular_multiply(n, a, b, x, ctrl)
|
|
163
|
-
control(ctrl, lambda: multiswap(x, b))
|
|
164
|
-
invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl))
|
|
165
|
-
free(b)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
@qperm(disable_perm_check=True)
|
|
169
|
-
def modular_add_qft_space(n: CInt, a: CInt, phi_b: QArray[QBit]) -> None:
|
|
170
|
-
"""
|
|
171
|
-
[Qmod Classiq-library function]
|
|
172
|
-
|
|
173
|
-
Adds a constant `a` to a quantum number `phi_b` modulo the constant `n`.
|
|
174
|
-
The quantum number `phi_b` is assumed to be in the QFT space.
|
|
175
|
-
|
|
176
|
-
Args:
|
|
177
|
-
n: The modulo number.
|
|
178
|
-
a: The constant to add to the quantum number.
|
|
179
|
-
phi_b: The quantum number to which the constant is added.
|
|
180
|
-
|
|
181
|
-
"""
|
|
182
|
-
aux = QBit()
|
|
183
|
-
|
|
184
|
-
allocate(aux)
|
|
185
|
-
qft_space_add_const(a, phi_b),
|
|
186
|
-
skip_control(
|
|
187
|
-
lambda: (
|
|
188
|
-
invert(lambda: qft_space_add_const(n, phi_b)),
|
|
189
|
-
_check_msb(1, phi_b, aux),
|
|
190
|
-
control(aux, lambda: qft_space_add_const(n, phi_b)),
|
|
191
|
-
)
|
|
192
|
-
)
|
|
193
|
-
invert(lambda: qft_space_add_const(a, phi_b))
|
|
194
|
-
skip_control(lambda: _check_msb(0, phi_b, aux))
|
|
195
|
-
qft_space_add_const(a, phi_b)
|
|
196
|
-
free(aux)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
@qperm(disable_perm_check=True)
|
|
200
|
-
def modular_multiply(
|
|
201
|
-
n: CInt,
|
|
202
|
-
a: CInt,
|
|
203
|
-
b: QArray[QBit],
|
|
204
|
-
x: Const[QArray[QBit]],
|
|
205
|
-
) -> None:
|
|
206
|
-
"""
|
|
207
|
-
[Qmod Classiq-library function]
|
|
208
|
-
|
|
209
|
-
Performs out-of-place multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`,
|
|
210
|
-
and adds the result to a quantum array `b` (Applies $b += xa \\mod n$).
|
|
211
|
-
|
|
212
|
-
Args:
|
|
213
|
-
n: The modulo number. Should be non-negative.
|
|
214
|
-
a: The classical factor. Should be non-negative.
|
|
215
|
-
b: The quantum number added to the multiplication result. Stores the result of the multiplication.
|
|
216
|
-
x: The quantum factor.
|
|
217
|
-
"""
|
|
218
|
-
within_apply(
|
|
219
|
-
lambda: qft(b),
|
|
220
|
-
lambda: repeat(
|
|
221
|
-
count=x.len,
|
|
222
|
-
iteration=lambda index: control(
|
|
223
|
-
x[index], lambda: modular_add_qft_space(n, (a * (2**index)) % n, b)
|
|
224
|
-
),
|
|
225
|
-
),
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
@qfunc
|
|
230
|
-
def inplace_modular_multiply(n: CInt, a: CInt, x: QArray[QBit]) -> None:
|
|
231
|
-
"""
|
|
232
|
-
[Qmod Classiq-library function]
|
|
233
|
-
|
|
234
|
-
Performs multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`
|
|
235
|
-
(Applies $x=xa \\mod n$).
|
|
236
|
-
|
|
237
|
-
Args:
|
|
238
|
-
n: The modulo number. Should be non-negative.
|
|
239
|
-
a: The classical factor. Should be non-negative.
|
|
240
|
-
x: The quantum factor.
|
|
241
|
-
|
|
242
|
-
Comment: It is assumed that `a` has an inverse modulo `n`
|
|
243
|
-
"""
|
|
244
|
-
b: QArray[QBit] = QArray(length=x.len + 1)
|
|
245
|
-
allocate(b)
|
|
246
|
-
modular_multiply(n, a, b, x)
|
|
247
|
-
multiswap(x, b)
|
|
248
|
-
invert(lambda: modular_multiply(n, mod_inverse(a, n), b, x))
|
|
249
|
-
free(b)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
@qfunc
|
|
253
|
-
def modular_exp(n: CInt, a: CInt, x: QArray[QBit], power: QArray[QBit]) -> None:
|
|
254
|
-
"""
|
|
255
|
-
[Qmod Classiq-library function]
|
|
256
|
-
|
|
257
|
-
Raises a classical integer `a` to the power of a quantum number `power` modulo classical integer `n`
|
|
258
|
-
times a quantum number `x`. Performs $x=(a^{power} \\mod n)*x$ in-place.
|
|
259
|
-
(and specifically if at the input $x=1$, at the output $x=a^{power} \\mod n$).
|
|
260
|
-
|
|
261
|
-
Args:
|
|
262
|
-
n: The modulus number. Should be non-negative.
|
|
263
|
-
a: The base of the exponentiation. Should be non-negative.
|
|
264
|
-
x: A quantum number that multiplies the modular exponentiation and holds the output. It should be at least the size of $\\lceil \\log(n) \rceil$.
|
|
265
|
-
power: The power of the exponentiation.
|
|
266
|
-
"""
|
|
267
|
-
repeat(
|
|
268
|
-
count=power.len,
|
|
269
|
-
iteration=lambda index: inplace_c_modular_multiply(
|
|
270
|
-
n, (a ** (2**index)) % n, x, power[index]
|
|
271
|
-
),
|
|
272
|
-
)
|