circom/src/compiler.js
src/compiler.jsRaw
1/*
2 Copyright 2018 0KIMS association.
3
4 This file is part of circom (Zero Knowledge Circuit Compiler).
5
6 circom is a free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 circom is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with circom. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20const Scalar = require("ffjavascript").Scalar;
21const sONE = 0;
22const build = require("./build");
23const BuilderC = require("../ports/c/builder.js");
24const BuilderWasm = require("../ports/wasm/builder.js");
25const constructionPhase = require("./construction_phase");
26const Ctx = require("./ctx");
27const utils = require("./utils");
28const buildR1cs = require("./r1csfile").buildR1cs;
29const BigArray = require("./bigarray");
30const buildSyms = require("./buildsyms");
31
32module.exports = compile;
33
34async function compile(srcFile, options) {
35 options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
36 if (!options) {
37 options = {};
38 }
39 if (typeof options.reduceConstraints === "undefined") {
40 options.reduceConstraints = true;
41 }
42 const ctx = new Ctx(options.prime);
43 ctx.verbose= options.verbose || false;
44 ctx.mainComponent = options.mainComponent || "main";
45 ctx.newThreadTemplates = options.newThreadTemplates;
46
47 constructionPhase(ctx, srcFile);
48
49 if (ctx.verbose) console.log("NConstraints Before: "+ctx.constraints.length);
50
51 if (ctx.error) {
52 throw(ctx.error);
53 }
54
55 if (ctx.getComponentIdx(ctx.mainComponent)<0) {
56 throw new Error("A main component must be defined");
57 }
58
59 if (ctx.verbose) console.log("Classify Signals");
60 classifySignals(ctx);
61
62 if (ctx.verbose) console.log("Reduce Constants");
63 reduceConstants(ctx);
64 if (options.reduceConstraints) {
65
66 if (ctx.verbose) console.log("Reduce Constraints");
67 // Repeat while reductions are performed
68/*
69 let oldNConstrains = -1;
70 while (ctx.constraints.length != oldNConstrains) {
71 if (ctx.verbose) console.log("Reducing constraints: "+ctx.constraints.length);
72 oldNConstrains = ctx.constraints.length;
73 reduceConstrains(ctx);
74 }
75*/
76
77 reduceConstrains(ctx);
78 }
79
80 if (ctx.verbose) console.log("NConstraints After: "+ctx.constraints.length);
81
82 generateWitnessNames(ctx);
83
84 if (ctx.error) {
85 throw(ctx.error);
86 }
87
88 if (options.cSourceWriteStream) {
89 if (ctx.verbose) console.log("Generating c...");
90 ctx.builder = new BuilderC(options.prime);
91 build(ctx);
92 const rdStream = ctx.builder.build();
93 rdStream.pipe(options.cSourceWriteStream);
94
95 // await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
96 }
97
98 if ((options.wasmWriteStream)||(options.watWriteStream)) {
99 if (ctx.verbose) console.log("Generating wasm...");
100 ctx.builder = new BuilderWasm(options.prime);
101 build(ctx);
102 if (options.wasmWriteStream) {
103 const rdStream = ctx.builder.build("wasm");
104 rdStream.pipe(options.wasmWriteStream);
105 }
106 if (options.watWriteStream) {
107 const rdStream = ctx.builder.build("wat");
108 rdStream.pipe(options.watWriteStream);
109 }
110
111 // await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill));
112 }
113
114 // const mainCode = gen(ctx,ast);
115 if (ctx.error) throw(ctx.error);
116
117 if (options.r1csFileName) {
118 await buildR1cs(ctx, options.r1csFileName);
119 }
120
121 if (options.symWriteStream) {
122 const rdStream = buildSyms(ctx);
123 rdStream.pipe(options.symWriteStream);
124
125 // await new Promise(fulfill => options.symWriteStream.on("finish", fulfill));
126 }
127
128// const def = buildCircuitDef(ctx, mainCode);
129
130}
131
132
133
134function classifySignals(ctx) {
135
136 const ERROR = 0xFFFF;
137
138 function priorize(t1, t2) {
139 if ((t1 == ERROR) || (t2==ERROR)) return ERROR;
140 if (t1 == ctx.stINTERNAL) {
141 return t2;
142 } else if (t2==ctx.stINTERNAL) {
143 return t1;
144 }
145 if ((t1 == ctx.stONE) || (t2 == ctx.stONE)) return ctx.stONE;
146 if ((t1 == ctx.stOUTPUT) || (t2 == ctx.stOUTPUT)) return ctx.stOUTPUT;
147 if ((t1 == ctx.stCONSTANT) || (t2 == ctx.stCONSTANT)) return ctx.stCONSTANT;
148 if ((t1 == ctx.stDISCARDED) || (t2 == ctx.stDISCARDED)) return ctx.stDISCARDED;
149 if (t1!=t2) return ERROR;
150 return t1;
151 }
152
153 // First classify the signals
154 for (let s=0; s<ctx.signals.length; s++) {
155 const signal = ctx.signals[s];
156 let tAll = ctx.stINTERNAL;
157 let lSignal = signal;
158 let end = false;
159 while (!end) {
160 let t = lSignal.c || ctx.stINTERNAL;
161 if (s == 0) {
162 t = ctx.stONE;
163 } else if (lSignal.o & ctx.MAIN) {
164 if (lSignal.o & ctx.IN) {
165 if (lSignal.o & ctx.PRV) {
166 t = ctx.stPRVINPUT;
167 } else {
168 t = ctx.stPUBINPUT;
169 }
170 } else if (lSignal.o & ctx.OUT) {
171 t = ctx.stOUTPUT;
172 }
173 } else if (utils.isDefined(lSignal.v)) {
174 t = ctx.stCONSTANT;
175 }
176 tAll = priorize(t,tAll);
177 if (lSignal.e>=0) {
178 lSignal = ctx.signals[lSignal.e];
179 } else {
180 end=true;
181 }
182 }
183 if (tAll == ERROR) {
184 throw new Error("Incompatible types in signal: " + s);
185 }
186 lSignal.c = tAll;
187 }
188}
189
190
191function generateWitnessNames(ctx) {
192 const totals = {};
193 totals[ctx.stONE] = 0;
194 totals[ctx.stOUTPUT] = 0;
195 totals[ctx.stPUBINPUT] = 0;
196 totals[ctx.stPRVINPUT] = 0;
197 totals[ctx.stINTERNAL] = 0;
198 totals[ctx.stDISCARDED] = 0;
199 totals[ctx.stCONSTANT] = 0;
200 const ids = {};
201
202 // First classify the signals
203 for (let s=0; s<ctx.signals.length; s++) {
204
205 if ((ctx.verbose)&&(s%10000 == 0)) console.log("generate witness (counting): ", s);
206
207 const signal = ctx.signals[s];
208 let lSignal = signal;
209 while (lSignal.e>=0) lSignal = ctx.signals[lSignal.e];
210
211 if (!( lSignal.o & ctx.COUNTED) ) {
212 lSignal.o |= ctx.COUNTED;
213 totals[lSignal.c] ++;
214 }
215 }
216
217 ids[ctx.stONE] = 0;
218 ids[ctx.stOUTPUT] = 1;
219 ids[ctx.stPUBINPUT] = ids[ctx.stOUTPUT] + totals[ctx.stOUTPUT];
220 ids[ctx.stPRVINPUT] = ids[ctx.stPUBINPUT] + totals[ctx.stPUBINPUT];
221 ids[ctx.stINTERNAL] = ids[ctx.stPRVINPUT] + totals[ctx.stPRVINPUT];
222 ids[ctx.stDISCARDED] = ids[ctx.stINTERNAL] + totals[ctx.stINTERNAL];
223 ids[ctx.stCONSTANT] = ids[ctx.stDISCARDED] + totals[ctx.stDISCARDED];
224 const nSignals = ids[ctx.stCONSTANT] + totals[ctx.stCONSTANT];
225
226 for (let s=0; s<ctx.signals.length; s++) {
227
228 if ((ctx.verbose)&&(s%10000 == 0)) console.log("seting id: ", s);
229
230 const signal = ctx.signals[s];
231 let lSignal = signal;
232 while (lSignal.e>=0) {
233 lSignal = ctx.signals[lSignal.e];
234 }
235 if ( typeof(lSignal.id) === "undefined" ) {
236 lSignal.id = ids[lSignal.c] ++;
237 }
238
239 signal.id = lSignal.id;
240 }
241
242 ctx.totals = totals;
243}
244
245function reduceConstants(ctx) {
246 const newConstraints = new BigArray();
247 for (let i=0; i<ctx.constraints.length; i++) {
248 if ((ctx.verbose)&&(i%10000 == 0)) console.log("reducing constants: ", i);
249 const c = ctx.lc.canonize(ctx, ctx.constraints[i]);
250 if (!ctx.lc.isZero(c)) {
251 newConstraints.push(c);
252 }
253 delete ctx.constraints[i];
254 }
255 ctx.constraints = newConstraints;
256}
257
258function reduceConstrains(ctx) {
259 const sig2constraint = {};
260 let removedSignals = {};
261 let nRemoved;
262 let lIdx;
263
264
265 let possibleConstraints = new Array(ctx.constraints.length);
266 let nextPossibleConstraints;
267 for (let i=0; i<ctx.constraints.length; i++) {
268 const insertedSig = {};
269 const c = ctx.constraints[i];
270 for (let s in c.a.coefs) {
271 if (!insertedSig[s]) {
272 if (!sig2constraint[s]) sig2constraint[s] = [];
273 sig2constraint[s].push(i);
274 insertedSig[s] = true;
275 }
276 }
277 for (let s in c.b.coefs) {
278 if (!insertedSig[s]) {
279 if (!sig2constraint[s]) sig2constraint[s] = [];
280 sig2constraint[s].push(i);
281 insertedSig[s] = true;
282 }
283 }
284 for (let s in c.c.coefs) {
285 if (!insertedSig[s]) {
286 if (!sig2constraint[s]) sig2constraint[s] = [];
287 sig2constraint[s].push(i);
288 insertedSig[s] = true;
289 }
290 }
291 possibleConstraints[i] = i;
292 }
293
294 while (possibleConstraints.length >0) {
295 nextPossibleConstraints = {};
296 removedSignals = {};
297 nRemoved = 0;
298 lIdx = {};
299 for (let i=0;i<possibleConstraints.length;i++) {
300 if ((ctx.verbose)&&(i%10000 == 0)) {
301 console.log(`reducing constraints: ${i}/${possibleConstraints.length} reduced: ${nRemoved}`);
302 }
303 const c = ctx.constraints[possibleConstraints[i]];
304 if (!c) continue;
305
306 // Swap a and b if b has more variables.
307 if (Object.keys(c.b).length > Object.keys(c.a).length) {
308 const aux = c.a;
309 c.a=c.b;
310 c.b=aux;
311 }
312
313 // Mov to C if possible.
314 if (isConstant(c.a)) {
315 const ct = {t: "N", v: c.a.coefs[sONE]};
316 c.c = ctx.lc.add(ctx.lc.mul(c.b, ct), c.c);
317 c.a = { t: "LC", coefs: {} };
318 c.b = { t: "LC", coefs: {} };
319 }
320 if (isConstant(c.b)) {
321 const ct = {t: "N", v: c.b.coefs[sONE]};
322 c.c = ctx.lc.add(ctx.lc.mul(c.a, ct), c.c);
323 c.a = { t: "LC", coefs: {} };
324 c.b = { t: "LC", coefs: {} };
325 }
326
327 if (ctx.lc.isZero(c.a) || ctx.lc.isZero(c.b)) {
328 const freeC = substituteRemoved(c.c);
329 const isolatedSignal = getFirstInternalSignal(ctx, freeC);
330 if (isolatedSignal) {
331 // console.log(isolatedSignal);
332 // console.log(freeC);
333 removedSignals[isolatedSignal] = isolateSignal(freeC, isolatedSignal);
334 if (lIdx[isolatedSignal]) {
335 lIdx[isolatedSignal].forEach( (s) => {
336 removedSignals[s] = substitute(removedSignals[s], isolatedSignal, removedSignals[isolatedSignal]);
337 });
338 }
339
340 addTolIdx(removedSignals[isolatedSignal], isolatedSignal);
341 ctx.constraints[possibleConstraints[i]] = null;
342 nRemoved ++;
343
344 sig2constraint[isolatedSignal].forEach( (s) => {
345 nextPossibleConstraints[s] = true;
346 });
347 }
348 }
349 }
350
351 nextPossibleConstraints = Object.keys(nextPossibleConstraints);
352
353 for (let i=0; i<nextPossibleConstraints.length;i++) {
354 const c = ctx.constraints[nextPossibleConstraints[i]];
355 if (c) {
356 const nc = {
357 a: substituteRemoved(c.a),
358 b: substituteRemoved(c.b),
359 c: substituteRemoved(c.c)
360 };
361 if (ctx.lc.isZero(nc)) {
362 delete ctx.constraints[nextPossibleConstraints[i]];
363 } else {
364 ctx.constraints[nextPossibleConstraints[i]] = nc;
365 }
366 }
367 }
368
369 for (let s in removedSignals) {
370
371 let lSignal = ctx.signals[s];
372 while (lSignal.e>=0) {
373 lSignal = ctx.signals[lSignal.e];
374 }
375
376 lSignal.c = ctx.stDISCARDED;
377 }
378
379 possibleConstraints = nextPossibleConstraints;
380
381 }
382
383 let o=0;
384 for (let i=0; i<ctx.constraints.length;i++) {
385 if (ctx.constraints[i]) {
386 if (!ctx.lc.isZero(ctx.constraints[i])) {
387 ctx.constraints[o] = ctx.constraints[i];
388 o++;
389 }
390 }
391 }
392
393 ctx.constraints.length = o;
394
395 function getFirstInternalSignal(ctx, l) {
396 for (let k in l.coefs) {
397 k = Number(k);
398 const signal = ctx.signals[k];
399 if ((signal.c == ctx.stINTERNAL)&&(!ctx.F.isZero(l.coefs[k])) &&(!removedSignals[k])) return k;
400 }
401 return null;
402 }
403
404 function isolateSignal(lc, s) {
405 const eq = {
406 t: "LC",
407 coefs: {}
408 };
409 const invCoef = ctx.F.inv(lc.coefs[s]);
410 for (const k in lc.coefs) {
411 if (k != s) {
412 const v = ctx.F.mul( ctx.F.neg(lc.coefs[k]), invCoef);
413 if (!ctx.F.isZero(v)) {
414 eq.coefs[k] = v;
415 }
416 }
417 }
418 return eq;
419 }
420
421 function substituteRemoved(lc) {
422 const newLc = ctx.lc._clone(lc);
423 for (let k in lc.coefs) {
424 if (removedSignals[k]) {
425 delete newLc.coefs[k];
426 for (let k2 in removedSignals[k].coefs) {
427 const newP = ctx.F.mul(removedSignals[k].coefs[k2], lc.coefs[k]);
428 if (!ctx.F.isZero(newP)) {
429 if (newLc.coefs[k2]) {
430 newLc.coefs[k2] = ctx.F.add(newLc.coefs[k2], newP);
431 if (ctx.F.isZero(newLc.coefs[k2])) delete newLc.coefs[k2];
432 } else {
433 newLc.coefs[k2] = newP;
434 }
435 }
436 }
437 }
438 }
439 return newLc;
440 }
441
442 function substitute(lc, s, eq) {
443 if (!lc.coefs[s]) return lc;
444 const newLc = ctx.lc._clone(lc);
445 delete newLc.coefs[s];
446 for (let k2 in eq.coefs) {
447 const newP = ctx.F.mul(eq.coefs[k2], lc.coefs[s]);
448 if (!ctx.F.isZero(newP)) {
449 if (newLc.coefs[k2]) {
450 newLc.coefs[k2] = ctx.F.add(newLc.coefs[k2], newP);
451 if (ctx.F.isZero(newLc.coefs[k2])) delete newLc.coefs[k2];
452 } else {
453 newLc.coefs[k2] = newP;
454 }
455 }
456 }
457 return newLc;
458 }
459
460 function isConstant(l) {
461 for (let k in l.coefs) {
462 if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false;
463 }
464 if (!l.coefs[sONE] || ctx.F.isZero(l.coefs[sONE])) return false;
465 return true;
466 }
467
468 function addTolIdx(lc, newS) {
469 for (let s in lc.coefs) {
470 if (!lIdx[s]) lIdx[s] = [];
471 lIdx[s].push(newS);
472 }
473 }
474
475
476}
477
478
479function reduceConstrains_old(ctx) {
480 indexVariables();
481 let possibleConstraints = ctx.constraints;
482 let ii=0;
483 while (possibleConstraints.length>0) {
484 let nextPossibleConstraints = new BigArray();
485 for (let i=0; i<possibleConstraints.length; i++) {
486 ii++;
487 if ((ctx.verbose)&&(ii%10000 == 0)) console.log("reducing constraints: ", i);
488 if (!ctx.constraints[i]) continue;
489 const c = ctx.constraints[i];
490
491 // Swap a and b if b has more variables.
492 if (Object.keys(c.b).length > Object.keys(c.a).length) {
493 const aux = c.a;
494 c.a=c.b;
495 c.b=aux;
496 }
497
498 // Mov to C if possible.
499 if (isConstant(c.a)) {
500 const ct = {t: "N", v: c.a.coefs[sONE]};
501 c.c = ctx.lc.add(ctx.lc.mul(c.b, ct), c.c);
502 c.a = { t: "LC", coefs: {} };
503 c.b = { t: "LC", coefs: {} };
504 }
505 if (isConstant(c.b)) {
506 const ct = {t: "N", v: c.b.coefs[sONE]};
507 c.c = ctx.lc.add(ctx.lc.mul(c.a, ct), c.c);
508 c.a = { t: "LC", coefs: {} };
509 c.b = { t: "LC", coefs: {} };
510 }
511
512 if (ctx.lc.isZero(c.a) || ctx.lc.isZero(c.b)) {
513 const isolatedSignal = getFirstInternalSignal(ctx, c.c);
514 if (isolatedSignal) {
515
516 let lSignal = ctx.signals[isolatedSignal];
517 while (lSignal.e>=0) {
518 lSignal = ctx.signals[lSignal.e];
519 }
520
521
522 const isolatedSignalEquivalence = {
523 t: "LC",
524 coefs: {}
525 };
526 const invCoef = ctx.F.inv(c.c.coefs[isolatedSignal]);
527 for (const s in c.c.coefs) {
528 if (s != isolatedSignal) {
529 const v = ctx.F.mul( ctx.F.neg(c.c.coefs[s]), invCoef);
530 if (!ctx.F.isZero(v)) {
531 isolatedSignalEquivalence.coefs[s] = v;
532 }
533 }
534 }
535
536 for (let j in lSignal.inConstraints) {
537 if ((j!=i)&&(ctx.constraints[j])) {
538 ctx.constraints[j] = ctx.lc.substitute(ctx.constraints[j], isolatedSignal, isolatedSignalEquivalence);
539 linkSignalsConstraint(j);
540 if (j<i) {
541 nextPossibleConstraints.push(j);
542 }
543 }
544 }
545
546 ctx.constraints[i] = null;
547
548 lSignal.c = ctx.stDISCARDED;
549 } else {
550 if (ctx.lc.isZero(c.c)) ctx.constraints[i] = null;
551 }
552 }
553 }
554 possibleConstraints = nextPossibleConstraints;
555 }
556 unindexVariables();
557
558 // Pack the constraints
559 let o = 0;
560 for (let i=0; i<ctx.constraints.length; i++) {
561 if (ctx.constraints[i]) {
562 if (o != i) {
563 ctx.constraints[o] = ctx.constraints[i];
564 }
565 o++;
566 }
567 }
568 ctx.constraints.length = o;
569
570 function indexVariables() {
571 for (let i=0; i<ctx.constraints.length; i++) linkSignalsConstraint(i);
572 }
573
574 function linkSignalsConstraint(cidx) {
575 const ct = ctx.constraints[cidx];
576 for (let k in ct.a.coefs) linkSignal(k, cidx);
577 for (let k in ct.b.coefs) linkSignal(k, cidx);
578 for (let k in ct.c.coefs) linkSignal(k, cidx);
579 }
580
581 function unindexVariables() {
582 for (let s=0; s<ctx.signals.length; s++) {
583 let lSignal = ctx.signals[s];
584 while (lSignal.e>=0) {
585 lSignal = ctx.signals[lSignal.e];
586 }
587 if (lSignal.inConstraints) delete lSignal.inConstraints;
588 }
589 }
590
591/*
592 function unlinkSignal(signalName, cidx) {
593 let lSignal = ctx.signals[signalName];
594 while (lSignal.e>=0) {
595 lSignal = ctx.signals[lSignal.e];
596 }
597 if ((lSignal.inConstraints)&&(lSignal.inConstraints[cidx])) {
598 delete lSignal.inConstraints[cidx];
599 }
600 }
601*/
602
603 function linkSignal(signalName, cidx) {
604 let lSignal = ctx.signals[signalName];
605 while (lSignal.e>=0) {
606 lSignal = ctx.signals[lSignal.e];
607 }
608 if (!lSignal.inConstraints) lSignal.inConstraints = {};
609 lSignal.inConstraints[cidx] = true;
610 }
611
612 function getFirstInternalSignal(ctx, l) {
613 for (let k in l.coefs) {
614 const signal = ctx.signals[k];
615 if (signal.c == ctx.stINTERNAL) return k;
616 }
617 return null;
618 }
619
620 function isConstant(l) {
621 for (let k in l.coefs) {
622 if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false;
623 }
624 if (!l.coefs[sONE] || ctx.F.isZero(l.coefs[sONE])) return false;
625 return true;
626 }
627
628}
629
630/*
631
632function buildCircuitDef(ctx, mainCode) {
633 const res = {
634 mainCode: mainCode
635 };
636 res.signalName2Idx = ctx.signalName2Idx;
637
638 res.components = [];
639 res.componentName2Idx = {};
640 for (let c in ctx.components) {
641 const idCoponent = res.components.length;
642 res.components.push({
643 name: c,
644 params: ctx.components[c].params,
645 template: ctx.components[c].template,
646 inputSignals: 0
647 });
648 res.componentName2Idx[c] = idCoponent;
649 }
650
651 res.signals = new Array(ctx.signalNames.length);
652 for (let i=0; i<ctx.signalNames.length; i++) {
653 res.signals[i] = {
654 names: ctx.signalNames[i],
655 triggerComponents: []
656 };
657 ctx.signalNames[i].map( (fullName) => {
658 const idComponet = res.componentName2Idx[ctx.signals[fullName].component];
659 if (ctx.signals[fullName].direction == "IN") {
660 res.signals[i].triggerComponents.push(idComponet);
661 res.components[idComponet].inputSignals++;
662 }
663 });
664 }
665
666 res.constraints = buildConstraints(ctx);
667
668 res.templates = ctx.templates;
669
670 res.functions = {};
671 for (let f in ctx.functions) {
672 res.functions[f] = {
673 params: ctx.functionParams[f],
674 func: ctx.functions[f]
675 };
676 }
677
678 res.nPrvInputs = ctx.totals.prvInput;
679 res.nPubInputs = ctx.totals.pubInput;
680 res.nInputs = res.nPrvInputs + res.nPubInputs;
681 res.nOutputs = ctx.totals.output;
682 res.nVars = res.nInputs + res.nOutputs + ctx.totals.one + ctx.totals.internal;
683 res.nConstants = ctx.totals.constant;
684 res.nSignals = res.nVars + res.nConstants;
685
686 return res;
687}
688
689*/
690
691
692/*
693 Build constraints
694
695A constraint like this
696
697 [s1 + 2*s2 + 3*s3] * [ s2 + 5*s4] - [s0 ] = 0
698 [ 5*s2 + 6*s3] * [ s2 + ] - [s0 + 2* s2] = 0
699 [s1 + s3] * [ s2 + 5*s3] - [s4 ] = 0
700
701is converted to
702
703[
704 [{"1":"1","2":"2","3":"3"} , {"2":"1","4":"5"} , {"0":"1" }],
705 [{ "2":"5","3":"6"} , {"2":"1" } , {"0":"1", "2":"2"}],
706 [{"1":"1", "3":"1"} , {"2":"1","3":"5"} , {"4":"1" }]
707]
708 ^ ^ ^
709 | | |
710 A B C
711
712*/
713/*
714function buildConstraints(ctx) {
715 const res = [];
716
717 function fillLC(dst, src) {
718 if (src.t != "LC") throw new Error("Constraint is not a LINEARCOMBINATION");
719 for (let s in src.coefs) {
720 const v = src.coefs[s].toString();
721 const id = ctx.signalName2Idx[s];
722 dst[id] = v;
723 }
724 }
725
726 for (let i=0; i<ctx.constraints.length; i++) {
727 const A = {};
728 const B = {};
729 const C = {};
730
731 fillLC(A, ctx.constraints[i].a);
732 fillLC(B, ctx.constraints[i].b);
733 fillLC(C, ctx.lc.negate(ctx.constraints[i].c));
734
735 res.push([A,B,C]);
736 }
737
738 return res;
739}
740*/
741
742/*
743function buildSyms(ctx, strm) {
744
745 let nSyms;
746
747 addSymbolsComponent(ctx.mainComponent + ".", ctx.getComponentIdx(ctx.mainComponent));
748
749
750 function addSymbolsComponent(prefix, idComponet) {
751 for (let n in ctx.components[idComponet].names.o) {
752 const entrie = ctx.components[idComponet].names.o[n];
753 addSymbolArray(prefix+n, entrie.type, entrie.sizes, entrie.offset);
754 }
755 }
756
757 function addSymbolArray(prefix, type, sizes, offset) {
758 if (sizes.length==0) {
759 if (type == "S") {
760 let s=offset;
761 while (ctx.signals[s].e >= 0) s = ctx.signals[s].e;
762 let wId = ctx.signals[s].id;
763 if (typeof(wId) == "undefined") wId=-1;
764 strm.write(`${offset},${wId},${prefix}\n`);
765 nSyms ++;
766 if ((ctx.verbose)&&(nSyms%10000 == 0)) console.log("Symbols saved: "+nSyms);
767 } else {
768 addSymbolsComponent(prefix+".", offset);
769 }
770 return 1;
771 } else {
772 let acc = 0;
773 for (let i=0; i<sizes[0]; i++) {
774 acc += addSymbolArray(`${prefix}[${i}]`, type, sizes.slice(1), offset + acc );
775 }
776 return acc;
777 }
778 }
779
780}
781
782*/
783