mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
Better fixed-base exponentiation and exp_power_of_2 (#340)
Saves 84 gates with `num_routed_wires: 48`.
This commit is contained in:
parent
1450ffb29c
commit
75fe5686a2
@ -33,14 +33,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
let g = F::primitive_root_of_unity(arity_bits);
|
||||
let g_inv = g.exp_u64((arity as u64) - 1);
|
||||
let g_inv_t = self.constant(g_inv);
|
||||
|
||||
// The evaluation vector needs to be reordered first.
|
||||
let mut evals = evals.to_vec();
|
||||
reverse_index_bits_in_place(&mut evals);
|
||||
// Want `g^(arity - rev_x_index_within_coset)` as in the out-of-circuit version. Compute it
|
||||
// as `(g^-1)^rev_x_index_within_coset`.
|
||||
let start = self.exp_from_bits(g_inv_t, x_index_within_coset_bits.iter().rev());
|
||||
let start = self.exp_from_bits_const_base(g_inv, x_index_within_coset_bits.iter().rev());
|
||||
let coset_start = self.mul(start, x);
|
||||
|
||||
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
|
||||
@ -334,9 +333,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
|
||||
let (mut subgroup_x, vanish_zeta) = with_context!(self, "compute x from its index", {
|
||||
let g = self.constant(F::coset_shift());
|
||||
let phi = self.constant(F::primitive_root_of_unity(n_log));
|
||||
|
||||
let phi = self.exp_from_bits(phi, x_index_bits.iter().rev());
|
||||
let phi = F::primitive_root_of_unity(n_log);
|
||||
let phi = self.exp_from_bits_const_base(phi, x_index_bits.iter().rev());
|
||||
let g_ext = self.convert_to_ext(g);
|
||||
let phi_ext = self.convert_to_ext(phi);
|
||||
// `subgroup_x = g*phi, vanish_zeta = g*phi - zeta`
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::gates::exponentiation::ExponentiationGate;
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -115,7 +116,16 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
/// Exponentiate `base` to the power of `2^power_log`.
|
||||
pub fn exp_power_of_2(&mut self, base: Target, power_log: usize) -> Target {
|
||||
self.exp_u64(base, 1 << power_log)
|
||||
if power_log > ArithmeticExtensionGate::<D>::new_from_config(&self.config).num_ops {
|
||||
// Cheaper to just use `ExponentiateGate`.
|
||||
return self.exp_u64(base, 1 << power_log);
|
||||
}
|
||||
|
||||
let mut product = base;
|
||||
for _ in 0..power_log {
|
||||
product = self.square(product);
|
||||
}
|
||||
product
|
||||
}
|
||||
|
||||
// TODO: Test
|
||||
@ -151,6 +161,39 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.exp_from_bits(base, exponent_bits.iter())
|
||||
}
|
||||
|
||||
/// Like `exp_from_bits` but with a constant base.
|
||||
pub fn exp_from_bits_const_base(
|
||||
&mut self,
|
||||
base: F,
|
||||
exponent_bits: impl IntoIterator<Item = impl Borrow<BoolTarget>>,
|
||||
) -> Target {
|
||||
let base_t = self.constant(base);
|
||||
let exponent_bits: Vec<_> = exponent_bits.into_iter().map(|b| *b.borrow()).collect();
|
||||
|
||||
if exponent_bits.len() > ArithmeticExtensionGate::<D>::new_from_config(&self.config).num_ops
|
||||
{
|
||||
// Cheaper to just use `ExponentiateGate`.
|
||||
return self.exp_from_bits(base_t, exponent_bits);
|
||||
}
|
||||
|
||||
let mut product = self.one();
|
||||
for (i, bit) in exponent_bits.iter().enumerate() {
|
||||
let pow = 1 << i;
|
||||
// If the bit is on, we multiply product by base^pow.
|
||||
// We can arithmetize this as:
|
||||
// product *= 1 + bit (base^pow - 1)
|
||||
// product = (base^pow - 1) product bit + product
|
||||
product = self.arithmetic(
|
||||
base.exp_u64(pow as u64) - F::ONE,
|
||||
F::ONE,
|
||||
product,
|
||||
bit.target,
|
||||
product,
|
||||
)
|
||||
}
|
||||
product
|
||||
}
|
||||
|
||||
/// Exponentiate `base` to the power of a known `exponent`.
|
||||
// TODO: Test
|
||||
pub fn exp_u64(&mut self, base: Target, mut exponent: u64) -> Target {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user