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

Builtin operators #197

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

Builtin operators #197

wants to merge 4 commits into from

Conversation

katat
Copy link
Collaborator

@katat katat commented Oct 2, 2024

To support operators and apply default constraints: <, /, %, <<

@katat katat requested a review from mimoo October 2, 2024 08:28
Copy link
Contributor

@mimoo mimoo left a comment

Choose a reason for hiding this comment

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

left some comments, I need to have another pass on the division which seems to be the most tricky part of the logic :o

also I remember that there was a nice way to check if a < b in the field without having to check a 256 bits decomposition but only a 128 bit decomposition. We should check how other implementations do it :o

// otherwise, the carry bit of sum_bits is 1.

/*
psuedo code:
Copy link
Contributor

Choose a reason for hiding this comment

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

pseudo*

(ConstOrCell::Cell(lhs_), ConstOrCell::Const(rhs_)) => {
let pow2 = B::Field::from(2u32).pow(rhs_.into_repr());
let res = compiler.backend.mul_const(lhs_, &pow2, span);
Var::new_var(res, span)
Copy link
Contributor

Choose a reason for hiding this comment

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

The weird thing to me is that at this point there is no way to tell if there is an overflow, the modulus length also impacts that. Maybe that's fine though... But I'm not sure what people would expect. Is this operator implemented in any other DSL? How do they handle overflows?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, overflow is probably something to take care of here.

One of the compilers restricts the value type to be integer and the shift amount to be u8. I guess the reason it restrict to be integer is for range checking the resulted value.

// convert to bigint
let pow2 = B::Field::from(2u32).pow(rhs.into_repr());
let res = *lhs * pow2;
Var::new_constant(res, span)
Copy link
Contributor

Choose a reason for hiding this comment

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

We should return an error on overflow perhaps

// until we refactor the backend to handle ConstOrCell or some kind of wrapper that encapsulate the different variable types
// convert cst to var for easier handling
let lhs = match lhs {
ConstOrCell::Const(lhs) => compiler.backend.add_constant(
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that we also wanted to remove this add_constant fn :p

let rem = Value::VarModVar(lhs.clone(), rhs.clone());
let rem_var = compiler.backend.new_internal_var(rem, span);

// rem < rhs
Copy link
Contributor

Choose a reason for hiding this comment

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

If lhs < rhs then we will have rem = lhs. So either we forbid lhs < rhs or we add an edge case to make it work as well. Both might lead to extra constraints tho...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, this constraint seems not well done. let me research a bit on how others constrain this.

// lhs + (1 << LEN) - rhs
// proof:
// lhs + (1 << LEN) will add a carry bit, valued 1, to the bit array representing lhs,
// resulted in a bit array of length LEN + 1, named as sum_bits.
Copy link
Contributor

Choose a reason for hiding this comment

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

Trying to understand this but intuitively this is not going to work when we are too close to the modulus


env.cached_values.insert(cache_key, res);
Ok(res)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

why not a single Value::Div(VarOrCst, VarOrCst)?

@katat katat mentioned this pull request Oct 11, 2024
2 tasks
@mimoo
Copy link
Contributor

mimoo commented Oct 23, 2024

what's the status here? Do we have these as native functions now or do we still want this PR merged?

@katat
Copy link
Collaborator Author

katat commented Oct 24, 2024

let's hold this one, until we figured out #214

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.

2 participants