2021-06-04 16:02:48 +02:00
|
|
|
use crate::circuit_builder::CircuitBuilder;
|
|
|
|
|
use crate::field::extension_field::Extendable;
|
2021-06-14 10:33:38 +02:00
|
|
|
use crate::gates::base_sum::BaseSumGate;
|
2021-06-04 16:02:48 +02:00
|
|
|
use crate::target::Target;
|
2021-06-14 10:33:38 +02:00
|
|
|
use crate::util::ceil_div_usize;
|
2021-06-04 16:02:48 +02:00
|
|
|
|
|
|
|
|
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
2021-06-09 17:39:45 +02:00
|
|
|
/// Split the given element into a list of targets, where each one represents a
|
|
|
|
|
/// base-B limb of the element, with little-endian ordering.
|
2021-06-10 16:48:05 +02:00
|
|
|
pub(crate) fn split_le_base<const B: usize>(
|
|
|
|
|
&mut self,
|
|
|
|
|
x: Target,
|
|
|
|
|
num_limbs: usize,
|
|
|
|
|
) -> Vec<Target> {
|
2021-06-04 17:07:14 +02:00
|
|
|
let gate = self.add_gate(BaseSumGate::<B>::new(num_limbs), vec![]);
|
2021-06-09 17:39:45 +02:00
|
|
|
let sum = Target::wire(gate, BaseSumGate::<B>::WIRE_SUM);
|
2021-06-04 16:02:48 +02:00
|
|
|
self.route(x, sum);
|
2021-06-09 10:51:50 +02:00
|
|
|
|
|
|
|
|
Target::wires_from_range(
|
|
|
|
|
gate,
|
2021-06-15 19:13:15 +02:00
|
|
|
BaseSumGate::<B>::START_LIMBS..BaseSumGate::<B>::START_LIMBS + num_limbs,
|
2021-06-09 10:51:50 +02:00
|
|
|
)
|
2021-06-04 16:02:48 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-17 09:49:41 +02:00
|
|
|
/// Asserts that `x`'s big-endian bit representation has at least `leading_zeros` leading zeros.
|
|
|
|
|
pub(crate) fn assert_leading_zeros(&mut self, x: Target, leading_zeros: u32) {
|
|
|
|
|
self.range_check(x, (64 - leading_zeros) as usize);
|
2021-06-04 16:02:48 +02:00
|
|
|
}
|
2021-06-09 17:39:45 +02:00
|
|
|
|
|
|
|
|
pub(crate) fn reverse_bits<const B: usize>(&mut self, x: Target, num_limbs: usize) -> Target {
|
|
|
|
|
let gate = self.add_gate(BaseSumGate::<B>::new(num_limbs), vec![]);
|
|
|
|
|
let sum = Target::wire(gate, BaseSumGate::<B>::WIRE_SUM);
|
|
|
|
|
self.route(x, sum);
|
|
|
|
|
|
|
|
|
|
Target::wire(gate, BaseSumGate::<B>::WIRE_REVERSED_SUM)
|
|
|
|
|
}
|
2021-06-04 16:02:48 +02:00
|
|
|
}
|
2021-06-04 17:07:14 +02:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use crate::circuit_data::CircuitConfig;
|
|
|
|
|
use crate::field::crandall_field::CrandallField;
|
2021-06-14 10:37:02 +02:00
|
|
|
use crate::field::field::Field;
|
|
|
|
|
use crate::witness::PartialWitness;
|
2021-06-04 17:07:14 +02:00
|
|
|
|
|
|
|
|
#[test]
|
2021-06-10 16:48:05 +02:00
|
|
|
fn test_split_base() {
|
2021-06-04 17:07:14 +02:00
|
|
|
type F = CrandallField;
|
2021-06-11 09:44:19 +02:00
|
|
|
let config = CircuitConfig::large_config();
|
2021-06-04 17:07:14 +02:00
|
|
|
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
2021-06-10 16:48:05 +02:00
|
|
|
let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6.
|
2021-06-04 17:07:14 +02:00
|
|
|
let xt = builder.constant(x);
|
2021-06-10 16:48:05 +02:00
|
|
|
let limbs = builder.split_le_base::<6>(xt, 24);
|
2021-06-04 17:07:14 +02:00
|
|
|
let one = builder.one();
|
|
|
|
|
let two = builder.two();
|
2021-06-10 16:48:05 +02:00
|
|
|
let three = builder.constant(F::from_canonical_u64(3));
|
|
|
|
|
let five = builder.constant(F::from_canonical_u64(5));
|
2021-06-16 08:15:44 +02:00
|
|
|
builder.route(limbs[0], two);
|
|
|
|
|
builder.route(limbs[1], three);
|
|
|
|
|
builder.route(limbs[2], five);
|
|
|
|
|
builder.route(limbs[3], one);
|
|
|
|
|
let rev = builder.constant(F::from_canonical_u64(11));
|
|
|
|
|
let revt = builder.reverse_bits::<2>(xt, 9);
|
|
|
|
|
builder.route(revt, rev);
|
2021-06-04 17:07:14 +02:00
|
|
|
|
2021-06-17 09:49:41 +02:00
|
|
|
builder.assert_leading_zeros(xt, 64 - 9);
|
2021-06-04 17:07:14 +02:00
|
|
|
let data = builder.build();
|
|
|
|
|
|
|
|
|
|
let proof = data.prove(PartialWitness::new());
|
|
|
|
|
}
|
|
|
|
|
}
|