@cloudglides/nox 1.1.6 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +9 -9
  2. package/example/package.json +1 -1
  3. package/example/src/App.css +38 -7
  4. package/example/src/App.jsx +328 -25
  5. package/package.json +7 -6
  6. package/pnpm-workspace.yaml +3 -0
  7. package/src/core.browser.js +37 -4
  8. package/src/core.js +37 -4
  9. package/src/generators/logistic.js +30 -25
  10. package/src/generators/mixer.js +7 -7
  11. package/src/generators/mt19937.js +10 -7
  12. package/src/generators/pcg64.js +23 -12
  13. package/src/generators/splitmix64.js +12 -6
  14. package/src/generators/tent.js +12 -7
  15. package/src/generators/xorshift64.js +6 -3
  16. package/src/index.browser.js +168 -1
  17. package/src/index.d.ts +68 -4
  18. package/src/index.js +169 -1
  19. package/src/rng.browser.js +5 -6
  20. package/src/rng.js +95 -94
  21. package/src/utils/arrays.js +149 -0
  22. package/src/utils/bits.js +146 -21
  23. package/src/utils/categorical.js +68 -31
  24. package/src/utils/clustering.js +143 -0
  25. package/src/utils/combinatorics.js +113 -69
  26. package/src/utils/confidence.js +145 -0
  27. package/src/utils/decomposition.js +204 -0
  28. package/src/utils/diagnostics.js +309 -0
  29. package/src/utils/distributions-advanced.js +122 -0
  30. package/src/utils/distributions-extra.js +102 -11
  31. package/src/utils/distributions-special.js +77 -20
  32. package/src/utils/distributions.js +99 -35
  33. package/src/utils/effects.js +172 -0
  34. package/src/utils/entropy.browser.js +29 -26
  35. package/src/utils/entropy.js +18 -8
  36. package/src/utils/helpers.js +64 -0
  37. package/src/utils/hypothesis.js +167 -0
  38. package/src/utils/integration.js +137 -0
  39. package/src/utils/interpolation.js +221 -0
  40. package/src/utils/logistic.js +91 -0
  41. package/src/utils/matrix.js +242 -0
  42. package/src/utils/noise.js +36 -22
  43. package/src/utils/odesolvers.js +176 -0
  44. package/src/utils/optimization.js +215 -0
  45. package/src/utils/polynomial.js +136 -0
  46. package/src/utils/precomputed.js +166 -0
  47. package/src/utils/probability.js +199 -0
  48. package/src/utils/pvalues.js +142 -0
  49. package/src/utils/regression.js +170 -0
  50. package/src/utils/resampling.js +112 -0
  51. package/src/utils/rootfinding.js +158 -0
  52. package/src/utils/sampling.js +86 -77
  53. package/src/utils/seed.js +10 -4
  54. package/src/utils/seeding.js +24 -12
  55. package/src/utils/sequence.js +116 -32
  56. package/src/utils/state.js +48 -36
  57. package/src/utils/statistics.js +64 -2
  58. package/src/utils/stochastic.js +91 -31
  59. package/src/utils/stratified.js +108 -0
  60. package/src/utils/timeseries.js +166 -0
  61. package/src/utils/transforms.js +146 -0
  62. package/test/comprehensive.js +4 -3
  63. package/test/new-features.js +52 -0
  64. package/IMPROVEMENTS.md +0 -58
  65. package/PERFORMANCE.md +0 -69
  66. package/example/pnpm-lock.yaml +0 -1006
@@ -0,0 +1,145 @@
1
+ export function bootstrapCI(r, data, statistic, level = 0.95, n = 1000) {
2
+ if (!Array.isArray(data) || data.length === 0) {
3
+ throw new TypeError('data must be non-empty array');
4
+ }
5
+ if (typeof statistic !== 'function') {
6
+ throw new TypeError('statistic must be function');
7
+ }
8
+ if (typeof level !== 'number' || level <= 0 || level >= 1) {
9
+ throw new RangeError('level must be in (0, 1)');
10
+ }
11
+
12
+ const samples = new Array(n);
13
+ const size = data.length;
14
+
15
+ for (let i = 0; i < n; i++) {
16
+ const resample = new Array(size);
17
+ for (let j = 0; j < size; j++) {
18
+ resample[j] = data[r.nextInt(size)];
19
+ }
20
+ samples[i] = statistic(resample);
21
+ }
22
+
23
+ samples.sort((a, b) => a - b);
24
+
25
+ const alpha = 1 - level;
26
+ const lower = Math.floor(alpha / 2 * n);
27
+ const upper = Math.ceil((1 - alpha / 2) * n);
28
+
29
+ return {
30
+ lower: samples[lower],
31
+ upper: samples[upper],
32
+ estimate: statistic(data),
33
+ level
34
+ };
35
+ }
36
+
37
+ export function meanCI(data, stddev, level = 0.95, variance = null) {
38
+ if (!Array.isArray(data) || data.length === 0) {
39
+ throw new TypeError('data must be non-empty array');
40
+ }
41
+ if (typeof level !== 'number' || level <= 0 || level >= 1) {
42
+ throw new RangeError('level must be in (0, 1)');
43
+ }
44
+
45
+ const n = data.length;
46
+ const mean = data.reduce((a, b) => a + b, 0) / n;
47
+
48
+ if (variance !== null) {
49
+ if (typeof variance !== 'number' || variance <= 0) {
50
+ throw new RangeError('variance must be positive');
51
+ }
52
+ const se = Math.sqrt(variance / n);
53
+ const z = invNormal((1 + level) / 2);
54
+ return {
55
+ mean,
56
+ lower: mean - z * se,
57
+ upper: mean + z * se,
58
+ level
59
+ };
60
+ }
61
+
62
+ if (typeof stddev !== 'number' || stddev <= 0) {
63
+ throw new RangeError('stddev must be positive');
64
+ }
65
+
66
+ const se = stddev / Math.sqrt(n);
67
+ const df = n - 1;
68
+ const t = invT((1 + level) / 2, df);
69
+
70
+ return {
71
+ mean,
72
+ lower: mean - t * se,
73
+ upper: mean + t * se,
74
+ level,
75
+ df
76
+ };
77
+ }
78
+
79
+ export function proportionCI(successes, n, level = 0.95, method = 'wilson') {
80
+ if (typeof successes !== 'number' || successes < 0 || successes > n) {
81
+ throw new RangeError('successes must be in [0, n]');
82
+ }
83
+ if (typeof n !== 'number' || n <= 0) {
84
+ throw new RangeError('n must be positive');
85
+ }
86
+ if (typeof level !== 'number' || level <= 0 || level >= 1) {
87
+ throw new RangeError('level must be in (0, 1)');
88
+ }
89
+
90
+ const p = successes / n;
91
+ const z = invNormal((1 + level) / 2);
92
+ const z2 = z * z;
93
+
94
+ if (method === 'wilson') {
95
+ const center = (successes + z2 / 2) / (n + z2);
96
+ const margin = z * Math.sqrt(p * (1 - p) / n + z2 / (4 * n * n)) / (1 + z2 / n);
97
+ return {
98
+ estimate: p,
99
+ lower: Math.max(0, center - margin),
100
+ upper: Math.min(1, center + margin),
101
+ level
102
+ };
103
+ }
104
+
105
+ if (method === 'normal') {
106
+ const se = Math.sqrt(p * (1 - p) / n);
107
+ return {
108
+ estimate: p,
109
+ lower: Math.max(0, p - z * se),
110
+ upper: Math.min(1, p + z * se),
111
+ level
112
+ };
113
+ }
114
+
115
+ throw new RangeError(`unknown method: ${method}`);
116
+ }
117
+
118
+ function invNormal(p) {
119
+ if (p <= 0.5) {
120
+ const t = Math.sqrt(-2 * Math.log(p));
121
+ const c0 = 2.515517;
122
+ const c1 = 0.802853;
123
+ const c2 = 0.010328;
124
+ const d1 = 1.432788;
125
+ const d2 = 0.189269;
126
+ const d3 = 0.001308;
127
+ return -(t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t));
128
+ } else {
129
+ const t = Math.sqrt(-2 * Math.log(1 - p));
130
+ const c0 = 2.515517;
131
+ const c1 = 0.802853;
132
+ const c2 = 0.010328;
133
+ const d1 = 1.432788;
134
+ const d2 = 0.189269;
135
+ const d3 = 0.001308;
136
+ return t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t);
137
+ }
138
+ }
139
+
140
+ function invT(p, df) {
141
+ const t = invNormal(p);
142
+ const t2 = t * t;
143
+ const g = (0.196 * t2 * t2 + 0.196 * t2 + 0.55) * (Math.exp(-0.0008 * t2 * t2 - 0.24 * t2 - 1.2)) + t * (1 + 0.0000092 * t2 * t2 + 0.00014 * t2);
144
+ return t + g / df;
145
+ }
@@ -0,0 +1,204 @@
1
+ export function svd(A, maxIter = 100) {
2
+ if (!Array.isArray(A) || A.length === 0) {
3
+ throw new TypeError('A must be non-empty matrix');
4
+ }
5
+
6
+ const m = A.length;
7
+ const n = A[0].length;
8
+ const k = Math.min(m, n);
9
+
10
+ const U = A.map(row => [...row]);
11
+ const VT = new Array(n);
12
+ for (let i = 0; i < n; i++) {
13
+ VT[i] = new Array(n);
14
+ for (let j = 0; j < n; j++) {
15
+ VT[i][j] = i === j ? 1 : 0;
16
+ }
17
+ }
18
+
19
+ const S = new Array(k);
20
+ for (let i = 0; i < k; i++) {
21
+ S[i] = 1;
22
+ }
23
+
24
+ for (let iter = 0; iter < maxIter; iter++) {
25
+ for (let i = 0; i < Math.min(m, n); i++) {
26
+ for (let j = i + 1; j < Math.min(m, n); j++) {
27
+ const x = new Array(m);
28
+ const y = new Array(m);
29
+
30
+ for (let p = 0; p < m; p++) {
31
+ x[p] = U[p][i];
32
+ y[p] = U[p][j];
33
+ }
34
+
35
+ const xNorm = Math.sqrt(x.reduce((a, b) => a + b * b, 0));
36
+ const yNorm = Math.sqrt(y.reduce((a, b) => a + b * b, 0));
37
+ const xy = x.reduce((a, b, p) => a + b * y[p], 0);
38
+
39
+ if (xNorm < 1e-10 || yNorm < 1e-10 || Math.abs(xy) < 1e-10) continue;
40
+
41
+ const cos = xy / (xNorm * yNorm);
42
+ const angle = Math.acos(Math.min(1, Math.max(-1, cos)));
43
+ const sin = Math.sin(angle);
44
+ const cosTheta = Math.cos(angle);
45
+ const sinTheta = Math.sin(angle);
46
+
47
+ for (let p = 0; p < m; p++) {
48
+ const up_i = U[p][i];
49
+ const up_j = U[p][j];
50
+ U[p][i] = cosTheta * up_i + sinTheta * up_j;
51
+ U[p][j] = -sinTheta * up_i + cosTheta * up_j;
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ for (let i = 0; i < k; i++) {
58
+ let colNorm = 0;
59
+ for (let j = 0; j < m; j++) {
60
+ colNorm += U[j][i] * U[j][i];
61
+ }
62
+ S[i] = Math.sqrt(colNorm);
63
+ }
64
+
65
+ return { U, S, VT };
66
+ }
67
+
68
+ export function qr(A) {
69
+ if (!Array.isArray(A) || A.length === 0) {
70
+ throw new TypeError('A must be non-empty matrix');
71
+ }
72
+
73
+ const m = A.length;
74
+ const n = A[0].length;
75
+
76
+ const Q = A.map(row => [...row]);
77
+ const R = new Array(n);
78
+ for (let i = 0; i < n; i++) {
79
+ R[i] = new Array(n);
80
+ for (let j = 0; j < n; j++) {
81
+ R[i][j] = 0;
82
+ }
83
+ }
84
+
85
+ for (let j = 0; j < n; j++) {
86
+ let normCol = 0;
87
+ for (let i = 0; i < m; i++) {
88
+ normCol += Q[i][j] * Q[i][j];
89
+ }
90
+ R[j][j] = Math.sqrt(normCol);
91
+
92
+ if (R[j][j] > 1e-10) {
93
+ for (let i = 0; i < m; i++) {
94
+ Q[i][j] /= R[j][j];
95
+ }
96
+ }
97
+
98
+ for (let k = j + 1; k < n; k++) {
99
+ R[j][k] = 0;
100
+ for (let i = 0; i < m; i++) {
101
+ R[j][k] += Q[i][j] * A[i][k];
102
+ }
103
+
104
+ for (let i = 0; i < m; i++) {
105
+ Q[i][k] -= R[j][k] * Q[i][j];
106
+ }
107
+ }
108
+ }
109
+
110
+ return { Q, R };
111
+ }
112
+
113
+ export function cholesky(A) {
114
+ if (!Array.isArray(A) || A.length !== A[0].length) {
115
+ throw new TypeError('A must be square matrix');
116
+ }
117
+
118
+ const n = A.length;
119
+ const L = new Array(n);
120
+ for (let i = 0; i < n; i++) {
121
+ L[i] = new Array(n);
122
+ for (let j = 0; j < n; j++) {
123
+ L[i][j] = 0;
124
+ }
125
+ }
126
+
127
+ for (let i = 0; i < n; i++) {
128
+ for (let j = 0; j <= i; j++) {
129
+ let sum = 0;
130
+ for (let k = 0; k < j; k++) {
131
+ sum += L[i][k] * L[j][k];
132
+ }
133
+
134
+ if (i === j) {
135
+ const val = A[i][i] - sum;
136
+ if (val <= 0) {
137
+ throw new RangeError('matrix must be positive definite');
138
+ }
139
+ L[i][j] = Math.sqrt(val);
140
+ } else {
141
+ L[i][j] = (A[i][j] - sum) / L[j][j];
142
+ }
143
+ }
144
+ }
145
+
146
+ return L;
147
+ }
148
+
149
+ export function lu(A) {
150
+ if (!Array.isArray(A) || A.length !== A[0].length) {
151
+ throw new TypeError('A must be square matrix');
152
+ }
153
+
154
+ const n = A.length;
155
+ const LU = A.map(row => [...row]);
156
+ const P = new Array(n);
157
+ for (let i = 0; i < n; i++) {
158
+ P[i] = i;
159
+ }
160
+
161
+ for (let i = 0; i < n; i++) {
162
+ let maxRow = i;
163
+ for (let k = i + 1; k < n; k++) {
164
+ if (Math.abs(LU[k][i]) > Math.abs(LU[maxRow][i])) {
165
+ maxRow = k;
166
+ }
167
+ }
168
+
169
+ [LU[i], LU[maxRow]] = [LU[maxRow], LU[i]];
170
+ [P[i], P[maxRow]] = [P[maxRow], P[i]];
171
+
172
+ if (Math.abs(LU[i][i]) < 1e-10) {
173
+ throw new RangeError('matrix is singular');
174
+ }
175
+
176
+ for (let k = i + 1; k < n; k++) {
177
+ LU[k][i] /= LU[i][i];
178
+ for (let j = i + 1; j < n; j++) {
179
+ LU[k][j] -= LU[k][i] * LU[i][j];
180
+ }
181
+ }
182
+ }
183
+
184
+ const L = new Array(n);
185
+ const U = new Array(n);
186
+ for (let i = 0; i < n; i++) {
187
+ L[i] = new Array(n);
188
+ U[i] = new Array(n);
189
+ for (let j = 0; j < n; j++) {
190
+ if (j < i) {
191
+ L[i][j] = LU[i][j];
192
+ U[i][j] = 0;
193
+ } else if (j === i) {
194
+ L[i][j] = 1;
195
+ U[i][j] = LU[i][j];
196
+ } else {
197
+ L[i][j] = 0;
198
+ U[i][j] = LU[i][j];
199
+ }
200
+ }
201
+ }
202
+
203
+ return { L, U, P };
204
+ }
@@ -0,0 +1,309 @@
1
+ export function residualDiagnostics(model) {
2
+ if (!model.residuals || !model.predictions) {
3
+ throw new TypeError('model must have residuals and predictions');
4
+ }
5
+
6
+ const residuals = model.residuals;
7
+ const predictions = model.predictions;
8
+ const n = residuals.length;
9
+
10
+ const mean = residuals.reduce((a, b) => a + b, 0) / n;
11
+ let variance = 0;
12
+ for (let i = 0; i < n; i++) {
13
+ variance += (residuals[i] - mean) ** 2;
14
+ }
15
+ variance /= (n - 1);
16
+ const stddev = Math.sqrt(variance);
17
+
18
+ const standardized = residuals.map(r => r / stddev);
19
+
20
+ const studentized = residuals.map((r, i) => {
21
+ const leverage = 1 / n;
22
+ const se = stddev * Math.sqrt(1 - leverage);
23
+ return r / se;
24
+ });
25
+
26
+ const qqData = [...standardized].sort((a, b) => a - b);
27
+ const qqTheoretical = new Array(n);
28
+ for (let i = 0; i < n; i++) {
29
+ const p = (i + 0.5) / n;
30
+ qqTheoretical[i] = invNormal(p);
31
+ }
32
+
33
+ let correlation = 0;
34
+ let sumX2 = 0, sumY2 = 0;
35
+ for (let i = 0; i < n; i++) {
36
+ correlation += qqData[i] * qqTheoretical[i];
37
+ sumX2 += qqData[i] * qqData[i];
38
+ sumY2 += qqTheoretical[i] * qqTheoretical[i];
39
+ }
40
+ const qqCorr = correlation / Math.sqrt(sumX2 * sumY2);
41
+
42
+ return {
43
+ residuals,
44
+ standardized,
45
+ studentized,
46
+ mean,
47
+ variance,
48
+ stddev,
49
+ qqCorrelation: qqCorr,
50
+ qqData,
51
+ qqTheoretical
52
+ };
53
+ }
54
+
55
+ export function leverageValues(X) {
56
+ if (!Array.isArray(X) || X.length === 0) {
57
+ throw new TypeError('X must be non-empty array');
58
+ }
59
+
60
+ const n = X.length;
61
+ const p = Array.isArray(X[0]) ? X[0].length : 1;
62
+
63
+ const Xmat = X.map(row => Array.isArray(row) ? [1, ...row] : [1, row]);
64
+ const XtX = matmul(transpose(Xmat), Xmat);
65
+
66
+ let invXtX;
67
+ try {
68
+ invXtX = matrixInverse(XtX);
69
+ } catch {
70
+ throw new RangeError('X matrix is singular');
71
+ }
72
+
73
+ const leverages = new Array(n);
74
+ for (let i = 0; i < n; i++) {
75
+ let leverage = 0;
76
+ for (let j = 0; j <= p; j++) {
77
+ for (let k = 0; k <= p; k++) {
78
+ leverage += Xmat[i][j] * invXtX[j][k] * Xmat[i][k];
79
+ }
80
+ }
81
+ leverages[i] = leverage;
82
+ }
83
+
84
+ return leverages;
85
+ }
86
+
87
+ export function cookDistance(residuals, predictions, leverage, n, p) {
88
+ if (!Array.isArray(residuals) || !Array.isArray(predictions)) {
89
+ throw new TypeError('residuals and predictions must be arrays');
90
+ }
91
+
92
+ const sigma2 = residuals.reduce((s, r) => s + r * r, 0) / (n - p - 1);
93
+ const cooks = new Array(n);
94
+
95
+ for (let i = 0; i < n; i++) {
96
+ const lev = leverage[i];
97
+ cooks[i] = (residuals[i] ** 2 / (sigma2 * (p + 1))) * (lev / (1 - lev));
98
+ }
99
+
100
+ return cooks;
101
+ }
102
+
103
+ export function durwinWatson(residuals) {
104
+ if (!Array.isArray(residuals) || residuals.length < 2) {
105
+ throw new TypeError('residuals must be array of length >= 2');
106
+ }
107
+
108
+ let numerator = 0;
109
+ let denominator = 0;
110
+
111
+ for (let i = 1; i < residuals.length; i++) {
112
+ const diff = residuals[i] - residuals[i - 1];
113
+ numerator += diff * diff;
114
+ }
115
+
116
+ for (let i = 0; i < residuals.length; i++) {
117
+ denominator += residuals[i] * residuals[i];
118
+ }
119
+
120
+ return numerator / denominator;
121
+ }
122
+
123
+ export function vif(X) {
124
+ if (!Array.isArray(X) || X.length === 0) {
125
+ throw new TypeError('X must be non-empty array of features');
126
+ }
127
+
128
+ const n = X.length;
129
+ const p = Array.isArray(X[0]) ? X[0].length : 1;
130
+ const vifs = new Array(p);
131
+
132
+ for (let j = 0; j < p; j++) {
133
+ const y = X.map(row => Array.isArray(row) ? row[j] : row);
134
+ const Xj = X.map((row, i) => {
135
+ const features = Array.isArray(row) ? row : [row];
136
+ return features.filter((_, k) => k !== j);
137
+ });
138
+
139
+ if (Xj[0].length === 0) {
140
+ vifs[j] = 1;
141
+ continue;
142
+ }
143
+
144
+ const r2 = computeR2(Xj, y);
145
+ vifs[j] = 1 / (1 - r2);
146
+ }
147
+
148
+ return vifs;
149
+ }
150
+
151
+ function computeR2(X, y) {
152
+ const n = X.length;
153
+ const yMean = y.reduce((a, b) => a + b, 0) / n;
154
+
155
+ let ssTot = 0;
156
+ for (let i = 0; i < n; i++) {
157
+ ssTot += (y[i] - yMean) ** 2;
158
+ }
159
+
160
+ const Xmat = X.map(row => Array.isArray(row) ? [1, ...row] : [1, row]);
161
+ const XtX = matmul(transpose(Xmat), Xmat);
162
+ const Xty = matmul(transpose(Xmat), y.map(yi => [yi]));
163
+
164
+ let beta;
165
+ try {
166
+ beta = solve(XtX, Xty).flat();
167
+ } catch {
168
+ return 0;
169
+ }
170
+
171
+ let ssRes = 0;
172
+ for (let i = 0; i < n; i++) {
173
+ let pred = beta[0];
174
+ for (let j = 1; j < beta.length; j++) {
175
+ pred += beta[j] * (Array.isArray(X[i]) ? X[i][j - 1] : X[i]);
176
+ }
177
+ ssRes += (y[i] - pred) ** 2;
178
+ }
179
+
180
+ return 1 - (ssRes / ssTot);
181
+ }
182
+
183
+ function transpose(matrix) {
184
+ const result = [];
185
+ for (let j = 0; j < matrix[0].length; j++) {
186
+ result[j] = [];
187
+ for (let i = 0; i < matrix.length; i++) {
188
+ result[j].push(matrix[i][j]);
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+
194
+ function matmul(A, B) {
195
+ const result = [];
196
+ for (let i = 0; i < A.length; i++) {
197
+ result[i] = [];
198
+ for (let j = 0; j < B[0].length; j++) {
199
+ let sum = 0;
200
+ for (let k = 0; k < A[0].length; k++) {
201
+ sum += A[i][k] * B[k][j];
202
+ }
203
+ result[i][j] = sum;
204
+ }
205
+ }
206
+ return result;
207
+ }
208
+
209
+ function solve(A, b) {
210
+ const n = A.length;
211
+ const aug = A.map((row, i) => [...row, b[i][0]]);
212
+
213
+ for (let i = 0; i < n; i++) {
214
+ let maxRow = i;
215
+ for (let k = i + 1; k < n; k++) {
216
+ if (Math.abs(aug[k][i]) > Math.abs(aug[maxRow][i])) {
217
+ maxRow = k;
218
+ }
219
+ }
220
+
221
+ [aug[i], aug[maxRow]] = [aug[maxRow], aug[i]];
222
+
223
+ if (Math.abs(aug[i][i]) < 1e-10) {
224
+ throw new RangeError('matrix is singular');
225
+ }
226
+
227
+ for (let k = i + 1; k < n; k++) {
228
+ const factor = aug[k][i] / aug[i][i];
229
+ for (let j = i; j < n + 1; j++) {
230
+ aug[k][j] -= factor * aug[i][j];
231
+ }
232
+ }
233
+ }
234
+
235
+ const x = new Array(n);
236
+ for (let i = n - 1; i >= 0; i--) {
237
+ x[i] = aug[i][n];
238
+ for (let j = i + 1; j < n; j++) {
239
+ x[i] -= aug[i][j] * x[j];
240
+ }
241
+ x[i] /= aug[i][i];
242
+ }
243
+
244
+ return x.map(xi => [xi]);
245
+ }
246
+
247
+ function matrixInverse(A) {
248
+ const n = A.length;
249
+ const aug = A.map((row, i) => {
250
+ const augRow = [...row];
251
+ for (let j = 0; j < n; j++) {
252
+ augRow.push(i === j ? 1 : 0);
253
+ }
254
+ return augRow;
255
+ });
256
+
257
+ for (let i = 0; i < n; i++) {
258
+ let maxRow = i;
259
+ for (let k = i + 1; k < n; k++) {
260
+ if (Math.abs(aug[k][i]) > Math.abs(aug[maxRow][i])) {
261
+ maxRow = k;
262
+ }
263
+ }
264
+
265
+ [aug[i], aug[maxRow]] = [aug[maxRow], aug[i]];
266
+
267
+ const pivot = aug[i][i];
268
+ for (let j = 0; j < 2 * n; j++) {
269
+ aug[i][j] /= pivot;
270
+ }
271
+
272
+ for (let k = 0; k < n; k++) {
273
+ if (k !== i) {
274
+ const factor = aug[k][i];
275
+ for (let j = 0; j < 2 * n; j++) {
276
+ aug[k][j] -= factor * aug[i][j];
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ const result = new Array(n);
283
+ for (let i = 0; i < n; i++) {
284
+ result[i] = aug[i].slice(n);
285
+ }
286
+ return result;
287
+ }
288
+
289
+ function invNormal(p) {
290
+ if (p <= 0.5) {
291
+ const t = Math.sqrt(-2 * Math.log(p));
292
+ const c0 = 2.515517;
293
+ const c1 = 0.802853;
294
+ const c2 = 0.010328;
295
+ const d1 = 1.432788;
296
+ const d2 = 0.189269;
297
+ const d3 = 0.001308;
298
+ return -(t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t));
299
+ } else {
300
+ const t = Math.sqrt(-2 * Math.log(1 - p));
301
+ const c0 = 2.515517;
302
+ const c1 = 0.802853;
303
+ const c2 = 0.010328;
304
+ const d1 = 1.432788;
305
+ const d2 = 0.189269;
306
+ const d3 = 0.001308;
307
+ return t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t);
308
+ }
309
+ }