2021-07-22 16:18:13 +02:00
|
|
|
use std::borrow::Borrow;
|
|
|
|
|
|
2021-06-25 16:49:29 +02:00
|
|
|
use crate::field::extension_field::Extendable;
|
2021-09-07 18:28:28 -07:00
|
|
|
use crate::field::field_types::RichField;
|
2021-07-28 10:56:12 -07:00
|
|
|
use crate::gates::exponentiation::ExponentiationGate;
|
2021-08-14 08:53:39 -07:00
|
|
|
use crate::iop::target::{BoolTarget, Target};
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::plonk::circuit_builder::CircuitBuilder;
|
2021-03-28 15:36:51 -07:00
|
|
|
|
2021-09-07 18:28:28 -07:00
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
2021-04-27 13:16:24 -07:00
|
|
|
/// Computes `-x`.
|
2021-04-02 15:29:21 -07:00
|
|
|
pub fn neg(&mut self, x: Target) -> Target {
|
|
|
|
|
let neg_one = self.neg_one();
|
|
|
|
|
self.mul(x, neg_one)
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 13:16:24 -07:00
|
|
|
/// Computes `x^2`.
|
|
|
|
|
pub fn square(&mut self, x: Target) -> Target {
|
|
|
|
|
self.mul(x, x)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes `x^3`.
|
|
|
|
|
pub fn cube(&mut self, x: Target) -> Target {
|
2021-08-17 00:38:41 -07:00
|
|
|
self.mul_many(&[x, x, x])
|
2021-04-27 13:16:24 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-21 11:47:18 -07:00
|
|
|
/// Computes `const_0 * multiplicand_0 * multiplicand_1 + const_1 * addend`.
|
|
|
|
|
pub fn arithmetic(
|
|
|
|
|
&mut self,
|
|
|
|
|
const_0: F,
|
|
|
|
|
multiplicand_0: Target,
|
|
|
|
|
multiplicand_1: Target,
|
|
|
|
|
const_1: F,
|
|
|
|
|
addend: Target,
|
|
|
|
|
) -> Target {
|
2021-06-25 13:53:14 +02:00
|
|
|
let multiplicand_0_ext = self.convert_to_ext(multiplicand_0);
|
|
|
|
|
let multiplicand_1_ext = self.convert_to_ext(multiplicand_1);
|
|
|
|
|
let addend_ext = self.convert_to_ext(addend);
|
|
|
|
|
|
|
|
|
|
self.arithmetic_extension(
|
|
|
|
|
const_0,
|
|
|
|
|
const_1,
|
|
|
|
|
multiplicand_0_ext,
|
|
|
|
|
multiplicand_1_ext,
|
|
|
|
|
addend_ext,
|
|
|
|
|
)
|
|
|
|
|
.0[0]
|
2021-04-02 15:29:21 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-27 13:16:24 -07:00
|
|
|
/// Computes `x * y + z`.
|
|
|
|
|
pub fn mul_add(&mut self, x: Target, y: Target, z: Target) -> Target {
|
|
|
|
|
self.arithmetic(F::ONE, x, y, F::ONE, z)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes `x * y - z`.
|
|
|
|
|
pub fn mul_sub(&mut self, x: Target, y: Target, z: Target) -> Target {
|
|
|
|
|
self.arithmetic(F::ONE, x, y, F::NEG_ONE, z)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes `x + y`.
|
2021-04-21 11:47:18 -07:00
|
|
|
pub fn add(&mut self, x: Target, y: Target) -> Target {
|
|
|
|
|
let one = self.one();
|
|
|
|
|
// x + y = 1 * x * 1 + 1 * y
|
|
|
|
|
self.arithmetic(F::ONE, x, one, F::ONE, y)
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-17 00:38:41 -07:00
|
|
|
/// Add `n` `Target`s.
|
|
|
|
|
// TODO: Can be made `D` times more efficient by using all wires of an `ArithmeticExtensionGate`.
|
2021-04-02 15:29:21 -07:00
|
|
|
pub fn add_many(&mut self, terms: &[Target]) -> Target {
|
2021-07-21 17:41:22 +02:00
|
|
|
let terms_ext = terms
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|&t| self.convert_to_ext(t))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
self.add_many_extension(&terms_ext).to_target_array()[0]
|
2021-03-28 15:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-27 13:16:24 -07:00
|
|
|
/// Computes `x - y`.
|
2021-03-28 15:36:51 -07:00
|
|
|
pub fn sub(&mut self, x: Target, y: Target) -> Target {
|
2021-04-21 11:47:18 -07:00
|
|
|
let one = self.one();
|
|
|
|
|
// x - y = 1 * x * 1 + (-1) * y
|
|
|
|
|
self.arithmetic(F::ONE, x, one, F::NEG_ONE, y)
|
2021-03-28 15:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-27 13:16:24 -07:00
|
|
|
/// Computes `x * y`.
|
2021-03-28 15:36:51 -07:00
|
|
|
pub fn mul(&mut self, x: Target, y: Target) -> Target {
|
2021-04-21 11:47:18 -07:00
|
|
|
// x * y = 1 * x * y + 0 * x
|
|
|
|
|
self.arithmetic(F::ONE, x, y, F::ZERO, x)
|
2021-03-28 15:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-17 00:38:41 -07:00
|
|
|
/// Multiply `n` `Target`s.
|
2021-04-02 15:29:21 -07:00
|
|
|
pub fn mul_many(&mut self, terms: &[Target]) -> Target {
|
2021-07-21 17:41:22 +02:00
|
|
|
let terms_ext = terms
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|&t| self.convert_to_ext(t))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
self.mul_many_extension(&terms_ext).to_target_array()[0]
|
2021-04-02 15:29:21 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-20 12:49:02 -07:00
|
|
|
/// Exponentiate `base` to the power of `2^power_log`.
|
2021-08-04 09:55:29 -07:00
|
|
|
pub fn exp_power_of_2(&mut self, base: Target, power_log: usize) -> Target {
|
|
|
|
|
self.exp_u64(base, 1 << power_log)
|
2021-04-02 15:29:21 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-25 16:27:20 +02:00
|
|
|
// TODO: Test
|
2021-07-20 15:25:03 +02:00
|
|
|
/// Exponentiate `base` to the power of `exponent`, given by its little-endian bits.
|
2021-07-23 08:53:00 +02:00
|
|
|
pub fn exp_from_bits(
|
|
|
|
|
&mut self,
|
|
|
|
|
base: Target,
|
2021-08-14 08:53:39 -07:00
|
|
|
exponent_bits: impl IntoIterator<Item = impl Borrow<BoolTarget>>,
|
2021-07-23 08:53:00 +02:00
|
|
|
) -> Target {
|
2021-08-14 08:53:39 -07:00
|
|
|
let _false = self._false();
|
2021-10-18 11:11:48 +02:00
|
|
|
let gate = ExponentiationGate::new_from_config(&self.config);
|
2021-07-29 15:15:40 -07:00
|
|
|
let num_power_bits = gate.num_power_bits;
|
2021-08-14 08:53:39 -07:00
|
|
|
let mut exp_bits_vec: Vec<BoolTarget> =
|
2021-08-05 08:03:49 -07:00
|
|
|
exponent_bits.into_iter().map(|b| *b.borrow()).collect();
|
2021-07-29 15:15:40 -07:00
|
|
|
while exp_bits_vec.len() < num_power_bits {
|
2021-08-14 08:53:39 -07:00
|
|
|
exp_bits_vec.push(_false);
|
2021-07-29 15:15:40 -07:00
|
|
|
}
|
2021-07-28 13:38:41 -07:00
|
|
|
let gate_index = self.add_gate(gate.clone(), vec![]);
|
2021-06-09 17:39:45 +02:00
|
|
|
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect(base, Target::wire(gate_index, gate.wire_base()));
|
2021-07-28 13:38:41 -07:00
|
|
|
exp_bits_vec.iter().enumerate().for_each(|(i, bit)| {
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect(bit.target, Target::wire(gate_index, gate.wire_power_bit(i)));
|
2021-07-28 13:38:41 -07:00
|
|
|
});
|
2021-06-09 17:39:45 +02:00
|
|
|
|
2021-07-28 13:38:41 -07:00
|
|
|
Target::wire(gate_index, gate.wire_output())
|
2021-06-09 17:39:45 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-20 15:25:03 +02:00
|
|
|
// TODO: Test
|
|
|
|
|
/// Exponentiate `base` to the power of `exponent`, where `exponent < 2^num_bits`.
|
|
|
|
|
pub fn exp(&mut self, base: Target, exponent: Target, num_bits: usize) -> Target {
|
|
|
|
|
let exponent_bits = self.split_le(exponent, num_bits);
|
2021-07-28 10:56:12 -07:00
|
|
|
|
2021-07-28 13:38:41 -07:00
|
|
|
self.exp_from_bits(base, exponent_bits.iter())
|
2021-07-20 15:25:03 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-25 16:27:20 +02:00
|
|
|
/// Exponentiate `base` to the power of a known `exponent`.
|
|
|
|
|
// TODO: Test
|
2021-08-04 09:55:29 -07:00
|
|
|
pub fn exp_u64(&mut self, base: Target, mut exponent: u64) -> Target {
|
|
|
|
|
let mut exp_bits = Vec::new();
|
|
|
|
|
while exponent != 0 {
|
2021-08-14 08:53:39 -07:00
|
|
|
let bit = (exponent & 1) == 1;
|
|
|
|
|
let bit_target = self.constant_bool(bit);
|
2021-08-04 09:55:29 -07:00
|
|
|
exp_bits.push(bit_target);
|
|
|
|
|
exponent >>= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.exp_from_bits(base, exp_bits)
|
2021-06-25 16:27:20 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-18 23:05:57 -07:00
|
|
|
/// Computes `x / y`. Results in an unsatisfiable instance if `y = 0`.
|
|
|
|
|
pub fn div(&mut self, x: Target, y: Target) -> Target {
|
2021-08-10 11:48:53 -07:00
|
|
|
let x = self.convert_to_ext(x);
|
|
|
|
|
let y = self.convert_to_ext(y);
|
|
|
|
|
self.div_extension(x, y).0[0]
|
2021-04-21 11:47:18 -07:00
|
|
|
}
|
2021-07-18 23:05:57 -07:00
|
|
|
|
|
|
|
|
/// Computes `1 / x`. Results in an unsatisfiable instance if `x = 0`.
|
|
|
|
|
pub fn inverse(&mut self, x: Target) -> Target {
|
|
|
|
|
let x_ext = self.convert_to_ext(x);
|
|
|
|
|
self.inverse_extension(x_ext).0[0]
|
|
|
|
|
}
|
2021-06-07 17:55:27 +02:00
|
|
|
}
|