diff --git a/qualtran/_infra/data_types.py b/qualtran/_infra/data_types.py index bc3e80e28d..4c270e04d0 100644 --- a/qualtran/_infra/data_types.py +++ b/qualtran/_infra/data_types.py @@ -792,8 +792,8 @@ class QMontgomeryUInt(QDType): We follow Montgomery form as described in the above paper; namely, r = 2^bitsize. """ - # TODO(https://github.com/quantumlib/Qualtran/issues/1471): Add modulus p as a class member. bitsize: SymbolicInt + modulus: Optional[SymbolicInt] = None @property def num_qubits(self): @@ -803,7 +803,9 @@ def is_symbolic(self) -> bool: return is_symbolic(self.bitsize) def get_classical_domain(self) -> Iterable[Any]: - return range(2**self.bitsize) + if self.modulus is None or is_symbolic(self.modulus): + return range(2**self.bitsize) + return range(1, int(self.modulus)) def to_bits(self, x: int) -> List[int]: self.assert_valid_classical_val(x) @@ -828,42 +830,44 @@ def assert_valid_classical_val_array( if np.any(val_array >= 2**self.bitsize): raise ValueError(f"Too-large classical values encountered in {debug_str}") - def montgomery_inverse(self, xm: int, p: int) -> int: + def montgomery_inverse(self, xm: int) -> int: """Returns the modular inverse of an integer in montgomery form. Args: xm: An integer in montgomery form. - p: The modulus of the finite field. """ - return ((pow(xm, -1, p)) * pow(2, 2 * self.bitsize, p)) % p + assert self.modulus is not None and not is_symbolic(self.modulus) + return ( + (pow(xm, -1, self.modulus)) * pow(2, 2 * self.bitsize, int(self.modulus)) + ) % self.modulus - def montgomery_product(self, xm: int, ym: int, p: int) -> int: + def montgomery_product(self, xm: int, ym: int) -> int: """Returns the modular product of two integers in montgomery form. Args: xm: The first montgomery form integer for the product. ym: The second montgomery form integer for the product. - p: The modulus of the finite field. """ - return (xm * ym * pow(2, -self.bitsize, p)) % p + assert self.modulus is not None and not is_symbolic(self.modulus) + return (xm * ym * pow(2, -self.bitsize, int(self.modulus))) % self.modulus - def montgomery_to_uint(self, xm: int, p: int) -> int: + def montgomery_to_uint(self, xm: int) -> int: """Converts an integer in montgomery form to a normal form integer. Args: xm: An integer in montgomery form. - p: The modulus of the finite field. """ - return (xm * pow(2, -self.bitsize, p)) % p + assert self.modulus is not None and not is_symbolic(self.modulus) + return (xm * pow(2, -self.bitsize, int(self.modulus))) % self.modulus - def uint_to_montgomery(self, x: int, p: int) -> int: + def uint_to_montgomery(self, x: int) -> int: """Converts an integer into montgomery form. Args: x: An integer. - p: The modulus of the finite field. """ - return (x * pow(2, int(self.bitsize), p)) % p + assert self.modulus is not None and not is_symbolic(self.modulus) + return (x * pow(2, int(self.bitsize), int(self.modulus))) % self.modulus @attrs.frozen diff --git a/qualtran/_infra/data_types_test.py b/qualtran/_infra/data_types_test.py index 0c889cdc8f..70494c5686 100644 --- a/qualtran/_infra/data_types_test.py +++ b/qualtran/_infra/data_types_test.py @@ -138,16 +138,14 @@ def test_qmontgomeryuint(): @pytest.mark.parametrize('p', [13, 17, 29]) @pytest.mark.parametrize('val', [1, 5, 7, 9]) def test_qmontgomeryuint_operations(val, p): - qmontgomeryuint_8 = QMontgomeryUInt(8) + qmontgomeryuint_8 = QMontgomeryUInt(8, p) # Convert value to montgomery form and get the modular inverse. - val_m = qmontgomeryuint_8.uint_to_montgomery(val, p) - mod_inv = qmontgomeryuint_8.montgomery_inverse(val_m, p) + val_m = qmontgomeryuint_8.uint_to_montgomery(val) + mod_inv = qmontgomeryuint_8.montgomery_inverse(val_m) # Calculate the product in montgomery form and convert back to normal form for assertion. assert ( - qmontgomeryuint_8.montgomery_to_uint( - qmontgomeryuint_8.montgomery_product(val_m, mod_inv, p), p - ) + qmontgomeryuint_8.montgomery_to_uint(qmontgomeryuint_8.montgomery_product(val_m, mod_inv)) == 1 ) @@ -155,10 +153,8 @@ def test_qmontgomeryuint_operations(val, p): @pytest.mark.parametrize('p', [13, 17, 29]) @pytest.mark.parametrize('val', [1, 5, 7, 9]) def test_qmontgomeryuint_conversions(val, p): - qmontgomeryuint_8 = QMontgomeryUInt(8) - assert val == qmontgomeryuint_8.montgomery_to_uint( - qmontgomeryuint_8.uint_to_montgomery(val, p), p - ) + qmontgomeryuint_8 = QMontgomeryUInt(8, p) + assert val == qmontgomeryuint_8.montgomery_to_uint(qmontgomeryuint_8.uint_to_montgomery(val)) def test_qgf(): diff --git a/qualtran/bloqs/cryptography/ecc/ec_add.py b/qualtran/bloqs/cryptography/ecc/ec_add.py index f764c70cbc..0c5d4109a4 100644 --- a/qualtran/bloqs/cryptography/ecc/ec_add.py +++ b/qualtran/bloqs/cryptography/ecc/ec_add.py @@ -250,10 +250,8 @@ def on_classical_vals( lam = lam_r f1 = 0 else: - lam = QMontgomeryUInt(self.n).montgomery_product( - int(y), - QMontgomeryUInt(self.n).montgomery_inverse(int(x), int(self.mod)), - int(self.mod), + lam = QMontgomeryUInt(self.n, self.mod).montgomery_product( + int(y), QMontgomeryUInt(self.n, self.mod).montgomery_inverse(int(x)) ) # TODO(https://github.com/quantumlib/Qualtran/issues/1461): Fix bug in circuit # which flips f1 when lam and lam_r are equal. @@ -540,10 +538,10 @@ def on_classical_vals( self, x: 'ClassicalValT', y: 'ClassicalValT', lam: 'ClassicalValT' ) -> Dict[str, 'ClassicalValT']: x = ( - x - QMontgomeryUInt(self.n).montgomery_product(int(lam), int(lam), int(self.mod)) + x - QMontgomeryUInt(self.n, self.mod).montgomery_product(int(lam), int(lam)) ) % self.mod if lam > 0: - y = QMontgomeryUInt(self.n).montgomery_product(int(x), int(lam), int(self.mod)) + y = QMontgomeryUInt(self.n, self.mod).montgomery_product(int(x), int(lam)) return {'x': x, 'y': y, 'lam': lam} def build_composite_bloq( @@ -1071,30 +1069,23 @@ def build_composite_bloq( return {'a': a, 'b': b, 'x': x, 'y': y, 'lam_r': lam_r} def on_classical_vals(self, a, b, x, y, lam_r) -> Dict[str, Union['ClassicalValT', sympy.Expr]]: + dtype = QMontgomeryUInt(self.n, self.mod) curve_a = ( - QMontgomeryUInt(self.n).montgomery_to_uint(lam_r, int(self.mod)) - * 2 - * QMontgomeryUInt(self.n).montgomery_to_uint(b, int(self.mod)) - - (3 * QMontgomeryUInt(self.n).montgomery_to_uint(a, int(self.mod)) ** 2) + dtype.montgomery_to_uint(lam_r) * 2 * dtype.montgomery_to_uint(b) + - (3 * dtype.montgomery_to_uint(a) ** 2) ) % self.mod p1 = ECPoint( - QMontgomeryUInt(self.n).montgomery_to_uint(a, int(self.mod)), - QMontgomeryUInt(self.n).montgomery_to_uint(b, int(self.mod)), - mod=self.mod, - curve_a=curve_a, + dtype.montgomery_to_uint(a), dtype.montgomery_to_uint(b), mod=self.mod, curve_a=curve_a ) p2 = ECPoint( - QMontgomeryUInt(self.n).montgomery_to_uint(x, int(self.mod)), - QMontgomeryUInt(self.n).montgomery_to_uint(y, int(self.mod)), - mod=self.mod, - curve_a=curve_a, + dtype.montgomery_to_uint(x), dtype.montgomery_to_uint(y), mod=self.mod, curve_a=curve_a ) result = p1 + p2 return { 'a': a, 'b': b, - 'x': QMontgomeryUInt(self.n).uint_to_montgomery(result.x, int(self.mod)), - 'y': QMontgomeryUInt(self.n).uint_to_montgomery(result.y, int(self.mod)), + 'x': dtype.uint_to_montgomery(result.x), + 'y': dtype.uint_to_montgomery(result.y), 'lam_r': lam_r, } diff --git a/qualtran/bloqs/cryptography/ecc/ec_add_r.py b/qualtran/bloqs/cryptography/ecc/ec_add_r.py index 6bf0206594..8fb88fa251 100644 --- a/qualtran/bloqs/cryptography/ecc/ec_add_r.py +++ b/qualtran/bloqs/cryptography/ecc/ec_add_r.py @@ -179,17 +179,17 @@ def qrom(self) -> QROAMClean: cR = self.R data_a, data_b, data_lam = [0], [0], [0] - mon_int = QMontgomeryUInt(self.n) + mon_int = QMontgomeryUInt(self.n, self.R.mod) for _ in range(1, 2**self.add_window_size): - data_a.append(mon_int.uint_to_montgomery(int(cR.x), int(self.R.mod))) - data_b.append(mon_int.uint_to_montgomery(int(cR.y), int(self.R.mod))) + data_a.append(mon_int.uint_to_montgomery(int(cR.x))) + data_b.append(mon_int.uint_to_montgomery(int(cR.y))) lam_num = (3 * cR.x**2 + cR.curve_a) % cR.mod lam_denom = (2 * cR.y) % cR.mod if lam_denom != 0: lam = (lam_num * pow(lam_denom, -1, mod=cR.mod)) % cR.mod else: lam = 0 - data_lam.append(mon_int.uint_to_montgomery(int(lam), int(self.R.mod))) + data_lam.append(mon_int.uint_to_montgomery(int(lam))) cR = cR + self.R return QROAMClean( @@ -244,9 +244,10 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT': def on_classical_vals(self, ctrl, x, y) -> Dict[str, Union['ClassicalValT', sympy.Expr]]: # TODO(https://github.com/quantumlib/Qualtran/issues/1476): make ECAdd accept SymbolicInt. + dtype = QMontgomeryUInt(self.n, self.R.mod) A = ECPoint( - QMontgomeryUInt(self.n).montgomery_to_uint(int(x), int(self.R.mod)), - QMontgomeryUInt(self.n).montgomery_to_uint(int(y), int(self.R.mod)), + dtype.montgomery_to_uint(int(x)), + dtype.montgomery_to_uint(int(y)), mod=self.R.mod, curve_a=self.R.curve_a, ) @@ -254,8 +255,8 @@ def on_classical_vals(self, ctrl, x, y) -> Dict[str, Union['ClassicalValT', symp result: ECPoint = A + (ctrls * self.R) return { 'ctrl': ctrl, - 'x': QMontgomeryUInt(self.n).uint_to_montgomery(int(result.x), int(self.R.mod)), - 'y': QMontgomeryUInt(self.n).uint_to_montgomery(int(result.y), int(self.R.mod)), + 'x': dtype.uint_to_montgomery(int(result.x)), + 'y': dtype.uint_to_montgomery(int(result.y)), } def wire_symbol( diff --git a/qualtran/bloqs/cryptography/ecc/ec_add_r_test.py b/qualtran/bloqs/cryptography/ecc/ec_add_r_test.py index daeffac54a..b47105fd91 100644 --- a/qualtran/bloqs/cryptography/ecc/ec_add_r_test.py +++ b/qualtran/bloqs/cryptography/ecc/ec_add_r_test.py @@ -60,8 +60,8 @@ def test_ec_window_add_r_bloq_counts(n, window_size, a, b): def test_ec_window_add_r_classical(n, m, ctrl, x, y, a, b): p = 17 R = ECPoint(a, b, mod=p) - x = QMontgomeryUInt(n).uint_to_montgomery(x, p) - y = QMontgomeryUInt(n).uint_to_montgomery(y, p) + x = QMontgomeryUInt(n, p).uint_to_montgomery(x) + y = QMontgomeryUInt(n, p).uint_to_montgomery(y) ctrl = np.array(QUInt(m).to_bits(ctrl % (2**m))) bloq = ECWindowAddR(n=n, R=R, add_window_size=m, mul_window_size=m) ret1 = bloq.call_classically(ctrl=ctrl, x=x, y=y) @@ -80,8 +80,8 @@ def test_ec_window_add_r_classical(n, m, ctrl, x, y, a, b): def test_ec_window_add_r_classical_slow(n, m, ctrl, x, y, a, b): p = 17 R = ECPoint(a, b, mod=p) - x = QMontgomeryUInt(n).uint_to_montgomery(x, p) - y = QMontgomeryUInt(n).uint_to_montgomery(y, p) + x = QMontgomeryUInt(n, p).uint_to_montgomery(x) + y = QMontgomeryUInt(n, p).uint_to_montgomery(y) ctrl = np.array(QUInt(m).to_bits(ctrl % (2**m))) bloq = ECWindowAddR(n=n, R=R, add_window_size=m, mul_window_size=m) ret1 = bloq.call_classically(ctrl=ctrl, x=x, y=y) diff --git a/qualtran/bloqs/cryptography/ecc/ec_add_test.py b/qualtran/bloqs/cryptography/ecc/ec_add_test.py index e095d8bc36..23839bc105 100644 --- a/qualtran/bloqs/cryptography/ecc/ec_add_test.py +++ b/qualtran/bloqs/cryptography/ecc/ec_add_test.py @@ -44,11 +44,12 @@ def test_ec_add_steps_classical_fast(n, m, a, b, x, y): lam_denom = (2 * b) % p lam_r = 0 if b == 0 else (lam_num * pow(lam_denom, -1, mod=p)) % p - a = QMontgomeryUInt(n).uint_to_montgomery(a, p) - b = QMontgomeryUInt(n).uint_to_montgomery(b, p) - x = QMontgomeryUInt(n).uint_to_montgomery(x, p) - y = QMontgomeryUInt(n).uint_to_montgomery(y, p) - lam_r = QMontgomeryUInt(n).uint_to_montgomery(lam_r, p) if lam_r != 0 else p + dtype = QMontgomeryUInt(n, p) + a = dtype.uint_to_montgomery(a) + b = dtype.uint_to_montgomery(b) + x = dtype.uint_to_montgomery(x) + y = dtype.uint_to_montgomery(y) + lam_r = dtype.uint_to_montgomery(lam_r) if lam_r != 0 else p bloq = _ECAddStepOne(n=n, mod=p) ret1 = bloq.call_classically(a=a, b=b, x=x, y=y) @@ -184,11 +185,12 @@ def test_ec_add_steps_classical(n, m, a, b, x, y): lam_denom = (2 * b) % p lam_r = 0 if b == 0 else (lam_num * pow(lam_denom, -1, mod=p)) % p - a = QMontgomeryUInt(n).uint_to_montgomery(a, p) - b = QMontgomeryUInt(n).uint_to_montgomery(b, p) - x = QMontgomeryUInt(n).uint_to_montgomery(x, p) - y = QMontgomeryUInt(n).uint_to_montgomery(y, p) - lam_r = QMontgomeryUInt(n).uint_to_montgomery(lam_r, p) if lam_r != 0 else p + dtype = QMontgomeryUInt(n, p) + a = dtype.uint_to_montgomery(a) + b = dtype.uint_to_montgomery(b) + x = dtype.uint_to_montgomery(x) + y = dtype.uint_to_montgomery(y) + lam_r = dtype.uint_to_montgomery(lam_r) if lam_r != 0 else p bloq = _ECAddStepOne(n=n, mod=p) ret1 = bloq.call_classically(a=a, b=b, x=x, y=y) @@ -307,19 +309,20 @@ def test_ec_add_classical_fast(n, m, a, b, x, y): lam_num = (3 * a**2) % p lam_denom = (2 * b) % p lam_r = p if b == 0 else (lam_num * pow(lam_denom, -1, mod=p)) % p + dtype = QMontgomeryUInt(n, p) ret1 = bloq.call_classically( - a=QMontgomeryUInt(n).uint_to_montgomery(a, p), - b=QMontgomeryUInt(n).uint_to_montgomery(b, p), - x=QMontgomeryUInt(n).uint_to_montgomery(x, p), - y=QMontgomeryUInt(n).uint_to_montgomery(y, p), - lam_r=QMontgomeryUInt(n).uint_to_montgomery(lam_r, p), + a=dtype.uint_to_montgomery(a), + b=dtype.uint_to_montgomery(b), + x=dtype.uint_to_montgomery(x), + y=dtype.uint_to_montgomery(y), + lam_r=dtype.uint_to_montgomery(lam_r), ) ret2 = bloq.decompose_bloq().call_classically( - a=QMontgomeryUInt(n).uint_to_montgomery(a, p), - b=QMontgomeryUInt(n).uint_to_montgomery(b, p), - x=QMontgomeryUInt(n).uint_to_montgomery(x, p), - y=QMontgomeryUInt(n).uint_to_montgomery(y, p), - lam_r=QMontgomeryUInt(n).uint_to_montgomery(lam_r, p), + a=dtype.uint_to_montgomery(a), + b=dtype.uint_to_montgomery(b), + x=dtype.uint_to_montgomery(x), + y=dtype.uint_to_montgomery(y), + lam_r=dtype.uint_to_montgomery(lam_r), ) assert ret1 == ret2 @@ -352,19 +355,20 @@ def test_ec_add_classical(n, m, a, b, x, y): lam_num = (3 * a**2) % p lam_denom = (2 * b) % p lam_r = p if b == 0 else (lam_num * pow(lam_denom, -1, mod=p)) % p + dtype = QMontgomeryUInt(n, p) ret1 = bloq.call_classically( - a=QMontgomeryUInt(n).uint_to_montgomery(a, p), - b=QMontgomeryUInt(n).uint_to_montgomery(b, p), - x=QMontgomeryUInt(n).uint_to_montgomery(x, p), - y=QMontgomeryUInt(n).uint_to_montgomery(y, p), - lam_r=QMontgomeryUInt(n).uint_to_montgomery(lam_r, p), + a=dtype.uint_to_montgomery(a), + b=dtype.uint_to_montgomery(b), + x=dtype.uint_to_montgomery(x), + y=dtype.uint_to_montgomery(y), + lam_r=dtype.uint_to_montgomery(lam_r), ) ret2 = bloq.decompose_bloq().call_classically( - a=QMontgomeryUInt(n).uint_to_montgomery(a, p), - b=QMontgomeryUInt(n).uint_to_montgomery(b, p), - x=QMontgomeryUInt(n).uint_to_montgomery(x, p), - y=QMontgomeryUInt(n).uint_to_montgomery(y, p), - lam_r=QMontgomeryUInt(n).uint_to_montgomery(lam_r, p), + a=dtype.uint_to_montgomery(a), + b=dtype.uint_to_montgomery(b), + x=dtype.uint_to_montgomery(x), + y=dtype.uint_to_montgomery(y), + lam_r=dtype.uint_to_montgomery(lam_r), ) assert ret1 == ret2 diff --git a/qualtran/bloqs/mod_arithmetic/mod_addition.py b/qualtran/bloqs/mod_arithmetic/mod_addition.py index b165a39466..0a167e84fe 100644 --- a/qualtran/bloqs/mod_arithmetic/mod_addition.py +++ b/qualtran/bloqs/mod_arithmetic/mod_addition.py @@ -79,8 +79,8 @@ class ModAdd(Bloq): def signature(self) -> 'Signature': return Signature( [ - Register('x', QMontgomeryUInt(self.bitsize)), - Register('y', QMontgomeryUInt(self.bitsize)), + Register('x', QMontgomeryUInt(self.bitsize, self.mod)), + Register('y', QMontgomeryUInt(self.bitsize, self.mod)), ] ) diff --git a/qualtran/bloqs/mod_arithmetic/mod_division.py b/qualtran/bloqs/mod_arithmetic/mod_division.py index ba734d4b4d..947f40eb5d 100644 --- a/qualtran/bloqs/mod_arithmetic/mod_division.py +++ b/qualtran/bloqs/mod_arithmetic/mod_division.py @@ -323,10 +323,10 @@ class _KaliskiIterationStep6(Bloq): def signature(self) -> 'Signature': return Signature( [ - Register('u', QMontgomeryUInt(self.bitsize)), - Register('v', QMontgomeryUInt(self.bitsize)), - Register('r', QMontgomeryUInt(self.bitsize)), - Register('s', QMontgomeryUInt(self.bitsize)), + Register('u', QMontgomeryUInt(self.bitsize, self.mod)), + Register('v', QMontgomeryUInt(self.bitsize, self.mod)), + Register('r', QMontgomeryUInt(self.bitsize, self.mod)), + Register('s', QMontgomeryUInt(self.bitsize, self.mod)), Register('b', QBit()), Register('a', QBit()), Register('m', QBit()), @@ -406,10 +406,10 @@ class _KaliskiIteration(Bloq): def signature(self) -> 'Signature': return Signature( [ - Register('u', QMontgomeryUInt(self.bitsize)), - Register('v', QMontgomeryUInt(self.bitsize)), - Register('r', QMontgomeryUInt(self.bitsize)), - Register('s', QMontgomeryUInt(self.bitsize)), + Register('u', QMontgomeryUInt(self.bitsize, self.mod)), + Register('v', QMontgomeryUInt(self.bitsize, self.mod)), + Register('r', QMontgomeryUInt(self.bitsize, self.mod)), + Register('s', QMontgomeryUInt(self.bitsize, self.mod)), Register('m', QBit()), Register('f', QBit()), Register('is_terminal', QBit()), @@ -515,10 +515,10 @@ class _KaliskiModInverseImpl(Bloq): def signature(self) -> 'Signature': return Signature( [ - Register('u', QMontgomeryUInt(self.bitsize)), - Register('v', QMontgomeryUInt(self.bitsize)), - Register('r', QMontgomeryUInt(self.bitsize)), - Register('s', QMontgomeryUInt(self.bitsize)), + Register('u', QMontgomeryUInt(self.bitsize, self.mod)), + Register('v', QMontgomeryUInt(self.bitsize, self.mod)), + Register('r', QMontgomeryUInt(self.bitsize, self.mod)), + Register('s', QMontgomeryUInt(self.bitsize, self.mod)), Register('m', QAny(2 * self.bitsize)), Register('f', QBit()), Register('terminal_condition', QAny(2 * self.bitsize)), @@ -657,7 +657,7 @@ def signature(self) -> 'Signature': side = Side.LEFT if self.uncompute else Side.RIGHT return Signature( [ - Register('x', QMontgomeryUInt(self.bitsize)), + Register('x', QMontgomeryUInt(self.bitsize, self.mod)), Register('junk', QAny(4 * self.bitsize), side=side), ] ) diff --git a/qualtran/bloqs/mod_arithmetic/mod_division_test.py b/qualtran/bloqs/mod_arithmetic/mod_division_test.py index 44165ece2e..2b8a7fbca1 100644 --- a/qualtran/bloqs/mod_arithmetic/mod_division_test.py +++ b/qualtran/bloqs/mod_arithmetic/mod_division_test.py @@ -30,18 +30,18 @@ def test_kaliski_mod_inverse_classical_action(bitsize, mod): blq = KaliskiModInverse(bitsize, mod) cblq = blq.decompose_bloq() - dtype = QMontgomeryUInt(bitsize) + dtype = QMontgomeryUInt(bitsize, mod) R = pow(2, bitsize, mod) for x in range(1, mod): if math.gcd(x, mod) != 1: continue - x_montgomery = dtype.uint_to_montgomery(x, mod) + x_montgomery = dtype.uint_to_montgomery(x) res = blq.call_classically(x=x_montgomery) assert res == cblq.call_classically(x=x_montgomery) assert len(res) == 2 - assert res[0] == dtype.montgomery_inverse(x_montgomery, mod) - assert dtype.montgomery_product(int(res[0]), x_montgomery, mod) == R + assert res[0] == dtype.montgomery_inverse(x_montgomery) + assert dtype.montgomery_product(int(res[0]), x_montgomery) == R assert blq.adjoint().call_classically(x=res[0], junk=res[1]) == (x_montgomery,) diff --git a/qualtran/bloqs/mod_arithmetic/mod_multiplication.py b/qualtran/bloqs/mod_arithmetic/mod_multiplication.py index 0e8f3ca0bc..810803b8cb 100644 --- a/qualtran/bloqs/mod_arithmetic/mod_multiplication.py +++ b/qualtran/bloqs/mod_arithmetic/mod_multiplication.py @@ -319,9 +319,9 @@ def signature(self) -> 'Signature': return Signature( [ Register('x', QBit(), shape=(self.window_size,)), - Register('y', QMontgomeryUInt(self.bitsize)), + Register('y', QMontgomeryUInt(self.bitsize, self.mod)), Register('target', QBit(), shape=(self.window_size + self.bitsize,)), - Register('qrom_index', QMontgomeryUInt(self.window_size)), + Register('qrom_index', QMontgomeryUInt(self.window_size, self.mod)), ] ) @@ -474,10 +474,10 @@ def signature(self) -> 'Signature': ) // self.window_size # = ceil(self.bitsize/self.window_size) return Signature( [ - Register('x', QMontgomeryUInt(self.bitsize)), - Register('y', QMontgomeryUInt(self.bitsize)), - Register('target', QMontgomeryUInt(self.bitsize)), - Register('qrom_indices', QMontgomeryUInt(num_windows * self.window_size)), + Register('x', QMontgomeryUInt(self.bitsize, self.mod)), + Register('y', QMontgomeryUInt(self.bitsize, self.mod)), + Register('target', QMontgomeryUInt(self.bitsize, self.mod)), + Register('qrom_indices', QMontgomeryUInt(num_windows * self.window_size, self.mod)), Register('reduced', QBit()), ] ) @@ -599,11 +599,13 @@ def signature(self) -> 'Signature': side = Side.LEFT if self.uncompute else Side.RIGHT return Signature( [ - Register('x', QMontgomeryUInt(self.bitsize)), - Register('y', QMontgomeryUInt(self.bitsize)), - Register('target', QMontgomeryUInt(self.bitsize), side=side), + Register('x', QMontgomeryUInt(self.bitsize, self.mod)), + Register('y', QMontgomeryUInt(self.bitsize, self.mod)), + Register('target', QMontgomeryUInt(self.bitsize, self.mod), side=side), Register( - 'qrom_indices', QMontgomeryUInt(num_windows * self.window_size), side=side + 'qrom_indices', + QMontgomeryUInt(num_windows * self.window_size, self.mod), + side=side, ), Register('reduced', QBit(), side=side), ]