mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
If added
This commit is contained in:
@@ -33,6 +33,51 @@ void ZqField::lt(PBigInt r, PBigInt a, PBigInt b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
int ZqField::isTrue(PBigInt a) {
|
||||||
return mpz_sgn(*a);
|
return mpz_sgn(*a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ public:
|
|||||||
void add(PBigInt r,PBigInt a, PBigInt b);
|
void add(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void mul(PBigInt r,PBigInt a, PBigInt b);
|
void mul(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void lt(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);
|
int isTrue(PBigInt a);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
58
src/c_gen.js
58
src/c_gen.js
@@ -190,15 +190,15 @@ function gen(ctx, ast) {
|
|||||||
} else if (ast.op == "<") {
|
} else if (ast.op == "<") {
|
||||||
return genBinaryOp(ctx, ast, "lt");
|
return genBinaryOp(ctx, ast, "lt");
|
||||||
} else if (ast.op == ">") {
|
} else if (ast.op == ">") {
|
||||||
return genGt(ctx, ast);
|
return genBinaryOp(ctx, ast, "gt");
|
||||||
} else if (ast.op == "<=") {
|
} else if (ast.op == "<=") {
|
||||||
return genLte(ctx, ast);
|
return genBinaryOp(ctx, ast, "leq");
|
||||||
} else if (ast.op == ">=") {
|
} else if (ast.op == ">=") {
|
||||||
return genGte(ctx, ast);
|
return genBinaryOp(ctx, ast, "geq");
|
||||||
} else if (ast.op == "==") {
|
} else if (ast.op == "==") {
|
||||||
return genEq(ctx, ast);
|
return genBinaryOp(ctx, ast, "eq");
|
||||||
} else if (ast.op == "!=") {
|
} else if (ast.op == "!=") {
|
||||||
return genNeq(ctx, ast);
|
return genBinaryOp(ctx, ast, "neq");
|
||||||
} else if (ast.op == "?") {
|
} else if (ast.op == "?") {
|
||||||
return genTerCon(ctx, ast);
|
return genTerCon(ctx, ast);
|
||||||
} else {
|
} else {
|
||||||
@@ -282,6 +282,11 @@ function genForSrcComment(ctx, ast) {
|
|||||||
ctx.code += `\n/* for (${init},${condition},${step}) */\n`;
|
ctx.code += `\n/* for (${init},${condition},${step}) */\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genIfSrcComment(ctx, ast) {
|
||||||
|
const condition = getSource(ctx, ast.condition);
|
||||||
|
ctx.code += `\n/* if (${condition}) */\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function genDeclareComponent(ctx, ast) {
|
function genDeclareComponent(ctx, ast) {
|
||||||
return ast.refId;
|
return ast.refId;
|
||||||
@@ -835,6 +840,8 @@ function genFor(ctx, ast) {
|
|||||||
|
|
||||||
|
|
||||||
const condRef = gen(ctx, ast.condition);
|
const condRef = gen(ctx, ast.condition);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
const cond = ctx.refs[condRef];
|
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 (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
|
||||||
|
|
||||||
@@ -867,6 +874,8 @@ function genFor(ctx, ast) {
|
|||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|
||||||
const condRef2 = gen(ctx, ast.condition);
|
const condRef2 = gen(ctx, ast.condition);
|
||||||
|
if (ctx.error) return;
|
||||||
|
|
||||||
const cond2 = ctx.refs[condRef2];
|
const cond2 = ctx.refs[condRef2];
|
||||||
|
|
||||||
if (!inLoop) {
|
if (!inLoop) {
|
||||||
@@ -917,16 +926,45 @@ function genCompute(ctx, ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function genIf(ctx, ast) {
|
function genIf(ctx, ast) {
|
||||||
const condition = gen(ctx, ast.condition);
|
genIfSrcComment(ctx, ast);
|
||||||
|
const condRef = gen(ctx, ast.condition);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
const thenBody = gen(ctx, ast.then);
|
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;
|
if (ctx.error) return;
|
||||||
|
|
||||||
|
ctx.code = oldCode + utils.ident(ctx.code);
|
||||||
|
|
||||||
if (ast.else) {
|
if (ast.else) {
|
||||||
const elseBody = gen(ctx, ast.else);
|
ctx.code += "} else {\n";
|
||||||
|
const oldCode = ctx.code;
|
||||||
|
ctx.code = "";
|
||||||
|
gen(ctx, ast.else);
|
||||||
if (ctx.error) return;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.code += "}\n";
|
||||||
|
|
||||||
} else {
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,5 +17,25 @@ module.exports = class ZqField {
|
|||||||
return a.lt(b) ? bigInt(1) : bigInt(0);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -107,4 +107,26 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
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]}],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
26
test/circuits/ifrolled.circom
Normal file
26
test/circuits/ifrolled.circom
Normal file
@@ -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();
|
||||||
31
test/circuits/ifunrolled.circom
Normal file
31
test/circuits/ifunrolled.circom
Normal file
@@ -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();
|
||||||
Reference in New Issue
Block a user