diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index a7f4fcb3..5be54eeb 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2_field::extension::Extendable; use plonky2_field::packed::PackedField; use plonky2_field::types::{Field, Field64}; +use plonky2_util::log_floor; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; @@ -32,7 +33,8 @@ impl BaseSumGate { } pub fn new_from_config(config: &CircuitConfig) -> Self { - let num_limbs = F::BITS.min(config.num_routed_wires - Self::START_LIMBS); + let num_limbs = + log_floor(F::ORDER - 1, B as u64).min(config.num_routed_wires - Self::START_LIMBS); Self::new(num_limbs) } diff --git a/util/src/lib.rs b/util/src/lib.rs index 61677ff0..bbc2af98 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -38,6 +38,23 @@ pub fn log2_strict(n: usize) -> usize { res as usize } +/// Returns the largest integer `i` such that `base**i <= n`. +pub const fn log_floor(n: u64, base: u64) -> usize { + assert!(n > 0); + assert!(base > 1); + let mut i = 0; + let mut cur: u64 = 1; + loop { + let (mul, overflow) = cur.overflowing_mul(base); + if overflow || mul > n { + return i; + } else { + i += 1; + cur = mul; + } + } +} + /// Permutes `arr` such that each index is mapped to its reverse in binary. pub fn reverse_index_bits(arr: &[T]) -> Vec { let n = arr.len();