2021-06-14 15:15:22 +02:00
|
|
|
use crate::circuit_builder::CircuitBuilder;
|
|
|
|
|
use crate::field::extension_field::target::ExtensionTarget;
|
|
|
|
|
use crate::field::extension_field::Extendable;
|
|
|
|
|
use crate::target::Target;
|
|
|
|
|
|
|
|
|
|
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
2021-06-30 07:08:36 -07:00
|
|
|
/// Evaluates to 1 if `x` and `y` are equal, 0 otherwise.
|
|
|
|
|
pub fn is_equal(
|
|
|
|
|
&mut self,
|
|
|
|
|
x: Target,
|
|
|
|
|
y: Target,
|
|
|
|
|
) -> Target {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-14 15:15:22 +02:00
|
|
|
/// Inserts a `Target` in a vector at a non-deterministic index. This is done by rotating to the
|
|
|
|
|
/// left, inserting at 0 and then rotating to the right.
|
|
|
|
|
/// Note: `index` is not range-checked.
|
|
|
|
|
pub fn insert(
|
|
|
|
|
&mut self,
|
|
|
|
|
index: Target,
|
|
|
|
|
element: ExtensionTarget<D>,
|
2021-06-16 11:37:07 +02:00
|
|
|
v: Vec<ExtensionTarget<D>>,
|
2021-06-14 15:15:22 +02:00
|
|
|
) -> Vec<ExtensionTarget<D>> {
|
2021-06-30 07:08:36 -07:00
|
|
|
let mut already_inserted = self.zero();
|
|
|
|
|
let mut new_list = Vec::new();
|
|
|
|
|
|
|
|
|
|
let mut cur_index = self.zero();
|
|
|
|
|
for i in 0..v.len() {
|
|
|
|
|
cur_index = self.add(cur_index, self.one());
|
|
|
|
|
let insert_here = self.is_equal(cur_index, index);
|
|
|
|
|
|
|
|
|
|
let mut new_item = self.zero();
|
|
|
|
|
new_item = self.add(new_item, self.mul(insert_here, element));
|
|
|
|
|
new_item = self.add(new_item, self.mul(already_inserted, v[i-1]));
|
|
|
|
|
already_inserted = self.add(already_inserted, insert_here);
|
|
|
|
|
new_item = self.add(new_item, self.mul(self.sub(self.one(), already_inserted), v[i]));
|
|
|
|
|
|
|
|
|
|
new_list.push(new_item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_list
|
2021-06-16 10:43:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use crate::circuit_data::CircuitConfig;
|
|
|
|
|
use crate::field::crandall_field::CrandallField;
|
|
|
|
|
use crate::field::extension_field::quartic::QuarticCrandallField;
|
|
|
|
|
use crate::field::field::Field;
|
|
|
|
|
use crate::witness::PartialWitness;
|
|
|
|
|
|
|
|
|
|
fn real_insert<const D: usize>(
|
|
|
|
|
index: usize,
|
|
|
|
|
element: ExtensionTarget<D>,
|
|
|
|
|
v: &[ExtensionTarget<D>],
|
|
|
|
|
) -> Vec<ExtensionTarget<D>> {
|
|
|
|
|
let mut res = v.to_vec();
|
|
|
|
|
res.insert(index, element);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn test_insert_given_len(len_log: usize) {
|
|
|
|
|
type F = CrandallField;
|
|
|
|
|
type FF = QuarticCrandallField;
|
|
|
|
|
let len = 1 << len_log;
|
|
|
|
|
let config = CircuitConfig::large_config();
|
|
|
|
|
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
|
|
|
|
let v = (0..len - 1)
|
|
|
|
|
.map(|_| builder.constant_extension(FF::rand()))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
for i in 0..len {
|
|
|
|
|
let it = builder.constant(F::from_canonical_usize(i));
|
|
|
|
|
let elem = builder.constant_extension(FF::rand());
|
|
|
|
|
let inserted = real_insert(i, elem, &v);
|
|
|
|
|
let purported_inserted = builder.insert(it, elem, v.clone());
|
|
|
|
|
|
|
|
|
|
for (x, y) in inserted.into_iter().zip(purported_inserted) {
|
|
|
|
|
builder.route_extension(x, y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let data = builder.build();
|
|
|
|
|
let proof = data.prove(PartialWitness::new());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_insert() {
|
|
|
|
|
for len_log in 1..3 {
|
|
|
|
|
test_insert_given_len(len_log);
|
|
|
|
|
}
|
2021-06-14 15:15:22 +02:00
|
|
|
}
|
|
|
|
|
}
|