mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-08 15:01:29 +01:00
Add back ToBytesGadget and ToBitsGadget to prelude (#136)
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -4,14 +4,26 @@
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- [\#121](https://github.com/arkworks-rs/r1cs-std/pull/121)
|
||||
- Refactor `UInt{8,16,64,128}` into one struct `UInt`.
|
||||
- Remove `bits` module.
|
||||
- Use `std::ops` traits for `UInt` and `Boolean`.
|
||||
- [\#134](https://github.com/arkworks-rs/r1cs-std/pull/134) Add `Mul<NonnativeFieldVar>` bounds and impls for `CurveVar`.
|
||||
- [\#135](https://github.com/arkworks-rs/r1cs-std/pull/135)
|
||||
- Rename `NonNativeFieldVar` to `EmulatedFpVar`.
|
||||
- Rename `fields::nonnative` to `fields::emulated_fp`.
|
||||
- Rename `fields::nonnative::{Allocated}NonNativeMulResultVar` to `fields::emulated_fp::{Allocated}MulResultVar`.
|
||||
- [\#136](https://github.com/arkworks-rs/r1cs-std/pull/136)
|
||||
- Rename `ToBytesGadget::to_{non_unique_}bytes` → `ToBytesGadget::to_{non_unique_}bytes_in_le`.
|
||||
|
||||
### Features
|
||||
|
||||
- [\#136](https://github.com/arkworks-rs/r1cs-std/pull/136)
|
||||
- Add `{BitAnd,BitOr,BitXor,BitAndAssign,BitOrAssign,BitXorAssign}<T> for UInt<N, T, F>`.
|
||||
- Add `UInt::rotate_{left,right}_in_place`.
|
||||
- Add `{Boolean,UInt}::not_in_place`.
|
||||
- Add `UInt::{from_bytes_le, from_bytes_be, to_bytes_be}`.
|
||||
|
||||
### Improvements
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::convert::{ToBytesGadget, ToConstraintFieldGadget};
|
||||
impl<F: Field> ToBytesGadget<F> for Boolean<F> {
|
||||
/// Outputs `1u8` if `self` is true, and `0u8` otherwise.
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
let value = self.value().map(u8::from).ok();
|
||||
let mut bits = [Boolean::FALSE; 8];
|
||||
bits[0] = self.clone();
|
||||
|
||||
@@ -215,7 +215,7 @@ mod test {
|
||||
for val in [true, false].iter() {
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
let a = Boolean::new_witness(cs.clone(), || Ok(*val))?;
|
||||
let bytes = a.to_bytes()?;
|
||||
let bytes = a.to_bytes_le()?;
|
||||
assert_eq!(bytes.len(), 1);
|
||||
let byte = &bytes[0];
|
||||
assert_eq!(byte.value()?, *val as u8);
|
||||
|
||||
@@ -6,10 +6,17 @@ use super::Boolean;
|
||||
|
||||
impl<F: Field> Boolean<F> {
|
||||
fn _not(&self) -> Result<Self, SynthesisError> {
|
||||
let mut result = self.clone();
|
||||
result.not_in_place()?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn not_in_place(&mut self) -> Result<(), SynthesisError> {
|
||||
match *self {
|
||||
Boolean::Constant(c) => Ok(Boolean::Constant(!c)),
|
||||
Boolean::Var(ref v) => Ok(Boolean::Var(v.not().unwrap())),
|
||||
Boolean::Constant(ref mut c) => *c = !*c,
|
||||
Boolean::Var(ref mut v) => *v = v.not()?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use ark_ff::Field;
|
||||
use ark_relations::r1cs::SynthesisError;
|
||||
|
||||
use crate::boolean::Boolean;
|
||||
use crate::{boolean::Boolean, R1CSVar};
|
||||
|
||||
/// Specifies how to generate constraints for comparing two variables.
|
||||
pub trait CmpGadget<F: Field> {
|
||||
pub trait CmpGadget<F: Field>: R1CSVar<F> {
|
||||
fn is_gt(&self, other: &Self) -> Result<Boolean<F>, SynthesisError> {
|
||||
other.is_lt(self)
|
||||
}
|
||||
|
||||
@@ -69,20 +69,24 @@ pub trait ToBytesGadget<F: Field> {
|
||||
/// Outputs a canonical, little-endian, byte decomposition of `self`.
|
||||
///
|
||||
/// This is the correct default for 99% of use cases.
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
|
||||
|
||||
/// Outputs a possibly non-unique byte decomposition of `self`.
|
||||
///
|
||||
/// If you're not absolutely certain that your usecase can get away with a
|
||||
/// non-canonical representation, please use `self.to_bytes(cs)` instead.
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
self.to_bytes()
|
||||
/// non-canonical representation, please use `self.to_bytes_le(cs)` instead.
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
self.to_bytes_le()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
(*self).to_bytes()
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
(*self).to_bytes_le()
|
||||
}
|
||||
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
(*self).to_non_unique_bytes_le()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -435,10 +435,10 @@ where
|
||||
P: CubicExtVarConfig<BF>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes()?;
|
||||
let mut c1 = self.c1.to_bytes()?;
|
||||
let mut c2 = self.c2.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes_le()?;
|
||||
let mut c1 = self.c1.to_bytes_le()?;
|
||||
let mut c2 = self.c2.to_bytes_le()?;
|
||||
c0.append(&mut c1);
|
||||
c0.append(&mut c2);
|
||||
|
||||
@@ -446,10 +446,10 @@ where
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_non_unique_bytes()?;
|
||||
let mut c1 = self.c1.to_non_unique_bytes()?;
|
||||
let mut c2 = self.c2.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_non_unique_bytes_le()?;
|
||||
let mut c1 = self.c1.to_non_unique_bytes_le()?;
|
||||
let mut c2 = self.c2.to_non_unique_bytes_le()?;
|
||||
|
||||
c0.append(&mut c1);
|
||||
c0.append(&mut c2);
|
||||
|
||||
@@ -681,7 +681,7 @@ impl<TargetF: PrimeField, BaseF: PrimeField> ToBytesGadget<BaseF>
|
||||
for AllocatedEmulatedFpVar<TargetF, BaseF>
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
fn to_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
let mut bits = self.to_bits_le()?;
|
||||
|
||||
let num_bits = TargetF::BigInt::NUM_LIMBS * 64;
|
||||
|
||||
@@ -297,23 +297,23 @@ impl<TargetF: PrimeField, BaseF: PrimeField> ToBytesGadget<BaseF>
|
||||
/// Outputs the unique byte decomposition of `self` in *little-endian*
|
||||
/// form.
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
fn to_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
match self {
|
||||
Self::Constant(c) => Ok(UInt8::constant_vec(
|
||||
c.into_bigint().to_bytes_le().as_slice(),
|
||||
)),
|
||||
|
||||
Self::Var(v) => v.to_bytes(),
|
||||
Self::Var(v) => v.to_bytes_le(),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
fn to_non_unique_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
|
||||
match self {
|
||||
Self::Constant(c) => Ok(UInt8::constant_vec(
|
||||
c.into_bigint().to_bytes_le().as_slice(),
|
||||
)),
|
||||
Self::Var(v) => v.to_non_unique_bytes(),
|
||||
Self::Var(v) => v.to_non_unique_bytes_le(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ impl<F: PrimeField> ToBytesGadget<F> for AllocatedFp<F> {
|
||||
/// This method enforces that the decomposition represents
|
||||
/// an integer that is less than `F::MODULUS`.
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
let num_bits = F::BigInt::NUM_LIMBS * 64;
|
||||
let mut bits = self.to_bits_le()?;
|
||||
let remainder = core::iter::repeat(Boolean::constant(false)).take(num_bits - bits.len());
|
||||
@@ -565,7 +565,7 @@ impl<F: PrimeField> ToBytesGadget<F> for AllocatedFp<F> {
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
let num_bits = F::BigInt::NUM_LIMBS * 64;
|
||||
let mut bits = self.to_non_unique_bits_le()?;
|
||||
let remainder = core::iter::repeat(Boolean::constant(false)).take(num_bits - bits.len());
|
||||
@@ -957,22 +957,22 @@ impl<F: PrimeField> ToBytesGadget<F> for FpVar<F> {
|
||||
/// Outputs the unique byte decomposition of `self` in *little-endian*
|
||||
/// form.
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
match self {
|
||||
Self::Constant(c) => Ok(UInt8::constant_vec(
|
||||
c.into_bigint().to_bytes_le().as_slice(),
|
||||
)),
|
||||
Self::Var(v) => v.to_bytes(),
|
||||
Self::Var(v) => v.to_bytes_le(),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
match self {
|
||||
Self::Constant(c) => Ok(UInt8::constant_vec(
|
||||
c.into_bigint().to_bytes_le().as_slice(),
|
||||
)),
|
||||
Self::Var(v) => v.to_non_unique_bytes(),
|
||||
Self::Var(v) => v.to_non_unique_bytes_le(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,17 +435,17 @@ where
|
||||
P: QuadExtVarConfig<BF>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes()?;
|
||||
let mut c1 = self.c1.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes_le()?;
|
||||
let mut c1 = self.c1.to_bytes_le()?;
|
||||
c0.append(&mut c1);
|
||||
Ok(c0)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_non_unique_bytes()?;
|
||||
let mut c1 = self.c1.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_non_unique_bytes_le()?;
|
||||
let mut c1 = self.c1.to_non_unique_bytes_le()?;
|
||||
c0.append(&mut c1);
|
||||
Ok(c0)
|
||||
}
|
||||
|
||||
@@ -79,20 +79,20 @@ impl<P: Bls12Config> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
|
||||
impl<P: Bls12Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = self.0.x.to_bytes()?;
|
||||
let y_bytes = self.0.y.to_bytes()?;
|
||||
let inf_bytes = self.0.infinity.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = self.0.x.to_bytes_le()?;
|
||||
let y_bytes = self.0.y.to_bytes_le()?;
|
||||
let inf_bytes = self.0.infinity.to_bytes_le()?;
|
||||
bytes.extend_from_slice(&y_bytes);
|
||||
bytes.extend_from_slice(&inf_bytes);
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = self.0.x.to_non_unique_bytes()?;
|
||||
let y_bytes = self.0.y.to_non_unique_bytes()?;
|
||||
let inf_bytes = self.0.infinity.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = self.0.x.to_non_unique_bytes_le()?;
|
||||
let y_bytes = self.0.y.to_non_unique_bytes_le()?;
|
||||
let inf_bytes = self.0.infinity.to_non_unique_bytes_le()?;
|
||||
bytes.extend_from_slice(&y_bytes);
|
||||
bytes.extend_from_slice(&inf_bytes);
|
||||
Ok(bytes)
|
||||
@@ -174,21 +174,21 @@ impl<P: Bls12Config> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||
impl<P: Bls12Config> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = Vec::new();
|
||||
for coeffs in &self.ell_coeffs {
|
||||
bytes.extend_from_slice(&coeffs.0.to_bytes()?);
|
||||
bytes.extend_from_slice(&coeffs.1.to_bytes()?);
|
||||
bytes.extend_from_slice(&coeffs.0.to_bytes_le()?);
|
||||
bytes.extend_from_slice(&coeffs.1.to_bytes_le()?);
|
||||
}
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut bytes = Vec::new();
|
||||
for coeffs in &self.ell_coeffs {
|
||||
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes()?);
|
||||
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes()?);
|
||||
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes_le()?);
|
||||
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes_le()?);
|
||||
}
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
@@ -105,11 +105,11 @@ impl<P: MNT4Config> G1PreparedVar<P> {
|
||||
impl<P: MNT4Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes()?;
|
||||
let mut y = self.y.to_bytes()?;
|
||||
let mut x_twist = self.x_twist.to_bytes()?;
|
||||
let mut y_twist = self.y_twist.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes_le()?;
|
||||
let mut y = self.y.to_bytes_le()?;
|
||||
let mut x_twist = self.x_twist.to_bytes_le()?;
|
||||
let mut y_twist = self.y_twist.to_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_twist);
|
||||
@@ -118,11 +118,11 @@ impl<P: MNT4Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes()?;
|
||||
let mut y = self.y.to_non_unique_bytes()?;
|
||||
let mut x_twist = self.x_twist.to_non_unique_bytes()?;
|
||||
let mut y_twist = self.y_twist.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes_le()?;
|
||||
let mut y = self.y.to_non_unique_bytes_le()?;
|
||||
let mut x_twist = self.x_twist.to_non_unique_bytes_le()?;
|
||||
let mut y_twist = self.y_twist.to_non_unique_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_twist);
|
||||
@@ -201,41 +201,41 @@ impl<P: MNT4Config> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||
impl<P: MNT4Config> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes()?;
|
||||
let mut y = self.y.to_bytes()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_bytes()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes_le()?;
|
||||
let mut y = self.y.to_bytes_le()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_bytes_le()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_over_twist);
|
||||
x.append(&mut y_over_twist);
|
||||
|
||||
for coeff in &self.double_coefficients {
|
||||
x.extend_from_slice(&coeff.to_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_bytes_le()?);
|
||||
}
|
||||
for coeff in &self.addition_coefficients {
|
||||
x.extend_from_slice(&coeff.to_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_bytes_le()?);
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes()?;
|
||||
let mut y = self.y.to_non_unique_bytes()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes_le()?;
|
||||
let mut y = self.y.to_non_unique_bytes_le()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes_le()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_over_twist);
|
||||
x.append(&mut y_over_twist);
|
||||
|
||||
for coeff in &self.double_coefficients {
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes_le()?);
|
||||
}
|
||||
for coeff in &self.addition_coefficients {
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes_le()?);
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
@@ -379,11 +379,11 @@ impl<P: MNT4Config> AllocVar<AteDoubleCoefficients<P>, P::Fp> for AteDoubleCoeff
|
||||
impl<P: MNT4Config> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_bytes()?;
|
||||
let mut c_4c = self.c_4c.to_bytes()?;
|
||||
let mut c_j = self.c_j.to_bytes()?;
|
||||
let mut c_l = self.c_l.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_bytes_le()?;
|
||||
let mut c_4c = self.c_4c.to_bytes_le()?;
|
||||
let mut c_j = self.c_j.to_bytes_le()?;
|
||||
let mut c_l = self.c_l.to_bytes_le()?;
|
||||
|
||||
c_h.append(&mut c_4c);
|
||||
c_h.append(&mut c_j);
|
||||
@@ -392,11 +392,11 @@ impl<P: MNT4Config> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_non_unique_bytes()?;
|
||||
let mut c_4c = self.c_4c.to_non_unique_bytes()?;
|
||||
let mut c_j = self.c_j.to_non_unique_bytes()?;
|
||||
let mut c_l = self.c_l.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_non_unique_bytes_le()?;
|
||||
let mut c_4c = self.c_4c.to_non_unique_bytes_le()?;
|
||||
let mut c_j = self.c_j.to_non_unique_bytes_le()?;
|
||||
let mut c_l = self.c_l.to_non_unique_bytes_le()?;
|
||||
|
||||
c_h.append(&mut c_4c);
|
||||
c_h.append(&mut c_j);
|
||||
@@ -456,18 +456,18 @@ impl<P: MNT4Config> AllocVar<AteAdditionCoefficients<P>, P::Fp> for AteAdditionC
|
||||
impl<P: MNT4Config> ToBytesGadget<P::Fp> for AteAdditionCoefficientsVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_bytes()?;
|
||||
let mut c_rz = self.c_rz.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_bytes_le()?;
|
||||
let mut c_rz = self.c_rz.to_bytes_le()?;
|
||||
|
||||
c_l1.append(&mut c_rz);
|
||||
Ok(c_l1)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_non_unique_bytes()?;
|
||||
let mut c_rz = self.c_rz.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_non_unique_bytes_le()?;
|
||||
let mut c_rz = self.c_rz.to_non_unique_bytes_le()?;
|
||||
|
||||
c_l1.append(&mut c_rz);
|
||||
Ok(c_l1)
|
||||
|
||||
@@ -105,11 +105,11 @@ impl<P: MNT6Config> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
|
||||
impl<P: MNT6Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes()?;
|
||||
let mut y = self.y.to_bytes()?;
|
||||
let mut x_twist = self.x_twist.to_bytes()?;
|
||||
let mut y_twist = self.y_twist.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes_le()?;
|
||||
let mut y = self.y.to_bytes_le()?;
|
||||
let mut x_twist = self.x_twist.to_bytes_le()?;
|
||||
let mut y_twist = self.y_twist.to_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_twist);
|
||||
@@ -118,11 +118,11 @@ impl<P: MNT6Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes()?;
|
||||
let mut y = self.y.to_non_unique_bytes()?;
|
||||
let mut x_twist = self.x_twist.to_non_unique_bytes()?;
|
||||
let mut y_twist = self.y_twist.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes_le()?;
|
||||
let mut y = self.y.to_non_unique_bytes_le()?;
|
||||
let mut x_twist = self.x_twist.to_non_unique_bytes_le()?;
|
||||
let mut y_twist = self.y_twist.to_non_unique_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_twist);
|
||||
@@ -201,41 +201,41 @@ impl<P: MNT6Config> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
|
||||
impl<P: MNT6Config> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes()?;
|
||||
let mut y = self.y.to_bytes()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_bytes()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_bytes_le()?;
|
||||
let mut y = self.y.to_bytes_le()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_bytes_le()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_over_twist);
|
||||
x.append(&mut y_over_twist);
|
||||
|
||||
for coeff in self.double_coefficients.iter() {
|
||||
x.extend_from_slice(&coeff.to_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_bytes_le()?);
|
||||
}
|
||||
for coeff in self.addition_coefficients.iter() {
|
||||
x.extend_from_slice(&coeff.to_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_bytes_le()?);
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes()?;
|
||||
let mut y = self.y.to_non_unique_bytes()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut x = self.x.to_non_unique_bytes_le()?;
|
||||
let mut y = self.y.to_non_unique_bytes_le()?;
|
||||
let mut x_over_twist = self.x_over_twist.to_non_unique_bytes_le()?;
|
||||
let mut y_over_twist = self.y_over_twist.to_non_unique_bytes_le()?;
|
||||
|
||||
x.append(&mut y);
|
||||
x.append(&mut x_over_twist);
|
||||
x.append(&mut y_over_twist);
|
||||
|
||||
for coeff in self.double_coefficients.iter() {
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes_le()?);
|
||||
}
|
||||
for coeff in self.addition_coefficients.iter() {
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes()?);
|
||||
x.extend_from_slice(&coeff.to_non_unique_bytes_le()?);
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
@@ -379,11 +379,11 @@ impl<P: MNT6Config> AllocVar<AteDoubleCoefficients<P>, P::Fp> for AteDoubleCoeff
|
||||
impl<P: MNT6Config> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_bytes()?;
|
||||
let mut c_4c = self.c_4c.to_bytes()?;
|
||||
let mut c_j = self.c_j.to_bytes()?;
|
||||
let mut c_l = self.c_l.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_bytes_le()?;
|
||||
let mut c_4c = self.c_4c.to_bytes_le()?;
|
||||
let mut c_j = self.c_j.to_bytes_le()?;
|
||||
let mut c_l = self.c_l.to_bytes_le()?;
|
||||
|
||||
c_h.append(&mut c_4c);
|
||||
c_h.append(&mut c_j);
|
||||
@@ -392,11 +392,11 @@ impl<P: MNT6Config> ToBytesGadget<P::Fp> for AteDoubleCoefficientsVar<P> {
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_non_unique_bytes()?;
|
||||
let mut c_4c = self.c_4c.to_non_unique_bytes()?;
|
||||
let mut c_j = self.c_j.to_non_unique_bytes()?;
|
||||
let mut c_l = self.c_l.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_h = self.c_h.to_non_unique_bytes_le()?;
|
||||
let mut c_4c = self.c_4c.to_non_unique_bytes_le()?;
|
||||
let mut c_j = self.c_j.to_non_unique_bytes_le()?;
|
||||
let mut c_l = self.c_l.to_non_unique_bytes_le()?;
|
||||
|
||||
c_h.append(&mut c_4c);
|
||||
c_h.append(&mut c_j);
|
||||
@@ -454,18 +454,18 @@ impl<P: MNT6Config> AllocVar<AteAdditionCoefficients<P>, P::Fp> for AteAdditionC
|
||||
impl<P: MNT6Config> ToBytesGadget<P::Fp> for AteAdditionCoefficientsVar<P> {
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_bytes()?;
|
||||
let mut c_rz = self.c_rz.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_bytes_le()?;
|
||||
let mut c_rz = self.c_rz.to_bytes_le()?;
|
||||
|
||||
c_l1.append(&mut c_rz);
|
||||
Ok(c_l1)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_non_unique_bytes()?;
|
||||
let mut c_rz = self.c_rz.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
|
||||
let mut c_l1 = self.c_l1.to_non_unique_bytes_le()?;
|
||||
let mut c_rz = self.c_rz.to_non_unique_bytes_le()?;
|
||||
|
||||
c_l1.append(&mut c_rz);
|
||||
Ok(c_l1)
|
||||
|
||||
@@ -953,22 +953,22 @@ where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bytes = g.x.to_bytes()?;
|
||||
let y_bytes = g.y.to_bytes()?;
|
||||
let inf_bytes = g.infinity.to_bytes()?;
|
||||
let mut bytes = g.x.to_bytes_le()?;
|
||||
let y_bytes = g.y.to_bytes_le()?;
|
||||
let inf_bytes = g.infinity.to_bytes_le()?;
|
||||
bytes.extend_from_slice(&y_bytes);
|
||||
bytes.extend_from_slice(&inf_bytes);
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bytes = g.x.to_non_unique_bytes()?;
|
||||
let y_bytes = g.y.to_non_unique_bytes()?;
|
||||
let inf_bytes = g.infinity.to_non_unique_bytes()?;
|
||||
let mut bytes = g.x.to_non_unique_bytes_le()?;
|
||||
let y_bytes = g.y.to_non_unique_bytes_le()?;
|
||||
let inf_bytes = g.infinity.to_non_unique_bytes_le()?;
|
||||
bytes.extend_from_slice(&y_bytes);
|
||||
bytes.extend_from_slice(&inf_bytes);
|
||||
Ok(bytes)
|
||||
|
||||
@@ -920,17 +920,17 @@ where
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_bytes()?;
|
||||
let y_bytes = self.y.to_bytes()?;
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_bytes_le()?;
|
||||
let y_bytes = self.y.to_bytes_le()?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
Ok(x_bytes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_non_unique_bytes()?;
|
||||
let y_bytes = self.y.to_non_unique_bytes()?;
|
||||
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_non_unique_bytes_le()?;
|
||||
let y_bytes = self.y.to_non_unique_bytes_le()?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
|
||||
Ok(x_bytes)
|
||||
|
||||
@@ -90,6 +90,7 @@ pub mod prelude {
|
||||
pub use crate::{
|
||||
alloc::*,
|
||||
boolean::Boolean,
|
||||
convert::{ToBitsGadget, ToBytesGadget},
|
||||
eq::*,
|
||||
fields::{FieldOpsBounds, FieldVar},
|
||||
groups::{CurveVar, GroupOpsBounds},
|
||||
|
||||
125
src/uint/and.rs
125
src/uint/and.rs
@@ -7,11 +7,16 @@ use super::*;
|
||||
impl<const N: usize, T: PrimUInt, F: Field> UInt<N, T, F> {
|
||||
fn _and(&self, other: &Self) -> Result<Self, SynthesisError> {
|
||||
let mut result = self.clone();
|
||||
for (a, b) in result.bits.iter_mut().zip(&other.bits) {
|
||||
result._and_in_place(other)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn _and_in_place(&mut self, other: &Self) -> Result<(), SynthesisError> {
|
||||
for (a, b) in self.bits.iter_mut().zip(&other.bits) {
|
||||
*a &= b;
|
||||
}
|
||||
result.value = self.value.and_then(|a| Some(a & other.value?));
|
||||
Ok(result)
|
||||
self.value = self.value.and_then(|a| Some(a & other.value?));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +75,9 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<&'a Self> for UInt<N, T,
|
||||
/// # }
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: &Self) -> Self::Output {
|
||||
self._and(&other).unwrap()
|
||||
fn bitand(mut self, other: &Self) -> Self::Output {
|
||||
self._and_in_place(other).unwrap();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +108,7 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<UInt<N, T, F>> for &'a UI
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: UInt<N, T, F>) -> Self::Output {
|
||||
self._and(&other).unwrap()
|
||||
other & self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +139,43 @@ impl<const N: usize, T: PrimUInt, F: Field> BitAnd<Self> for UInt<N, T, F> {
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: Self) -> Self::Output {
|
||||
self._and(&other).unwrap()
|
||||
self & &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: T) -> Self::Output {
|
||||
self & UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<&'a T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: &'a T) -> Self::Output {
|
||||
self & UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<&'a T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: &'a T) -> Self::Output {
|
||||
self & UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitAnd<T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand(self, other: T) -> Self::Output {
|
||||
self & UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +205,7 @@ impl<const N: usize, T: PrimUInt, F: Field> BitAndAssign<Self> for UInt<N, T, F>
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand_assign(&mut self, other: Self) {
|
||||
let result = self._and(&other).unwrap();
|
||||
*self = result;
|
||||
self._and_in_place(&other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +235,21 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> BitAndAssign<&'a Self> for UInt<
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand_assign(&mut self, other: &'a Self) {
|
||||
let result = self._and(other).unwrap();
|
||||
*self = result;
|
||||
self._and_in_place(&other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: Field> BitAndAssign<T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand_assign(&mut self, other: T) {
|
||||
*self &= &Self::constant(other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitAndAssign<&'a T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitand_assign(&mut self, other: &'a T) {
|
||||
*self &= &Self::constant(*other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +259,7 @@ mod tests {
|
||||
use crate::{
|
||||
alloc::{AllocVar, AllocationMode},
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_binary_exhaustive, run_binary_random},
|
||||
uint::test_utils::{run_binary_exhaustive_both, run_binary_random_both},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
@@ -236,28 +290,65 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_and_native<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
a: UInt<N, T, F>,
|
||||
b: T,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = a.cs();
|
||||
let computed = &a & b;
|
||||
let expected_mode = if a.is_constant() {
|
||||
AllocationMode::Constant
|
||||
} else {
|
||||
AllocationMode::Witness
|
||||
};
|
||||
let expected =
|
||||
UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a.value()? & b), expected_mode)?;
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !a.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_and() {
|
||||
run_binary_exhaustive(uint_and::<u8, 8, Fr>).unwrap()
|
||||
run_binary_exhaustive_both(uint_and::<u8, 8, Fr>, uint_and_native::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_and() {
|
||||
run_binary_random::<1000, 16, _, _>(uint_and::<u16, 16, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 16, _, _>(
|
||||
uint_and::<u16, 16, Fr>,
|
||||
uint_and_native::<u16, 16, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_and() {
|
||||
run_binary_random::<1000, 32, _, _>(uint_and::<u32, 32, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 32, _, _>(
|
||||
uint_and::<u32, 32, Fr>,
|
||||
uint_and_native::<u32, 32, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_and() {
|
||||
run_binary_random::<1000, 64, _, _>(uint_and::<u64, 64, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 64, _, _>(
|
||||
uint_and::<u64, 64, Fr>,
|
||||
uint_and_native::<u64, 64, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_and() {
|
||||
run_binary_random::<1000, 128, _, _>(uint_and::<u128, 128, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 128, _, _>(
|
||||
uint_and::<u128, 128, Fr>,
|
||||
uint_and_native::<u128, 128, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,71 @@ impl<const N: usize, F: Field, T: PrimUInt> UInt<N, T, F> {
|
||||
let value = value_exists.then_some(value);
|
||||
Self { bits, value }
|
||||
}
|
||||
|
||||
/// Converts a big-endian list of bytes into a `UInt`.
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
|
||||
/// // We'll use the BLS12-381 scalar field for our constraints.
|
||||
/// use ark_test_curves::bls12_381::Fr;
|
||||
/// use ark_relations::r1cs::*;
|
||||
/// use ark_r1cs_std::prelude::*;
|
||||
///
|
||||
/// let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
/// let var = UInt16::new_witness(cs.clone(), || Ok(2 * (u8::MAX as u16)))?;
|
||||
///
|
||||
/// // Construct u8::MAX * 2
|
||||
/// let bytes = UInt8::constant_vec(&(2 * (u8::MAX as u16)).to_be_bytes());
|
||||
///
|
||||
/// let c = UInt16::from_bytes_be(&bytes)?;
|
||||
/// var.enforce_equal(&c)?;
|
||||
/// assert!(cs.is_satisfied().unwrap());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn from_bytes_be(bytes: &[UInt8<F>]) -> Result<Self, SynthesisError> {
|
||||
let bits = bytes
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|b| b.to_bits_le().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
Ok(Self::from_bits_le(&bits))
|
||||
}
|
||||
|
||||
/// Converts a little-endian byte order list of bytes into a `UInt`.
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
|
||||
/// // We'll use the BLS12-381 scalar field for our constraints.
|
||||
/// use ark_test_curves::bls12_381::Fr;
|
||||
/// use ark_relations::r1cs::*;
|
||||
/// use ark_r1cs_std::prelude::*;
|
||||
///
|
||||
/// let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
/// let var = UInt16::new_witness(cs.clone(), || Ok(2 * (u8::MAX as u16)))?;
|
||||
///
|
||||
/// // Construct u8::MAX * 2
|
||||
/// let bytes = UInt8::constant_vec(&(2 * (u8::MAX as u16)).to_le_bytes());
|
||||
///
|
||||
/// let c = UInt16::from_bytes_le(&bytes)?;
|
||||
/// var.enforce_equal(&c)?;
|
||||
/// assert!(cs.is_satisfied().unwrap());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn from_bytes_le(bytes: &[UInt8<F>]) -> Result<Self, SynthesisError> {
|
||||
let bits = bytes
|
||||
.iter()
|
||||
.flat_map(|b| b.to_bits_le().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
Ok(Self::from_bits_le(&bits))
|
||||
}
|
||||
|
||||
pub fn to_bytes_be(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
let mut bytes = self.to_bytes_le()?;
|
||||
bytes.reverse();
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: Field> ToBitsGadget<F> for UInt<N, T, F> {
|
||||
@@ -97,7 +162,7 @@ impl<const N: usize, T: PrimUInt, ConstraintF: Field> ToBytesGadget<ConstraintF>
|
||||
for UInt<N, T, ConstraintF>
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<ConstraintF>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<ConstraintF>>, SynthesisError> {
|
||||
Ok(self
|
||||
.to_bits_le()?
|
||||
.chunks(8)
|
||||
@@ -107,23 +172,209 @@ impl<const N: usize, T: PrimUInt, ConstraintF: Field> ToBytesGadget<ConstraintF>
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for [UInt<N, T, F>] {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
let mut bytes = Vec::with_capacity(self.len() * (N / 8));
|
||||
for elem in self {
|
||||
bytes.extend_from_slice(&elem.to_bytes()?);
|
||||
bytes.extend_from_slice(&elem.to_bytes_le()?);
|
||||
}
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for Vec<UInt<N, T, F>> {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
self.as_slice().to_bytes()
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
self.as_slice().to_bytes_le()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for &'a [UInt<N, T, F>] {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
(*self).to_bytes()
|
||||
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
|
||||
(*self).to_bytes_le()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_unary_exhaustive, run_unary_random},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
use ark_test_curves::bls12_381::Fr;
|
||||
|
||||
fn uint_to_bytes_le<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
a: UInt<N, T, F>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = a.cs();
|
||||
let computed = a.to_bytes_le()?;
|
||||
let expected = UInt8::constant_vec(a.value()?.to_le_bytes().as_ref());
|
||||
assert_eq!(expected.len(), computed.len());
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !a.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_to_bytes_be<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
a: UInt<N, T, F>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = a.cs();
|
||||
let computed = a.to_bytes_be()?;
|
||||
let expected = UInt8::constant_vec(a.value()?.to_be_bytes().as_ref());
|
||||
assert_eq!(expected.len(), computed.len());
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !a.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_from_bytes_le<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
expected: UInt<N, T, F>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = expected.cs();
|
||||
let mode = if expected.is_constant() {
|
||||
AllocationMode::Constant
|
||||
} else {
|
||||
AllocationMode::Witness
|
||||
};
|
||||
let computed = {
|
||||
let value = expected.value()?.to_le_bytes();
|
||||
let a = Vec::<UInt8<F>>::new_variable(cs.clone(), || Ok(value.as_ref()), mode)?;
|
||||
UInt::from_bytes_le(&a)?
|
||||
};
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !expected.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_from_bytes_be<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
expected: UInt<N, T, F>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = expected.cs();
|
||||
let mode = if expected.is_constant() {
|
||||
AllocationMode::Constant
|
||||
} else {
|
||||
AllocationMode::Witness
|
||||
};
|
||||
let computed = {
|
||||
let value = expected.value()?.to_be_bytes();
|
||||
let a = Vec::<UInt8<F>>::new_variable(cs.clone(), || Ok(value.as_ref()), mode)?;
|
||||
UInt::from_bytes_be(&a)?
|
||||
};
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !expected.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_to_bytes_le() {
|
||||
run_unary_exhaustive(uint_to_bytes_le::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_to_bytes_le() {
|
||||
run_unary_random::<1000, 16, _, _>(uint_to_bytes_le::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_to_bytes_le() {
|
||||
run_unary_random::<1000, 32, _, _>(uint_to_bytes_le::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_to_bytes_le() {
|
||||
run_unary_random::<1000, 64, _, _>(uint_to_bytes_le::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_to_bytes_le() {
|
||||
run_unary_random::<1000, 128, _, _>(uint_to_bytes_le::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_to_bytes_be() {
|
||||
run_unary_exhaustive(uint_to_bytes_be::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_to_bytes_be() {
|
||||
run_unary_random::<1000, 16, _, _>(uint_to_bytes_be::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_to_bytes_be() {
|
||||
run_unary_random::<1000, 32, _, _>(uint_to_bytes_be::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_to_bytes_be() {
|
||||
run_unary_random::<1000, 64, _, _>(uint_to_bytes_be::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_to_bytes_be() {
|
||||
run_unary_random::<1000, 128, _, _>(uint_to_bytes_be::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_from_bytes_le() {
|
||||
run_unary_exhaustive(uint_from_bytes_le::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_from_bytes_le() {
|
||||
run_unary_random::<1000, 16, _, _>(uint_from_bytes_le::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_from_bytes_le() {
|
||||
run_unary_random::<1000, 32, _, _>(uint_from_bytes_le::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_from_bytes_le() {
|
||||
run_unary_random::<1000, 64, _, _>(uint_from_bytes_le::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_from_bytes_le() {
|
||||
run_unary_random::<1000, 128, _, _>(uint_from_bytes_le::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_from_bytes_be() {
|
||||
run_unary_exhaustive(uint_from_bytes_be::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_from_bytes_be() {
|
||||
run_unary_random::<1000, 16, _, _>(uint_from_bytes_be::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_from_bytes_be() {
|
||||
run_unary_random::<1000, 32, _, _>(uint_from_bytes_be::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_from_bytes_be() {
|
||||
run_unary_random::<1000, 64, _, _>(uint_from_bytes_be::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_from_bytes_be() {
|
||||
run_unary_random::<1000, 128, _, _>(uint_from_bytes_be::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,17 @@ use super::*;
|
||||
impl<const N: usize, T: PrimUInt, F: Field> UInt<N, T, F> {
|
||||
fn _not(&self) -> Result<Self, SynthesisError> {
|
||||
let mut result = self.clone();
|
||||
for a in &mut result.bits {
|
||||
*a = !&*a
|
||||
}
|
||||
result.value = self.value.map(Not::not);
|
||||
result._not_in_place()?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn _not_in_place(&mut self) -> Result<(), SynthesisError> {
|
||||
for a in &mut self.bits {
|
||||
a.not_in_place()?;
|
||||
}
|
||||
self.value = self.value.map(Not::not);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> Not for &'a UInt<N, T, F> {
|
||||
@@ -67,8 +72,9 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> Not for UInt<N, T, F> {
|
||||
/// # }
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
fn not(self) -> Self::Output {
|
||||
self._not().unwrap()
|
||||
fn not(mut self) -> Self::Output {
|
||||
self._not_in_place().unwrap();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
125
src/uint/or.rs
125
src/uint/or.rs
@@ -7,11 +7,16 @@ use super::{PrimUInt, UInt};
|
||||
impl<const N: usize, T: PrimUInt, F: PrimeField> UInt<N, T, F> {
|
||||
fn _or(&self, other: &Self) -> Result<Self, SynthesisError> {
|
||||
let mut result = self.clone();
|
||||
for (a, b) in result.bits.iter_mut().zip(&other.bits) {
|
||||
result._or_in_place(other)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn _or_in_place(&mut self, other: &Self) -> Result<(), SynthesisError> {
|
||||
for (a, b) in self.bits.iter_mut().zip(&other.bits) {
|
||||
*a |= b;
|
||||
}
|
||||
result.value = self.value.and_then(|a| Some(a | other.value?));
|
||||
Ok(result)
|
||||
self.value = self.value.and_then(|a| Some(a | other.value?));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +55,9 @@ impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<&'a Self> for UInt<N,
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: &Self) -> Self::Output {
|
||||
self._or(&other).unwrap()
|
||||
fn bitor(mut self, other: &Self) -> Self::Output {
|
||||
self._or_in_place(&other).unwrap();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +66,7 @@ impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<UInt<N, T, F>> for &'
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: UInt<N, T, F>) -> Self::Output {
|
||||
self._or(&other).unwrap()
|
||||
other | self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +75,43 @@ impl<const N: usize, T: PrimUInt, F: PrimeField> BitOr<Self> for UInt<N, T, F> {
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: Self) -> Self::Output {
|
||||
self._or(&other).unwrap()
|
||||
self | &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: T) -> Self::Output {
|
||||
self | &UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<&'a T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: &'a T) -> Self::Output {
|
||||
self | &UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<&'a T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: &'a T) -> Self::Output {
|
||||
self | &UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOr<T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor(self, other: T) -> Self::Output {
|
||||
self | &UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,16 +141,28 @@ impl<const N: usize, T: PrimUInt, F: PrimeField> BitOrAssign<Self> for UInt<N, T
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor_assign(&mut self, other: Self) {
|
||||
let result = self._or(&other).unwrap();
|
||||
*self = result;
|
||||
self._or_in_place(&other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOrAssign<&'a Self> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor_assign(&mut self, other: &'a Self) {
|
||||
let result = self._or(other).unwrap();
|
||||
*self = result;
|
||||
self._or_in_place(other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: PrimeField> BitOrAssign<T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor_assign(&mut self, other: T) {
|
||||
*self |= &UInt::constant(other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: PrimeField> BitOrAssign<&'a T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitor_assign(&mut self, other: &'a T) {
|
||||
*self |= &UInt::constant(*other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +172,7 @@ mod tests {
|
||||
use crate::{
|
||||
alloc::{AllocVar, AllocationMode},
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_binary_exhaustive, run_binary_random},
|
||||
uint::test_utils::{run_binary_exhaustive_both, run_binary_random_both},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
@@ -149,28 +203,65 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_or_native<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
a: UInt<N, T, F>,
|
||||
b: T,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = a.cs();
|
||||
let computed = &a | &b;
|
||||
let expected_mode = if a.is_constant() {
|
||||
AllocationMode::Constant
|
||||
} else {
|
||||
AllocationMode::Witness
|
||||
};
|
||||
let expected =
|
||||
UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a.value()? | b), expected_mode)?;
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !a.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_or() {
|
||||
run_binary_exhaustive(uint_or::<u8, 8, Fr>).unwrap()
|
||||
run_binary_exhaustive_both(uint_or::<u8, 8, Fr>, uint_or_native::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_or() {
|
||||
run_binary_random::<1000, 16, _, _>(uint_or::<u16, 16, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 16, _, _>(
|
||||
uint_or::<u16, 16, Fr>,
|
||||
uint_or_native::<u16, 16, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_or() {
|
||||
run_binary_random::<1000, 32, _, _>(uint_or::<u32, 32, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 32, _, _>(
|
||||
uint_or::<u32, 32, Fr>,
|
||||
uint_or_native::<u32, 32, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_or() {
|
||||
run_binary_random::<1000, 64, _, _>(uint_or::<u64, 64, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 64, _, _>(
|
||||
uint_or::<u64, 64, Fr>,
|
||||
uint_or_native::<u64, 64, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_or() {
|
||||
run_binary_random::<1000, 128, _, _>(uint_or::<u128, 128, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 128, _, _>(
|
||||
uint_or::<u128, 128, Fr>,
|
||||
uint_or_native::<u128, 128, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,37 @@ impl<const N: usize, T: PrimUInt, ConstraintF: Field> UInt<N, T, ConstraintF> {
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
pub fn rotate_right(&self, by: usize) -> Self {
|
||||
let by = by % N;
|
||||
let mut result = self.clone();
|
||||
// `[T]::rotate_left` corresponds to a `rotate_right` of the bits.
|
||||
result.bits.rotate_left(by);
|
||||
result.value = self.value.map(|v| v.rotate_right(by as u32));
|
||||
result.rotate_right_in_place(by);
|
||||
result
|
||||
}
|
||||
/// Rotates `self` to the right *in place* by `by` steps, wrapping around.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
|
||||
/// // We'll use the BLS12-381 scalar field for our constraints.
|
||||
/// use ark_test_curves::bls12_381::Fr;
|
||||
/// use ark_relations::r1cs::*;
|
||||
/// use ark_r1cs_std::prelude::*;
|
||||
///
|
||||
/// let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
/// let mut a = UInt32::new_witness(cs.clone(), || Ok(0xb301u32))?;
|
||||
/// let b = UInt32::new_witness(cs.clone(), || Ok(0x10000b3))?;
|
||||
///
|
||||
/// a.rotate_right_in_place(8);
|
||||
/// a.enforce_equal(&b)?;
|
||||
/// assert!(cs.is_satisfied().unwrap());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
pub fn rotate_right_in_place(&mut self, by: usize) {
|
||||
let by = by % N;
|
||||
// `[T]::rotate_left` corresponds to a `rotate_right` of the bits.
|
||||
self.bits.rotate_left(by);
|
||||
self.value = self.value.map(|v| v.rotate_right(by as u32));
|
||||
}
|
||||
|
||||
/// Rotates `self` to the left by `by` steps, wrapping around.
|
||||
///
|
||||
@@ -51,13 +75,37 @@ impl<const N: usize, T: PrimUInt, ConstraintF: Field> UInt<N, T, ConstraintF> {
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
pub fn rotate_left(&self, by: usize) -> Self {
|
||||
let by = by % N;
|
||||
let mut result = self.clone();
|
||||
// `[T]::rotate_right` corresponds to a `rotate_left` of the bits.
|
||||
result.bits.rotate_right(by);
|
||||
result.value = self.value.map(|v| v.rotate_left(by as u32));
|
||||
result.rotate_left_in_place(by);
|
||||
result
|
||||
}
|
||||
|
||||
/// Rotates `self` to the left *in place* by `by` steps, wrapping around.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
|
||||
/// // We'll use the BLS12-381 scalar field for our constraints.
|
||||
/// use ark_test_curves::bls12_381::Fr;
|
||||
/// use ark_relations::r1cs::*;
|
||||
/// use ark_r1cs_std::prelude::*;
|
||||
///
|
||||
/// let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
/// let mut a = UInt32::new_witness(cs.clone(), || Ok(0x10000b3))?;
|
||||
/// let b = UInt32::new_witness(cs.clone(), || Ok(0xb301u32))?;
|
||||
///
|
||||
/// a.rotate_left_in_place(8);
|
||||
/// a.enforce_equal(&b)?;
|
||||
/// assert!(cs.is_satisfied().unwrap());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn rotate_left_in_place(&mut self, by: usize) {
|
||||
let by = by % N;
|
||||
// `[T]::rotate_right` corresponds to a `rotate_left` of the bits.
|
||||
self.bits.rotate_right(by);
|
||||
self.value = self.value.map(|v| v.rotate_left(by as u32));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -99,7 +99,7 @@ mod tests {
|
||||
use crate::{
|
||||
alloc::{AllocVar, AllocationMode},
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_binary_exhaustive_with_native, run_binary_random_with_native},
|
||||
uint::test_utils::{run_binary_exhaustive_native_only, run_binary_random_native_only},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
@@ -129,26 +129,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn u8_shl() {
|
||||
run_binary_exhaustive_with_native(uint_shl::<u8, 8, Fr>).unwrap()
|
||||
run_binary_exhaustive_native_only(uint_shl::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_shl() {
|
||||
run_binary_random_with_native::<1000, 16, _, _>(uint_shl::<u16, 16, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 16, _, _>(uint_shl::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_shl() {
|
||||
run_binary_random_with_native::<1000, 32, _, _>(uint_shl::<u32, 32, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 32, _, _>(uint_shl::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_shl() {
|
||||
run_binary_random_with_native::<1000, 64, _, _>(uint_shl::<u64, 64, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 64, _, _>(uint_shl::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_shl() {
|
||||
run_binary_random_with_native::<1000, 128, _, _>(uint_shl::<u128, 128, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 128, _, _>(uint_shl::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ mod tests {
|
||||
use crate::{
|
||||
alloc::{AllocVar, AllocationMode},
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_binary_exhaustive_with_native, run_binary_random_with_native},
|
||||
uint::test_utils::{run_binary_exhaustive_native_only, run_binary_random_native_only},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
@@ -129,26 +129,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn u8_shr() {
|
||||
run_binary_exhaustive_with_native(uint_shr::<u8, 8, Fr>).unwrap()
|
||||
run_binary_exhaustive_native_only(uint_shr::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_shr() {
|
||||
run_binary_random_with_native::<1000, 16, _, _>(uint_shr::<u16, 16, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 16, _, _>(uint_shr::<u16, 16, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_shr() {
|
||||
run_binary_random_with_native::<1000, 32, _, _>(uint_shr::<u32, 32, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 32, _, _>(uint_shr::<u32, 32, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_shr() {
|
||||
run_binary_random_with_native::<1000, 64, _, _>(uint_shr::<u64, 64, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 64, _, _>(uint_shr::<u64, 64, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_shr() {
|
||||
run_binary_random_with_native::<1000, 128, _, _>(uint_shr::<u128, 128, Fr>).unwrap()
|
||||
run_binary_random_native_only::<1000, 128, _, _>(uint_shr::<u128, 128, Fr>).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,29 @@ pub(crate) fn test_binary_op_with_native<T: PrimUInt, const N: usize, F: PrimeFi
|
||||
test(a, b)
|
||||
}
|
||||
|
||||
pub(crate) fn run_binary_random_both<const ITERATIONS: usize, const N: usize, T, F>(
|
||||
test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
|
||||
test_native: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
T: PrimUInt,
|
||||
F: PrimeField,
|
||||
{
|
||||
let mut rng = ark_std::test_rng();
|
||||
|
||||
for _ in 0..ITERATIONS {
|
||||
for mode_a in modes() {
|
||||
let a = T::rand(&mut rng);
|
||||
for mode_b in modes() {
|
||||
let b = T::rand(&mut rng);
|
||||
test_binary_op(a, b, mode_a, mode_b, test)?;
|
||||
test_binary_op_with_native(a, b, mode_a, test_native)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn run_binary_random<const ITERATIONS: usize, const N: usize, T, F>(
|
||||
test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
|
||||
) -> Result<(), SynthesisError>
|
||||
@@ -76,7 +99,25 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn run_binary_random_with_native<const ITERATIONS: usize, const N: usize, T, F>(
|
||||
pub(crate) fn run_binary_exhaustive_both<const N: usize, T, F>(
|
||||
test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
|
||||
test_native: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
T: PrimUInt,
|
||||
F: PrimeField,
|
||||
RangeInclusive<T>: Iterator<Item = T>,
|
||||
{
|
||||
for (mode_a, a) in test_utils::combination(T::min_value()..=T::max_value()) {
|
||||
for (mode_b, b) in test_utils::combination(T::min_value()..=T::max_value()) {
|
||||
test_binary_op(a, b, mode_a, mode_b, test)?;
|
||||
test_binary_op_with_native(a, b, mode_a, test_native)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn run_binary_random_native_only<const ITERATIONS: usize, const N: usize, T, F>(
|
||||
test: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
@@ -95,7 +136,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn run_binary_exhaustive_with_native<const N: usize, T, F>(
|
||||
pub(crate) fn run_binary_exhaustive_native_only<const N: usize, T, F>(
|
||||
test: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
|
||||
125
src/uint/xor.rs
125
src/uint/xor.rs
@@ -7,11 +7,16 @@ use super::*;
|
||||
impl<const N: usize, T: PrimUInt, F: Field> UInt<N, T, F> {
|
||||
fn _xor(&self, other: &Self) -> Result<Self, SynthesisError> {
|
||||
let mut result = self.clone();
|
||||
for (a, b) in result.bits.iter_mut().zip(&other.bits) {
|
||||
result._xor_in_place(other)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn _xor_in_place(&mut self, other: &Self) -> Result<(), SynthesisError> {
|
||||
for (a, b) in self.bits.iter_mut().zip(&other.bits) {
|
||||
*a ^= b;
|
||||
}
|
||||
result.value = self.value.and_then(|a| Some(a ^ other.value?));
|
||||
Ok(result)
|
||||
self.value = self.value.and_then(|a| Some(a ^ other.value?));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +54,9 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<&'a Self> for UInt<N, T,
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: &Self) -> Self::Output {
|
||||
self._xor(&other).unwrap()
|
||||
fn bitxor(mut self, other: &Self) -> Self::Output {
|
||||
self._xor_in_place(&other).unwrap();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +65,7 @@ impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<UInt<N, T, F>> for &'a UI
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: UInt<N, T, F>) -> Self::Output {
|
||||
self._xor(&other).unwrap()
|
||||
other ^ self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +74,43 @@ impl<const N: usize, T: PrimUInt, F: Field> BitXor<Self> for UInt<N, T, F> {
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: Self) -> Self::Output {
|
||||
self._xor(&other).unwrap()
|
||||
self ^ &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: T) -> Self::Output {
|
||||
self ^ &UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<&'a T> for UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: &'a T) -> Self::Output {
|
||||
self ^ &UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<&'a T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: &'a T) -> Self::Output {
|
||||
self ^ UInt::constant(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXor<T> for &'a UInt<N, T, F> {
|
||||
type Output = UInt<N, T, F>;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor(self, other: T) -> Self::Output {
|
||||
self ^ UInt::constant(other)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,16 +140,28 @@ impl<const N: usize, T: PrimUInt, F: Field> BitXorAssign<Self> for UInt<N, T, F>
|
||||
/// ```
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor_assign(&mut self, other: Self) {
|
||||
let result = self._xor(&other).unwrap();
|
||||
*self = result;
|
||||
self._xor_in_place(&other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXorAssign<&'a Self> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor_assign(&mut self, other: &'a Self) {
|
||||
let result = self._xor(other).unwrap();
|
||||
*self = result;
|
||||
self._xor_in_place(other).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T: PrimUInt, F: Field> BitXorAssign<T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor_assign(&mut self, other: T) {
|
||||
*self ^= Self::constant(other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const N: usize, T: PrimUInt, F: Field> BitXorAssign<&'a T> for UInt<N, T, F> {
|
||||
#[tracing::instrument(target = "r1cs", skip(self, other))]
|
||||
fn bitxor_assign(&mut self, other: &'a T) {
|
||||
*self ^= Self::constant(*other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +171,7 @@ mod tests {
|
||||
use crate::{
|
||||
alloc::{AllocVar, AllocationMode},
|
||||
prelude::EqGadget,
|
||||
uint::test_utils::{run_binary_exhaustive, run_binary_random},
|
||||
uint::test_utils::{run_binary_exhaustive_both, run_binary_random_both},
|
||||
R1CSVar,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
@@ -148,28 +202,65 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uint_xor_native<T: PrimUInt, const N: usize, F: PrimeField>(
|
||||
a: UInt<N, T, F>,
|
||||
b: T,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let cs = a.cs();
|
||||
let computed = &a ^ &b;
|
||||
let expected_mode = if a.is_constant() {
|
||||
AllocationMode::Constant
|
||||
} else {
|
||||
AllocationMode::Witness
|
||||
};
|
||||
let expected =
|
||||
UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a.value()? ^ b), expected_mode)?;
|
||||
assert_eq!(expected.value(), computed.value());
|
||||
expected.enforce_equal(&computed)?;
|
||||
if !a.is_constant() {
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u8_xor() {
|
||||
run_binary_exhaustive(uint_xor::<u8, 8, Fr>).unwrap()
|
||||
run_binary_exhaustive_both(uint_xor::<u8, 8, Fr>, uint_xor_native::<u8, 8, Fr>).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u16_xor() {
|
||||
run_binary_random::<1000, 16, _, _>(uint_xor::<u16, 16, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 16, _, _>(
|
||||
uint_xor::<u16, 16, Fr>,
|
||||
uint_xor_native::<u16, 16, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u32_xor() {
|
||||
run_binary_random::<1000, 32, _, _>(uint_xor::<u32, 32, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 32, _, _>(
|
||||
uint_xor::<u32, 32, Fr>,
|
||||
uint_xor_native::<u32, 32, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u64_xor() {
|
||||
run_binary_random::<1000, 64, _, _>(uint_xor::<u64, 64, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 64, _, _>(
|
||||
uint_xor::<u64, 64, Fr>,
|
||||
uint_xor_native::<u64, 64, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn u128_xor() {
|
||||
run_binary_random::<1000, 128, _, _>(uint_xor::<u128, 128, Fr>).unwrap()
|
||||
run_binary_random_both::<1000, 128, _, _>(
|
||||
uint_xor::<u128, 128, Fr>,
|
||||
uint_xor_native::<u128, 128, Fr>,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user