UNPKG

ts-math

Version:

A collection of math functions and packages written in Typescript

123 lines 3.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createNormalSamples = exports.BrownianBridge = exports.brownianBridge = void 0; const _1 = require("."); const { ceil, log2, sqrt, exp, log } = Math; function binaryFlip(n, N) { let b = N - 1 - n; let p = N >> 1; let s = 0; while (b > 0) { if (b % 2 === 1) { s += p; } b >>= 1; p >>= 1; } return s; } /** Calculates the intermediate value at d, between start point (d0, s0) and end point (dT, sT) * rnd is N(0,1), sigma is standard deviation */ function brownianBridge(d, s0, sT, t0, tT, rnd) { var T = tT - t0; var t = d - t0; var f = t / T; var g = f * (T - t); var m = (1 - f) * s0 + f * sT; var s = sqrt(g); return m + s * rnd; } exports.brownianBridge = brownianBridge; class BrownianBridge { constructor(dim) { this.dim = dim; const N = 1 << ceil(log2(dim)); binaryFlip(dim, N); this.steps = [...Array(dim)].map((d, index) => ({ index, sortOrder: binaryFlip(index, N), time: 0, startTime: 0, endTime: 0, })); this.steps.sort((d1, d2) => d1.sortOrder - d2.sortOrder); for (let i = 0; i < dim; i++) { this.steps[i].time = i + 1; } this.steps.sort((d1, d2) => d1.index - d2.index); for (let i = 0; i < dim; i++) { const step = this.steps[i]; let startTime = 0; let endTime = dim; for (let j = 0; j < i; j++) { let st = this.steps[j].time; if (st < step.time && st > startTime) { startTime = st; } if (st > step.time && st < endTime) { endTime = st; } } step.startTime = startTime; step.endTime = endTime; } } calculateSample(rnds) { const bs = new Array(this.dim + 1); bs[0] = 0; bs[this.dim] = rnds[0] * sqrt(this.dim); for (let i = 1; i < this.steps.length; i++) { const step = this.steps[i]; const t = step.time; const t0 = step.startTime; const tT = step.endTime; const s0 = bs[t0]; const sT = bs[tT]; bs[step.time] = brownianBridge(t, s0, sT, t0, tT, rnds[i]); } const res = new Array(this.dim); for (let i = 0; i < this.dim; i++) { res[i] = bs[i + 1] - bs[i]; } return res; } } exports.BrownianBridge = BrownianBridge; /** * createNormalSamples genrates normally distributed samples. They are correlated if parameter * corrs is passed as a square matrix number[][]. * @param nSamples Number of samples to be returned. * @param nDim Number of dimensions. * @param corrs Correlation matrix, a square {nDim x nDim} matrix. * @returns samples as a number[][] matrix, nSamples rows and nDim columns. */ function createNormalSamples(nSamples, nDim, corrs = null) { const ssg = new _1.SobolSequenceGenerator(nDim); ssg.skip(3); const bb = new BrownianBridge(nDim); const res = new Array(nSamples); const chol = corrs ? _1.cholesky(corrs) : null; for (let i = 0; i < nSamples; i++) { const ns = ssg.nextSample(); const r = bb.calculateSample(ns.map((d) => _1.normalInv(d, 0, 1))); if (chol) { let q = new Array(nDim); for (let j = 0; j < nDim; j++) { const cs = chol[j]; let p = 0; for (let k = 0; k <= j; k++) { p += cs[k] * r[k]; } q[j] = p; } res[i] = q; } else { res[i] = r; } } return res; } exports.createNormalSamples = createNormalSamples; //# sourceMappingURL=brownianBridge.js.map