ltcode
Version:
Luby Transform Code implementation.
70 lines (69 loc) • 2.57 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PRNG = void 0;
class PRNG {
constructor(numBlocks, seed) {
this.DEFAULT_DELTA = 0.5;
this.PRNG_M = 2147483647;
this.seed = seed;
this.numBlocks = numBlocks;
this.cumulativeDistributionFunction = this.generateRsdCdf();
}
sample_source_blocks(seed) {
const initialSamplingSeed = seed !== null ? seed : this.seed;
if (seed !== null) {
this.seed = seed;
}
const degree = this.sampleDegree();
const selectedBlocks = new Set();
while (selectedBlocks.size < degree) {
const nextRandom = this.nextRandom();
const blockNumber = nextRandom % this.numBlocks;
selectedBlocks.add(blockNumber);
}
return [initialSamplingSeed, selectedBlocks];
}
nextRandom() {
this.seed = 16807 * this.seed % this.PRNG_M;
return this.seed;
}
sampleDegree() {
const probability = this.nextRandom() / (this.PRNG_M - 1);
for (let index = 0; index < this.cumulativeDistributionFunction.length; index++) {
if (this.cumulativeDistributionFunction[index] > probability) {
return index + 1;
}
}
return this.cumulativeDistributionFunction.length;
}
generateTau(S) {
const pivot = Math.floor(this.numBlocks / S);
const tau = Array.from({ length: pivot - 1 }, (_, d) => S / this.numBlocks / (d + 1));
tau.push(S / this.numBlocks * Math.log(S / this.DEFAULT_DELTA));
tau.push(...Array.from({ length: this.numBlocks - pivot }, () => 0));
return tau;
}
generateRho() {
return [1 / this.numBlocks, ...Array.from({ length: this.numBlocks - 1 }, (_, d) => 1 / ((d + 2) * (d + 1)))];
}
generateMu() {
const S = Math.log(this.numBlocks / this.DEFAULT_DELTA) * Math.sqrt(this.numBlocks) * 0.1;
const tau = this.generateTau(S);
const rho = this.generateRho();
const normalizer = this.sum(rho) + this.sum(tau);
return Array.from({ length: this.numBlocks }, (_, d) => (rho[d] + tau[d]) / normalizer);
}
sum(arr) {
return arr.reduce((a, b) => a + b, 0);
}
generateRsdCdf() {
const mu = this.generateMu();
const arr = [];
for (let d = 0; d < this.numBlocks; d++) {
const slice_mu = mu.slice(0, d + 1);
arr.push(this.sum(slice_mu));
}
return arr;
}
}
exports.PRNG = PRNG;