plonky2/src/gadgets/range_check.rs

67 lines
2.2 KiB
Rust
Raw Normal View History

2021-06-10 15:55:29 +02:00
use crate::field::extension_field::Extendable;
use crate::field::field_types::RichField;
2021-08-20 09:55:49 +02:00
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target};
2021-08-20 11:13:40 +02:00
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
2021-06-10 15:55:29 +02:00
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
2021-06-10 15:55:29 +02:00
/// Checks that `x < 2^n_log` using a `BaseSumGate`.
pub fn range_check(&mut self, x: Target, n_log: usize) {
2021-10-21 12:56:02 +02:00
self.split_le(x, n_log);
2021-06-10 15:55:29 +02:00
}
2021-07-23 08:15:13 +02:00
/// Returns the first `num_low_bits` little-endian bits of `x`.
pub fn low_bits(&mut self, x: Target, num_low_bits: usize, num_bits: usize) -> Vec<BoolTarget> {
2021-07-22 15:10:55 +02:00
let mut res = self.split_le(x, num_bits);
2021-07-23 08:15:13 +02:00
res.truncate(num_low_bits);
2021-07-22 15:10:55 +02:00
res
}
2021-06-10 15:55:29 +02:00
/// Returns `(a,b)` such that `x = a + 2^n_log * b` with `a < 2^n_log`.
2021-06-16 08:40:28 +02:00
/// `x` is assumed to be range-checked for having `num_bits` bits.
pub fn split_low_high(&mut self, x: Target, n_log: usize, num_bits: usize) -> (Target, Target) {
let low = self.add_virtual_target();
let high = self.add_virtual_target();
2021-09-02 15:03:03 -07:00
self.add_simple_generator(LowHighGenerator {
2021-06-10 15:55:29 +02:00
integer: x,
n_log,
low,
high,
});
self.range_check(low, n_log);
self.range_check(high, num_bits - n_log);
2021-06-10 15:55:29 +02:00
let pow2 = self.constant(F::from_canonical_u64(1 << n_log));
let comp_x = self.mul_add(high, pow2, low);
2021-08-24 08:25:11 +02:00
self.connect(x, comp_x);
2021-06-10 15:55:29 +02:00
(low, high)
}
}
#[derive(Debug)]
struct LowHighGenerator {
integer: Target,
n_log: usize,
low: Target,
high: Target,
}
impl<F: RichField> SimpleGenerator<F> for LowHighGenerator {
2021-06-10 15:55:29 +02:00
fn dependencies(&self) -> Vec<Target> {
vec![self.integer]
}
2021-08-20 09:55:49 +02:00
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
2021-06-16 11:37:07 +02:00
let integer_value = witness.get_target(self.integer).to_canonical_u64();
2021-06-10 15:55:29 +02:00
let low = integer_value & ((1 << self.n_log) - 1);
let high = integer_value >> self.n_log;
out_buffer.set_target(self.low, F::from_canonical_u64(low));
out_buffer.set_target(self.high, F::from_canonical_u64(high));
2021-06-10 15:55:29 +02:00
}
}