Skip to content

Commit 647c279

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 647c279

File tree

1 file changed

+59
-128
lines changed

1 file changed

+59
-128
lines changed
Lines changed: 59 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,104 @@
11
use std::collections::HashMap;
2-
3-
use num::One;
4-
use num::Zero;
5-
use rand::prelude::*;
62
use triton_vm::prelude::*;
73

8-
use crate::empty_stack;
94
use crate::prelude::*;
10-
use crate::push_encodable;
11-
use crate::traits::deprecated_snippet::DeprecatedSnippet;
12-
use crate::InitVmState;
13-
14-
#[derive(Clone, Debug)]
5+
use crate::traits::basic_snippet::{Reviewer, SignOffFingerprint};
6+
7+
/// Is the top of the stack a u32?
8+
///
9+
/// ### Behavior
10+
///
11+
/// ```text
12+
/// BEFORE: _ value
13+
/// AFTER: _ [is_u32: bool]
14+
/// ```
15+
///
16+
/// ### Preconditions
17+
///
18+
/// None.
19+
///
20+
/// ### Postconditions
21+
///
22+
/// - the output is properly [`BFieldCodec`] encoded
23+
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
1524
pub struct IsU32;
1625

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()]
26+
impl BasicSnippet for IsU32 {
27+
fn inputs(&self) -> Vec<(DataType, String)> {
28+
vec![(DataType::U32, "value".to_string())]
3229
}
3330

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

38-
fn stack_diff(&self) -> isize {
39-
0
35+
fn entrypoint(&self) -> String {
36+
"tasmlib_arithmetic_u32_is_u32".to_string()
4037
}
4138

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}:
39+
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
40+
triton_asm!(
41+
{self.entrypoint()}:
5142
// _ a
5243
split // _ hi lo
5344
pop 1 // _ hi
5445
push 0 // _ hi 0
5546
eq // _ (hi == 0)
5647
return
57-
"
5848
)
5949
}
6050

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-
});
51+
fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
52+
let mut sign_offs = HashMap::new();
53+
sign_offs.insert(Reviewer("ferdinand"), 0x95dae6d2fe11abda.into());
54+
sign_offs
10155
}
10256
}
10357

10458
#[cfg(test)]
10559
mod tests {
10660
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;
61+
use crate::test_prelude::*;
11062

111-
#[test]
112-
fn is_u32_test() {
113-
test_rust_equivalence_multiple_deprecated(&IsU32, true);
114-
}
63+
impl Closure for IsU32 {
64+
type Args = BFieldElement;
11565

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();
120-
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-
}
66+
fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
67+
let value = stack.pop().unwrap();
68+
let is_u32 = u32::try_from(value).is_ok();
69+
push_encodable(stack, &is_u32);
70+
}
13471

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();
72+
fn pseudorandom_args(
73+
&self,
74+
seed: [u8; 32],
75+
bench_case: Option<BenchmarkCase>,
76+
) -> Self::Args {
77+
match bench_case {
78+
Some(BenchmarkCase::CommonCase) => bfe!(1 << 16),
79+
Some(BenchmarkCase::WorstCase) => bfe!(u32::MAX),
80+
None => StdRng::from_seed(seed).gen(),
81+
}
82+
}
13983

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-
);
84+
fn corner_case_args(&self) -> Vec<Self::Args> {
85+
bfe_vec![0, u32::MAX, u64::from(u32::MAX) + 1, BFieldElement::MAX]
14786
}
14887
}
14988

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-
);
89+
#[test]
90+
fn rust_shadow() {
91+
ShadowedClosure::new(IsU32).test();
16192
}
16293
}
16394

16495
#[cfg(test)]
16596
mod benches {
16697
use super::*;
167-
use crate::snippet_bencher::bench_and_write;
98+
use crate::test_prelude::*;
16899

169100
#[test]
170101
fn is_u32_benchmark() {
171-
bench_and_write(IsU32);
102+
ShadowedClosure::new(IsU32).bench();
172103
}
173104
}

0 commit comments

Comments
 (0)