-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create KaliskiModInverse #1464
Create KaliskiModInverse #1464
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally lgtm, but curious to hear your response to my comment
a = b = 0 | ||
assert m == 0 | ||
m ^= f & (v == 0) | ||
f ^= m | ||
|
||
a ^= f & (u % 2 == 0) | ||
m ^= f & (a == 0) & (v % 2 == 0) | ||
b ^= a | ||
b ^= m | ||
|
||
t = (u > v) & (b == 0) & f | ||
a ^= t | ||
m ^= t | ||
|
||
if a: | ||
u, v = v, u | ||
r, s = s, r | ||
|
||
if f and b == 0: | ||
v -= u | ||
s += r | ||
|
||
b ^= m | ||
b ^= a | ||
if f: | ||
assert v % 2 == 0, f'{u=} {v=} {r=} {s=} {a=} {b=} {m=} {f=}' | ||
v >>= 1 | ||
r = (r << 1) % self.mod | ||
if a: | ||
u, v = v, u | ||
s, r = r, s | ||
a ^= s == 0 | ||
return {'u': u, 'v': v, 'r': r, 's': s, 'a': a, 'b': b, 'm': m, 'f': f} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a broader comment, but attaching it to these lines since this is the place where it's most acute.
Is this just a transcription of the individual bloq operations? ideally the classical implementation would be inspectably-correct so that we can write effective unit tests against it. If possible, we would like to avoid a unit test where one inscrutable routine produces the same output as another inscrutable routine (although this is better than nothing!). Some concrete suggestions and requests:
- Can we have a unit test that proves that the bloqs in this PR are computing a modular inverse? You can take a bunch of numbers, run them through the bloq simulator, and assert that
x * (x^-1) = 1
or usepow(x, -1, p)
to validate the output. - Maybe some inline comments in this
on_classical_vals
. Presumably there's some method to this madness :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I wrote it like this is that I didn't want to write individual tests for the _KaliskiIterationStepX
bloqs. Instead I prefered a blackbox style test where I test the thing that we will actually use KaliskiModInverse
which produces two register, the first has the modular inverse and the second has the ancillas. The problem here is that the value in the ancilla register is not trivial.
Reimplementing this by calling the individual _KaliskiIterationStepX.on_each is not a good idea since that will make the test useless. The test now compares the output of _KaliskiIteration.on_classical_data
with the output of the individual steps. but if _KaliskiIteration.on_classical_data
calls those steps then the test becomes useless.
Can we have a unit test that proves that the bloqs in this PR are computing a modular inverse?
That's what test_kaliski_mod_inverse_classical_action
does. The modular inverse in motegomry form is such that
Maybe some inline comments in this on_classical_vals. Presumably there's some method to this madness
I added a docstring explaining what happens here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe some inline comments in this on_classical_vals. Presumably there's some method to this madness
nvm I updated the method to follow the pseudocode of the original algorithm from Fig7b in https://arxiv.org/abs/2001.09580 which is alot more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes! I agree with all the motivation and blackbox style testing. Good to know you already had a "systems test" and even better to see it written out in a readable way now.
Implemented Kaliski modular inversion from appendix C5 https://arxiv.org/abs/2302.06639. The Toffoli complexity is$26n^2 + 7n - 1$ is higher than the formula in Litenski of $26n^2 + 2n$ because litenski drops constant factors in his estimates ... but these constant factors get multiplied by 2n (the number of iterations).
That's the cost of a single iteration is$13n + 3$ but litenski calculates it as $13n$