@@ -40,19 +40,85 @@ import (
40
40
func (builder * builder ) Add (i1 , i2 frontend.Variable , in ... frontend.Variable ) frontend.Variable {
41
41
// extract frontend.Variables from input
42
42
vars , s := builder .toVariables (append ([]frontend.Variable {i1 , i2 }, in ... )... )
43
- return builder .add (vars , false , s )
43
+ return builder .add (vars , false , s , nil )
44
44
45
45
}
46
46
47
+ func (builder * builder ) MAC (a frontend.Variable , b , c frontend.Variable ) frontend.Variable {
48
+ builder .macBuffer1 = builder .macBuffer1 [:0 ]
49
+ // do the multiplication
50
+ mul := func () {
51
+ n1 , v1Constant := builder .constantValue (b )
52
+ n2 , v2Constant := builder .constantValue (c )
53
+
54
+ // v1 and v2 are both unknown, this is the only case we add a constraint
55
+ if ! v1Constant && ! v2Constant {
56
+ res := builder .newInternalVariable ()
57
+ builder .cs .AddConstraint (builder .newR1C (b , c , res ))
58
+ builder .macBuffer1 = append (builder .macBuffer1 , res ... )
59
+ return
60
+ }
61
+
62
+ // v1 and v2 are constants, we multiply big.Int values and return resulting constant
63
+ if v1Constant && v2Constant {
64
+ builder .cs .Mul (& n1 , & n2 )
65
+ builder .macBuffer1 = append (builder .macBuffer1 , expr .NewTerm (0 , n1 ))
66
+ return
67
+ }
68
+
69
+ if v1Constant {
70
+ builder .macBuffer1 = append (builder .macBuffer1 , builder .toVariable (c )... )
71
+ builder .mulConstant (builder .macBuffer1 , n1 , true )
72
+ return
73
+ }
74
+ builder .macBuffer1 = append (builder .macBuffer1 , builder .toVariable (b )... )
75
+ builder .mulConstant (builder .macBuffer1 , n2 , true )
76
+ }
77
+ mul ()
78
+
79
+ // we can't mutate a, but we return an address to mutate it in subsequent calls.
80
+ _a := builder .toVariable (a )
81
+ builder .macBuffer2 = builder .macBuffer2 [:0 ]
82
+ builder .add ([]expr.LinearExpression {_a , builder .macBuffer1 }, false , 0 , & builder .macBuffer2 )
83
+ if cap (_a ) >= len (builder .macBuffer2 ) {
84
+ _a = _a [:0 ]
85
+ _a = append (_a , builder .macBuffer2 ... )
86
+ } else {
87
+ _a = make (expr.LinearExpression , len (builder .macBuffer2 ))
88
+ copy (_a , builder .macBuffer2 )
89
+ }
90
+ return _a
91
+
92
+ // if _a, ok := a.(*expr.LinearExpression); ok {
93
+ // // we can mutate a
94
+ // builder.macBuffer2 = builder.macBuffer2[:0]
95
+ // builder.macBuffer2 = append(builder.macBuffer2, *_a...)
96
+
97
+ // builder.add([]expr.LinearExpression{builder.macBuffer2, builder.macBuffer1}, false, 0, _a)
98
+ // return _a
99
+ // } else {
100
+ // // we can't mutate a, but we return an address to mutate it in subsequent calls.
101
+ // _a := builder.toVariable(a)
102
+ // r := builder.add([]expr.LinearExpression{_a, builder.macBuffer1}, false, len(_a)+len(builder.macBuffer1), nil).(expr.LinearExpression)
103
+ // return &r
104
+ // }
105
+ // // fmt.Println(reflect.TypeOf(a))
106
+ // // if reflect.TypeOf(a) == tPointerVariable {
107
+ // // fmt.Println("HERE")
108
+ // // a = *(reflect.ValueOf(a).Interface().(*frontend.Variable))
109
+ // // }
110
+ // return builder.Add(a, builder.Mul(b, c))
111
+ }
112
+
47
113
// Sub returns res = i1 - i2
48
114
func (builder * builder ) Sub (i1 , i2 frontend.Variable , in ... frontend.Variable ) frontend.Variable {
49
115
// extract frontend.Variables from input
50
116
vars , s := builder .toVariables (append ([]frontend.Variable {i1 , i2 }, in ... )... )
51
- return builder .add (vars , true , s )
117
+ return builder .add (vars , true , s , nil )
52
118
}
53
119
54
120
// returns res = Σ(vars) or res = vars[0] - Σ(vars[1:]) if sub == true.
55
- func (builder * builder ) add (vars []expr.LinearExpression , sub bool , capacity int ) frontend.Variable {
121
+ func (builder * builder ) add (vars []expr.LinearExpression , sub bool , capacity int , res * expr. LinearExpression ) frontend.Variable {
56
122
// we want to merge all terms from input linear expressions
57
123
// if they are duplicate, we reduce; that is, if multiple terms in different vars have the
58
124
// same variable id.
@@ -68,7 +134,11 @@ func (builder *builder) add(vars []expr.LinearExpression, sub bool, capacity int
68
134
}
69
135
builder .heap .heapify ()
70
136
71
- res := make (expr.LinearExpression , 0 , capacity )
137
+ if res == nil {
138
+ t := make (expr.LinearExpression , 0 , capacity )
139
+ res = & t
140
+ }
141
+ // res := make(expr.LinearExpression, 0, capacity)
72
142
curr := - 1
73
143
74
144
// process all the terms from all the inputs, in sorted order
@@ -87,37 +157,37 @@ func (builder *builder) add(vars []expr.LinearExpression, sub bool, capacity int
87
157
if t .Coeff .IsZero () {
88
158
continue // is this really needed?
89
159
}
90
- if curr != - 1 && t .VID == res [curr ].VID {
160
+ if curr != - 1 && t .VID == ( * res ) [curr ].VID {
91
161
// accumulate, it's the same variable ID
92
162
if sub && lID != 0 {
93
- builder .cs .Sub (& res [curr ].Coeff , & t .Coeff )
163
+ builder .cs .Sub (& ( * res ) [curr ].Coeff , & t .Coeff )
94
164
} else {
95
- builder .cs .Add (& res [curr ].Coeff , & t .Coeff )
165
+ builder .cs .Add (& ( * res ) [curr ].Coeff , & t .Coeff )
96
166
}
97
- if res [curr ].Coeff .IsZero () {
167
+ if ( * res ) [curr ].Coeff .IsZero () {
98
168
// remove self.
99
- res = res [:curr ]
169
+ ( * res ) = ( * res ) [:curr ]
100
170
curr --
101
171
}
102
172
} else {
103
173
// append, it's a new variable ID
104
- res = append (res , * t )
174
+ ( * res ) = append (( * res ) , * t )
105
175
curr ++
106
176
if sub && lID != 0 {
107
- builder .cs .Neg (& res [curr ].Coeff )
177
+ builder .cs .Neg (& ( * res ) [curr ].Coeff )
108
178
}
109
179
}
110
180
}
111
181
112
- if len (res ) == 0 {
182
+ if len (( * res ) ) == 0 {
113
183
// keep the linear expression valid (assertIsSet)
114
- res = expr .NewLinearExpression (0 , constraint.Coeff {})
184
+ ( * res ) = append (( * res ), expr .NewTerm (0 , constraint.Coeff {}) )
115
185
}
116
186
// if the linear expression LE is too long then record an equality
117
187
// constraint LE * 1 = t and return short linear expression instead.
118
- res = builder .compress (res )
188
+ ( * res ) = builder .compress (( * res ) )
119
189
120
- return res
190
+ return * res
121
191
}
122
192
123
193
// Neg returns -i
@@ -151,7 +221,6 @@ func (builder *builder) Mul(i1, i2 frontend.Variable, in ...frontend.Variable) f
151
221
// v1 and v2 are constants, we multiply big.Int values and return resulting constant
152
222
if v1Constant && v2Constant {
153
223
builder .cs .Mul (& n1 , & n2 )
154
- // n1.Mul(n1, n2).Mod(n1, builder.q)
155
224
return expr .NewLinearExpression (0 , n1 )
156
225
}
157
226
@@ -547,7 +616,7 @@ func (builder *builder) Println(a ...frontend.Variable) {
547
616
if i > 0 {
548
617
sbb .WriteByte (' ' )
549
618
}
550
- if v , ok := arg .(expr. LinearExpression ); ok {
619
+ if v , ok := builder . isLinearExpression ( arg ); ok {
551
620
assertIsSet (v )
552
621
553
622
sbb .WriteString ("%s" )
0 commit comments