use std::borrow::Borrow;
use std::ops::{Add, Mul, Neg, Sub};
use group::ff::Field;
use crate::plonk::{Assigned, Error};
#[derive(Clone, Copy, Debug)]
pub struct Value<V> {
inner: Option<V>,
}
impl<V> Default for Value<V> {
fn default() -> Self {
Self::unknown()
}
}
impl<V> Value<V> {
pub const fn unknown() -> Self {
Self { inner: None }
}
pub const fn known(value: V) -> Self {
Self { inner: Some(value) }
}
pub(crate) fn assign(self) -> Result<V, Error> {
self.inner.ok_or(Error::Synthesis)
}
pub fn as_ref(&self) -> Value<&V> {
Value {
inner: self.inner.as_ref(),
}
}
pub fn as_mut(&mut self) -> Value<&mut V> {
Value {
inner: self.inner.as_mut(),
}
}
pub(crate) fn into_option(self) -> Option<V> {
self.inner
}
pub fn assert_if_known<F: FnOnce(&V) -> bool>(&self, f: F) {
if let Some(value) = self.inner.as_ref() {
assert!(f(value));
}
}
pub fn error_if_known_and<F: FnOnce(&V) -> bool>(&self, f: F) -> Result<(), Error> {
match self.inner.as_ref() {
Some(value) if f(value) => Err(Error::Synthesis),
_ => Ok(()),
}
}
pub fn map<W, F: FnOnce(V) -> W>(self, f: F) -> Value<W> {
Value {
inner: self.inner.map(f),
}
}
pub fn and_then<W, F: FnOnce(V) -> Value<W>>(self, f: F) -> Value<W> {
match self.inner {
Some(v) => f(v),
None => Value::unknown(),
}
}
pub fn zip<W>(self, other: Value<W>) -> Value<(V, W)> {
Value {
inner: self.inner.zip(other.inner),
}
}
}
impl<V, W> Value<(V, W)> {
pub fn unzip(self) -> (Value<V>, Value<W>) {
match self.inner {
Some((a, b)) => (Value::known(a), Value::known(b)),
None => (Value::unknown(), Value::unknown()),
}
}
}
impl<V> Value<&V> {
#[must_use = "`self` will be dropped if the result is not used"]
pub fn copied(self) -> Value<V>
where
V: Copy,
{
Value {
inner: self.inner.copied(),
}
}
#[must_use = "`self` will be dropped if the result is not used"]
pub fn cloned(self) -> Value<V>
where
V: Clone,
{
Value {
inner: self.inner.cloned(),
}
}
}
impl<V> Value<&mut V> {
#[must_use = "`self` will be dropped if the result is not used"]
pub fn copied(self) -> Value<V>
where
V: Copy,
{
Value {
inner: self.inner.copied(),
}
}
#[must_use = "`self` will be dropped if the result is not used"]
pub fn cloned(self) -> Value<V>
where
V: Clone,
{
Value {
inner: self.inner.cloned(),
}
}
}
impl<V: Copy, const LEN: usize> Value<[V; LEN]> {
pub fn transpose_array(self) -> [Value<V>; LEN] {
let mut ret = [Value::unknown(); LEN];
if let Some(arr) = self.inner {
for (entry, value) in ret.iter_mut().zip(arr) {
*entry = Value::known(value);
}
}
ret
}
}
impl<V, I> Value<I>
where
I: IntoIterator<Item = V>,
I::IntoIter: ExactSizeIterator,
{
pub fn transpose_vec(self, length: usize) -> Vec<Value<V>> {
match self.inner {
Some(values) => {
let values = values.into_iter();
assert_eq!(values.len(), length);
values.map(Value::known).collect()
}
None => (0..length).map(|_| Value::unknown()).collect(),
}
}
}
impl<A, V: FromIterator<A>> FromIterator<Value<A>> for Value<V> {
fn from_iter<I: IntoIterator<Item = Value<A>>>(iter: I) -> Self {
Self {
inner: iter.into_iter().map(|v| v.inner).collect(),
}
}
}
impl<V: Neg> Neg for Value<V> {
type Output = Value<V::Output>;
fn neg(self) -> Self::Output {
Value {
inner: self.inner.map(|v| -v),
}
}
}
impl<V, O> Add for Value<V>
where
V: Add<Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: Self) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
}
}
}
impl<V, O> Add for &Value<V>
where
for<'v> &'v V: Add<Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: Self) -> Self::Output {
Value {
inner: self
.inner
.as_ref()
.zip(rhs.inner.as_ref())
.map(|(a, b)| a + b),
}
}
}
impl<V, O> Add<Value<&V>> for Value<V>
where
for<'v> V: Add<&'v V, Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: Value<&V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
}
}
}
impl<V, O> Add<Value<V>> for Value<&V>
where
for<'v> &'v V: Add<V, Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: Value<V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
}
}
}
impl<V, O> Add<&Value<V>> for Value<V>
where
for<'v> V: Add<&'v V, Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: &Self) -> Self::Output {
self + rhs.as_ref()
}
}
impl<V, O> Add<Value<V>> for &Value<V>
where
for<'v> &'v V: Add<V, Output = O>,
{
type Output = Value<O>;
fn add(self, rhs: Value<V>) -> Self::Output {
self.as_ref() + rhs
}
}
impl<V, O> Sub for Value<V>
where
V: Sub<Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: Self) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
}
}
}
impl<V, O> Sub for &Value<V>
where
for<'v> &'v V: Sub<Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: Self) -> Self::Output {
Value {
inner: self
.inner
.as_ref()
.zip(rhs.inner.as_ref())
.map(|(a, b)| a - b),
}
}
}
impl<V, O> Sub<Value<&V>> for Value<V>
where
for<'v> V: Sub<&'v V, Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: Value<&V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
}
}
}
impl<V, O> Sub<Value<V>> for Value<&V>
where
for<'v> &'v V: Sub<V, Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: Value<V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
}
}
}
impl<V, O> Sub<&Value<V>> for Value<V>
where
for<'v> V: Sub<&'v V, Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: &Self) -> Self::Output {
self - rhs.as_ref()
}
}
impl<V, O> Sub<Value<V>> for &Value<V>
where
for<'v> &'v V: Sub<V, Output = O>,
{
type Output = Value<O>;
fn sub(self, rhs: Value<V>) -> Self::Output {
self.as_ref() - rhs
}
}
impl<V, O> Mul for Value<V>
where
V: Mul<Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: Self) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
}
}
}
impl<V, O> Mul for &Value<V>
where
for<'v> &'v V: Mul<Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: Self) -> Self::Output {
Value {
inner: self
.inner
.as_ref()
.zip(rhs.inner.as_ref())
.map(|(a, b)| a * b),
}
}
}
impl<V, O> Mul<Value<&V>> for Value<V>
where
for<'v> V: Mul<&'v V, Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: Value<&V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
}
}
}
impl<V, O> Mul<Value<V>> for Value<&V>
where
for<'v> &'v V: Mul<V, Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: Value<V>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
}
}
}
impl<V, O> Mul<&Value<V>> for Value<V>
where
for<'v> V: Mul<&'v V, Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: &Self) -> Self::Output {
self * rhs.as_ref()
}
}
impl<V, O> Mul<Value<V>> for &Value<V>
where
for<'v> &'v V: Mul<V, Output = O>,
{
type Output = Value<O>;
fn mul(self, rhs: Value<V>) -> Self::Output {
self.as_ref() * rhs
}
}
impl<F: Field> From<Value<F>> for Value<Assigned<F>> {
fn from(value: Value<F>) -> Self {
Self {
inner: value.inner.map(Assigned::from),
}
}
}
impl<F: Field> Add<Value<F>> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn add(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
}
}
}
impl<F: Field> Add<F> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn add(self, rhs: F) -> Self::Output {
self + Value::known(rhs)
}
}
impl<F: Field> Add<Value<F>> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn add(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
}
}
}
impl<F: Field> Add<F> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn add(self, rhs: F) -> Self::Output {
self + Value::known(rhs)
}
}
impl<F: Field> Sub<Value<F>> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn sub(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
}
}
}
impl<F: Field> Sub<F> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn sub(self, rhs: F) -> Self::Output {
self - Value::known(rhs)
}
}
impl<F: Field> Sub<Value<F>> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn sub(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
}
}
}
impl<F: Field> Sub<F> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn sub(self, rhs: F) -> Self::Output {
self - Value::known(rhs)
}
}
impl<F: Field> Mul<Value<F>> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn mul(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
}
}
}
impl<F: Field> Mul<F> for Value<Assigned<F>> {
type Output = Value<Assigned<F>>;
fn mul(self, rhs: F) -> Self::Output {
self * Value::known(rhs)
}
}
impl<F: Field> Mul<Value<F>> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn mul(self, rhs: Value<F>) -> Self::Output {
Value {
inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
}
}
}
impl<F: Field> Mul<F> for Value<&Assigned<F>> {
type Output = Value<Assigned<F>>;
fn mul(self, rhs: F) -> Self::Output {
self * Value::known(rhs)
}
}
impl<V> Value<V> {
pub fn to_field<F: Field>(&self) -> Value<Assigned<F>>
where
for<'v> Assigned<F>: From<&'v V>,
{
Value {
inner: self.inner.as_ref().map(|v| v.into()),
}
}
pub fn into_field<F: Field>(self) -> Value<Assigned<F>>
where
V: Into<Assigned<F>>,
{
Value {
inner: self.inner.map(|v| v.into()),
}
}
pub fn double<F: Field>(&self) -> Value<Assigned<F>>
where
V: Borrow<Assigned<F>>,
{
Value {
inner: self.inner.as_ref().map(|v| v.borrow().double()),
}
}
pub fn square<F: Field>(&self) -> Value<Assigned<F>>
where
V: Borrow<Assigned<F>>,
{
Value {
inner: self.inner.as_ref().map(|v| v.borrow().square()),
}
}
pub fn cube<F: Field>(&self) -> Value<Assigned<F>>
where
V: Borrow<Assigned<F>>,
{
Value {
inner: self.inner.as_ref().map(|v| v.borrow().cube()),
}
}
pub fn invert<F: Field>(&self) -> Value<Assigned<F>>
where
V: Borrow<Assigned<F>>,
{
Value {
inner: self.inner.as_ref().map(|v| v.borrow().invert()),
}
}
}
impl<F: Field> Value<Assigned<F>> {
pub fn evaluate(self) -> Value<F> {
Value {
inner: self.inner.map(|v| v.evaluate()),
}
}
}