const bigInt=require("big-integer"); class ZqBuilder { constructor(q, name) { this.q=bigInt(q); this.h = []; this.c = []; this.name = name; } build() { this._buildHeaders(); this._buildAdd(); this._buildMul(); this.c.push(""); this.h.push(""); return [this.h.join("\n"), this.c.join("\n")]; } _buildHeaders() { this.n64 = Math.floor((this.q.bitLength() - 1) / 64)+1; this.h.push("typedef unsigned long long u64;"); this.h.push(`typedef u64 ${this.name}Element[${this.n64}];`); this.h.push(`typedef u64 *P${this.name}Element;`); this.h.push(`extern ${this.name}Element ${this.name}_q;`); this.h.push(`#define ${this.name}_N64 ${this.n64}`); this.c.push(`#include "${this.name.toLowerCase()}.h"`); this._defineConstant(`${this.name}_q`, this.q); this.c.push(""); this.h.push(""); } _defineConstant(n, v) { let S = `${this.name}Element ${n}={`; const mask = bigInt("FFFFFFFFFFFFFFFF", 16); for (let i=0; i0) S = S+","; let shex = v.shiftRight(i*64).and(mask).toString(16); while (shex <16) shex = "0" + shex; S = S + "0x" + shex + "ULL"; } S += "};"; this.c.push(S); } _buildAdd() { this.h.push(`void ${this.name}_add(P${this.name}Element r, P${this.name}Element a, P${this.name}Element b);`); this.c.push(`void ${this.name}_add(P${this.name}Element r, P${this.name}Element a, P${this.name}Element b) {`); this.c.push(" __asm__ __volatile__ ("); for (let i=0; i0) { this.c.push(` "movq ${(this.n64 - i-1)*8}(%0), %%rax;"`); } this.c.push(` "cmp ${(this.n64 - i-1)*8}(%3), %%rax;"`); this.c.push(" \"jg SQ;\""); this.c.push(" \"jl DONE;\""); } this.c.push(" \"SQ:\""); for (let i=0; i=0; j--) { if (((i-j)