arnaucube
arnaucube/circomPublic Self-hosted repository
If added
Jordi Baylina jordi@baylina.cat
Sat, 07 Dec 2019 14:15:27 +0100
commit

2a45647274860e866361343baae8f69c0f2c1c5d

parent

305bc7456f6e49c461e1094362163b50fbbf2873

M c/zqfield.cpp → c/zqfield.cpp

@@ -33,6 +33,51 @@ mpz_set(*r, zero);

} } +void ZqField::eq(PBigInt r, PBigInt a, PBigInt b) { + int c = mpz_cmp(*a, *b); + if (c==0) { + mpz_set(*r, one); + } else { + mpz_set(*r, zero); + } +} + +void ZqField::gt(PBigInt r, PBigInt a, PBigInt b) { + int c = mpz_cmp(*a, *b); + if (c>0) { + mpz_set(*r, one); + } else { + mpz_set(*r, zero); + } +} + +void ZqField::leq(PBigInt r, PBigInt a, PBigInt b) { + int c = mpz_cmp(*a, *b); + if (c<=0) { + mpz_set(*r, one); + } else { + mpz_set(*r, zero); + } +} + +void ZqField::geq(PBigInt r, PBigInt a, PBigInt b) { + int c = mpz_cmp(*a, *b); + if (c>=0) { + mpz_set(*r, one); + } else { + mpz_set(*r, zero); + } +} + +void ZqField::neq(PBigInt r, PBigInt a, PBigInt b) { + int c = mpz_cmp(*a, *b); + if (c!=0) { + mpz_set(*r, one); + } else { + mpz_set(*r, zero); + } +} + int ZqField::isTrue(PBigInt a) { return mpz_sgn(*a); }
M c/zqfield.h → c/zqfield.h

@@ -17,6 +17,11 @@ void copyn(PBigInt a, PBigInt b, int n);

void add(PBigInt r,PBigInt a, PBigInt b); void mul(PBigInt r,PBigInt a, PBigInt b); void lt(PBigInt r, PBigInt a, PBigInt b); + void eq(PBigInt r, PBigInt a, PBigInt b); + void gt(PBigInt r, PBigInt a, PBigInt b); + void leq(PBigInt r, PBigInt a, PBigInt b); + void geq(PBigInt r, PBigInt a, PBigInt b); + void neq(PBigInt r, PBigInt a, PBigInt b); int isTrue(PBigInt a); };
M src/c_gen.js → src/c_gen.js

@@ -190,15 +190,15 @@ return genShr(ctx, ast);

} else if (ast.op == "<") { return genBinaryOp(ctx, ast, "lt"); } else if (ast.op == ">") { - return genGt(ctx, ast); + return genBinaryOp(ctx, ast, "gt"); } else if (ast.op == "<=") { - return genLte(ctx, ast); + return genBinaryOp(ctx, ast, "leq"); } else if (ast.op == ">=") { - return genGte(ctx, ast); + return genBinaryOp(ctx, ast, "geq"); } else if (ast.op == "==") { - return genEq(ctx, ast); + return genBinaryOp(ctx, ast, "eq"); } else if (ast.op == "!=") { - return genNeq(ctx, ast); + return genBinaryOp(ctx, ast, "neq"); } else if (ast.op == "?") { return genTerCon(ctx, ast); } else {

@@ -280,6 +280,11 @@ const init = getSource(ctx, ast.init);

const condition = getSource(ctx, ast.condition); const step = getSource(ctx, ast.step); ctx.code += `\n/* for (${init},${condition},${step}) */\n`; +} + +function genIfSrcComment(ctx, ast) { + const condition = getSource(ctx, ast.condition); + ctx.code += `\n/* if (${condition}) */\n`; }

@@ -835,6 +840,8 @@ let condVar;

const condRef = gen(ctx, ast.condition); + if (ctx.error) return; + const cond = ctx.refs[condRef]; if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");

@@ -867,6 +874,8 @@ gen(ctx, ast.step);

if (ctx.error) return; const condRef2 = gen(ctx, ast.condition); + if (ctx.error) return; + const cond2 = ctx.refs[condRef2]; if (!inLoop) {

@@ -917,16 +926,45 @@ return `{\n${body}\n}\n`;

} function genIf(ctx, ast) { - const condition = gen(ctx, ast.condition); - if (ctx.error) return; - const thenBody = gen(ctx, ast.then); + genIfSrcComment(ctx, ast); + const condRef = gen(ctx, ast.condition); if (ctx.error) return; - if (ast.else) { - const elseBody = gen(ctx, ast.else); + const cond = ctx.refs[condRef]; + if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array"); + + if (cond.used) { + enterConditionalCode(ctx, ast); + + ctx.code += `if (ctx->field->isTrue(${cond.label})) {\n`; + + const oldCode = ctx.code; + ctx.code = ""; + + gen(ctx, ast.then); if (ctx.error) return; - return `if (bigInt(${condition}).neq(bigInt(0))) {\n${thenBody}\n} else {\n${elseBody}\n}\n`; + + ctx.code = oldCode + utils.ident(ctx.code); + + if (ast.else) { + ctx.code += "} else {\n"; + const oldCode = ctx.code; + ctx.code = ""; + gen(ctx, ast.else); + if (ctx.error) return; + ctx.code = oldCode + utils.ident(ctx.code); + } + + ctx.code += "}\n"; + } else { - return `if (bigInt(${condition}).neq(bigInt(0))) {\n${thenBody}\n}\n`; + if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned"); + if (!cond.value[0].isZero()) { + gen(ctx, ast.then); + } else { + if (ast.else) { + gen(ctx, ast.else); + } + } } }
M src/zqfield.js → src/zqfield.js

@@ -17,5 +17,25 @@ lt(a, b) {

return a.lt(b) ? bigInt(1) : bigInt(0); } + eq(a, b) { + return a.eq(b) ? bigInt(1) : bigInt(0); + } + + gt(a, b) { + return a.gt(b) ? bigInt(1) : bigInt(0); + } + + leq(a, b) { + return a.leq(b) ? bigInt(1) : bigInt(0); + } + + geq(a, b) { + return a.geq(b) ? bigInt(1) : bigInt(0); + } + + neq(a, b) { + return a.neq(b) ? bigInt(1) : bigInt(0); + } + };
M test/basiccases.js → test/basiccases.js

@@ -107,4 +107,26 @@ [{in: __P__.minus(2)}, {out: [__P__.minus(1), 4, 39]}],

] ); }); + it("if unrolled", async () => { + await doTest( + "ifunrolled.circom", + [ + [{in: 0}, {out: [1, 3, 6]}], + [{in: 10}, {out: [11, 13, 16]}], + [{in: __P__.minus(2)}, {out: [__P__.minus(1), 1, 4]}], + ] + ); + }); + it("if rolled", async () => { + await doTest( + "ifrolled.circom", + [ + [{in: 0}, {out: [1, 0, 0]}], + [{in: 1}, {out: [0, 1, 0]}], + [{in: 2}, {out: [0, 0, 1]}], + [{in: 3}, {out: [0, 0, 0]}], + [{in: __P__.minus(2)}, {out: [0,0,0]}], + ] + ); + }); });
A test/circuits/ifrolled.circom

@@ -0,0 +1,26 @@

+template Main() { + signal input in; + signal output out[3]; + + if (in == 0) { + out[0] <-- 1; // TRUE + } + if (in != 0) { + out[0] <-- 0; + } + + if (in == 1) { + out[1] <-- 1; // TRUE + } else { + out[1] <-- 0; + } + + if (in == 2) { + out[2] <-- 1; + } else { + out[2] <-- 0; // TRUE + } + +} + +component main = Main();
A test/circuits/ifunrolled.circom

@@ -0,0 +1,31 @@

+ + +template Main() { + signal input in; + signal output out[3]; + + var c = 1; + if (c == 1) { + out[0] <== in +1; // TRUE + } + if (c == 0) { + out[0] <== in +2; + } + + c = c +1; + if (c == 2) { + out[1] <== in + 3; // TRUE + } else { + out[1] <== in + 4; + } + + c = c +1; + if (c == 2) { + out[2] <== in + 5; + } else { + out[2] <== in + 6; // TRUE + } + +} + +component main = Main();