Test rotate gadget

This commit is contained in:
wborgeaud 2021-06-11 09:59:55 +02:00
parent 1eb372326a
commit 4106a47ded
3 changed files with 52 additions and 12 deletions

View File

@ -19,10 +19,12 @@ impl<const D: usize> ExtensionTarget<D> {
pub fn frobenius<F: Extendable<D>>(&self, builder: &mut CircuitBuilder<F, D>) -> Self {
let arr = self.to_target_array();
let k = (F::ORDER - 1) / (D as u64);
let zs = (0..D as u64).map(|i| builder.constant(F::Extension::W.exp(k * i)));
let zs = (0..D as u64)
.map(|i| builder.constant(F::Extension::W.exp(k * i)))
.collect::<Vec<_>>();
let mut res = Vec::with_capacity(D);
for (z, a) in zs.zip(arr) {
for (z, a) in zs.into_iter().zip(arr) {
res.push(builder.mul(z, a));
}

View File

@ -16,8 +16,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
/// Left-rotates an array `k` times if `b=1` else return the same array.
pub fn rotate_fixed(&mut self, b: Target, k: usize, v: Vec<Target>, len: usize) -> Vec<Target> {
debug_assert_eq!(v.len(), len);
pub fn rotate_fixed(&mut self, b: Target, k: usize, v: &[Target], len: usize) -> Vec<Target> {
let mut res = Vec::new();
for i in 0..len {
@ -30,13 +29,56 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Left-rotates an array by `num_rotation`. Assumes that `num_rotation` is range-checked to be
/// less than `len`.
/// Note: We assume `len` is less than 8 since we won't use any arity greater than 8 in FRI (maybe?).
pub fn rotate(&mut self, num_rotation: Target, mut v: Vec<Target>, len: usize) -> Vec<Target> {
pub fn rotate(&mut self, num_rotation: Target, v: &[Target], len: usize) -> Vec<Target> {
debug_assert_eq!(v.len(), len);
let bits = self.split_le_base::<2>(num_rotation, 3);
v = self.rotate_fixed(bits[0], 1, v, len);
v = self.rotate_fixed(bits[1], 2, v, len);
v = self.rotate_fixed(bits[2], 4, v, len);
let v = self.rotate_fixed(bits[0], 1, v, len);
let v = self.rotate_fixed(bits[1], 2, &v, len);
let v = self.rotate_fixed(bits[2], 4, &v, len);
v
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::circuit_data::CircuitConfig;
use crate::field::crandall_field::CrandallField;
fn real_rotate(num_rotation: usize, v: &[Target]) -> Vec<Target> {
let mut res = v.to_vec();
res.rotate_left(num_rotation);
res
}
fn test_rotate_given_len(len: usize) {
type F = CrandallField;
let config = CircuitConfig::large_config();
let mut builder = CircuitBuilder::<F, 4>::new(config);
let v = (0..len)
.map(|_| builder.constant(F::rand()))
.collect::<Vec<_>>(); // 416 = 1532 in base 6.
for i in 0..len {
let it = builder.constant(F::from_canonical_usize(i));
let rotated = real_rotate(i, &v);
let purported_rotated = builder.rotate(it, &v, len);
for (x, y) in rotated.into_iter().zip(purported_rotated) {
builder.assert_equal(x, y);
}
}
let data = builder.build();
let proof = data.prove(PartialWitness::new());
}
#[test]
fn test_rotate() {
for i_log in 1..4 {
test_rotate_given_len(1 << i_log);
}
}
}

View File

@ -71,10 +71,6 @@ mod tests {
use super::*;
use crate::circuit_data::CircuitConfig;
use crate::field::crandall_field::CrandallField;
use crate::fri::FriConfig;
use crate::prover::PLONK_BLINDING;
use crate::verifier::verify;
use anyhow::Result;
#[test]
fn test_split_base() {