Skip to content

Commit 0914583

Browse files
committed
signoff!: u64::or
BREAKING CHANGE: Remove the implementation of `DeprecatedSnippet` for `u64::or::Or`, implement `BasicSnippet` directly.
1 parent 99e3802 commit 0914583

File tree

5 files changed

+103
-188
lines changed

5 files changed

+103
-188
lines changed

tasm-lib/benchmarks/tasmlib_arithmetic_u64_div_mod.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"benchmark_result": {
1616
"clock_cycle_count": 7950,
1717
"hash_table_height": 516,
18-
"u32_table_height": 10526,
18+
"u32_table_height": 9503,
1919
"op_stack_table_height": 5382,
2020
"ram_table_height": 142
2121
},

tasm-lib/benchmarks/tasmlib_arithmetic_u64_or_u64.json renamed to tasm-lib/benchmarks/tasmlib_arithmetic_u64_or.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[
22
{
3-
"name": "tasmlib_arithmetic_u64_or_u64",
3+
"name": "tasmlib_arithmetic_u64_or",
44
"benchmark_result": {
55
"clock_cycle_count": 17,
66
"hash_table_height": 18,
@@ -11,7 +11,7 @@
1111
"case": "CommonCase"
1212
},
1313
{
14-
"name": "tasmlib_arithmetic_u64_or_u64",
14+
"name": "tasmlib_arithmetic_u64_or",
1515
"benchmark_result": {
1616
"clock_cycle_count": 17,
1717
"hash_table_height": 18,

tasm-lib/src/arithmetic/u64/and.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl BasicSnippet for And {
7070
}
7171

7272
#[cfg(test)]
73-
mod tests {
73+
pub(crate) mod tests {
7474
use super::*;
7575
use crate::test_prelude::*;
7676

@@ -98,14 +98,9 @@ mod tests {
9898
let edge_points = [0, 1 << 32, u64::MAX]
9999
.into_iter()
100100
.flat_map(|p| [p.checked_sub(1), Some(p), p.checked_add(1)])
101-
.flatten()
102-
.collect_vec();
103-
104-
edge_points
105-
.iter()
106-
.cartesian_product(&edge_points)
107-
.map(|(&l, &r)| (l, r))
108-
.collect()
101+
.flatten();
102+
103+
edge_points.clone().cartesian_product(edge_points).collect()
109104
}
110105
}
111106

tasm-lib/src/arithmetic/u64/or.rs

Lines changed: 95 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,204 +1,124 @@
1-
use rand::prelude::*;
1+
use std::collections::HashMap;
2+
23
use triton_vm::prelude::*;
3-
use twenty_first::prelude::U32s;
44

5-
use crate::empty_stack;
65
use crate::prelude::*;
7-
use crate::push_encodable;
8-
use crate::traits::deprecated_snippet::DeprecatedSnippet;
9-
use crate::InitVmState;
10-
11-
#[derive(Clone, Debug)]
6+
use crate::traits::basic_snippet::Reviewer;
7+
use crate::traits::basic_snippet::SignOffFingerprint;
8+
9+
/// [Bitwise “or”][bitor] (“`|`”) for `u64`s.
10+
///
11+
/// ### Behavior
12+
///
13+
/// ```text
14+
/// BEFORE: _ [right: u64] [left: u64]
15+
/// AFTER: _ [left | right: u64]
16+
/// ```
17+
///
18+
/// ### Preconditions
19+
///
20+
/// - all input arguments are properly [`BFieldCodec`] encoded
21+
///
22+
/// ### Postconditions
23+
///
24+
/// - the output is the bitwise “or” of the input
25+
/// - the output is properly [`BFieldCodec`] encoded
26+
///
27+
/// [bitor]: core::ops::BitOr
28+
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
1229
pub struct Or;
1330

14-
impl DeprecatedSnippet for Or {
15-
fn entrypoint_name(&self) -> String {
16-
"tasmlib_arithmetic_u64_or_u64".to_string()
17-
}
18-
19-
fn input_field_names(&self) -> Vec<String> {
20-
vec![
21-
"rhs_hi".to_string(),
22-
"rhs_lo".to_string(),
23-
"lhs_hi".to_string(),
24-
"lhs_lo".to_string(),
25-
]
26-
}
27-
28-
fn input_types(&self) -> Vec<DataType> {
29-
vec![DataType::U64, DataType::U64]
30-
}
31-
32-
fn output_field_names(&self) -> Vec<String> {
33-
vec!["(lhs | rhs)_hi".to_string(), "(lhs | rhs)_lo".to_string()]
34-
}
35-
36-
fn output_types(&self) -> Vec<DataType> {
37-
vec![DataType::U64]
38-
}
39-
40-
fn stack_diff(&self) -> isize {
41-
-2
42-
}
43-
44-
fn function_code(&self, _library: &mut crate::library::Library) -> String {
45-
let entrypoint = self.entrypoint_name();
46-
format!(
47-
"
48-
// BEFORE: _ rhs_hi rhs_lo lhs_hi lhs_lo
49-
// AFTER: _ (lhs | rhs)_hi (lhs | rhs)_lo
50-
{entrypoint}:
51-
dup 2
52-
dup 1
53-
xor
54-
// _ rhs_hi rhs_lo lhs_hi lhs_lo (rhs_lo ^ lhs_lo)
55-
56-
swap 3
57-
and
58-
// _ rhs_hi (rhs_lo ^ lhs_lo) lhs_hi (lhs_lo & rhs_lo)
59-
60-
swap 3
61-
// _ (lhs_lo & rhs_lo) (rhs_lo ^ lhs_lo) lhs_hi rhs_hi
62-
63-
dup 1
64-
dup 1
65-
xor
66-
// _ (lhs_lo & rhs_lo) (rhs_lo ^ lhs_lo) lhs_hi rhs_hi (lhs_hi ^ rhs_hi)
67-
68-
swap 2
69-
and
70-
// _ (lhs_lo & rhs_lo) (rhs_lo ^ lhs_lo) (lhs_hi ^ rhs_hi) (rhs_hi & lhs_hi)
71-
72-
add
73-
// _ (lhs_lo & rhs_lo) (rhs_lo ^ lhs_lo) (lhs_hi | rhs_hi)
74-
75-
swap 2
76-
add
77-
// _ (lhs_hi | rhs_hi) (rhs_lo | lhs_lo)
78-
79-
return
80-
"
31+
impl BasicSnippet for Or {
32+
fn inputs(&self) -> Vec<(DataType, String)> {
33+
["right", "left"]
34+
.map(|s| (DataType::U64, s.to_string()))
35+
.to_vec()
36+
}
37+
38+
fn outputs(&self) -> Vec<(DataType, String)> {
39+
vec![(DataType::U64, "left | right".to_string())]
40+
}
41+
42+
fn entrypoint(&self) -> String {
43+
"tasmlib_arithmetic_u64_or".to_string()
44+
}
45+
46+
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
47+
let entrypoint = self.entrypoint();
48+
triton_asm!(
49+
// BEFORE: _ r_hi r_lo l_hi l_lo
50+
// AFTER: _ (l | r)_hi (l | r)_lo
51+
{entrypoint}:
52+
dup 2
53+
dup 1
54+
xor // _ r_hi r_lo l_hi l_lo (r_lo ^ l_lo)
55+
swap 3
56+
and // _ r_hi (r_lo ^ l_lo) l_hi (l_lo & r_lo)
57+
swap 3 // _ (l_lo & r_lo) (r_lo ^ l_lo) l_hi r_hi
58+
dup 1
59+
dup 1
60+
xor // _ (l_lo & r_lo) (r_lo ^ l_lo) l_hi r_hi (l_hi ^ r_hi)
61+
place 2
62+
and // _ (l_lo & r_lo) (r_lo ^ l_lo) (l_hi ^ r_hi) (r_hi & l_hi)
63+
add // _ (l_lo & r_lo) (r_lo ^ l_lo) (l_hi | r_hi)
64+
place 2
65+
add // _ (l_hi | r_hi) (r_lo | l_lo)
66+
return
8167
)
8268
}
8369

84-
fn crash_conditions(&self) -> Vec<String> {
85-
vec!["Inputs are not u32".to_owned()]
86-
}
87-
88-
fn gen_input_states(&self) -> Vec<InitVmState> {
89-
let mut ret: Vec<InitVmState> = vec![];
90-
for _ in 0..100 {
91-
ret.push(prepare_state(
92-
thread_rng().next_u64(),
93-
thread_rng().next_u64(),
94-
));
95-
}
96-
97-
ret
98-
}
99-
100-
fn common_case_input_state(&self) -> InitVmState {
101-
prepare_state(u32::MAX as u64, u32::MAX as u64)
70+
fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
71+
let mut sign_offs = HashMap::new();
72+
sign_offs.insert(Reviewer("ferdinand"), 0x9304a37ae367ed6.into());
73+
sign_offs
10274
}
103-
104-
fn worst_case_input_state(&self) -> InitVmState {
105-
prepare_state(u64::MAX, u64::MAX)
106-
}
107-
108-
fn rust_shadowing(
109-
&self,
110-
stack: &mut Vec<BFieldElement>,
111-
_std_in: Vec<BFieldElement>,
112-
_secret_in: Vec<BFieldElement>,
113-
_memory: &mut std::collections::HashMap<BFieldElement, BFieldElement>,
114-
) {
115-
let lhs_lo: u32 = stack.pop().unwrap().try_into().unwrap();
116-
let lhs_hi: u32 = stack.pop().unwrap().try_into().unwrap();
117-
let rhs_lo: u32 = stack.pop().unwrap().try_into().unwrap();
118-
let rhs_hi: u32 = stack.pop().unwrap().try_into().unwrap();
119-
120-
let lhs = ((lhs_hi as u64) << 32) + lhs_lo as u64;
121-
let rhs = ((rhs_hi as u64) << 32) + rhs_lo as u64;
122-
123-
let or = lhs | rhs;
124-
stack.push(BFieldElement::new(or >> 32));
125-
stack.push(BFieldElement::new(or & u32::MAX as u64));
126-
}
127-
}
128-
129-
fn prepare_state(a: u64, b: u64) -> InitVmState {
130-
let a = U32s::<2>::try_from(a).unwrap();
131-
let b = U32s::<2>::try_from(b).unwrap();
132-
let mut init_stack = empty_stack();
133-
push_encodable(&mut init_stack, &a);
134-
push_encodable(&mut init_stack, &b);
135-
InitVmState::with_stack(init_stack)
13675
}
13776

13877
#[cfg(test)]
13978
mod tests {
140-
use std::collections::HashMap;
141-
14279
use super::*;
143-
use crate::test_helpers::test_rust_equivalence_given_input_values_deprecated;
144-
use crate::test_helpers::test_rust_equivalence_multiple_deprecated;
80+
use crate::arithmetic::u64::and::And;
81+
use crate::test_prelude::*;
14582

146-
#[test]
147-
fn snippet_test() {
148-
test_rust_equivalence_multiple_deprecated(&Or, true);
149-
}
83+
impl Closure for Or {
84+
type Args = (u64, u64);
15085

151-
#[test]
152-
fn or_simple_test() {
153-
prop_safe_or(10, 1, Some(11));
154-
prop_safe_or(10, (1 << 36) + 1, Some(11 + (1 << 36)));
155-
prop_safe_or(256, 30, Some(286));
156-
prop_safe_or(123, 0, Some(123));
157-
prop_safe_or(0, 123, Some(123));
158-
prop_safe_or(1 << 31, 1 << 30, Some((1 << 30) + (1 << 31)));
159-
prop_safe_or(0, 0, Some(0));
160-
prop_safe_or(14, 0, Some(14));
161-
prop_safe_or(u32::MAX as u64, 0, Some(u32::MAX as u64));
162-
prop_safe_or(0, u32::MAX as u64, Some(u32::MAX as u64));
163-
prop_safe_or(u32::MAX as u64, u32::MAX as u64, Some(u32::MAX as u64));
164-
prop_safe_or(u64::MAX, u64::MAX, Some(u64::MAX));
165-
prop_safe_or(u64::MAX, 0, Some(u64::MAX));
166-
prop_safe_or(0, u64::MAX, Some(u64::MAX));
167-
}
86+
fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
87+
let (right, left) = pop_encodable::<Self::Args>(stack);
88+
let or = left | right;
89+
push_encodable(stack, &or);
90+
}
16891

169-
fn prop_safe_or(lhs: u64, rhs: u64, expected: Option<u64>) {
170-
let res = lhs | rhs;
171-
if let Some(exp) = expected {
172-
assert_eq!(exp, { res });
92+
fn pseudorandom_args(
93+
&self,
94+
seed: [u8; 32],
95+
bench_case: Option<BenchmarkCase>,
96+
) -> Self::Args {
97+
match bench_case {
98+
Some(BenchmarkCase::CommonCase) => (u32::MAX.into(), u32::MAX.into()),
99+
Some(BenchmarkCase::WorstCase) => (u64::MAX, u64::MAX),
100+
None => StdRng::from_seed(seed).gen(),
101+
}
173102
}
174103

175-
let rhs = U32s::<2>::try_from(rhs).unwrap();
176-
let lhs = U32s::<2>::try_from(lhs).unwrap();
177-
let mut init_stack = empty_stack();
178-
push_encodable(&mut init_stack, &rhs);
179-
push_encodable(&mut init_stack, &lhs);
180-
181-
let mut expected = empty_stack();
182-
expected.push(BFieldElement::new(res >> 32));
183-
expected.push(BFieldElement::new(res & u32::MAX as u64));
184-
185-
test_rust_equivalence_given_input_values_deprecated(
186-
&Or,
187-
&init_stack,
188-
&[],
189-
HashMap::default(),
190-
Some(&expected),
191-
);
104+
fn corner_case_args(&self) -> Vec<Self::Args> {
105+
And.corner_case_args()
106+
}
107+
}
108+
109+
#[test]
110+
fn rust_shadow() {
111+
ShadowedClosure::new(Or).test();
192112
}
193113
}
194114

195115
#[cfg(test)]
196116
mod benches {
197117
use super::*;
198-
use crate::snippet_bencher::bench_and_write;
118+
use crate::test_prelude::*;
199119

200120
#[test]
201-
fn u64_or_benchmark() {
202-
bench_and_write(Or);
121+
fn benchmark() {
122+
ShadowedClosure::new(Or).bench();
203123
}
204124
}

tasm-lib/src/exported_snippets.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ pub fn name_to_snippet(fn_name: &str) -> Option<Box<dyn BasicSnippet>> {
117117
"tasmlib_arithmetic_u64_mul_two_u64s_to_u128_u64" => {
118118
Some(Box::new(u64::mul_two_u64s_to_u128::MulTwoU64sToU128))
119119
}
120-
"tasmlib_arithmetic_u64_or_u64" => Some(Box::new(u64::or::Or)),
120+
"tasmlib_arithmetic_u64_or" => Some(Box::new(u64::or::Or)),
121121
"tasmlib_arithmetic_u64_overflowing_sub" => {
122122
Some(Box::new(u64::overflowing_sub::OverflowingSub))
123123
}

0 commit comments

Comments
 (0)