UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

82 lines 2.75 kB
import { provableTuple } from '../types/struct.js'; import { Field } from '../wrapped.js'; import { assert } from '../../util/errors.js'; import { Provable } from '../provable.js'; import { rangeCheck32, rangeCheck64, rangeCheckN } from './range-check.js'; export { divMod32, addMod32, divMod64, addMod64 }; function divMod32(n, nBits = 64) { assert(nBits >= 0 && nBits < 255, `nBits must be in the range [0, 255), got ${nBits}`); const quotientBits = Math.max(0, nBits - 32); if (n.isConstant()) { assert(n.toBigInt() < 1n << BigInt(nBits), `n needs to fit into ${nBits} bits, but got ${n.toBigInt()}`); let nBigInt = n.toBigInt(); let q = nBigInt >> 32n; let r = nBigInt - (q << 32n); return { remainder: new Field(r), quotient: new Field(q), }; } let [quotient, remainder] = Provable.witness(provableTuple([Field, Field]), () => { let nBigInt = n.toBigInt(); let q = nBigInt >> 32n; let r = nBigInt - (q << 32n); // why do we have to do this? return [q, r]; }); if (quotientBits === 1) { quotient.assertBool(); } else { rangeCheckN(quotientBits, quotient); } rangeCheck32(remainder); n.assertEquals(quotient.mul(1n << 32n).add(remainder)); return { remainder, quotient, }; } function addMod32(x, y) { return divMod32(x.add(y), 33).remainder; } function divMod64(n, nBits = 128) { assert(nBits >= 0 && nBits < 255, `nBits must be in the range [0, 255), got ${nBits}`); // calculate the number of bits allowed for the quotient to avoid overflow const quotientBits = Math.max(0, nBits - 64); if (n.isConstant()) { assert(n.toBigInt() < 1n << BigInt(nBits), `n needs to fit into ${nBits} bits, but got ${n.toBigInt()}`); let nBigInt = n.toBigInt(); let q = nBigInt >> 64n; let r = nBigInt - (q << 64n); return { remainder: new Field(r), quotient: new Field(q), }; } let [quotient, remainder] = Provable.witness(provableTuple([Field, Field]), () => { let nBigInt = n.toBigInt(); let q = nBigInt >> 64n; let r = nBigInt - (q << 64n); return [q, r]; }); if (quotientBits === 1) { quotient.assertBool(); } else if (quotientBits === 64) { rangeCheck64(quotient); } else { rangeCheckN(quotientBits, quotient); } rangeCheck64(remainder); n.assertEquals(quotient.mul(1n << 64n).add(remainder)); return { remainder, quotient, }; } function addMod64(x, y) { return divMod64(x.add(y), 65).remainder; } //# sourceMappingURL=arithmetic.js.map