mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-10 16:01:28 +01:00
Add UInt128 for u128 (#21)
This commit is contained in:
@@ -20,13 +20,15 @@ ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features
|
|||||||
|
|
||||||
derivative = { version = "2", features = ["use_core"] }
|
derivative = { version = "2", features = ["use_core"] }
|
||||||
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] }
|
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] }
|
||||||
|
num-bigint = {version = "0.3", default-features = false }
|
||||||
|
num-traits = {version = "0.2", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = { version = "0.7", default-features = false }
|
rand = { version = "0.7", default-features = false }
|
||||||
rand_xorshift = "0.2"
|
rand_xorshift = "0.2"
|
||||||
ark-test-curves = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = ["bls12_381_scalar_field"] }
|
ark-test-curves = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = ["bls12_381_scalar_field", "mnt4_753_scalar_field"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [ "ark-ff/std", "ark-relations/std", "ark-std/std" ]
|
std = [ "ark-ff/std", "ark-relations/std", "ark-std/std", "num-bigint/std" ]
|
||||||
parallel = [ "std", "ark-ff/parallel" ]
|
parallel = [ "std", "ark-ff/parallel" ]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ pub mod uint;
|
|||||||
make_uint!(UInt16, 16, u16, uint16, "16");
|
make_uint!(UInt16, 16, u16, uint16, "16");
|
||||||
make_uint!(UInt32, 32, u32, uint32, "32");
|
make_uint!(UInt32, 32, u32, uint32, "32");
|
||||||
make_uint!(UInt64, 64, u64, uint64, "64");
|
make_uint!(UInt64, 64, u64, uint64, "64");
|
||||||
|
make_uint!(UInt128, 128, u128, uint128, "128");
|
||||||
|
|
||||||
/// Specifies constraints for conversion to a little-endian bit representation
|
/// Specifies constraints for conversion to a little-endian bit representation
|
||||||
/// of `self`.
|
/// of `self`.
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ macro_rules! make_uint {
|
|||||||
#[doc = $native_doc_name]
|
#[doc = $native_doc_name]
|
||||||
#[doc = "`type."]
|
#[doc = "`type."]
|
||||||
pub mod $mod_name {
|
pub mod $mod_name {
|
||||||
use ark_ff::{Field, FpParameters, PrimeField};
|
use ark_ff::{Field, FpParameters, One, PrimeField, Zero};
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::cast::ToPrimitive;
|
||||||
|
|
||||||
use ark_relations::r1cs::{
|
use ark_relations::r1cs::{
|
||||||
ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable,
|
ConstraintSystemRef, LinearCombination, Namespace, SynthesisError, Variable,
|
||||||
@@ -183,6 +185,9 @@ macro_rules! make_uint {
|
|||||||
// in the scalar field
|
// in the scalar field
|
||||||
assert!(F::Params::MODULUS_BITS >= 2 * $size);
|
assert!(F::Params::MODULUS_BITS >= 2 * $size);
|
||||||
|
|
||||||
|
// Support up to 128
|
||||||
|
assert!($size <= 128);
|
||||||
|
|
||||||
assert!(operands.len() >= 1);
|
assert!(operands.len() >= 1);
|
||||||
assert!($size * operands.len() <= F::Params::MODULUS_BITS as usize);
|
assert!($size * operands.len() <= F::Params::MODULUS_BITS as usize);
|
||||||
|
|
||||||
@@ -192,10 +197,10 @@ macro_rules! make_uint {
|
|||||||
|
|
||||||
// Compute the maximum value of the sum so we allocate enough bits for
|
// Compute the maximum value of the sum so we allocate enough bits for
|
||||||
// the result
|
// the result
|
||||||
let mut max_value = (operands.len() as u128) * u128::from($native::max_value());
|
let mut max_value = BigUint::from($native::max_value()) * BigUint::from(operands.len());
|
||||||
|
|
||||||
// Keep track of the resulting value
|
// Keep track of the resulting value
|
||||||
let mut result_value = Some(0u128);
|
let mut result_value = Some(BigUint::zero());
|
||||||
|
|
||||||
// This is a linear combination that we will enforce to be "zero"
|
// This is a linear combination that we will enforce to be "zero"
|
||||||
let mut lc = LinearCombination::zero();
|
let mut lc = LinearCombination::zero();
|
||||||
@@ -207,7 +212,7 @@ macro_rules! make_uint {
|
|||||||
// Accumulate the value
|
// Accumulate the value
|
||||||
match op.value {
|
match op.value {
|
||||||
Some(val) => {
|
Some(val) => {
|
||||||
result_value.as_mut().map(|v| *v += u128::from(val));
|
result_value.as_mut().map(|v| *v += BigUint::from(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
@@ -246,7 +251,12 @@ macro_rules! make_uint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The value of the actual result is modulo 2^$size
|
// The value of the actual result is modulo 2^$size
|
||||||
let modular_value = result_value.map(|v| v as $native);
|
let modular_value = result_value.clone().map(|v|
|
||||||
|
{
|
||||||
|
let modulus = BigUint::from(1u64) << ($size as u32);
|
||||||
|
(v % modulus).to_u128().unwrap() as $native
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if all_constants && modular_value.is_some() {
|
if all_constants && modular_value.is_some() {
|
||||||
// We can just return a constant, rather than
|
// We can just return a constant, rather than
|
||||||
@@ -262,11 +272,9 @@ macro_rules! make_uint {
|
|||||||
// Allocate each bit_gadget of the result
|
// Allocate each bit_gadget of the result
|
||||||
let mut coeff = F::one();
|
let mut coeff = F::one();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while max_value != 0 {
|
while max_value != BigUint::zero() {
|
||||||
// Allocate the bit_gadget
|
// Allocate the bit_gadget
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || {
|
let b = AllocatedBit::new_witness(cs.clone(), || result_value.clone().map(|v| (v >> i) & BigUint::one() == BigUint::one()).get())?;
|
||||||
result_value.map(|v| (v >> i) & 1 == 1).get()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Subtract this bit_gadget from the linear combination to ensure the sums
|
// Subtract this bit_gadget from the linear combination to ensure the sums
|
||||||
// balance out
|
// balance out
|
||||||
@@ -384,7 +392,7 @@ macro_rules! make_uint {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::$name;
|
use super::$name;
|
||||||
use crate::{bits::boolean::Boolean, prelude::*, Vec};
|
use crate::{bits::boolean::Boolean, prelude::*, Vec};
|
||||||
use ark_test_curves::bls12_381::Fr;
|
use ark_test_curves::mnt4_753::Fr;
|
||||||
use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
|
use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
@@ -517,7 +525,6 @@ macro_rules! make_uint {
|
|||||||
let r = $name::addmany(&[r, c_bit, d_bit]).unwrap();
|
let r = $name::addmany(&[r, c_bit, d_bit]).unwrap();
|
||||||
|
|
||||||
assert!(cs.is_satisfied().unwrap());
|
assert!(cs.is_satisfied().unwrap());
|
||||||
|
|
||||||
assert!(r.value == Some(expected));
|
assert!(r.value == Some(expected));
|
||||||
|
|
||||||
for b in r.bits.iter() {
|
for b in r.bits.iter() {
|
||||||
|
|||||||
Reference in New Issue
Block a user