Skip to content

Commit c7c5b80

Browse files
committed
bytecode: implement Operation
1 parent 40154d5 commit c7c5b80

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

crates/leanVm/src/bytecode/operation.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use p3_field::PrimeField64;
2+
13
/// The basic arithmetic operations supported by the VM's `Computation` instruction.
24
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35
pub enum Operation {
@@ -6,3 +8,102 @@ pub enum Operation {
68
/// Field multiplication in the base field.
79
Mul,
810
}
11+
12+
impl Operation {
13+
/// Computes the result of applying this arithmetic operation to two operands.
14+
///
15+
/// # Parameters
16+
///
17+
/// - `a`: The left-hand operand.
18+
/// - `b`: The right-hand operand.
19+
///
20+
/// # Returns
21+
///
22+
/// The result of `a ⊕ b`, where `⊕` is the operation represented by `self`.
23+
/// For example:
24+
/// - If `self` is `Add`, returns `a + b`.
25+
/// - If `self` is `Mul`, returns `a * b`.
26+
pub fn compute<F>(&self, a: F, b: F) -> F
27+
where
28+
F: PrimeField64,
29+
{
30+
match self {
31+
Self::Add => a + b,
32+
Self::Mul => a * b,
33+
}
34+
}
35+
36+
/// Computes the inverse of the operation with respect to the right-hand operand.
37+
///
38+
/// Solves for `a` given the result `c = a ⊕ b`, by computing `a = c ⊖ b`, where `⊖`
39+
/// is the inverse of the operation represented by `self`.
40+
///
41+
/// # Parameters
42+
///
43+
/// - `a`: The result value (i.e., `a ⊕ b`).
44+
/// - `b`: The right-hand operand of the original operation.
45+
///
46+
/// # Returns
47+
///
48+
/// - `Some(a)` if the inverse exists.
49+
/// - `None` if the inverse does not exist (e.g., `b == 0` for `Mul`).
50+
pub fn inverse_compute<F>(&self, a: F, b: F) -> Option<F>
51+
where
52+
F: PrimeField64,
53+
{
54+
match self {
55+
Self::Add => Some(a - b),
56+
Self::Mul => (!b.is_zero()).then(|| a / b),
57+
}
58+
}
59+
}
60+
61+
#[cfg(test)]
62+
mod tests {
63+
use p3_baby_bear::BabyBear;
64+
use p3_field::PrimeCharacteristicRing;
65+
66+
use super::*;
67+
68+
type F = BabyBear;
69+
70+
#[test]
71+
fn test_compute_add() {
72+
let op = Operation::Add;
73+
let val1 = F::from_u32(100);
74+
let val2 = F::from_u32(50);
75+
assert_eq!(op.compute(val1, val2), F::from_u32(150));
76+
}
77+
78+
#[test]
79+
fn test_compute_mul() {
80+
let op = Operation::Mul;
81+
let val1 = F::from_u32(10);
82+
let val2 = F::from_u32(5);
83+
assert_eq!(op.compute(val1, val2), F::from_u32(50));
84+
}
85+
86+
#[test]
87+
fn test_inverse_compute_add() {
88+
let op = Operation::Add;
89+
let val1 = F::from_u32(150);
90+
let val2 = F::from_u32(50);
91+
assert_eq!(op.inverse_compute(val1, val2), Some(F::from_u32(100)));
92+
}
93+
94+
#[test]
95+
fn test_inverse_compute_mul_success() {
96+
let op = Operation::Mul;
97+
let val1 = F::from_u32(50);
98+
let val2 = F::from_u32(5);
99+
assert_eq!(op.inverse_compute(val1, val2), Some(F::from_u32(10)));
100+
}
101+
102+
#[test]
103+
fn test_inverse_compute_mul_by_zero() {
104+
let op = Operation::Mul;
105+
let val1 = F::from_u32(50);
106+
let val2 = F::ZERO;
107+
assert_eq!(op.inverse_compute(val1, val2), None);
108+
}
109+
}

0 commit comments

Comments
 (0)