forked from jancarlsson/snarkfront
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Alg_bool.hpp
130 lines (108 loc) · 3.62 KB
/
Alg_bool.hpp
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef _SNARKFRONT_ALG_BOOL_HPP_
#define _SNARKFRONT_ALG_BOOL_HPP_
#include <cassert>
#include "Alg.hpp"
namespace snarkfront {
////////////////////////////////////////////////////////////////////////////////
// Alg_bool
//
template <typename FR>
void evalStackOp(std::stack<Alg_bool<FR>>& S, const LogicalOps op)
{
typedef typename Alg_bool<FR>::R1T R1T;
auto& RS = TL<R1C<FR>>::singleton();
// y is right argument
const auto R = S.top();
S.pop();
const bool yvalue = R.value();
#ifdef USE_ASSERT
assert(1 == R.r1Terms().size());
#endif
const R1T y = RS->argScalar(R);
// z is result
bool zvalue;
FR zwitness;
R1T z;
// complement takes one argument
if (LogicalOps::CMPLMNT == op) {
zvalue = ! yvalue;
zwitness = boolTo<FR>(zvalue);
z = RS->createResult(op, y, y, zwitness);
} else {
// x is left argument
const auto L = S.top();
S.pop();
const bool xvalue = L.value();
#ifdef USE_ASSERT
assert(1 == L.r1Terms().size());
#endif
const R1T x = RS->argScalar(L);
zvalue = evalOp(op, xvalue, yvalue);
zwitness = boolTo<FR>(zvalue);
const bool
xIsVar = x.isVariable(),
yIsVar = y.isVariable();
const LogicalOps NOT = LogicalOps::CMPLMNT;
if (xIsVar == yIsVar) {
z = RS->createResult(op, x, y, zwitness);
} else if (xIsVar) { // && ! yIsVar
if (yvalue) {
switch (op) {
case (LogicalOps::AND) : z = x; break;
case (LogicalOps::OR) : z = y; break;
case (LogicalOps::XOR) : z = RS->createResult(NOT, x, x, zwitness); break;
case (LogicalOps::SAME) : z = x; break;
}
} else {
switch (op) {
case (LogicalOps::AND) : z = y; break;
case (LogicalOps::OR) : z = x; break;
case (LogicalOps::XOR) : z = x; break;
case (LogicalOps::SAME) : z = RS->createResult(NOT, x, x, zwitness); break;
}
}
} else if (yIsVar) { // && ! xIsVar
if (xvalue) {
switch (op) {
case (LogicalOps::AND) : z = y; break;
case (LogicalOps::OR) : z = x; break;
case (LogicalOps::XOR) : z = RS->createResult(NOT, y, y, zwitness); break;
case (LogicalOps::SAME) : z = y; break;
}
} else {
switch (op) {
case (LogicalOps::AND) : z = x; break;
case (LogicalOps::OR) : z = y; break;
case (LogicalOps::XOR) : z = y; break;
case (LogicalOps::SAME) : z = RS->createResult(NOT, y, y, zwitness); break;
}
}
}
}
S.push(
Alg_bool<FR>(zvalue, zwitness, valueBits(zvalue), {z}));
}
template <typename FR>
void evalStackCmp(std::stack<Alg_bool<FR>>& S, const EqualityCmp op)
{
typedef typename Alg_bool<FR>::R1T R1T;
auto& RS = TL<R1C<FR>>::singleton();
// y is right argument
const auto R = S.top();
S.pop();
const bool yvalue = R.value();
const R1T y = RS->argScalar(R);
// x is left argument
const auto L = S.top();
S.pop();
const bool xvalue = L.value();
const R1T x = RS->argScalar(L);
// z is result
const bool zvalue = evalOp(op, xvalue, yvalue);
const FR zwitness = boolTo<FR>(zvalue);
const R1T z = RS->createResult(eqToLogical(op), x, y, zwitness);
S.push(
Alg_bool<FR>(zvalue, zwitness, valueBits(zvalue), {z}));
}
} // namespace snarkfront
#endif