Skip to content

Commit 4b2e8bf

Browse files
TomAFrenchguipublic
authored andcommitted
feat: implement euclidean division and signed division in terms of AcirVars (#3230)
1 parent 7d73590 commit 4b2e8bf

70 files changed

Lines changed: 292 additions & 342 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

acvm-repo/brillig_vm/src/arithmetic.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,28 @@ pub(crate) fn evaluate_binary_bigint_op(
2525
a: BigUint,
2626
b: BigUint,
2727
bit_size: u32,
28-
) -> BigUint {
28+
) -> Result<BigUint, String> {
2929
let bit_modulo = &(BigUint::one() << bit_size);
30-
match op {
30+
let result = match op {
3131
// Perform addition, subtraction, and multiplication, applying a modulo operation to keep the result within the bit size.
3232
BinaryIntOp::Add => (a + b) % bit_modulo,
3333
BinaryIntOp::Sub => (bit_modulo + a - b) % bit_modulo,
3434
BinaryIntOp::Mul => (a * b) % bit_modulo,
3535
// Perform unsigned division using the modulo operation on a and b.
36-
BinaryIntOp::UnsignedDiv => (a % bit_modulo) / (b % bit_modulo),
36+
BinaryIntOp::UnsignedDiv => {
37+
let b_mod = b % bit_modulo;
38+
if b_mod.is_zero() {
39+
return Err("Division by zero".to_owned());
40+
}
41+
(a % bit_modulo) / b_mod
42+
}
3743
// Perform signed division by first converting a and b to signed integers and then back to unsigned after the operation.
3844
BinaryIntOp::SignedDiv => {
39-
let signed_div = to_big_signed(a, bit_size) / to_big_signed(b, bit_size);
45+
let b_signed = to_big_signed(b, bit_size);
46+
if b_signed.is_zero() {
47+
return Err("Division by zero".to_owned());
48+
}
49+
let signed_div = to_big_signed(a, bit_size) / b_signed;
4050
to_big_unsigned(signed_div, bit_size)
4151
}
4252
// Perform a == operation, returning 0 or 1
@@ -77,7 +87,9 @@ pub(crate) fn evaluate_binary_bigint_op(
7787
let b = b.to_u128().unwrap();
7888
(a >> b) % bit_modulo
7989
}
80-
}
90+
};
91+
92+
Ok(result)
8193
}
8294

8395
fn to_big_signed(a: BigUint, bit_size: u32) -> BigInt {
@@ -111,7 +123,7 @@ mod tests {
111123
// Convert to big integers
112124
let lhs_big = BigUint::from(a);
113125
let rhs_big = BigUint::from(b);
114-
let result_value = evaluate_binary_bigint_op(op, lhs_big, rhs_big, bit_size);
126+
let result_value = evaluate_binary_bigint_op(op, lhs_big, rhs_big, bit_size).unwrap();
115127
// Convert back to u128
116128
result_value.to_u128().unwrap()
117129
}

acvm-repo/brillig_vm/src/lib.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,12 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> {
177177
self.increment_program_counter()
178178
}
179179
Opcode::BinaryIntOp { op, bit_size, lhs, rhs, destination: result } => {
180-
self.process_binary_int_op(*op, *bit_size, *lhs, *rhs, *result);
181-
self.increment_program_counter()
180+
if let Err(error) = self.process_binary_int_op(*op, *bit_size, *lhs, *rhs, *result)
181+
{
182+
self.fail(error)
183+
} else {
184+
self.increment_program_counter()
185+
}
182186
}
183187
Opcode::Jump { location: destination } => self.set_program_counter(*destination),
184188
Opcode::JumpIf { condition, location: destination } => {
@@ -391,17 +395,18 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> {
391395
lhs: RegisterIndex,
392396
rhs: RegisterIndex,
393397
result: RegisterIndex,
394-
) {
398+
) -> Result<(), String> {
395399
let lhs_value = self.registers.get(lhs);
396400
let rhs_value = self.registers.get(rhs);
397401

398402
// Convert to big integers
399403
let lhs_big = BigUint::from_bytes_be(&lhs_value.to_field().to_be_bytes());
400404
let rhs_big = BigUint::from_bytes_be(&rhs_value.to_field().to_be_bytes());
401-
let result_value = evaluate_binary_bigint_op(&op, lhs_big, rhs_big, bit_size);
405+
let result_value = evaluate_binary_bigint_op(&op, lhs_big, rhs_big, bit_size)?;
402406
// Convert back to field element
403407
self.registers
404408
.set(result, FieldElement::from_be_bytes_reduce(&result_value.to_bytes_be()).into());
409+
Ok(())
405410
}
406411
}
407412

0 commit comments

Comments
 (0)