-
Notifications
You must be signed in to change notification settings - Fork 22
feat: remove generic parameter from the BigNum trait
#44
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
Changes from 6 commits
bb32c1f
6eb9af4
aa944aa
c3162ac
6fcc990
fa6e282
f92c12e
d0acce7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,23 +18,23 @@ pub struct BigNum<let N: u32, let MOD_BITS: u32, Params> { | |
| pub limbs: [Field; N], | ||
| } | ||
|
|
||
| pub(crate) trait BigNumTrait<let N: u32> { | ||
| pub trait BigNumTrait { | ||
| // TODO: this crashes the compiler? v0.32 | ||
| // fn default() -> Self { std::default::Default::default () } | ||
| pub fn new() -> Self; | ||
| pub fn one() -> Self; | ||
| pub fn derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self; | ||
| pub unconstrained fn __derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self; | ||
| pub fn from_slice(limbs: [Field]) -> Self; | ||
| pub fn from_array(limbs: [Field; N]) -> Self; | ||
| // pub fn from_array<let M: u32>(limbs: [Field; M]) -> Self; | ||
|
TomAFrench marked this conversation as resolved.
Outdated
|
||
| pub fn from_be_bytes<let NBytes: u32>(x: [u8; NBytes]) -> Self; | ||
| pub fn to_le_bytes<let NBytes: u32>(self) -> [u8; NBytes]; | ||
|
|
||
| pub fn modulus() -> Self; | ||
| pub fn modulus_bits() -> u32; | ||
| pub fn num_limbs() -> u32; | ||
| // pub fn get(self) -> [Field]; | ||
| pub fn get_limbs(self) -> [Field; N]; | ||
| pub fn modulus_bits(self) -> u32; | ||
| pub fn num_limbs(self) -> u32; | ||
| pub fn get_limbs_slice(self) -> [Field]; | ||
| // pub fn get_limbs<let M: u32>(self) -> [Field; M]; | ||
|
TomAFrench marked this conversation as resolved.
Outdated
|
||
| pub fn get_limb(self, idx: u32) -> Field; | ||
| pub fn set_limb(&mut self, idx: u32, value: Field); | ||
|
|
||
|
|
@@ -100,7 +100,7 @@ pub(crate) trait BigNumTrait<let N: u32> { | |
| pub fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self; | ||
| } | ||
|
|
||
| impl<let N: u32, let MOD_BITS: u32, Params> BigNumTrait<N> for BigNum<N, MOD_BITS, Params> | ||
| impl<let N: u32, let MOD_BITS: u32, Params> BigNumTrait for BigNum<N, MOD_BITS, Params> | ||
| where | ||
| Params: BigNumParamsGetter<N, MOD_BITS>, | ||
| { | ||
|
|
@@ -129,9 +129,12 @@ where | |
| Self { limbs: limbs.as_array() } | ||
| } | ||
|
|
||
| fn from_array(limbs: [Field; N]) -> Self { | ||
| Self { limbs } | ||
| } | ||
| // We avoid passing an array, because that would require the array length to be expressed as a generic param of BigNumTrait, and we don't want BigNumTrait to have any generic params, so that when we use BigNum, we can cleanly say `where BigNum: BigNumTrait`, without any extra generics being used. | ||
|
TomAFrench marked this conversation as resolved.
Outdated
|
||
| // fn from_array<let M: u32>(limbs: [Field; M]) -> Self { | ||
| // // This static assertion doesn't trick the compiler. | ||
| // std::static_assert(M == N, ""); | ||
| // Self { limbs } | ||
| // } | ||
|
TomAFrench marked this conversation as resolved.
Outdated
|
||
|
|
||
| fn from_be_bytes<let NBytes: u32>(x: [u8; NBytes]) -> Self { | ||
| Self { limbs: from_be_bytes::<_, MOD_BITS, _>(x) } | ||
|
|
@@ -145,22 +148,25 @@ where | |
| Self { limbs: Params::get_params().modulus } | ||
| } | ||
|
|
||
| fn modulus_bits() -> u32 { | ||
| fn modulus_bits(_: Self) -> u32 { | ||
| MOD_BITS | ||
| } | ||
|
|
||
| fn num_limbs() -> u32 { | ||
| fn num_limbs(_: Self) -> u32 { | ||
| N | ||
| } | ||
|
|
||
| // fn get(self) -> [Field] { | ||
| // self.get_limbs() | ||
| // } | ||
|
|
||
| fn get_limbs(self) -> [Field; N] { | ||
| fn get_limbs_slice(self) -> [Field] { | ||
| self.limbs | ||
| } | ||
|
|
||
| // We avoid returning an array, because that would require the array length to be expressed as a generic param of BigNumTrait, and we don't want BigNumTrait to have any generic params, so that when we use BigNum, we can cleanly say `where BigNum: BigNumTrait`, without any extra generics being used. | ||
| // fn get_limbs<let M: u32>(self) -> [Field; M] { | ||
| // // This static assertion doesn't trick the compiler. | ||
| // std::static_assert(M == N, ""); | ||
| // self.limbs | ||
| // } | ||
|
|
||
|
TomAFrench marked this conversation as resolved.
Outdated
|
||
| fn get_limb(self, idx: u32) -> Field { | ||
| self.limbs[idx] | ||
| } | ||
|
|
@@ -179,27 +185,27 @@ where | |
|
|
||
| unconstrained fn __neg(self) -> Self { | ||
| let params = Params::get_params(); | ||
| Self::from_array(__neg(params, self.limbs)) | ||
| Self::from_slice(__neg(params, self.limbs)) | ||
| } | ||
|
|
||
| unconstrained fn __add(self, other: Self) -> Self { | ||
| let params = Params::get_params(); | ||
| Self::from_array(__add(params, self.limbs, other.limbs)) | ||
| Self::from_slice(__add(params, self.limbs, other.limbs)) | ||
| } | ||
|
|
||
| unconstrained fn __sub(self, other: Self) -> Self { | ||
| let params = Params::get_params(); | ||
| Self::from_array(__sub(params, self.limbs, other.limbs)) | ||
| Self::from_slice(__sub(params, self.limbs, other.limbs)) | ||
| } | ||
|
|
||
| unconstrained fn __mul(self, other: Self) -> Self { | ||
| let params = Params::get_params(); | ||
| Self::from_array(__mul::<_, MOD_BITS>(params, self.limbs, other.limbs)) | ||
| Self::from_slice(__mul::<_, MOD_BITS>(params, self.limbs, other.limbs)) | ||
| } | ||
|
|
||
| unconstrained fn __div(self, divisor: Self) -> Self { | ||
| let params = Params::get_params(); | ||
| Self::from_array(__div::<_, MOD_BITS>(params, self.limbs, divisor.limbs)) | ||
| Self::from_slice(__div::<_, MOD_BITS>(params, self.limbs, divisor.limbs)) | ||
| } | ||
|
|
||
| unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self) { | ||
|
|
@@ -221,17 +227,18 @@ where | |
| unconstrained fn __batch_invert<let M: u32>(x: [Self; M]) -> [Self; M] { | ||
| let params = Params::get_params(); | ||
| assert(params.has_multiplicative_inverse); | ||
| __batch_invert::<_, MOD_BITS, _>(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| { | ||
| Self { limbs } | ||
| }) | ||
| __batch_invert::<_, MOD_BITS, _>(params, x.map(|bn| Self::get_limbs_slice(bn).as_array())) | ||
| .map(|limbs| { Self { limbs } }) | ||
| } | ||
|
|
||
| unconstrained fn __batch_invert_slice<let M: u32>(x: [Self]) -> [Self] { | ||
| let params = Params::get_params(); | ||
| assert(params.has_multiplicative_inverse); | ||
| __batch_invert_slice::<_, MOD_BITS>(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| { | ||
| Self { limbs } | ||
| }) | ||
| __batch_invert_slice::<_, MOD_BITS>( | ||
| params, | ||
| x.map(|bn| Self::get_limbs_slice(bn).as_array()), | ||
| ) | ||
| .map(|limbs| { Self { limbs } }) | ||
| } | ||
|
|
||
| unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option<Self> { | ||
|
|
@@ -251,11 +258,17 @@ where | |
| let params = Params::get_params(); | ||
| let (q_limbs, r_limbs) = __compute_quadratic_expression::<_, MOD_BITS, _, _, _, _>( | ||
| params, | ||
| map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), | ||
| map( | ||
| lhs_terms, | ||
| |bns| map(bns, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| ), | ||
| lhs_flags, | ||
| map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), | ||
| map( | ||
| rhs_terms, | ||
| |bns| map(bns, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| ), | ||
| rhs_flags, | ||
| map(linear_terms, |bn| Self::get_limbs(bn)), | ||
| map(linear_terms, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| linear_flags, | ||
| ); | ||
| (Self { limbs: q_limbs }, Self { limbs: r_limbs }) | ||
|
|
@@ -272,11 +285,17 @@ where | |
| let params = Params::get_params(); | ||
| evaluate_quadratic_expression::<_, MOD_BITS, _, _, _, _>( | ||
| params, | ||
| map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), | ||
| map( | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @TomAFrench I've honed in on this PR being the one that caused a regression in the constraint counts of BigNum. In particular, I was measuring the constraints of calls to this
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The extra ACIR opcodes (for a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this is bad actor codegen as we're just reading all the values out of the array to write into another one.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neater code here, to fix it: #53 |
||
| lhs_terms, | ||
| |bns| map(bns, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| ), | ||
| lhs_flags, | ||
| map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), | ||
| map( | ||
| rhs_terms, | ||
| |bns| map(bns, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| ), | ||
| rhs_flags, | ||
| map(linear_terms, |bn| Self::get_limbs(bn)), | ||
| map(linear_terms, |bn| Self::get_limbs_slice(bn).as_array()), | ||
| linear_flags, | ||
| ) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.