Skip to content

Commit

Permalink
signoff: Xfe to the fourth
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-ferdinand committed Dec 9, 2024
1 parent f40dfc7 commit 11d6760
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 56 deletions.
4 changes: 2 additions & 2 deletions tasm-lib/src/arithmetic/xfe/mod_pow_u32_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl BasicSnippet for XfeModPowU32Generic {
}

#[cfg(test)]
mod tests {
pub mod tests {
use std::cell::RefCell;
use std::rc::Rc;

Expand Down Expand Up @@ -204,7 +204,7 @@ mod tests {
}

impl XfeModPowU32Generic {
fn prepare_state(&self, base: XFieldElement, exponent: u32) -> Vec<BFieldElement> {
pub fn prepare_state(&self, base: XFieldElement, exponent: u32) -> Vec<BFieldElement> {
let base = base.coefficients.into_iter().rev().collect();
[
self.init_stack_for_isolated_run(),
Expand Down
104 changes: 50 additions & 54 deletions tasm-lib/src/arithmetic/xfe/to_the_fourth.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
use std::collections::HashMap;
use triton_vm::prelude::*;

use crate::data_type::DataType;
use crate::library::Library;
use crate::traits::basic_snippet::BasicSnippet;

use crate::traits::basic_snippet::Reviewer;
use crate::traits::basic_snippet::SignOffFingerprint;

/// Take an [extension field element](XFieldElement) to the fourth power.
///
/// ### Behavior
///
/// ```text
/// BEFORE: _ [arg; 3]
/// AFTER: _ [result; 3]
/// ```
///
/// ### Preconditions
///
/// None.
///
/// ### Postconditions
///
/// - the result is the argument raised to the fourth power
pub struct ToTheFourth;

impl BasicSnippet for ToTheFourth {
Expand All @@ -19,10 +38,9 @@ impl BasicSnippet for ToTheFourth {
"tasmlib_arithmetic_xfe_to_the_fourth".to_owned()
}

fn code(&self, _library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
triton_asm!(
{entrypoint}:
{self.entrypoint()}:
dup 2
dup 2
dup 2
Expand All @@ -36,68 +54,59 @@ impl BasicSnippet for ToTheFourth {
return
)
}

fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
let mut sign_offs = HashMap::new();
sign_offs.insert(Reviewer("ferdinand"), 0x7277edad6da06ec.into());
sign_offs
}
}

#[cfg(test)]
mod tests {
use itertools::Itertools;
use num::One;
use num::Zero;
use rand::prelude::*;
use triton_vm::twenty_first::math::traits::ModPowU32;
use triton_vm::twenty_first::math::x_field_element::EXTENSION_DEGREE;

use super::*;
use crate::arithmetic::xfe::mod_pow_u32_generic::XfeModPowU32Generic;
use crate::pop_encodable;
use crate::push_encodable;
use crate::snippet_bencher::BenchmarkCase;
use crate::test_helpers::test_rust_equivalence_given_complete_state;
use crate::traits::closure::Closure;
use crate::traits::closure::ShadowedClosure;
use crate::traits::rust_shadow::RustShadow;

impl ToTheFourth {
fn setup_init_stack(&self, input_value: XFieldElement) -> Vec<BFieldElement> {
[
self.init_stack_for_isolated_run(),
input_value.encode().into_iter().rev().collect_vec(),
]
.concat()
fn setup_init_stack(&self, arg: XFieldElement) -> Vec<BFieldElement> {
let mut stack = self.init_stack_for_isolated_run();
push_encodable(&mut stack, &arg);

stack
}
}

impl Closure for ToTheFourth {
fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
let input = XFieldElement::new([
stack.pop().unwrap(),
stack.pop().unwrap(),
stack.pop().unwrap(),
]);
let result = input.mod_pow_u32(4);
for word in result.encode().into_iter().rev() {
stack.push(word)
}
let arg = pop_encodable::<XFieldElement>(stack);
push_encodable(stack, &arg.mod_pow_u32(4));
}

fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
_bench_case: Option<BenchmarkCase>,
_: Option<BenchmarkCase>,
) -> Vec<BFieldElement> {
let mut rng = StdRng::from_seed(seed);
let random_input: XFieldElement = rng.gen();

self.setup_init_stack(random_input)
self.setup_init_stack(StdRng::from_seed(seed).gen())
}

fn corner_case_initial_states(&self) -> Vec<Vec<BFieldElement>> {
let zero = self.setup_init_stack(XFieldElement::zero());
let one = self.setup_init_stack(XFieldElement::one());

let max_bfe = BFieldElement::new(BFieldElement::MAX);
let max_max_max =
self.setup_init_stack(XFieldElement::new([max_bfe; EXTENSION_DEGREE]));
let bfe_max = BFieldElement::MAX;
let xfe_max = xfe!([bfe_max, bfe_max, bfe_max]);

vec![zero, one, max_max_max]
xfe_array![0, 1, xfe_max]
.map(|arg| self.setup_init_stack(arg))
.to_vec()
}
}

Expand All @@ -108,42 +117,29 @@ mod tests {

#[test]
fn compare_to_generic_pow_u32() {
// Run `to_the_fourth` snippet
let input: XFieldElement = random();
let init_stack_to_fourth = [
ToTheFourth.init_stack_for_isolated_run(),
input.coefficients.into_iter().rev().collect_vec(),
]
.concat();
let input = random();

let final_state_from_to_fourth = test_rust_equivalence_given_complete_state(
&ShadowedClosure::new(ToTheFourth),
&init_stack_to_fourth,
&ToTheFourth.setup_init_stack(input),
&[],
&NonDeterminism::default(),
&None,
None,
);

// Run snippet for generic pow
let init_stack_to_generic = [
XfeModPowU32Generic.init_stack_for_isolated_run(),
vec![BFieldElement::new(4)],
input.coefficients.into_iter().rev().collect_vec(),
]
.concat();
let final_state_from_generic = test_rust_equivalence_given_complete_state(
&ShadowedClosure::new(XfeModPowU32Generic),
&init_stack_to_generic,
&XfeModPowU32Generic.prepare_state(input, 4),
&[],
&NonDeterminism::default(),
&None,
None,
);

// Assert that height agrees, and the top-3 elements agree
assert_eq!(
final_state_from_generic.op_stack.stack.len(),
final_state_from_to_fourth.op_stack.stack.len()
final_state_from_generic.op_stack.len(),
final_state_from_to_fourth.op_stack.len(),
);
assert_eq!(
final_state_from_generic.op_stack.stack[16..=18],
Expand Down

0 comments on commit 11d6760

Please sign in to comment.