Skip to content

Commit

Permalink
cache limbs to avoid conversion multiple time
Browse files Browse the repository at this point in the history
  • Loading branch information
hero78119 committed Sep 5, 2024
1 parent cb23b25 commit d4eb57e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
11 changes: 4 additions & 7 deletions ceno_zkvm/src/instructions/riscv/addsub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,17 @@ impl<E: ExtensionField> Instruction<E> for AddInstruction {
// TODO use fields from step
set_val!(instance, config.pc, 1);
set_val!(instance, config.ts, 2);
let addend_0 = UIntValue(step.rs1().unwrap().value);
let addend_1 = UIntValue(step.rs2().unwrap().value);
let addend_0 = UIntValue::new(step.rs1().unwrap().value);
let addend_1 = UIntValue::new(step.rs2().unwrap().value);
config
.prev_rd_value
.assign_limbs(instance, [0, 0].iter().map(E::BaseField::from).collect());
config
.addend_0
.assign_limbs(instance, addend_0.as_u16_fields());
.assign_limbs(instance, addend_0.u16_fields());
config
.addend_1
.assign_limbs(instance, addend_1.as_u16_fields());
.assign_limbs(instance, addend_1.u16_fields());
let carries = addend_0.add_u16_carries(&addend_1);
config.outcome.assign_carries(
instance,
Expand Down Expand Up @@ -234,9 +234,6 @@ impl<E: ExtensionField> Instruction<E> for SubInstruction {

#[cfg(test)]
mod test {

use std::u32;

use ceno_emul::{ReadOp, StepRecord};
use goldilocks::GoldilocksExt2;
use itertools::Itertools;
Expand Down
37 changes: 23 additions & 14 deletions ceno_zkvm/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,22 @@ impl<E: ExtensionField, const M: usize, const C: usize> ToExpr<E> for UInt<M, C,
}
}

pub struct UIntValue<T: Into<u64> + Copy>(pub T);
pub struct UIntValue<T: Into<u64> + Copy> {
#[allow(dead_code)]
val: T,
pub limbs: Vec<u16>,
}

// TODO generalize to support non 16 bit limbs
// TODO optimize api with fixed size array
impl<T: Into<u64> + Copy> UIntValue<T> {
pub fn new(val: T) -> Self {
UIntValue::<T> {
val,
limbs: Self::split_to_u16(val),
}
}

fn split_to_u16(value: T) -> Vec<u16> {
let mut limbs = Vec::new();
let value: u64 = value.into(); // Convert to u64 for generality
Expand All @@ -477,31 +489,28 @@ impl<T: Into<u64> + Copy> UIntValue<T> {
limbs
}

pub fn as_u16_limbs(&self) -> Vec<u16> {
Self::split_to_u16(self.0)
pub fn as_u16_limbs(&self) -> &[u16] {
&self.limbs
}

pub fn as_u16_fields<F: SmallField>(&self) -> Vec<F> {
Self::split_to_u16(self.0)
.into_iter()
.map(|v| F::from(v as u64))
.collect_vec()
pub fn u16_fields<F: SmallField>(&self) -> Vec<F> {
self.limbs.iter().map(|v| F::from(*v as u64)).collect_vec()
}

pub fn add_u16_carries(&self, rhs: &Self) -> Vec<bool> {
self.as_u16_limbs()
.into_iter()
.zip(rhs.as_u16_limbs())
.fold(vec![], |mut acc, (a_limb, b_limb)| {
let (a, b) = a_limb.overflowing_add(b_limb);
self.as_u16_limbs().iter().zip(rhs.as_u16_limbs()).fold(
vec![],
|mut acc, (a_limb, b_limb)| {
let (a, b) = a_limb.overflowing_add(*b_limb);
if let Some(prev_carry) = acc.last() {
let (_, d) = a.overflowing_add(*prev_carry as u16);
acc.push(b || d);
} else {
acc.push(b);
}
acc
})
},
)
}
}

Expand Down

0 comments on commit d4eb57e

Please sign in to comment.