mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
All Bit and logical operators working
This commit is contained in:
@@ -5,6 +5,10 @@ ZqField::ZqField(PBigInt ap) {
|
|||||||
mpz_init_set(p, *ap);
|
mpz_init_set(p, *ap);
|
||||||
mpz_init_set_ui(zero, 0);
|
mpz_init_set_ui(zero, 0);
|
||||||
mpz_init_set_ui(one, 1);
|
mpz_init_set_ui(one, 1);
|
||||||
|
nBits = mpz_sizeinbase (p, 2);
|
||||||
|
mpz_init(mask);
|
||||||
|
mpz_mul_2exp(mask, one, nBits-1);
|
||||||
|
mpz_sub(mask, mask, one);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZqField::~ZqField() {
|
ZqField::~ZqField() {
|
||||||
@@ -30,6 +34,14 @@ void ZqField::sub(PBigInt r, PBigInt a, PBigInt b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZqField::neg(PBigInt r, PBigInt a) {
|
||||||
|
if (mpz_sgn(*a) > 0) {
|
||||||
|
mpz_sub(*r, p, *a);
|
||||||
|
} else {
|
||||||
|
mpz_set(*r, *a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ZqField::mul(PBigInt r, PBigInt a, PBigInt b) {
|
void ZqField::mul(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
mpz_mul(tmp,*a,*b);
|
mpz_mul(tmp,*a,*b);
|
||||||
mpz_fdiv_r(*r, tmp, p);
|
mpz_fdiv_r(*r, tmp, p);
|
||||||
@@ -49,6 +61,10 @@ void ZqField::mod(PBigInt r, PBigInt a, PBigInt b) {
|
|||||||
mpz_fdiv_r(*r, *a, *b);
|
mpz_fdiv_r(*r, *a, *b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZqField::pow(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
mpz_powm(*r, *a, *b, p);
|
||||||
|
}
|
||||||
|
|
||||||
void ZqField::lt(PBigInt r, PBigInt a, PBigInt b) {
|
void ZqField::lt(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
int c = mpz_cmp(*a, *b);
|
int c = mpz_cmp(*a, *b);
|
||||||
if (c<0) {
|
if (c<0) {
|
||||||
@@ -103,6 +119,30 @@ void ZqField::neq(PBigInt r, PBigInt a, PBigInt b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZqField::land(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
if (mpz_sgn(*a) && mpz_sgn(*b)) {
|
||||||
|
mpz_set(*r, one);
|
||||||
|
} else {
|
||||||
|
mpz_set(*r, zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::lor(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
if (mpz_sgn(*a) || mpz_sgn(*b)) {
|
||||||
|
mpz_set(*r, one);
|
||||||
|
} else {
|
||||||
|
mpz_set(*r, zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::lnot(PBigInt r, PBigInt a) {
|
||||||
|
if (mpz_sgn(*a)) {
|
||||||
|
mpz_set(*r, zero);
|
||||||
|
} else {
|
||||||
|
mpz_set(*r, one);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ZqField::isTrue(PBigInt a) {
|
int ZqField::isTrue(PBigInt a) {
|
||||||
return mpz_sgn(*a);
|
return mpz_sgn(*a);
|
||||||
}
|
}
|
||||||
@@ -110,3 +150,42 @@ int ZqField::isTrue(PBigInt a) {
|
|||||||
void ZqField::copyn(PBigInt a, PBigInt b, int n) {
|
void ZqField::copyn(PBigInt a, PBigInt b, int n) {
|
||||||
for (int i=0;i<n; i++) mpz_set(a[i], b[i]);
|
for (int i=0;i<n; i++) mpz_set(a[i], b[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZqField::band(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
mpz_and(*r, *a, *b);
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::bor(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
mpz_ior(*r, *a, *b);
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::bxor(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
mpz_xor(*r, *a, *b);
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::bnot(PBigInt r, PBigInt a) {
|
||||||
|
mpz_xor(*r, *a, mask);
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::shl(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
if (mpz_cmp_ui(*b, nBits) >= 0) {
|
||||||
|
mpz_set(*r, zero);
|
||||||
|
} else {
|
||||||
|
mpz_mul_2exp(*r, *a, mpz_get_ui(*b));
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZqField::shr(PBigInt r, PBigInt a, PBigInt b) {
|
||||||
|
if (mpz_cmp_ui(*b, nBits) >= 0) {
|
||||||
|
mpz_set(*r, zero);
|
||||||
|
} else {
|
||||||
|
mpz_tdiv_q_2exp(*r, *a, mpz_get_ui(*b));
|
||||||
|
mpz_and(*r, *r, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
18
c/zqfield.h
18
c/zqfield.h
@@ -10,22 +10,40 @@ public:
|
|||||||
BigInt p;
|
BigInt p;
|
||||||
BigInt one;
|
BigInt one;
|
||||||
BigInt zero;
|
BigInt zero;
|
||||||
|
size_t nBits;
|
||||||
|
BigInt mask;
|
||||||
ZqField(PBigInt ap);
|
ZqField(PBigInt ap);
|
||||||
~ZqField();
|
~ZqField();
|
||||||
|
|
||||||
void copyn(PBigInt a, PBigInt b, int n);
|
void copyn(PBigInt a, PBigInt b, int n);
|
||||||
|
|
||||||
void add(PBigInt r,PBigInt a, PBigInt b);
|
void add(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void sub(PBigInt r,PBigInt a, PBigInt b);
|
void sub(PBigInt r,PBigInt a, PBigInt b);
|
||||||
|
void neg(PBigInt r,PBigInt a);
|
||||||
void mul(PBigInt r,PBigInt a, PBigInt b);
|
void mul(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void div(PBigInt r,PBigInt a, PBigInt b);
|
void div(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void idiv(PBigInt r,PBigInt a, PBigInt b);
|
void idiv(PBigInt r,PBigInt a, PBigInt b);
|
||||||
void mod(PBigInt r,PBigInt a, PBigInt b);
|
void mod(PBigInt r,PBigInt a, PBigInt b);
|
||||||
|
void pow(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 eq(PBigInt r, PBigInt a, PBigInt b);
|
||||||
void gt(PBigInt r, PBigInt a, PBigInt b);
|
void gt(PBigInt r, PBigInt a, PBigInt b);
|
||||||
void leq(PBigInt r, PBigInt a, PBigInt b);
|
void leq(PBigInt r, PBigInt a, PBigInt b);
|
||||||
void geq(PBigInt r, PBigInt a, PBigInt b);
|
void geq(PBigInt r, PBigInt a, PBigInt b);
|
||||||
void neq(PBigInt r, PBigInt a, PBigInt b);
|
void neq(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
|
||||||
|
void land(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void lor(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void lnot(PBigInt r, PBigInt a);
|
||||||
|
|
||||||
|
void band(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void bor(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void bxor(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void bnot(PBigInt r, PBigInt a);
|
||||||
|
void shl(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
void shr(PBigInt r, PBigInt a, PBigInt b);
|
||||||
|
|
||||||
int isTrue(PBigInt a);
|
int isTrue(PBigInt a);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ include { return 'include'; }
|
|||||||
\& { return '&'; }
|
\& { return '&'; }
|
||||||
\| { return '|'; }
|
\| { return '|'; }
|
||||||
\! { return '!'; }
|
\! { return '!'; }
|
||||||
|
\~ { return '~'; }
|
||||||
\< { return '<'; }
|
\< { return '<'; }
|
||||||
\> { return '>'; }
|
\> { return '>'; }
|
||||||
\! { return '!'; }
|
\! { return '!'; }
|
||||||
|
|||||||
@@ -1329,42 +1329,44 @@ case 59: return 65;
|
|||||||
break;
|
break;
|
||||||
case 60: return 94;
|
case 60: return 94;
|
||||||
break;
|
break;
|
||||||
case 61: return 77;
|
case 61: return 95;
|
||||||
break;
|
break;
|
||||||
case 62: return 78;
|
case 62: return 77;
|
||||||
break;
|
break;
|
||||||
case 63: return 94;
|
case 63: return 78;
|
||||||
break;
|
break;
|
||||||
case 64: return 57;
|
case 64: return 94;
|
||||||
break;
|
break;
|
||||||
case 65: return 58;
|
case 65: return 57;
|
||||||
break;
|
break;
|
||||||
case 66: return 20;
|
case 66: return 58;
|
||||||
break;
|
break;
|
||||||
case 67: return 22;
|
case 67: return 20;
|
||||||
break;
|
break;
|
||||||
case 68: return 112;
|
case 68: return 22;
|
||||||
break;
|
break;
|
||||||
case 69: return 113;
|
case 69: return 112;
|
||||||
break;
|
break;
|
||||||
case 70: return 36;
|
case 70: return 113;
|
||||||
break;
|
break;
|
||||||
case 71: return 37;
|
case 71: return 36;
|
||||||
break;
|
break;
|
||||||
case 72: return 29;
|
case 72: return 37;
|
||||||
break;
|
break;
|
||||||
case 73: return 24;
|
case 73: return 29;
|
||||||
break;
|
break;
|
||||||
case 74: return 102;
|
case 74: return 24;
|
||||||
break;
|
break;
|
||||||
case 75: return 5;
|
case 75: return 102;
|
||||||
break;
|
break;
|
||||||
case 76: console.log("INVALID: " + yy_.yytext); return 'INVALID'
|
case 76: return 5;
|
||||||
|
break;
|
||||||
|
case 77: console.log("INVALID: " + yy_.yytext); return 'INVALID'
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/],
|
rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/],
|
||||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76],"inclusive":true}}
|
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77],"inclusive":true}}
|
||||||
});
|
});
|
||||||
return lexer;
|
return lexer;
|
||||||
})();
|
})();
|
||||||
|
|||||||
150
src/c_gen.js
150
src/c_gen.js
@@ -154,15 +154,15 @@ function gen(ctx, ast) {
|
|||||||
} else if (ast.op == "*=") {
|
} else if (ast.op == "*=") {
|
||||||
return genVarMulAssignement(ctx, ast);
|
return genVarMulAssignement(ctx, ast);
|
||||||
} else if (ast.op == "+") {
|
} else if (ast.op == "+") {
|
||||||
return genBinaryOp(ctx, ast, "add");
|
return genOp(ctx, ast, "add", 2);
|
||||||
} else if (ast.op == "-") {
|
} else if (ast.op == "-") {
|
||||||
return genBinaryOp(ctx, ast, "sub");
|
return genOp(ctx, ast, "sub", 2);
|
||||||
} else if (ast.op == "UMINUS") {
|
} else if (ast.op == "UMINUS") {
|
||||||
return genUMinus(ctx, ast);
|
return genOp(ctx, ast, "neg", 1);
|
||||||
} else if (ast.op == "*") {
|
} else if (ast.op == "*") {
|
||||||
return genBinaryOp(ctx, ast, "mul");
|
return genOp(ctx, ast, "mul", 2);
|
||||||
} else if (ast.op == "%") {
|
} else if (ast.op == "%") {
|
||||||
return genBinaryOp(ctx, ast, "mod");
|
return genOp(ctx, ast, "mod", 2);
|
||||||
} else if (ast.op == "PLUSPLUSRIGHT") {
|
} else if (ast.op == "PLUSPLUSRIGHT") {
|
||||||
return genOpOp(ctx, ast, "add", "RIGHT");
|
return genOpOp(ctx, ast, "add", "RIGHT");
|
||||||
} else if (ast.op == "PLUSPLUSLEFT") {
|
} else if (ast.op == "PLUSPLUSLEFT") {
|
||||||
@@ -172,33 +172,41 @@ function gen(ctx, ast) {
|
|||||||
} else if (ast.op == "MINUSMINUSLEFT") {
|
} else if (ast.op == "MINUSMINUSLEFT") {
|
||||||
return genOpOp(ctx, ast, "sub", "LEFT");
|
return genOpOp(ctx, ast, "sub", "LEFT");
|
||||||
} else if (ast.op == "**") {
|
} else if (ast.op == "**") {
|
||||||
return genExp(ctx, ast);
|
return genOp(ctx, ast, "pow", 2);
|
||||||
} else if (ast.op == "/") {
|
} else if (ast.op == "/") {
|
||||||
return genBinaryOp(ctx, ast, "div");
|
return genOp(ctx, ast, "div", 2);
|
||||||
} else if (ast.op == "\\") {
|
} else if (ast.op == "\\") {
|
||||||
return genBinaryOp(ctx, ast, "idiv");
|
return genOp(ctx, ast, "idiv", 2);
|
||||||
} else if (ast.op == "&") {
|
} else if (ast.op == "&") {
|
||||||
return genBAnd(ctx, ast);
|
return genOp(ctx, ast, "band", 2);
|
||||||
|
} else if (ast.op == "|") {
|
||||||
|
return genOp(ctx, ast, "bor", 2);
|
||||||
|
} else if (ast.op == "^") {
|
||||||
|
return genOp(ctx, ast, "bxor", 2);
|
||||||
|
} else if (ast.op == "~") {
|
||||||
|
return genOp(ctx, ast, "bnot", 1);
|
||||||
} else if (ast.op == "&&") {
|
} else if (ast.op == "&&") {
|
||||||
return genAnd(ctx, ast);
|
return genOp(ctx, ast, "land", 2);
|
||||||
} else if (ast.op == "||") {
|
} else if (ast.op == "||") {
|
||||||
return genOr(ctx, ast);
|
return genOp(ctx, ast, "lor", 2);
|
||||||
|
} else if (ast.op == "!") {
|
||||||
|
return genOp(ctx, ast, "lnot", 1);
|
||||||
} else if (ast.op == "<<") {
|
} else if (ast.op == "<<") {
|
||||||
return genShl(ctx, ast);
|
return genOp(ctx, ast, "shl", 2);
|
||||||
} else if (ast.op == ">>") {
|
} else if (ast.op == ">>") {
|
||||||
return genShr(ctx, ast);
|
return genOp(ctx, ast, "shr", 2);
|
||||||
} else if (ast.op == "<") {
|
} else if (ast.op == "<") {
|
||||||
return genBinaryOp(ctx, ast, "lt");
|
return genOp(ctx, ast, "lt", 2);
|
||||||
} else if (ast.op == ">") {
|
} else if (ast.op == ">") {
|
||||||
return genBinaryOp(ctx, ast, "gt");
|
return genOp(ctx, ast, "gt", 2);
|
||||||
} else if (ast.op == "<=") {
|
} else if (ast.op == "<=") {
|
||||||
return genBinaryOp(ctx, ast, "leq");
|
return genOp(ctx, ast, "leq", 2);
|
||||||
} else if (ast.op == ">=") {
|
} else if (ast.op == ">=") {
|
||||||
return genBinaryOp(ctx, ast, "geq");
|
return genOp(ctx, ast, "geq", 2);
|
||||||
} else if (ast.op == "==") {
|
} else if (ast.op == "==") {
|
||||||
return genBinaryOp(ctx, ast, "eq");
|
return genOp(ctx, ast, "eq", 2);
|
||||||
} else if (ast.op == "!=") {
|
} else if (ast.op == "!=") {
|
||||||
return genBinaryOp(ctx, ast, "neq");
|
return genOp(ctx, ast, "neq", 2);
|
||||||
} else if (ast.op == "?") {
|
} else if (ast.op == "?") {
|
||||||
return genTerCon(ctx, ast);
|
return genTerCon(ctx, ast);
|
||||||
} else {
|
} else {
|
||||||
@@ -1037,76 +1045,56 @@ function genOpOp(ctx, ast, op, lr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function genBinaryOp(ctx, ast, op) {
|
function genOp(ctx, ast, op, nOps) {
|
||||||
let aRef = gen(ctx, ast.values[0]);
|
const vals = [];
|
||||||
if (ctx.error) return;
|
const valRefs = [];
|
||||||
let a = ctx.refs[aRef];
|
|
||||||
|
|
||||||
let bRef = gen(ctx, ast.values[1]);
|
var anyUsed=false;
|
||||||
if (ctx.error) return;
|
|
||||||
let b = ctx.refs[bRef];
|
|
||||||
|
|
||||||
if ((!a.used)&&(!utils.isDefined(a.value))) return ctx.throwError(ast, "Using a not assigned varialble: ");
|
for (let i=0; i<nOps; i++) {
|
||||||
if ((!b.used)&&(!utils.isDefined(b.value))) return ctx.throwError(ast, "Using a not assigned varialble: ");
|
const ref = gen(ctx, ast.values[i]);
|
||||||
if (!utils.sameSizes(a.sizes, [1,0])) return ctx.throwError(ast, "Operation cannot be done on an array");
|
if (ctx.error) return;
|
||||||
if (!utils.sameSizes(b.sizes, [1,0])) return ctx.throwError(ast, "Operation cannot be done on an array");
|
let v = ctx.refs[ref];
|
||||||
|
valRefs.push(ref);
|
||||||
|
vals.push(v);
|
||||||
|
|
||||||
|
if (!utils.sameSizes(v.sizes, [1,0])) return ctx.throwError(ast, "Operation cannot be done on an array");
|
||||||
|
if ( (!v.used)
|
||||||
|
&&( (!utils.isDefined(v.value))
|
||||||
|
||(!utils.isDefined(v.value[0]))))
|
||||||
|
return ctx.throwError(ast, "Using a not assigned varialble: ");
|
||||||
|
|
||||||
|
if (v.used) anyUsed=true;
|
||||||
|
}
|
||||||
|
|
||||||
let rRef;
|
let rRef;
|
||||||
if (a.used || b.used) {
|
if (anyUsed) {
|
||||||
if (!a.used) {
|
for (let i=0; i<nOps; i++) {
|
||||||
aRef = instantiateConstant(ctx, a.value);
|
if (!vals[i].used) {
|
||||||
a = ctx.refs[aRef];
|
valRefs[i] = instantiateConstant(ctx, vals[i].value);
|
||||||
|
vals[i] = ctx.refs[valRefs[i]];
|
||||||
}
|
}
|
||||||
if (!b.used) {
|
|
||||||
bRef = instantiateConstant(ctx, b.value);
|
|
||||||
b = ctx.refs[bRef];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rRef = newRef(ctx, "BIGINT", "_tmp");
|
rRef = newRef(ctx, "BIGINT", "_tmp");
|
||||||
instantiateRef(ctx, rRef);
|
instantiateRef(ctx, rRef);
|
||||||
const r = ctx.refs[rRef];
|
const r = ctx.refs[rRef];
|
||||||
ctx.code += `ctx->field->${op}(${r.label},${a.label}, ${b.label});\n`;
|
let c = `ctx->field->${op}(${r.label}`;
|
||||||
|
for (let i=0; i<nOps; i++) {
|
||||||
|
c+=`,${vals[i].label}`;
|
||||||
|
}
|
||||||
|
c += ");\n";
|
||||||
|
ctx.code += c;
|
||||||
} else {
|
} else {
|
||||||
rRef = newRef(ctx, "BIGINT", "_tmp", ctx.field[op](a.value[0], b.value[0]));
|
const params = [];
|
||||||
|
for (let i=0; i<nOps; i++) {
|
||||||
|
params.push(vals[i].value[0]);
|
||||||
|
}
|
||||||
|
rRef = newRef(ctx, "BIGINT", "_tmp", ctx.field[op](...params));
|
||||||
}
|
}
|
||||||
return rRef;
|
return rRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function genSub(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
const b = gen(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
return `bigInt(${a}).add(__P__).sub(bigInt(${b})).mod(__P__)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genDiv(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
const b = gen(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
|
|
||||||
return `bigInt(${a}).mul( bigInt(${b}).inverse(__P__) ).mod(__P__)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genIDiv(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
const b = gen(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
|
|
||||||
return `bigInt(${a}).div( bigInt(${b}))`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genExp(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
const b = gen(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
return `bigInt(${a}).modPow(bigInt(${b}), __P__)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genBAnd(ctx, ast) {
|
function genBAnd(ctx, ast) {
|
||||||
const a = gen(ctx, ast.values[0]);
|
const a = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -1147,20 +1135,6 @@ function genShr(ctx, ast) {
|
|||||||
return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shr(bigInt(${b})).and(__MASK__)`;
|
return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shr(bigInt(${b})).and(__MASK__)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function genMod(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
const b = gen(ctx, ast.values[1]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
return `bigInt(${a}).mod(bigInt(${b}))`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genUMinus(ctx, ast) {
|
|
||||||
const a = gen(ctx, ast.values[0]);
|
|
||||||
if (ctx.error) return;
|
|
||||||
return `__P__.sub(bigInt(${a})).mod(__P__)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genTerCon(ctx, ast) {
|
function genTerCon(ctx, ast) {
|
||||||
const a = gen(ctx, ast.values[0]);
|
const a = gen(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|||||||
66
src/exec.js
66
src/exec.js
@@ -92,10 +92,18 @@ function exec(ctx, ast) {
|
|||||||
return execExp(ctx, ast);
|
return execExp(ctx, ast);
|
||||||
} else if (ast.op == "&") {
|
} else if (ast.op == "&") {
|
||||||
return execBAnd(ctx, ast);
|
return execBAnd(ctx, ast);
|
||||||
|
} else if (ast.op == "|") {
|
||||||
|
return execBOr(ctx, ast);
|
||||||
|
} else if (ast.op == "^") {
|
||||||
|
return execBXor(ctx, ast);
|
||||||
|
} else if (ast.op == "~") {
|
||||||
|
return execBNot(ctx, ast);
|
||||||
} else if (ast.op == "&&") {
|
} else if (ast.op == "&&") {
|
||||||
return execAnd(ctx, ast);
|
return execAnd(ctx, ast);
|
||||||
} else if (ast.op == "||") {
|
} else if (ast.op == "||") {
|
||||||
return execOr(ctx, ast);
|
return execOr(ctx, ast);
|
||||||
|
} else if (ast.op == "!") {
|
||||||
|
return execLNot(ctx, ast);
|
||||||
} else if (ast.op == "<<") {
|
} else if (ast.op == "<<") {
|
||||||
return execShl(ctx, ast);
|
return execShl(ctx, ast);
|
||||||
} else if (ast.op == ">>") {
|
} else if (ast.op == ">>") {
|
||||||
@@ -854,7 +862,6 @@ function execNeq(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function execBAnd(ctx, ast) {
|
function execBAnd(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -869,6 +876,51 @@ function execBAnd(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execBOr(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: a.value.or(b.value).and(__MASK__)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function execBXor(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
const b = exec(ctx, ast.values[1]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (b.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value || !b.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: a.value.xor(b.value).and(__MASK__)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function execBNot(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value) return { type: "NUMBER" };
|
||||||
|
|
||||||
|
const res = lc.negate(a);
|
||||||
|
if (res.type == "ERROR") return error(ctx, ast, res.errStr);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: a.value.xor(__MASK__).and(__MASK__)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function execAnd(ctx, ast) {
|
function execAnd(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
@@ -897,6 +949,18 @@ function execOr(ctx, ast) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execLNot(ctx, ast) {
|
||||||
|
const a = exec(ctx, ast.values[0]);
|
||||||
|
if (ctx.error) return;
|
||||||
|
if (a.type != "NUMBER") return { type: "NUMBER" };
|
||||||
|
if (!a.value) return { type: "NUMBER" };
|
||||||
|
return {
|
||||||
|
type: "NUMBER",
|
||||||
|
value: (a.value.eq(0)) ? bigInt(1) : bigInt(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function execShl(ctx, ast) {
|
function execShl(ctx, ast) {
|
||||||
const a = exec(ctx, ast.values[0]);
|
const a = exec(ctx, ast.values[0]);
|
||||||
if (ctx.error) return;
|
if (ctx.error) return;
|
||||||
|
|||||||
@@ -1,16 +1,32 @@
|
|||||||
const bigInt = require("big-integer");
|
const bigInt = require("big-integer");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
module.exports = class ZqField {
|
module.exports = class ZqField {
|
||||||
constructor(p) {
|
constructor(p) {
|
||||||
this.p = p;
|
this.p = p;
|
||||||
|
this.bitLength = p.bitLength();
|
||||||
|
this.mask = bigInt.one.shiftLeft(this.bitLength - 1).minus(bigInt.one);
|
||||||
}
|
}
|
||||||
|
|
||||||
add(a, b) {
|
add(a, b) {
|
||||||
return a.add(b).mod(this.p);
|
let res = a.add(b);
|
||||||
|
if (res.geq(this.p)) {
|
||||||
|
res = res.minsu(this.p);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub(a, b) {
|
sub(a, b) {
|
||||||
return a.minus(b).mod(this.p);
|
if (a.geq(b)) {
|
||||||
|
return a.minus(b);
|
||||||
|
} else {
|
||||||
|
return this.p.minus(b.minus(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
neg(a) {
|
||||||
|
if (a.isZero()) return a;
|
||||||
|
return this.p.minus(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
mul(a, b) {
|
mul(a, b) {
|
||||||
@@ -46,6 +62,7 @@ module.exports = class ZqField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
idiv(a, b) {
|
idiv(a, b) {
|
||||||
|
assert(!b.isZero(), "Division by zero");
|
||||||
return a.divide(b);
|
return a.divide(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,5 +70,46 @@ module.exports = class ZqField {
|
|||||||
return a.mod(b);
|
return a.mod(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pow(a, b) {
|
||||||
|
return a.modPow(b, this.p);
|
||||||
|
}
|
||||||
|
|
||||||
|
band(a, b) {
|
||||||
|
return a.and(b).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bor(a, b) {
|
||||||
|
return a.or(b).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bxor(a, b) {
|
||||||
|
return a.xor(b).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bnot(a) {
|
||||||
|
return a.xor(this.mask).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
shl(a, b) {
|
||||||
|
if (b.geq(this.bitLength)) return bigInt.zero;
|
||||||
|
return a.shiftLeft(b).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
shr(a, b) {
|
||||||
|
if (b.geq(this.bitLength)) return bigInt.zero;
|
||||||
|
return a.shiftRight(b).and(this.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
land(a, b) {
|
||||||
|
return (a.isZero() || b.isZero) ? bigInt.zero : bigInt.one;
|
||||||
|
}
|
||||||
|
|
||||||
|
lor(a, b) {
|
||||||
|
return (a.isZero() && b.isZero) ? bigInt.zero : bigInt.one;
|
||||||
|
}
|
||||||
|
|
||||||
|
lnot(a) {
|
||||||
|
return a.isZero() ? bigInt.one : bigInt.zero;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -202,4 +202,48 @@ describe("basic cases", function () {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it("ops3", async () => {
|
||||||
|
await doTest(
|
||||||
|
"ops3.circom",
|
||||||
|
[
|
||||||
|
[{in: [-2, 2]}, {neg1: 2,neg2: -2, pow: 4}],
|
||||||
|
[{in: [0, 1]}, {neg1: 0, neg2: -1, pow: 0}],
|
||||||
|
[{in: [ 1,-1]}, {neg1: -1, neg2: 1, pow: 1}],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("Comparation ops", async () => {
|
||||||
|
await doTest(
|
||||||
|
"opscmp.circom",
|
||||||
|
[
|
||||||
|
[{in: [ 8, 9]}, {lt: 1, leq: 1, eq:0, neq:1, geq: 0, gt:0}],
|
||||||
|
[{in: [-2,-2]}, {lt: 0, leq: 1, eq:1, neq:0, geq: 1, gt:0}],
|
||||||
|
[{in: [-1,-2]}, {lt: 0, leq: 0, eq:0, neq:1, geq: 1, gt:1}],
|
||||||
|
[{in: [ 1,-1]}, {lt: 1, leq: 1, eq:0, neq:1, geq: 0, gt:0}], // In mod, negative values are higher than positive.
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("Bit ops", async () => {
|
||||||
|
const mask = bigInt("14474011154664524427946373126085988481658748083205070504932198000989141204991");
|
||||||
|
const m1m = bigInt("7414231717174750794300032619171286606889616317210963838766006185586667290624");
|
||||||
|
await doTest(
|
||||||
|
"opsbit.circom",
|
||||||
|
[
|
||||||
|
[{in: [ 5, 3]}, {and: 1, or: 7, xor:6, not1:mask.minus(5), shl: 40, shr:0}],
|
||||||
|
[{in: [ 0, 0]}, {and: 0, or: 0, xor:0, not1:mask, shl: 0, shr:0}],
|
||||||
|
[{in: [-1, 1]}, {and: 0, or: m1m.add(bigInt.one), xor:m1m.add(bigInt.one), not1:mask.minus(m1m), shl: m1m.shiftLeft(1).and(mask), shr:__P__.shiftRight(1).and(mask)}],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("Logical ops", async () => {
|
||||||
|
await doTest(
|
||||||
|
"opslog.circom",
|
||||||
|
[
|
||||||
|
[{in: [ 5, 0]}, {and: 0, or: 1, not1:0}],
|
||||||
|
[{in: [ 0, 1]}, {and: 0, or: 1, not1:1}],
|
||||||
|
[{in: [-1, 9]}, {and: 1, or: 1, not1:0}],
|
||||||
|
[{in: [ 0, 0]}, {and: 0, or: 0, not1:1}],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
12
test/circuits/ops3.circom
Normal file
12
test/circuits/ops3.circom
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
template Ops3() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output neg1;
|
||||||
|
signal output neg2;
|
||||||
|
signal output pow;
|
||||||
|
|
||||||
|
neg1 <-- -in[0];
|
||||||
|
neg2 <-- -in[1];
|
||||||
|
pow <-- in[0] ** in[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = Ops3();
|
||||||
18
test/circuits/opsbit.circom
Normal file
18
test/circuits/opsbit.circom
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
template OpsBit() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output and;
|
||||||
|
signal output or;
|
||||||
|
signal output xor;
|
||||||
|
signal output not1;
|
||||||
|
signal output shl;
|
||||||
|
signal output shr;
|
||||||
|
|
||||||
|
and <-- in[0] & in[1];
|
||||||
|
or <-- in[0] | in[1];
|
||||||
|
xor <-- in[0] ^ in[1];
|
||||||
|
not1 <-- ~in[0];
|
||||||
|
shl <-- in[0] << in[1];
|
||||||
|
shr <-- in[0] >> in[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = OpsBit();
|
||||||
18
test/circuits/opscmp.circom
Normal file
18
test/circuits/opscmp.circom
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
template OpsCmp() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output lt;
|
||||||
|
signal output leq;
|
||||||
|
signal output eq;
|
||||||
|
signal output neq;
|
||||||
|
signal output geq;
|
||||||
|
signal output gt;
|
||||||
|
|
||||||
|
lt <-- in[0] < in[1];
|
||||||
|
leq <-- in[0] <= in[1];
|
||||||
|
eq <-- in[0] == in[1];
|
||||||
|
neq <-- in[0] != in[1];
|
||||||
|
geq <-- in[0] >= in[1];
|
||||||
|
gt <-- in[0] > in[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = OpsCmp();
|
||||||
12
test/circuits/opslog.circom
Normal file
12
test/circuits/opslog.circom
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
template OpsLog() {
|
||||||
|
signal input in[2];
|
||||||
|
signal output and;
|
||||||
|
signal output or;
|
||||||
|
signal output not1;
|
||||||
|
|
||||||
|
and <-- in[0] && in[1];
|
||||||
|
or <-- in[0] || in[1];
|
||||||
|
not1 <-- !in[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
component main = OpsLog();
|
||||||
Reference in New Issue
Block a user