Skip to content

Commit

Permalink
add pow(Fr, BigInt|Number)
Browse files Browse the repository at this point in the history
  • Loading branch information
herumi committed Sep 12, 2024
1 parent 6422c4c commit ac0aa43
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
51 changes: 44 additions & 7 deletions src/value-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 18 additions & 1 deletion test/test-ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit ac0aa43

Please sign in to comment.