Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big integer PoC #1304

Open
wants to merge 13 commits into
base: develop
Choose a base branch
from
Next Next commit
bigint wip
  • Loading branch information
dark64 committed Dec 6, 2022
commit 13aa6ce5fabd45d89329bf33743561017e9d2440
64 changes: 64 additions & 0 deletions zokrates_stdlib/stdlib/bigint.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from "field" import FIELD_SIZE_IN_BITS;
import "utils/pack/bool/unpack_unchecked" as unpack;

struct bigint<N> {
field[N] limbs;
}

def bigint_from_limbs<N, P>(field[N] values) -> bigint<P> {
assert(P >= N, "invalid number of limbs");
return bigint { limbs: [...values, ...[0; P-N]] };
}

// Big integer addition
def bigint_add<N, F>(bigint<N> a, bigint<N> b) -> bigint<N> {
assert(F < FIELD_SIZE_IN_BITS - 1);
bigint<N> mut c = bigint_from_limbs([0; N]);
field mut carry = 0;
for u32 i in 0..N {
field sum = a.limbs[i] + b.limbs[i] + carry;
bool[F + 1] bits = unpack(sum);
carry = bits[0] ? 1 : 0;
c.limbs[i] = sum - carry * (2**F);
}
return c;
}

// Big integer subtraction
// assumes a >= b
def bigint_sub<N, F>(bigint<N> a, bigint<N> b) -> bigint<N> {
assert(F < FIELD_SIZE_IN_BITS - 1);
bigint<N> mut c = bigint_from_limbs([0; N]);
field mut borrow = 0;
for u32 i in 0..N {
c.limbs[i] = borrow * (2**F) + (a.limbs[i] - b.limbs[i]);
bool[F + 1] bits = unpack(a.limbs[i] + (2**F) - b.limbs[i]);
borrow = bits[0] ? 0 : 1;
}
return c;
}

// Right shift by `nlimbs`
def bigint_rshift_limb<N>(bigint<N> mut a, u32 nlimbs) -> bigint<N> {
assert(nlimbs < N);
for u32 i in 0..N-nlimbs {
a.limbs[i] = a.limbs[i + nlimbs];
}
for u32 i in N-nlimbs..N {
a.limbs[i] = 0;
}
return a;
}

// Left shift by `nlimbs`
def bigint_lshift_limb<N>(bigint<N> mut a, u32 nlimbs) -> bigint<N> {
assert(nlimbs < N);
for u32 i in 0..N-nlimbs {
u32 j = N - i - 1;
a.limbs[j] = a.limbs[j - nlimbs];
}
for u32 i in 0..nlimbs {
a.limbs[i] = 0;
}
return a;
}
36 changes: 36 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_add.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"max_constraint_count": 22,
"curves": ["Bn128"],
"tests": [
{
"input": {
"values": [{ "limbs": ["2", "2"] }, { "limbs": ["2", "0"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["4", "2"] }
}
}
},
{
"input": {
"values": [{ "limbs": ["255", "0"] }, { "limbs": ["1", "0"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["0", "1"] }
}
}
},
{
"input": {
"values": [{ "limbs": ["129", "1"] }, { "limbs": ["128", "1"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["1", "3"] }
}
}
}
]
}
6 changes: 6 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_add.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from "bigint" import bigint, bigint_add;

def main(bigint<2> a, bigint<2> b) -> bigint<2> {
bigint<2> c = bigint_add::<2, 8>(a, b);
return c;
}
16 changes: 16 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_lshift_limb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"max_constraint_count": 22,
"curves": ["Bn128"],
"tests": [
{
"input": {
"values": [{ "limbs": ["2", "2"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["0", "2"] }
}
}
}
]
}
6 changes: 6 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_lshift_limb.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from "bigint" import bigint, bigint_lshift_limb;

def main(bigint<2> a) -> bigint<2> {
bigint<2> c = bigint_lshift_limb(a, 1);
return c;
}
16 changes: 16 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_rshift_limb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"max_constraint_count": 22,
"curves": ["Bn128"],
"tests": [
{
"input": {
"values": [{ "limbs": ["2", "2"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["2", "0"] }
}
}
}
]
}
6 changes: 6 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_rshift_limb.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from "bigint" import bigint, bigint_rshift_limb;

def main(bigint<2> a) -> bigint<2> {
bigint<2> c = bigint_rshift_limb(a, 1);
return c;
}
36 changes: 36 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_sub.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"max_constraint_count": 22,
"curves": ["Bn128"],
"tests": [
{
"input": {
"values": [{ "limbs": ["2", "2"] }, { "limbs": ["2", "0"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["0", "2"] }
}
}
},
{
"input": {
"values": [{ "limbs": ["255", "0"] }, { "limbs": ["1", "0"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["254", "0"] }
}
}
},
{
"input": {
"values": [{ "limbs": ["129", "1"] }, { "limbs": ["128", "1"] }]
},
"output": {
"Ok": {
"value": { "limbs": ["1", "0"] }
}
}
}
]
}
6 changes: 6 additions & 0 deletions zokrates_stdlib/tests/tests/bigint/bigint_sub.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from "bigint" import bigint, bigint_sub;

def main(bigint<2> a, bigint<2> b) -> bigint<2> {
bigint<2> c = bigint_sub::<2, 8>(a, b);
return c;
}