mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Have le_sum use arithmetic ops if it's cheaper (#362)
* Have le_sum use arithmetic ops if it's cheaper * fmt
This commit is contained in:
parent
7185c2d7d2
commit
efab3177ce
@ -215,7 +215,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
|
|
||||||
/// Exponentiate `base` to the power of `2^power_log`.
|
/// Exponentiate `base` to the power of `2^power_log`.
|
||||||
pub fn exp_power_of_2(&mut self, base: Target, power_log: usize) -> Target {
|
pub fn exp_power_of_2(&mut self, base: Target, power_log: usize) -> Target {
|
||||||
if power_log > ArithmeticGate::new_from_config(&self.config).num_ops {
|
if power_log > self.num_base_arithmetic_ops_per_gate() {
|
||||||
// Cheaper to just use `ExponentiateGate`.
|
// Cheaper to just use `ExponentiateGate`.
|
||||||
return self.exp_u64(base, 1 << power_log);
|
return self.exp_u64(base, 1 << power_log);
|
||||||
}
|
}
|
||||||
@ -269,7 +269,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
let base_t = self.constant(base);
|
let base_t = self.constant(base);
|
||||||
let exponent_bits: Vec<_> = exponent_bits.into_iter().map(|b| *b.borrow()).collect();
|
let exponent_bits: Vec<_> = exponent_bits.into_iter().map(|b| *b.borrow()).collect();
|
||||||
|
|
||||||
if exponent_bits.len() > ArithmeticGate::new_from_config(&self.config).num_ops {
|
if exponent_bits.len() > self.num_base_arithmetic_ops_per_gate() {
|
||||||
// Cheaper to just use `ExponentiateGate`.
|
// Cheaper to just use `ExponentiateGate`.
|
||||||
return self.exp_from_bits(base_t, exponent_bits);
|
return self.exp_from_bits(base_t, exponent_bits);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::field::extension_field::Extendable;
|
use crate::field::extension_field::Extendable;
|
||||||
use crate::field::field_types::{Field, RichField};
|
use crate::field::field_types::{Field, RichField};
|
||||||
use crate::gates::base_sum::BaseSumGate;
|
use crate::gates::base_sum::BaseSumGate;
|
||||||
@ -29,21 +31,26 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
/// the number with little-endian bit representation given by `bits`.
|
/// the number with little-endian bit representation given by `bits`.
|
||||||
pub(crate) fn le_sum(
|
pub(crate) fn le_sum(
|
||||||
&mut self,
|
&mut self,
|
||||||
bits: impl ExactSizeIterator<Item = impl Borrow<BoolTarget>> + Clone,
|
mut bits: impl Iterator<Item = impl Borrow<BoolTarget>>,
|
||||||
) -> Target {
|
) -> Target {
|
||||||
|
let bits = bits.map(|b| *b.borrow()).collect_vec();
|
||||||
let num_bits = bits.len();
|
let num_bits = bits.len();
|
||||||
if num_bits == 0 {
|
if num_bits == 0 {
|
||||||
return self.zero();
|
return self.zero();
|
||||||
} else if num_bits == 1 {
|
|
||||||
let mut bits = bits;
|
|
||||||
return bits.next().unwrap().borrow().target;
|
|
||||||
} else if num_bits == 2 {
|
|
||||||
let two = self.two();
|
|
||||||
let mut bits = bits;
|
|
||||||
let b0 = bits.next().unwrap().borrow().target;
|
|
||||||
let b1 = bits.next().unwrap().borrow().target;
|
|
||||||
return self.mul_add(two, b1, b0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if it's cheaper to just do this with arithmetic operations.
|
||||||
|
let arithmetic_ops = num_bits - 1;
|
||||||
|
if arithmetic_ops <= self.num_base_arithmetic_ops_per_gate() {
|
||||||
|
let two = self.two();
|
||||||
|
let mut rev_bits = bits.iter().rev();
|
||||||
|
let mut sum = rev_bits.next().unwrap().target;
|
||||||
|
for &bit in rev_bits {
|
||||||
|
sum = self.mul_add(two, sum, bit.target);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
BaseSumGate::<2>::START_LIMBS + num_bits <= self.config.num_routed_wires,
|
BaseSumGate::<2>::START_LIMBS + num_bits <= self.config.num_routed_wires,
|
||||||
"Not enough routed wires."
|
"Not enough routed wires."
|
||||||
@ -51,10 +58,10 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
let gate_type = BaseSumGate::<2>::new_from_config::<F>(&self.config);
|
let gate_type = BaseSumGate::<2>::new_from_config::<F>(&self.config);
|
||||||
let gate_index = self.add_gate(gate_type, vec![]);
|
let gate_index = self.add_gate(gate_type, vec![]);
|
||||||
for (limb, wire) in bits
|
for (limb, wire) in bits
|
||||||
.clone()
|
.iter()
|
||||||
.zip(BaseSumGate::<2>::START_LIMBS..BaseSumGate::<2>::START_LIMBS + num_bits)
|
.zip(BaseSumGate::<2>::START_LIMBS..BaseSumGate::<2>::START_LIMBS + num_bits)
|
||||||
{
|
{
|
||||||
self.connect(limb.borrow().target, Target::wire(gate_index, wire));
|
self.connect(limb.target, Target::wire(gate_index, wire));
|
||||||
}
|
}
|
||||||
for l in gate_type.limbs().skip(num_bits) {
|
for l in gate_type.limbs().skip(num_bits) {
|
||||||
self.assert_zero(Target::wire(gate_index, l));
|
self.assert_zero(Target::wire(gate_index, l));
|
||||||
@ -62,7 +69,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
|
|
||||||
self.add_simple_generator(BaseSumGenerator::<2> {
|
self.add_simple_generator(BaseSumGenerator::<2> {
|
||||||
gate_index,
|
gate_index,
|
||||||
limbs: bits.map(|l| *l.borrow()).collect(),
|
limbs: bits,
|
||||||
});
|
});
|
||||||
|
|
||||||
Target::wire(gate_index, BaseSumGate::<2>::WIRE_SUM)
|
Target::wire(gate_index, BaseSumGate::<2>::WIRE_SUM)
|
||||||
|
|||||||
@ -379,6 +379,20 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of (base field) `arithmetic` operations that can be performed in a single gate.
|
||||||
|
pub(crate) fn num_base_arithmetic_ops_per_gate(&self) -> usize {
|
||||||
|
if self.config.use_base_arithmetic_gate {
|
||||||
|
ArithmeticGate::new_from_config(&self.config).num_ops
|
||||||
|
} else {
|
||||||
|
self.num_ext_arithmetic_ops_per_gate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The number of `arithmetic_extension` operations that can be performed in a single gate.
|
||||||
|
pub(crate) fn num_ext_arithmetic_ops_per_gate(&self) -> usize {
|
||||||
|
ArithmeticExtensionGate::<D>::new_from_config(&self.config).num_ops
|
||||||
|
}
|
||||||
|
|
||||||
/// The number of polynomial values that will be revealed per opening, both for the "regular"
|
/// The number of polynomial values that will be revealed per opening, both for the "regular"
|
||||||
/// polynomials and for the Z polynomials. Because calculating these values involves a recursive
|
/// polynomials and for the Z polynomials. Because calculating these values involves a recursive
|
||||||
/// dependence (the amount of blinding depends on the degree, which depends on the blinding),
|
/// dependence (the amount of blinding depends on the degree, which depends on the blinding),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user