tasm_lib/arithmetic/xfe/
to_the_power_of_power_of_2.rsuse triton_vm::prelude::*;
use crate::data_type::DataType;
use crate::library::Library;
use crate::traits::basic_snippet::BasicSnippet;
pub struct ToThePowerOfPowerOf2;
impl BasicSnippet for ToThePowerOfPowerOf2 {
fn inputs(&self) -> Vec<(DataType, String)> {
vec![
(DataType::U32, "log_2_exponent".to_owned()),
(DataType::Xfe, "base".to_owned()),
]
}
fn outputs(&self) -> Vec<(DataType, String)> {
vec![(DataType::Xfe, "result".to_owned())]
}
fn entrypoint(&self) -> String {
"tasmlib_arithmetic_xfe_to_the_power_of_power_of_2".to_owned()
}
fn code(&self, _library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();
let loop_label = format!("{}_loop", entrypoint);
let loop_code = triton_asm!(
{loop_label}:
dup 3
push 0
eq
skiz
return
dup 2
dup 2
dup 2
xx_mul
swap 3
push -1
add
swap 3
recurse
);
triton_asm!(
{entrypoint}:
call {loop_label}
swap 1
swap 2
swap 3
pop 1
return
{&loop_code}
)
}
}
#[cfg(test)]
mod tests {
use itertools::Itertools;
use rand::prelude::*;
use triton_vm::prelude::*;
use triton_vm::twenty_first::math::traits::ModPowU32;
use super::*;
use crate::arithmetic::xfe::mod_pow_u32_generic::XfeModPowU32Generic;
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 Closure for ToThePowerOfPowerOf2 {
fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
let base = XFieldElement::new([
stack.pop().unwrap(),
stack.pop().unwrap(),
stack.pop().unwrap(),
]);
let exponent_log_2: u32 = stack.pop().unwrap().try_into().unwrap();
let result = base.mod_pow_u32(2u32.pow(exponent_log_2));
for elem in result.coefficients.into_iter().rev() {
stack.push(elem);
}
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
bench_case: Option<crate::snippet_bencher::BenchmarkCase>,
) -> Vec<BFieldElement> {
let mut rng: StdRng = SeedableRng::from_seed(seed);
let exponent = match bench_case {
Some(BenchmarkCase::CommonCase) => 20,
Some(BenchmarkCase::WorstCase) => 31,
None => rng.gen_range(0..32),
};
let base: XFieldElement = rng.gen();
self.prepare_state(base, exponent)
}
fn corner_case_initial_states(&self) -> Vec<Vec<BFieldElement>> {
let bfe_14 = BFieldElement::new(14);
let an_xfe = XFieldElement::new([bfe_14, bfe_14, bfe_14]);
(0..=5)
.chain([30, 31])
.map(|log_2_exp| self.prepare_state(an_xfe, log_2_exp))
.collect_vec()
}
}
impl ToThePowerOfPowerOf2 {
fn prepare_state(&self, base: XFieldElement, log_2_exp: u32) -> Vec<BFieldElement> {
let base = base.coefficients.into_iter().rev().collect();
[
self.init_stack_for_isolated_run(),
vec![BFieldElement::new(log_2_exp as u64)],
base,
]
.concat()
}
}
#[test]
fn to_the_power_of_power_of_2_pbt() {
ShadowedClosure::new(ToThePowerOfPowerOf2).test()
}
#[test]
fn compare_to_generic_pow_u32() {
let base: XFieldElement = random();
for log_2_exponent in 0..32 {
let init_stack_pow_pow = [
ToThePowerOfPowerOf2.init_stack_for_isolated_run(),
vec![BFieldElement::new(log_2_exponent)],
base.coefficients.into_iter().rev().collect_vec(),
]
.concat();
let final_state_pow_pow = test_rust_equivalence_given_complete_state(
&ShadowedClosure::new(ToThePowerOfPowerOf2),
&init_stack_pow_pow,
&[],
&NonDeterminism::default(),
&None,
None,
);
let init_stack_to_generic = [
XfeModPowU32Generic.init_stack_for_isolated_run(),
vec![BFieldElement::new(
2u64.pow(log_2_exponent.try_into().unwrap()),
)],
base.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,
&[],
&NonDeterminism::default(),
&None,
None,
);
assert_eq!(
final_state_from_generic.op_stack.stack.len(),
final_state_pow_pow.op_stack.stack.len()
);
assert_eq!(
final_state_from_generic.op_stack.stack[16..=18],
final_state_pow_pow.op_stack.stack[16..=18],
);
}
}
}
#[cfg(test)]
mod benches {
use super::*;
use crate::traits::closure::ShadowedClosure;
use crate::traits::rust_shadow::RustShadow;
#[test]
fn xfe_mod_pow_benchmark() {
ShadowedClosure::new(ToThePowerOfPowerOf2).bench();
}
}