use alloc::vec::Vec;
use miden_core::{
Felt, ONE, ZERO,
field::{BasedVectorSpace, Field, QuadFelt},
program::{MIN_STACK_DEPTH, StackInputs},
};
use miden_utils_testing::rand::rand_value;
use super::{
op_add, op_and, op_eq, op_eqz, op_expacc, op_ext2mul, op_incr, op_inv, op_mul, op_neg, op_not,
op_or,
};
use crate::fast::FastProcessor;
#[test]
fn test_op_add() {
let (a, b, c) = get_rand_values();
let mut processor = FastProcessor::new(StackInputs::new(&[a, b, c]).unwrap());
op_add(&mut processor).unwrap();
let expected = build_expected(&[a + b, c]);
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::default());
op_add(&mut processor).unwrap();
}
#[test]
fn test_op_neg() {
let (a, b, c) = get_rand_values();
let mut processor = FastProcessor::new(StackInputs::new(&[a, b, c]).unwrap());
op_neg(&mut processor);
let expected = build_expected(&[-a, b, c]);
assert_eq!(expected, processor.stack_top());
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
}
#[test]
fn test_op_mul() {
let (a, b, c) = get_rand_values();
let mut processor = FastProcessor::new(StackInputs::new(&[a, b, c]).unwrap());
op_mul(&mut processor).unwrap();
let expected = build_expected(&[a * b, c]);
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::default());
op_mul(&mut processor).unwrap();
}
#[test]
fn test_op_inv() {
let (a, b, c) = get_rand_values();
let mut processor = FastProcessor::new(StackInputs::new(&[a, b, c]).unwrap());
if a != ZERO {
op_inv(&mut processor).unwrap();
let expected = build_expected(&[a.inverse(), b, c]);
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
assert_eq!(expected, processor.stack_top());
}
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO]).unwrap());
assert!(op_inv(&mut processor).is_err());
}
#[test]
fn test_op_incr() {
let (a, b, c) = get_rand_values();
let mut processor = FastProcessor::new(StackInputs::new(&[a, b, c]).unwrap());
op_incr(&mut processor);
let expected = build_expected(&[a + ONE, b, c]);
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
assert_eq!(expected, processor.stack_top());
}
#[test]
fn test_op_and() {
let two = Felt::new(2);
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, ZERO, two]).unwrap());
op_and(&mut processor).unwrap();
let expected = build_expected(&[ZERO, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, ZERO, two]).unwrap());
op_and(&mut processor).unwrap();
let expected = build_expected(&[ZERO, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, ONE, two]).unwrap());
op_and(&mut processor).unwrap();
let expected = build_expected(&[ZERO, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, ONE, two]).unwrap());
op_and(&mut processor).unwrap();
let expected = build_expected(&[ONE, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[two, ONE, two]).unwrap());
assert!(op_and(&mut processor).is_err());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, two, two]).unwrap());
assert!(op_and(&mut processor).is_err());
let mut processor = FastProcessor::new(StackInputs::default());
assert!(op_and(&mut processor).is_ok());
}
#[test]
fn test_op_or() {
let two = Felt::new(2);
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, ZERO, two]).unwrap());
op_or(&mut processor).unwrap();
let expected = build_expected(&[ZERO, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, ZERO, two]).unwrap());
op_or(&mut processor).unwrap();
let expected = build_expected(&[ONE, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, ONE, two]).unwrap());
op_or(&mut processor).unwrap();
let expected = build_expected(&[ONE, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, ONE, two]).unwrap());
op_or(&mut processor).unwrap();
let expected = build_expected(&[ONE, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[two, ONE, two]).unwrap());
assert!(op_or(&mut processor).is_err());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, two, two]).unwrap());
assert!(op_or(&mut processor).is_err());
let mut processor = FastProcessor::new(StackInputs::default());
assert!(op_or(&mut processor).is_ok());
}
#[test]
fn test_op_not() {
let two = Felt::new(2);
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, two]).unwrap());
op_not(&mut processor).unwrap();
let expected = build_expected(&[ONE, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[ONE, two]).unwrap());
op_not(&mut processor).unwrap();
let expected = build_expected(&[ZERO, two]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[two, two]).unwrap());
assert!(op_not(&mut processor).is_err());
}
#[test]
fn test_op_eq() {
let three = Felt::new(3);
let five = Felt::new(5);
let seven = Felt::new(7);
let mut processor = FastProcessor::new(StackInputs::new(&[seven, seven, three]).unwrap());
let _ = op_eq(&mut processor);
let expected = build_expected(&[ONE, three]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[seven, five, three]).unwrap());
let _ = op_eq(&mut processor);
let expected = build_expected(&[ZERO, three]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::default());
let _ = op_eq(&mut processor);
}
#[test]
fn test_op_eqz() {
let three = Felt::new(3);
let four = Felt::new(4);
let mut processor = FastProcessor::new(StackInputs::new(&[ZERO, three]).unwrap());
let _ = op_eqz(&mut processor);
let expected = build_expected(&[ONE, three]);
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::new(&[four, three]).unwrap());
let _ = op_eqz(&mut processor);
let expected = build_expected(&[ZERO, three]);
assert_eq!(expected, processor.stack_top());
}
#[test]
fn test_op_expacc() {
let old_exp = Felt::new(8);
let old_acc = Felt::new(1);
let old_base = Felt::new(0);
let new_exp = Felt::new(4);
let new_acc = Felt::new(1);
let new_base = Felt::new(0);
let mut processor =
FastProcessor::new(StackInputs::new(&[ZERO, old_base, old_acc, old_exp]).unwrap());
let _ = op_expacc(&mut processor);
let expected = build_expected(&[ZERO, new_base, new_acc, new_exp]);
assert_eq!(expected, processor.stack_top());
let old_exp = Felt::new(9);
let old_acc = Felt::new(1);
let old_base = Felt::new(0);
let new_exp = Felt::new(4);
let new_acc = Felt::new(0);
let new_base = Felt::new(0);
let mut processor =
FastProcessor::new(StackInputs::new(&[ZERO, old_base, old_acc, old_exp]).unwrap());
let _ = op_expacc(&mut processor);
let expected = build_expected(&[ONE, new_base, new_acc, new_exp]);
assert_eq!(expected, processor.stack_top());
let old_exp = Felt::new(0);
let old_acc = Felt::new(32);
let old_base = Felt::new(4);
let new_exp = Felt::new(0);
let new_acc = Felt::new(32);
let new_base = Felt::new(16);
let mut processor =
FastProcessor::new(StackInputs::new(&[ZERO, old_base, old_acc, old_exp]).unwrap());
let _ = op_expacc(&mut processor);
let expected = build_expected(&[ZERO, new_base, new_acc, new_exp]);
assert_eq!(expected, processor.stack_top());
let old_exp = Felt::new(3);
let old_acc = Felt::new(1);
let old_base = Felt::new(16);
let new_exp = Felt::new(1);
let new_acc = Felt::new(16);
let new_base = Felt::new(16 * 16);
let mut processor =
FastProcessor::new(StackInputs::new(&[ZERO, old_base, old_acc, old_exp]).unwrap());
let _ = op_expacc(&mut processor);
let expected = build_expected(&[ONE, new_base, new_acc, new_exp]);
assert_eq!(expected, processor.stack_top());
let old_exp_val = 17u64;
let old_acc_val = 5u64;
let old_base_val = u32::MAX as u64 + 1;
let new_exp = Felt::new(8);
let new_acc = Felt::new(old_acc_val * old_base_val);
let new_base = Felt::new(old_base_val) * Felt::new(old_base_val);
let mut processor = FastProcessor::new(
StackInputs::new(&[
ZERO,
Felt::new(old_base_val),
Felt::new(old_acc_val),
Felt::new(old_exp_val),
])
.unwrap(),
);
let _ = op_expacc(&mut processor);
let expected = build_expected(&[ONE, new_base, new_acc, new_exp]);
assert_eq!(expected, processor.stack_top());
}
#[test]
fn test_op_ext2mul() {
let [a0, a1, b0, b1] = [rand_value::<Felt>(); 4];
let mut processor = FastProcessor::new(StackInputs::new(&[b0, b1, a0, a1]).unwrap());
op_ext2mul(&mut processor);
let a = QuadFelt::new([a0, a1]);
let b = QuadFelt::new([b0, b1]);
let product = b * a;
let c = product.as_basis_coefficients_slice();
let expected = build_expected(&[b0, b1, c[0], c[1]]);
assert_eq!(MIN_STACK_DEPTH as u32, processor.stack_depth());
assert_eq!(expected, processor.stack_top());
let mut processor = FastProcessor::new(StackInputs::default());
op_ext2mul(&mut processor);
}
fn get_rand_values() -> (Felt, Felt, Felt) {
let a: u64 = rand_value();
let b: u64 = rand_value();
let c: u64 = rand_value();
(Felt::new(a), Felt::new(b), Felt::new(c))
}
fn build_expected(values: &[Felt]) -> Vec<Felt> {
let mut expected = vec![ZERO; 16];
for (i, &value) in values.iter().enumerate() {
expected[15 - i] = value;
}
expected
}