plonky2/src/gadgets/split_join.rs

78 lines
2.3 KiB
Rust
Raw Normal View History

2021-04-21 22:31:45 +02:00
use crate::circuit_builder::CircuitBuilder;
2021-03-18 12:44:45 -07:00
use crate::field::field::Field;
use crate::generator::{SimpleGenerator, WitnessGenerator};
use crate::target::Target;
use crate::wire::Wire;
2021-03-30 20:16:20 -07:00
use crate::witness::PartialWitness;
2021-03-18 12:44:45 -07:00
2021-04-12 10:38:07 +02:00
impl<F: Field> CircuitBuilder<F> {
/// Split the given integer into a list of virtual advice targets, where each one represents a
/// bit of the integer, with little-endian ordering.
///
/// Note that this only handles witness generation; it does not enforce that the decomposition
/// is correct. The output should be treated as a "purported" decomposition which must be
/// enforced elsewhere.
2021-04-21 22:31:45 +02:00
pub(crate) fn split_le_virtual(&mut self, integer: Target, num_bits: usize) -> Vec<Target> {
2021-04-12 10:38:07 +02:00
let bit_targets = self.add_virtual_advice_targets(num_bits);
2021-04-12 10:18:16 -07:00
self.add_generator(SplitGenerator { integer, bits: bit_targets.clone() });
2021-04-12 10:38:07 +02:00
bit_targets
}
}
2021-03-18 12:44:45 -07:00
/// Generator for a little-endian split.
2021-04-12 10:18:16 -07:00
#[must_use]
2021-03-18 12:44:45 -07:00
pub fn split_le_generator<F: Field>(
integer: Target,
bits: Vec<Target>,
) -> Box<dyn WitnessGenerator<F>> {
Box::new(SplitGenerator { integer, bits })
}
/// Generator for a little-endian split.
2021-04-12 10:18:16 -07:00
#[must_use]
2021-03-18 12:44:45 -07:00
pub fn split_le_generator_local_wires<F: Field>(
gate: usize,
integer_input_index: usize,
bit_input_indices: &[usize],
) -> Box<dyn WitnessGenerator<F>> {
2021-04-21 22:31:45 +02:00
let integer = Target::Wire(Wire {
gate,
input: integer_input_index,
});
let bits = bit_input_indices
.iter()
2021-03-18 12:44:45 -07:00
.map(|&input| Target::Wire(Wire { gate, input }))
.collect();
Box::new(SplitGenerator { integer, bits })
}
2021-03-25 15:20:14 -07:00
#[derive(Debug)]
2021-03-18 12:44:45 -07:00
struct SplitGenerator {
integer: Target,
bits: Vec<Target>,
}
impl<F: Field> SimpleGenerator<F> for SplitGenerator {
fn dependencies(&self) -> Vec<Target> {
vec![self.integer]
}
2021-03-21 11:17:00 -07:00
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
2021-03-18 12:44:45 -07:00
let mut integer_value = witness.get_target(self.integer).to_canonical_u64();
let mut result = PartialWitness::new();
for &b in &self.bits {
let b_value = integer_value & 1;
result.set_target(b, F::from_canonical_u64(b_value));
integer_value >>= 1;
}
2021-04-21 22:31:45 +02:00
debug_assert_eq!(
integer_value, 0,
"Integer too large to fit in given number of bits"
);
2021-03-18 12:44:45 -07:00
result
}
}