Skip to content

Commit

Permalink
feat: implement u32clz, u32ctz, u32clo, u32cto and ilog2 instrs (#1176)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fumuran authored and bobbinth committed Feb 26, 2024
1 parent 21bd410 commit 3a1848c
Show file tree
Hide file tree
Showing 20 changed files with 1,089 additions and 270 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Introduced the `procref.<proc_name>` assembly instruction (#1113).
- Added the ability to use constants as counters in `repeat` loops (#1124).
- All `checked` versions of the u32 instructions were removed. All `unchecked` versions were renamed: this mode specification was removed from their titles (#1115).
- Introduced the `u32clz`, `u32ctz`, `u32clo`, `u32cto` and `ilog2` assembly instructions (#1176).
- Added support for hexadecimal values in constants (#1199).
- Added the `RCombBase` instruction (#1216).

Expand Down
44 changes: 44 additions & 0 deletions assembly/src/assembler/instruction/field_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{
ZERO,
};
use crate::MAX_EXP_BITS;
use vm_core::AdviceInjector::ILog2;

/// Field element representing TWO in the base field of the VM.
const TWO: Felt = Felt::new(2);
Expand Down Expand Up @@ -235,6 +236,49 @@ fn perform_exp_for_small_power(span: &mut SpanBuilder, pow: u64) {
}
}

// LOGARITHMIC OPERATIONS
// ================================================================================================

/// Appends a sequence of operations to calculate the base 2 integer logarithm of the stack top
/// element, using non-deterministic technique (i.e. it takes help of advice provider).
///
/// This operation takes 44 VM cycles.
///
/// # Errors
/// Returns an error if the logarithm argument (top stack element) equals ZERO.
pub fn ilog2(span: &mut SpanBuilder) -> Result<Option<CodeBlock>, AssemblyError> {
span.push_advice_injector(ILog2);
span.push_op(AdvPop); // [ilog2, n, ...]

// compute the power-of-two for the value given in the advice tape (17 cycles)
span.push_op(Dup0);
append_pow2_op(span);
// => [pow2, ilog2, n, ...]

#[rustfmt::skip]
let ops = [
// split the words into u32 halves to use the bitwise operations (4 cycles)
MovUp2, U32split, MovUp2, U32split,
// => [pow2_high, pow2_low, n_high, n_low, ilog2, ...]

// only one of the two halves in pow2 has a bit set, drop the other (9 cycles)
Dup1, Eqz, Dup0, MovDn3,
// => [drop_low, pow2_high, pow2_low, drop_low, n_high, n_low, ilog2, ...]
CSwap, Drop, MovDn3, CSwap, Drop,
// => [n_half, pow2_half, ilog2, ...]

// set all bits to 1 lower than pow2_half (00010000 -> 00011111)
Swap, Pad, Incr, Incr, Mul, Pad, Incr, Neg, Add,
// => [pow2_half * 2 - 1, n_half, ilog2, ...]
Dup1, U32and,
// => [m, n_half, ilog2, ...] if ilog2 calculation was correct, m should be equal to n_half
Eq, Assert(0),
// => [ilog2, ...]
];

span.add_ops(ops)
}

// COMPARISON OPERATIONS
// ================================================================================================

Expand Down
5 changes: 5 additions & 0 deletions assembly/src/assembler/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Assembler {
Instruction::Exp => field_ops::exp(span, 64),
Instruction::ExpImm(pow) => field_ops::exp_imm(span, *pow),
Instruction::ExpBitLength(num_pow_bits) => field_ops::exp(span, *num_pow_bits),
Instruction::ILog2 => field_ops::ilog2(span),

Instruction::Not => span.add_op(Not),
Instruction::And => span.add_op(And),
Expand Down Expand Up @@ -145,6 +146,10 @@ impl Assembler {
Instruction::U32Rotr => u32_ops::u32rotr(span, None),
Instruction::U32RotrImm(v) => u32_ops::u32rotr(span, Some(*v)),
Instruction::U32Popcnt => u32_ops::u32popcnt(span),
Instruction::U32Clz => u32_ops::u32clz(span),
Instruction::U32Ctz => u32_ops::u32ctz(span),
Instruction::U32Clo => u32_ops::u32clo(span),
Instruction::U32Cto => u32_ops::u32cto(span),

Instruction::U32Lt => u32_ops::u32lt(span),
Instruction::U32Lte => u32_ops::u32lte(span),
Expand Down
Loading

0 comments on commit 3a1848c

Please sign in to comment.