Skip to content

Commit 1d2c543

Browse files
committed
signoff!: u32::is_u32
BREAKING CHANGE: Remove the implementation of `DeprecatedSnippet` for `u32::is_u32::IsU32`, implement `BasicSnippet` directly.
1 parent a9f3f88 commit 1d2c543

File tree

1 file changed

+53
-130
lines changed

1 file changed

+53
-130
lines changed
Lines changed: 53 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,96 @@
1-
use std::collections::HashMap;
2-
3-
use num::One;
4-
use num::Zero;
5-
use rand::prelude::*;
61
use triton_vm::prelude::*;
72

8-
use crate::empty_stack;
93
use crate::prelude::*;
10-
use crate::push_encodable;
11-
use crate::traits::deprecated_snippet::DeprecatedSnippet;
12-
use crate::InitVmState;
134

14-
#[derive(Clone, Debug)]
5+
/// Is the top of the stack a u32?
6+
///
7+
/// ### Behavior
8+
///
9+
/// ```text
10+
/// BEFORE: _ value
11+
/// AFTER: _ [is_u32: bool]
12+
/// ```
13+
///
14+
/// ### Preconditions
15+
///
16+
/// None.
17+
///
18+
/// ### Postconditions
19+
///
20+
/// - the output is properly [`BFieldCodec`] encoded
21+
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
1522
pub struct IsU32;
1623

17-
impl DeprecatedSnippet for IsU32 {
18-
fn entrypoint_name(&self) -> String {
19-
"tasmlib_arithmetic_u32_is_u32".to_string()
20-
}
21-
22-
fn input_field_names(&self) -> Vec<String> {
23-
vec!["value".to_string()]
24-
}
25-
26-
fn input_types(&self) -> Vec<DataType> {
27-
vec![DataType::U32]
28-
}
29-
30-
fn output_field_names(&self) -> Vec<String> {
31-
vec!["value < 2^32".to_string()]
24+
impl BasicSnippet for IsU32 {
25+
fn inputs(&self) -> Vec<(DataType, String)> {
26+
vec![(DataType::U32, "value".to_string())]
3227
}
3328

34-
fn output_types(&self) -> Vec<DataType> {
35-
vec![DataType::Bool]
29+
fn outputs(&self) -> Vec<(DataType, String)> {
30+
vec![(DataType::Bool, "value < 2^32".to_string())]
3631
}
3732

38-
fn stack_diff(&self) -> isize {
39-
0
33+
fn entrypoint(&self) -> String {
34+
"tasmlib_arithmetic_u32_is_u32".to_string()
4035
}
4136

42-
/// Place 1 on stack iff top element is less than $2^32$. Otherwise
43-
/// place 0 on stack. Consumes top element of stack, leaves a boolean
44-
/// on top of stack. So this subroutine does not change the height
45-
/// of the stack
46-
fn function_code(&self, _library: &mut Library) -> String {
47-
let entrypoint = self.entrypoint_name();
48-
format!(
49-
"
50-
{entrypoint}:
37+
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
38+
triton_asm!(
39+
{self.entrypoint()}:
5140
// _ a
5241
split // _ hi lo
5342
pop 1 // _ hi
5443
push 0 // _ hi 0
5544
eq // _ (hi == 0)
5645
return
57-
"
5846
)
5947
}
60-
61-
fn crash_conditions(&self) -> Vec<String> {
62-
vec![]
63-
}
64-
65-
fn gen_input_states(&self) -> Vec<InitVmState> {
66-
let n: u32 = rand::thread_rng().next_u32();
67-
68-
let mut true_stack = empty_stack();
69-
push_encodable(&mut true_stack, &n);
70-
71-
let mut false_stack = empty_stack();
72-
push_encodable(&mut false_stack, &(u32::MAX));
73-
74-
vec![
75-
InitVmState::with_stack(true_stack),
76-
InitVmState::with_stack(false_stack),
77-
]
78-
}
79-
80-
fn common_case_input_state(&self) -> InitVmState {
81-
InitVmState::with_stack([empty_stack(), vec![BFieldElement::new(1 << 16)]].concat())
82-
}
83-
84-
fn worst_case_input_state(&self) -> InitVmState {
85-
InitVmState::with_stack([empty_stack(), vec![BFieldElement::new((1 << 32) - 1)]].concat())
86-
}
87-
88-
fn rust_shadowing(
89-
&self,
90-
stack: &mut Vec<BFieldElement>,
91-
_std_in: Vec<BFieldElement>,
92-
_secret_in: Vec<BFieldElement>,
93-
_memory: &mut HashMap<BFieldElement, BFieldElement>,
94-
) {
95-
let top = stack.pop().unwrap();
96-
stack.push(if top.value() < (1 << 32) {
97-
BFieldElement::one()
98-
} else {
99-
BFieldElement::zero()
100-
});
101-
}
10248
}
10349

10450
#[cfg(test)]
10551
mod tests {
10652
use super::*;
107-
use crate::empty_stack;
108-
use crate::test_helpers::test_rust_equivalence_given_input_values_deprecated;
109-
use crate::test_helpers::test_rust_equivalence_multiple_deprecated;
110-
111-
#[test]
112-
fn is_u32_test() {
113-
test_rust_equivalence_multiple_deprecated(&IsU32, true);
114-
}
53+
use crate::test_prelude::*;
11554

116-
#[test]
117-
fn is_u32_simple() {
118-
let stack_true: Vec<BFieldElement> = [empty_stack(), vec![BFieldElement::one()]].concat();
119-
let stack_false: Vec<BFieldElement> = [empty_stack(), vec![BFieldElement::zero()]].concat();
55+
impl Closure for IsU32 {
56+
type Args = BFieldElement;
12057

121-
prop_is_u32(BFieldElement::zero(), Some(&stack_true));
122-
prop_is_u32(BFieldElement::one(), Some(&stack_true));
123-
prop_is_u32(BFieldElement::new(1 << 10), Some(&stack_true));
124-
prop_is_u32(BFieldElement::new(1 << 20), Some(&stack_true));
125-
prop_is_u32(BFieldElement::new(1 << 30), Some(&stack_true));
126-
prop_is_u32(BFieldElement::new(1 << 40), Some(&stack_false));
127-
prop_is_u32(BFieldElement::new(1 << 50), Some(&stack_false));
128-
prop_is_u32(BFieldElement::new(1 << 60), Some(&stack_false));
129-
prop_is_u32(
130-
BFieldElement::new((1 << 63) + (1 << 42)),
131-
Some(&stack_false),
132-
);
133-
}
58+
fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
59+
let value = stack.pop().unwrap();
60+
let is_u32 = u32::try_from(value).is_ok();
61+
push_encodable(stack, &is_u32);
62+
}
13463

135-
#[test]
136-
fn is_u32_pbt() {
137-
let stack_true: Vec<BFieldElement> = [empty_stack(), vec![BFieldElement::one()]].concat();
138-
let stack_false: Vec<BFieldElement> = [empty_stack(), vec![BFieldElement::zero()]].concat();
64+
fn pseudorandom_args(
65+
&self,
66+
seed: [u8; 32],
67+
bench_case: Option<BenchmarkCase>,
68+
) -> Self::Args {
69+
match bench_case {
70+
Some(BenchmarkCase::CommonCase) => bfe!(1 << 16),
71+
Some(BenchmarkCase::WorstCase) => bfe!(u32::MAX),
72+
None => StdRng::from_seed(seed).gen(),
73+
}
74+
}
13975

140-
let mut rng = rand::thread_rng();
141-
for _ in 0..10 {
142-
prop_is_u32(BFieldElement::new(rng.next_u32() as u64), Some(&stack_true));
143-
prop_is_u32(
144-
BFieldElement::new((rng.next_u32() as u64) + (1u64 << 32)),
145-
Some(&stack_false),
146-
);
76+
fn corner_case_args(&self) -> Vec<Self::Args> {
77+
bfe_vec![0, u32::MAX, u64::from(u32::MAX) + 1, BFieldElement::MAX]
14778
}
14879
}
14980

150-
fn prop_is_u32(some_value: BFieldElement, expected: Option<&[BFieldElement]>) {
151-
let mut init_stack = empty_stack();
152-
init_stack.push(some_value);
153-
154-
test_rust_equivalence_given_input_values_deprecated::<IsU32>(
155-
&IsU32,
156-
&init_stack,
157-
&[],
158-
HashMap::default(),
159-
expected,
160-
);
81+
#[test]
82+
fn rust_shadow() {
83+
ShadowedClosure::new(IsU32).test();
16184
}
16285
}
16386

16487
#[cfg(test)]
16588
mod benches {
16689
use super::*;
167-
use crate::snippet_bencher::bench_and_write;
90+
use crate::test_prelude::*;
16891

16992
#[test]
17093
fn is_u32_benchmark() {
171-
bench_and_write(IsU32);
94+
ShadowedClosure::new(IsU32).bench();
17295
}
17396
}

0 commit comments

Comments
 (0)