Skip to content
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: add comparison operators #130

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

feat: add comparison operators #130

wants to merge 13 commits into from

Conversation

kashbrti
Copy link
Contributor

@kashbrti kashbrti commented Feb 18, 2025

Description

resolves #112

Problem*

Resolves

Summary*

Additional Context

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

validate_in_range::<_, MOD_BITS>(result);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved the constraining of the output of __validate_gt_remainder to a separate function called check_gt_with_flags.

@@ -41,14 +41,19 @@ pub(crate) unconstrained fn __validate_in_field_compute_borrow_flags<let N: u32,
pub(crate) unconstrained fn __validate_gt_remainder<let N: u32>(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__validate_gt_remainder now also returns the boolean value of the underflow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the lhs and rhs are swapped if the underflow is true, and the rest of the logic stays the same

Copy link
Contributor

github-actions bot commented Feb 18, 2025

Changes to circuit sizes

Generated at commit: 2e3b5b391a07ed65a734826fb41a28315007fb42, compared to commit: 1e9bd8a8b9a5993ce252bb60fc60fee40d0efd87

🧾 Summary (10% most significant diffs)

Program ACIR opcodes (+/-) % Circuit size (+/-) %
bench_from_field_Fq.json +1 ❌ +4.76% +1 ❌ +0.04%
bench_from_field_BN256.json +1 ❌ +4.76% +1 ❌ +0.04%

Full diff report 👇
Program ACIR opcodes (+/-) % Circuit size (+/-) %
bench_from_field_Fq.json 22 (+1) +4.76% 2,834 (+1) +0.04%
bench_from_field_BN256.json 22 (+1) +4.76% 2,840 (+1) +0.04%

@kashbrti kashbrti marked this pull request as ready for review February 18, 2025 15:24
Copy link
Collaborator

@iAmMichaelConnor iAmMichaelConnor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for delving into this code! Just 3 minor comments :)

@@ -572,3 +557,41 @@ pub(crate) fn umod<let N: u32, let MOD_BITS: u32>(
) -> [Field; N] {
udiv_mod::<_, MOD_BITS>(params, numerator, divisor).1
}

// a comparison function. returns true if lhs > rhs and false otherwise
pub(crate) fn cmp<let N: u32, let MOD_BITS: u32>(lhs: [Field; N], rhs: [Field; N]) -> bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the convention should be, but it looks like cmp functions in the noir stdlib always return the Ordering type. Perhaps, therefore, this function should be renamed to something like gt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you check bignum.nr I have an impl for the Cmp trait that returns an ordering object.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry, yes I saw that one. I just mean for this function in particular, perhaps its name should be changed to something that isn't cmp.

}

#[test]
fn test_cmp_BN_2() {
Copy link
Collaborator

@iAmMichaelConnor iAmMichaelConnor Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it's also worth testing other common edge cases:

  • 0 < 1
  • 0 < -1
    And if you're feeling adventurous:
  • Choose lots of random bignums r and s check that if r < s then r - (p-1)/2 > s
    • The reason I suggest something like this is because these current tests only test limbs[0] being different; what if the other limbs aren't equal?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I've written 0 < -1... but I don't actually know what the convention should be for comparison.
I think in the Aztec codebase, we consider the "first half" of the field as "positive" numbers, and the 2nd half of the field as "negative" numbers. So we check whether things are < (p-1)/2.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the U256 type, regular integer comparison makes sense.
For the prime field types, I'm less sure...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah that's a good point, at the moment everything is being treated as usual integers between 0 and modulus. I think it'll be quite ugly to have two different impl depending on whether a number is positive or negative.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, being consistent makes sense to me!

where
Params: BigNumParamsGetter<N, MOD_BITS>,
{
fn cmp(self, other: Self) -> Ordering {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also implement this for the RuntimeBignum?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep will do.

@kashbrti
Copy link
Contributor Author

@iAmMichaelConnor this should be at a good place for a review!

Copy link
Member

@TomAFrench TomAFrench left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nits but LGTM

@@ -921,3 +921,56 @@ fn test_sub_underflow_regression() {
let c = b - a;
assert(c.limbs == [0, 0, 0]);
}

#[test]
fn test_cmp_BN() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move these all inside of a submodule grouping all of the tests related to cmp?

}

#[test]
fn test_cmp_BN_fuzz(seed: [u8; 2]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn test_cmp_BN_fuzz(seed: [u8; 2]) {
fn test_cmp_BN_fuzz(seed: [u8; 5]) {

There's currently only ~65k potential inputs here.

@@ -27,6 +27,8 @@ use crate::params::BigNumParams as P;
* udiv_mod
* udiv
* umod
* gt
* check_gt_with_flags
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just remove this comment. It's pretty meaningless.

Comment on lines +401 to +411
let comp_result: bool = gt::<_, MOD_BITS>(self.limbs, other.limbs);
if self.limbs == other.limbs {
Ordering::equal()
} else if comp_result {
// there was an underflow
Ordering::greater()
} else {
// there was no underflow
Ordering::less()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we push a cmp function into constrained_ops? We can then avoid the duplicated logic between here and RuntimeBigNum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for comparison of bignums
3 participants