function randomBigInt(bits) {
const data = new BigUint64Array(Math.ceil(bits / 64))
self.crypto.getRandomValues(data)
return data.reduce((n, x, i) => n | (x << BigInt(i * 64)), 0n)
}
const n = randomBigInt(1024)
const testersCoeff = []
const testersBigCoeff = []
const testers = []
let testersN = 0
n.toString(2).length
let i = (n.toString(16).length - 1) * 4
i += 32 - Math.clz32(Number(n >> BigInt(i)))
// TODO: check nonnegative
// find upper bound
let i = 0
while (true) {
if (testersN === i) {
testersCoeff.push(32 << testersN)
testersBigCoeff.push(BigInt(testersCoeff[testersN]))
testers.push(1n << testersBigCoeff[testersN])
testersN++
}
if (n < testers[i]) break
i++
}
// determine length by bisection
i--
let r = testersCoeff[i]
let b = n >> testersBigCoeff[i]
while (i) {
i--
let a = b >> testersBigCoeff[i]
if (a)
(r += testersCoeff[i], b = a)
}
r += 32 - Math.clz32(Number(b))
// TODO: check nonnegative
// find upper bound
let i = 0
while (true) {
if (testersN === i) {
testersCoeff.push(32 << testersN)
testersBigCoeff.push(BigInt(testersCoeff[testersN]))
testers.push(1n << testersBigCoeff[testersN])
testersN++
}
if (n < testers[i]) break
i++
}
// determine length by bisection
i--
let r = testersCoeff[i]
let b = n >> testersBigCoeff[i]
while (i) {
i--
if (b < testers[i]) continue
r += testersCoeff[i]
b >>= testersBigCoeff[i]
}
r += 32 - Math.clz32(Number(b))