-
Notifications
You must be signed in to change notification settings - Fork 16
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
SRAI #463
SRAI #463
Conversation
Regarding the constraints, here is a more efficient way, without division or limb decomposition. First calculate the sign-extension, that is bits flowing in from the left. let imm = cb.create_witin(…); // UInt not necessary.
let ones = imm - 1; // 2**shift - 1, or 00…111 in binary.
let inflow = msb * ones; // Extend with 0s or 1s. Calculate the bits flowing out to the right // outflow < imm
AssertLTConfig::construct_circuit(…, outflow, imm, …) Then require: rd * imm + outflow == inflow * 2**32 + rs1 Other checks:
|
This technique can also be refactored with SRLI by setting constant |
What an insightful observation bro!! |
Thanks! I have updated the implementation
I had to keep imm as UInt so that it gets range checked to be under 32 bits. |
Unnecessary, it is a fixed value. Following the code, it will go through a |
One more argument for soundness, both sides of the equation are 63 bits numbers (<2**63), fitting in Goldilocks.
|
Yes! And part of that is arguably unnecessary, too. |
|| "require_equal", | ||
|cb| { | ||
cb.cs | ||
.require_zero(name_fn, a.to_monomial_form() - b.to_monomial_form()) |
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.
What does this change have to do with SRAI?
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 not related to SRAI. This is for MockProver accurate error description. The way MockProver infers assert equal is by destructuring LHS,RHS = Sum(LHS, RHS)
. After the monomial PR, Mock Prover is not able to infer require equal correctly because to_monomial_form
is performed on Sum(LHS, RHS)
the result doesn't correctly destructure to what it should be.
This change can be in other PR.
ceno_zkvm/src/expression.rs
Outdated
@@ -757,7 +757,9 @@ pub mod fmt { | |||
) -> String { | |||
match expression { | |||
Expression::WitIn(wit_in) => { | |||
wtns.push(*wit_in); | |||
if !wtns.contains(wit_in) { |
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.
What does this change have to do with SRAI?
Seems like an unrelated improvement?
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 not related to SRAI. If Wtns(x) appears multiple times in the expression, then it is duplicated.
This change can be in other PR.
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.
I'm happy to review that extracted PR fast.
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.
Putting unrelated changes in their own PR is best; but as a second best alternative you can also expand the PR description for this PR to include the additional unrelated changes.
Changing |
Why don't you get that other PR into |
That's
Already done. |
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.
A quick review went through.
👍 Per offline discussion, make SLLI follow in/out flow
and the final config sharing with same imm as witin is nice
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.
Nice implementation of the arithmetic approach and nice refactoring of all three instructions!
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.
LGTM!
let outflow = match I::INST_KIND { | ||
InsnKind::SLLI => (rs1_read.as_u64() * imm as u64) >> UInt::<E>::TOTAL_BITS, | ||
InsnKind::SRAI | InsnKind::SRLI => { | ||
if I::INST_KIND == InsnKind::SRAI { |
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.
Why do you mix pattern matching with if
?
InsnKind::SRAI | InsnKind::SRLI => { | ||
if I::INST_KIND == InsnKind::SRAI { | ||
let max_signed_limb_expr = (1 << (UInt::<E>::LIMB_BITS - 1)) - 1; | ||
config.is_lt_config.as_ref().unwrap().assign_instance( |
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.
@hero78119 We are freely mixing .unwrap()
s into our code. We pay the mental tax for the extra complexity of the Result
wrapper but don't actually use it.
(The unwrap might even be justified here. It's honestly hard to tell.)
This PR adds SRAI to shift_imm, also changes logic for SLLI and SRLI.
Closes #365