Created
December 17, 2024 09:50
-
-
Save Yaffle/74c3c9b0d675e304caa788d00208c346 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const e = B2 >= 10**7 && d * d < 2**53 ? 2 : 1; | |
const dsP = scalePoint(curve, sP, Math.pow(d, e)); | |
const range = function (n) { | |
const a = new Array(n); | |
for (let i = 0; i < n; i += 1) { | |
a[i] = i; | |
} | |
return a; | |
}; | |
const multiScalePoint = function (curve, P, s) { | |
//console.time('chain'); | |
const heap = new Heap(range(s.length).reverse(), function (a, b) { | |
return s[a] > s[b] ? 1 : 0; | |
}); | |
const chain = []; | |
while (true) { | |
const max = heap.getMax(); | |
const next = heap.getNextMax(); | |
if (s[next] < 2) { | |
break; | |
} | |
s[max] -= s[next]; | |
heap.updateMax(); | |
chain.push(max); | |
chain.push(next); | |
} | |
//console.timeEnd('chain'); | |
let additions = 0; | |
const res = s.map(function (i) { | |
return i === 0 ? null : (i === 1 ? P : scalePoint(curve, P, i)); | |
}); | |
while (chain.length >= 2) { | |
const next = chain.pop(); | |
const max = chain.pop(); | |
const b = s[next]; | |
const a = s[max]; | |
s[max] = a + b; | |
res[max] = a === 0 ? res[next] : (a === b ? curve.doublePoint(res[next]) : curve.addPoints(res[max], res[next])); | |
additions += a !== 0 ? 1 : 0; | |
} | |
//console.log('additions', additions, s.length, heap.swaps); | |
return res; | |
}; | |
const pointsRange = function (curve, P, to, filter, e) { | |
const s = range(to + 1).map(i => (filter == null || filter(i)) && i !== 0 ? Math.pow(i, e) : null); | |
return restoreNulls(multiScalePoint(curve, P, s.filter(i => i != null)), s); | |
}; | |
function Heap(data, cmpfn) { | |
this.data = data; | |
this.cmpfn = cmpfn; | |
this.swaps = 0; | |
} | |
Heap.prototype.getMax = function () { | |
if (this.data.length < 1) { | |
throw new RangeError(); | |
} | |
return this.data[0]; | |
}; | |
Heap.prototype.getNextMax = function () { | |
if (this.data.length < 2) { | |
throw new RangeError(); | |
} | |
if (this.data.length < 3) { | |
return this.data[1]; | |
} | |
const left = this.data[1]; | |
const right = this.data[2]; | |
return this.cmpfn(left, right) > 0 ? left : right; | |
}; | |
Heap.prototype.updateMax = function () { | |
let index = 0; | |
while (index !== -1) { | |
let largest = index; | |
const left = 2 * index + 1; | |
if (left < this.data.length && this.cmpfn(this.data[left], this.data[largest]) > 0) { | |
largest = left; | |
} | |
const right = 2 * index + 2; | |
if (right < this.data.length && this.cmpfn(this.data[right], this.data[largest]) > 0) { | |
largest = right; | |
} | |
if (largest !== index) { | |
const tmp = this.data[index]; | |
this.data[index] = this.data[largest]; | |
this.data[largest] = tmp; | |
index = largest; | |
this.swaps += 1; | |
} else { | |
index = -1; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment