-
Notifications
You must be signed in to change notification settings - Fork 18
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
Feat/MULH opcode #492
Feat/MULH opcode #492
Conversation
The circuit design has been updated from the initial description above; see the doc comment of the |
@bgillesp Did you / could you update the PR description to reflect the updated circuit design? Thanks! |
let rd_sign_bit = IsLtConfig::construct_circuit( | ||
circuit_builder, | ||
|| "rd_sign_bit", | ||
((1u64 << (LIMB_BITS - 1)) - 1).into(), |
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.
You can use IsLtConfig::constrain_last_limb
from #506 to make this a bit easier to read.
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.
See my comment in #506 about making it a separate gadget MSBConfig
rather than an extra constructor variant of IsLtConfig
, but whatever design we decide I can definitely use it here. Will make the change once #506 is merged with master.
Thanks for the documentation of the constraints too! It helped me to double-check numerically: # Range of variables:
u32max = 2**32 - 1
pos = 2**31 - 1
neg = -2**31
p = 2**64 - 2**32 + 1 # Goldilocks.
# Range of the constraint:
# rs1 * rs2 - (rd * 2**32 + low)
greatest = neg * neg - (neg * 2**32 + 0)
smallest = neg * pos - (pos * 2**32 + u32max)
assert -p < smallest < 0 < greatest < p
|
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.
Beautiful!
This came up when reviewing #492
Implement MULH opcode
Circuit is validated by the following strategy:
rs1
,rs2
andrd
registersrs1
andrs2
is equal to the result of interpretingrd
as the high limb of a 2s complement value with some 32-bit low limb.The latter value in step 2 is expressed as: the 32-bit signed 2s complement value of the
rd
register times2^32
, plus the unsigned value of the 32-bit low limb.The soundness here is a bit subtle. The signed values of 32-bit inputs
rs1
andrs2
have values between-2^31
and2^31 - 1
, so their product is constrained to lie between-2^62 + 2^31
and2^62
. In a prime field of size smaller than2^64
, the range of values represented by a 64-bit 2s complement value, integers between-2^63
and2^63 - 1
, have some ambiguity. Ifp = 2^64 - k
, then the values between-2^63
and-2^63 + k - 1
correspond with the values between2^63 - k
and2^63 - 1
.However, as long as the values required by signed products don't overlap with this ambiguous range, an arbitrary 64-bit 2s complement value can represent a signed 32-bit product in only one way, so there is no ambiguity in the representation. This is the case for the Goldilocks field with order
p = 2^64 - 2^32 + 1
.