diff --git a/src/value-types.ts b/src/value-types.ts index f3958b3..9be8c31 100644 --- a/src/value-types.ts +++ b/src/value-types.ts @@ -906,15 +906,52 @@ export const hashAndMapToG2 = (s: string | Uint8Array): G2 => { return x } -export function pow (x: Fr, y: Fr): Fr -export function pow (x: Fp, y: Fp): Fp +const IntToArray = (_x: bigint | number): Uint8Array => { + let x = typeof _x === 'number'? BigInt(_x) : _x + if (x < 0n) { + throw new Error('IntToArray: negative value') + } + if (x === 0n) return new Uint8Array(1) + const a = [] + while (x) { + a.push(Number(BigInt.asUintN(8, x))) + x >>= 8n + } + return new Uint8Array(a) +} + +const powArray = (cstr: any, powArray: Function, x: Common, _y: Number | BigInt): Common => { + const y = IntToArray(_y.valueOf()) + const z = new cstr() + const stack = mod.stackSave() + const zPos = z._salloc() + const xPos = x._sallocAndCopy() + const yPos = mod.stackAlloc(y.length) + mod.HEAP8.set(y, yPos) + const r = powArray(zPos, xPos, yPos, y.length) + z._save(zPos) + mod.stackRestore(stack) + if (r < 0) throw new Error('powArray err') + return z +} + +export function pow (x: Fr, y: Fr | Number | BigInt): Fr +export function pow (x: Fp, y: Fp | Number | BigInt): Fp export function pow (x: GT, y: Fr): GT -export function pow (x: Common, y: Common): Common { - if (x instanceof Fr && y instanceof Fr) { - return x._op2(mod._mclBnFr_pow, y) +export function pow (x: Common, y: Common | Number | BigInt): Common { + if (x instanceof Fr) { + if (y instanceof Fr) { + return x._op2(mod._mclBnFr_pow, y) + } else if (typeof(y) === 'number' || typeof(y) === 'bigint') { + return powArray(Fr, mod._mclBnFr_powArray, x, y) + } } - if (x instanceof Fp && y instanceof Fp) { - return x._op2(mod._mclBnFp_pow, y) + if (x instanceof Fp) { + if (y instanceof Fp) { + return x._op2(mod._mclBnFp_pow, y) + } else if (typeof(y) === 'number' || typeof(y) === 'bigint') { + return powArray(Fp, mod._mclBnFp_powArray, x, y) + } } if (x instanceof GT && y instanceof Fr) { return x._op2(mod._mclBnGT_pow, y) diff --git a/test/test-ts.ts b/test/test-ts.ts index 6c78dd5..393ce8c 100644 --- a/test/test-ts.ts +++ b/test/test-ts.ts @@ -78,10 +78,27 @@ function powTest(Fcstr: any): void { z1.setInt(1) for (let i = 0; i < 100; i++) { y.setInt(i) - const z2 = mcl.pow(x, y) + const z2 = mcl.pow(x, y) // Fr assert(z1.isEqual(z2)) + const z3 = mcl.pow(x, i) // number + assert(z1.isEqual(z3)) + const z4 = mcl.pow(x, BigInt(i)) // bigint + assert(z1.isEqual(z4)) z1 = mcl.mul(z1, x) } + // large pow + const one = new Fcstr() + one.setInt(1) + const negOne = new Fcstr() + negOne.setInt(-1) + y.a_ = z1.a_.slice() + for (let i = 0; i < 100; i++) { + z1 = mcl.pow(x, y) // Fr + const y2 = mcl.sub(negOne, y) // y-1 + const z2 = mcl.pow(x, BigInt(y2.getStr())) + z1 = mcl.mul(z1, z2) + assert(z1.isEqual(one)) + } } function FrTest() {