overtake 1.4.0 → 2.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.
- package/README.md +4 -15
- package/bin/overtake.js +1 -1
- package/build/executor.d.ts +7 -3
- package/build/index.d.ts +10 -11
- package/build/reporter.d.ts +10 -2
- package/build/runner.d.ts +1 -1
- package/build/types.d.ts +6 -6
- package/build/utils.d.ts +1 -17
- package/package.json +8 -26
- package/src/__tests__/assert-no-closure.ts +135 -0
- package/src/__tests__/benchmark-execute.ts +48 -0
- package/src/cli.ts +139 -144
- package/src/executor.ts +48 -18
- package/src/index.ts +85 -57
- package/src/reporter.ts +27 -19
- package/src/runner.ts +2 -5
- package/src/types.ts +8 -8
- package/src/utils.ts +15 -54
- package/src/worker.ts +6 -3
- package/tsconfig.json +3 -1
- package/build/cli.cjs +0 -179
- package/build/cli.cjs.map +0 -1
- package/build/cli.js +0 -134
- package/build/cli.js.map +0 -1
- package/build/executor.cjs +0 -123
- package/build/executor.cjs.map +0 -1
- package/build/executor.js +0 -113
- package/build/executor.js.map +0 -1
- package/build/gc-watcher.cjs +0 -30
- package/build/gc-watcher.cjs.map +0 -1
- package/build/gc-watcher.js +0 -20
- package/build/gc-watcher.js.map +0 -1
- package/build/index.cjs +0 -442
- package/build/index.cjs.map +0 -1
- package/build/index.js +0 -377
- package/build/index.js.map +0 -1
- package/build/reporter.cjs +0 -311
- package/build/reporter.cjs.map +0 -1
- package/build/reporter.js +0 -293
- package/build/reporter.js.map +0 -1
- package/build/runner.cjs +0 -532
- package/build/runner.cjs.map +0 -1
- package/build/runner.js +0 -522
- package/build/runner.js.map +0 -1
- package/build/types.cjs +0 -66
- package/build/types.cjs.map +0 -1
- package/build/types.js +0 -33
- package/build/types.js.map +0 -1
- package/build/utils.cjs +0 -174
- package/build/utils.cjs.map +0 -1
- package/build/utils.js +0 -132
- package/build/utils.js.map +0 -1
- package/build/worker.cjs +0 -155
- package/build/worker.cjs.map +0 -1
- package/build/worker.js +0 -110
- package/build/worker.js.map +0 -1
- package/src/__tests__/assert-no-closure.js +0 -134
package/build/reporter.cjs
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get Report () {
|
|
13
|
-
return Report;
|
|
14
|
-
},
|
|
15
|
-
get createReport () {
|
|
16
|
-
return createReport;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const _utilscjs = require("./utils.cjs");
|
|
20
|
-
const _typescjs = require("./types.cjs");
|
|
21
|
-
const units = [
|
|
22
|
-
{
|
|
23
|
-
unit: 'ns',
|
|
24
|
-
factor: 1
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
unit: 'µs',
|
|
28
|
-
factor: 1e3
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
unit: 'ms',
|
|
32
|
-
factor: 1e6
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
unit: 's',
|
|
36
|
-
factor: 1e9
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
unit: 'm',
|
|
40
|
-
factor: 60 * 1e9
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
unit: 'h',
|
|
44
|
-
factor: 3600 * 1e9
|
|
45
|
-
}
|
|
46
|
-
];
|
|
47
|
-
function smartFixed(n) {
|
|
48
|
-
return n.toLocaleString(undefined, {
|
|
49
|
-
minimumFractionDigits: 0,
|
|
50
|
-
maximumFractionDigits: 2,
|
|
51
|
-
useGrouping: true
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
class Report {
|
|
55
|
-
type;
|
|
56
|
-
value;
|
|
57
|
-
uncertainty;
|
|
58
|
-
scale;
|
|
59
|
-
constructor(type, value, uncertainty = 0, scale = 1n){
|
|
60
|
-
this.type = type;
|
|
61
|
-
this.value = value;
|
|
62
|
-
this.uncertainty = uncertainty;
|
|
63
|
-
this.scale = scale;
|
|
64
|
-
}
|
|
65
|
-
valueOf() {
|
|
66
|
-
return Number((0, _utilscjs.div)(this.value, this.scale));
|
|
67
|
-
}
|
|
68
|
-
toString() {
|
|
69
|
-
const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';
|
|
70
|
-
const value = this.valueOf();
|
|
71
|
-
if (this.type === 'ops') {
|
|
72
|
-
return `${smartFixed(value)} ops/s${uncertainty}`;
|
|
73
|
-
}
|
|
74
|
-
if (this.type === 'rme') {
|
|
75
|
-
return `${smartFixed(value)}%`;
|
|
76
|
-
}
|
|
77
|
-
if (this.type === 'variance') {
|
|
78
|
-
let display = value;
|
|
79
|
-
let unit = 'ns²';
|
|
80
|
-
const varianceUnits = [
|
|
81
|
-
{
|
|
82
|
-
unit: 'ns²',
|
|
83
|
-
factor: 1
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
unit: 'µs²',
|
|
87
|
-
factor: 1e6
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
unit: 'ms²',
|
|
91
|
-
factor: 1e12
|
|
92
|
-
}
|
|
93
|
-
];
|
|
94
|
-
for (const { unit: u, factor } of varianceUnits){
|
|
95
|
-
const candidate = value / factor;
|
|
96
|
-
if (candidate < 1000) {
|
|
97
|
-
display = candidate;
|
|
98
|
-
unit = u;
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return `${smartFixed(display)} ${unit}`;
|
|
103
|
-
}
|
|
104
|
-
let display = value;
|
|
105
|
-
let unit = 'ns';
|
|
106
|
-
for (const { unit: u, factor } of units){
|
|
107
|
-
const candidate = value / factor;
|
|
108
|
-
if (candidate < 1000) {
|
|
109
|
-
display = candidate;
|
|
110
|
-
unit = u;
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return `${smartFixed(display)} ${unit}${uncertainty}`;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
const SQRT_SCALE = 1_000_000n;
|
|
118
|
-
const SQRT_SCALE_SQ = SQRT_SCALE * SQRT_SCALE;
|
|
119
|
-
const Z95_NUM = 196n;
|
|
120
|
-
const Z95_DENOM = 100n;
|
|
121
|
-
const computeStats = (durations)=>{
|
|
122
|
-
let sum = 0n;
|
|
123
|
-
for (const d of durations)sum += d;
|
|
124
|
-
const n = BigInt(durations.length);
|
|
125
|
-
const mean = sum / n;
|
|
126
|
-
let ssd = 0n;
|
|
127
|
-
for (const d of durations){
|
|
128
|
-
const diff = d - mean;
|
|
129
|
-
ssd += diff * diff;
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
sum,
|
|
133
|
-
mean,
|
|
134
|
-
ssd,
|
|
135
|
-
n
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
const createReport = (durations, type)=>{
|
|
139
|
-
const n = durations.length;
|
|
140
|
-
if (n === 0) {
|
|
141
|
-
return new Report(type, 0n);
|
|
142
|
-
}
|
|
143
|
-
switch(type){
|
|
144
|
-
case 'min':
|
|
145
|
-
{
|
|
146
|
-
return new Report(type, durations[0], 0, _typescjs.DURATION_SCALE);
|
|
147
|
-
}
|
|
148
|
-
case 'max':
|
|
149
|
-
{
|
|
150
|
-
return new Report(type, durations[n - 1], 0, _typescjs.DURATION_SCALE);
|
|
151
|
-
}
|
|
152
|
-
case 'median':
|
|
153
|
-
{
|
|
154
|
-
const mid = Math.floor(n / 2);
|
|
155
|
-
const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];
|
|
156
|
-
return new Report(type, med, 0, _typescjs.DURATION_SCALE);
|
|
157
|
-
}
|
|
158
|
-
case 'mode':
|
|
159
|
-
{
|
|
160
|
-
const freq = new Map();
|
|
161
|
-
let maxCount = 0n;
|
|
162
|
-
let modeVal = durations[0];
|
|
163
|
-
for (const d of durations){
|
|
164
|
-
const count = (freq.get(d) || 0n) + 1n;
|
|
165
|
-
freq.set(d, count);
|
|
166
|
-
if (count > maxCount) {
|
|
167
|
-
maxCount = count;
|
|
168
|
-
modeVal = d;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
let lower = modeVal;
|
|
172
|
-
let upper = modeVal;
|
|
173
|
-
const firstIdx = durations.indexOf(modeVal);
|
|
174
|
-
const lastIdx = durations.lastIndexOf(modeVal);
|
|
175
|
-
if (firstIdx > 0) lower = durations[firstIdx - 1];
|
|
176
|
-
if (lastIdx < n - 1) upper = durations[lastIdx + 1];
|
|
177
|
-
const gap = (0, _utilscjs.max)(modeVal - lower, upper - modeVal);
|
|
178
|
-
const uncertainty = modeVal > 0 ? Number(gap / 2n * 100n / modeVal) : 0;
|
|
179
|
-
return new Report(type, modeVal, uncertainty, _typescjs.DURATION_SCALE);
|
|
180
|
-
}
|
|
181
|
-
case 'ops':
|
|
182
|
-
{
|
|
183
|
-
const { mean: avgScaled, ssd, n: nBig } = computeStats(durations);
|
|
184
|
-
const nsPerSecScaled = 1_000_000_000n * _typescjs.DURATION_SCALE;
|
|
185
|
-
const raw = Number(nsPerSecScaled) / Number(avgScaled);
|
|
186
|
-
const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;
|
|
187
|
-
const exp = raw > 100 ? 0 : 2 + extra;
|
|
188
|
-
const scale = 10n ** BigInt(exp);
|
|
189
|
-
const value = avgScaled > 0n ? nsPerSecScaled * scale / avgScaled : 0n;
|
|
190
|
-
let uncertainty = 0;
|
|
191
|
-
if (n >= 2 && avgScaled > 0n) {
|
|
192
|
-
const RME_PRECISION = 1_000_000n;
|
|
193
|
-
const semOverMeanSqScaled = ssd * RME_PRECISION * RME_PRECISION / (BigInt(n - 1) * nBig * avgScaled * avgScaled);
|
|
194
|
-
const semOverMeanScaled = (0, _utilscjs.isqrt)(semOverMeanSqScaled);
|
|
195
|
-
uncertainty = Number(Z95_NUM * semOverMeanScaled) / Number(RME_PRECISION);
|
|
196
|
-
}
|
|
197
|
-
return new Report(type, value, uncertainty, scale);
|
|
198
|
-
}
|
|
199
|
-
case 'mean':
|
|
200
|
-
{
|
|
201
|
-
const { sum } = computeStats(durations);
|
|
202
|
-
const value = (0, _utilscjs.divs)(sum, BigInt(n), 1n);
|
|
203
|
-
return new Report(type, value, 0, _typescjs.DURATION_SCALE);
|
|
204
|
-
}
|
|
205
|
-
case 'variance':
|
|
206
|
-
{
|
|
207
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE * _typescjs.DURATION_SCALE);
|
|
208
|
-
const { ssd } = computeStats(durations);
|
|
209
|
-
const variance = ssd / BigInt(n - 1);
|
|
210
|
-
return new Report(type, variance, 0, _typescjs.DURATION_SCALE * _typescjs.DURATION_SCALE);
|
|
211
|
-
}
|
|
212
|
-
case 'sd':
|
|
213
|
-
{
|
|
214
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
215
|
-
const { ssd } = computeStats(durations);
|
|
216
|
-
const scaledVariance = ssd * SQRT_SCALE_SQ / BigInt(n - 1);
|
|
217
|
-
const sdScaled = (0, _utilscjs.isqrt)(scaledVariance);
|
|
218
|
-
return new Report(type, sdScaled, 0, _typescjs.DURATION_SCALE * SQRT_SCALE);
|
|
219
|
-
}
|
|
220
|
-
case 'sem':
|
|
221
|
-
{
|
|
222
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
223
|
-
const { ssd, n: nBig } = computeStats(durations);
|
|
224
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
225
|
-
const semScaled = (0, _utilscjs.isqrt)(semSqScaled);
|
|
226
|
-
return new Report(type, semScaled, 0, _typescjs.DURATION_SCALE * SQRT_SCALE);
|
|
227
|
-
}
|
|
228
|
-
case 'moe':
|
|
229
|
-
{
|
|
230
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
231
|
-
const { ssd, n: nBig } = computeStats(durations);
|
|
232
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
233
|
-
const semScaled = (0, _utilscjs.isqrt)(semSqScaled);
|
|
234
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
235
|
-
return new Report(type, moeScaled, 0, _typescjs.DURATION_SCALE * SQRT_SCALE);
|
|
236
|
-
}
|
|
237
|
-
case 'rme':
|
|
238
|
-
{
|
|
239
|
-
if (n < 2) return new Report(type, 0n);
|
|
240
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
241
|
-
if (mean === 0n) return new Report(type, 0n);
|
|
242
|
-
const RME_PRECISION = 1_000_000n;
|
|
243
|
-
const semOverMeanSqScaled = ssd * RME_PRECISION * RME_PRECISION / (BigInt(n - 1) * nBig * mean * mean);
|
|
244
|
-
const semOverMeanScaled = (0, _utilscjs.isqrt)(semOverMeanSqScaled);
|
|
245
|
-
const rmeScaled = Z95_NUM * semOverMeanScaled * 100n / RME_PRECISION;
|
|
246
|
-
return new Report(type, rmeScaled, 0, 100n);
|
|
247
|
-
}
|
|
248
|
-
case 'mad':
|
|
249
|
-
{
|
|
250
|
-
const medianIdx = Math.floor(n / 2);
|
|
251
|
-
const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;
|
|
252
|
-
const deviations = new BigUint64Array(n);
|
|
253
|
-
for(let i = 0; i < n; i++){
|
|
254
|
-
const diff = durations[i] > median ? durations[i] - median : median - durations[i];
|
|
255
|
-
deviations[i] = diff;
|
|
256
|
-
}
|
|
257
|
-
deviations.sort();
|
|
258
|
-
const madIdx = Math.floor(n / 2);
|
|
259
|
-
const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;
|
|
260
|
-
return new Report(type, mad, 0, _typescjs.DURATION_SCALE);
|
|
261
|
-
}
|
|
262
|
-
case 'iqr':
|
|
263
|
-
{
|
|
264
|
-
const q1Idx = Math.floor(n * 0.25);
|
|
265
|
-
const q3Idx = Math.floor(n * 0.75);
|
|
266
|
-
const q1 = durations[q1Idx];
|
|
267
|
-
const q3 = durations[q3Idx];
|
|
268
|
-
const iqr = q3 - q1;
|
|
269
|
-
return new Report(type, iqr, 0, _typescjs.DURATION_SCALE);
|
|
270
|
-
}
|
|
271
|
-
case 'ci_lower':
|
|
272
|
-
{
|
|
273
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
274
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
275
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
276
|
-
const semScaled = (0, _utilscjs.isqrt)(semSqScaled);
|
|
277
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
278
|
-
const ciLowerScaled = mean * SQRT_SCALE - moeScaled;
|
|
279
|
-
return new Report(type, ciLowerScaled > 0n ? ciLowerScaled : 0n, 0, _typescjs.DURATION_SCALE * SQRT_SCALE);
|
|
280
|
-
}
|
|
281
|
-
case 'ci_upper':
|
|
282
|
-
{
|
|
283
|
-
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
284
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
285
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
286
|
-
const semScaled = (0, _utilscjs.isqrt)(semSqScaled);
|
|
287
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
288
|
-
const ciUpperScaled = mean * SQRT_SCALE + moeScaled;
|
|
289
|
-
return new Report(type, ciUpperScaled, 0, _typescjs.DURATION_SCALE * SQRT_SCALE);
|
|
290
|
-
}
|
|
291
|
-
default:
|
|
292
|
-
{
|
|
293
|
-
const p = Number(type.slice(1));
|
|
294
|
-
if (p === 0) {
|
|
295
|
-
return new Report(type, durations[0], 0, _typescjs.DURATION_SCALE);
|
|
296
|
-
}
|
|
297
|
-
if (p === 100) {
|
|
298
|
-
return new Report(type, durations[n - 1], 0, _typescjs.DURATION_SCALE);
|
|
299
|
-
}
|
|
300
|
-
const idx = Math.ceil(p / 100 * n) - 1;
|
|
301
|
-
const value = durations[Math.min(Math.max(idx, 0), n - 1)];
|
|
302
|
-
const prev = idx > 0 ? durations[idx - 1] : value;
|
|
303
|
-
const next = idx < n - 1 ? durations[idx + 1] : value;
|
|
304
|
-
const gap = (0, _utilscjs.max)(value - prev, next - value);
|
|
305
|
-
const uncertainty = value > 0 ? Number((0, _utilscjs.div)((0, _utilscjs.divs)(gap, 2n, 100_00n), value)) / 100 : 0;
|
|
306
|
-
return new Report(type, value, uncertainty, _typescjs.DURATION_SCALE);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
//# sourceMappingURL=reporter.cjs.map
|
package/build/reporter.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs, isqrt } from './utils.js';\nimport { ReportType, DURATION_SCALE } from './types.js';\n\nconst units = [\n { unit: 'ns', factor: 1 },\n { unit: 'µs', factor: 1e3 },\n { unit: 'ms', factor: 1e6 },\n { unit: 's', factor: 1e9 },\n { unit: 'm', factor: 60 * 1e9 },\n { unit: 'h', factor: 3600 * 1e9 },\n] as const;\n\nfunction smartFixed(n: number): string {\n return n.toLocaleString(undefined, {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n useGrouping: true,\n });\n}\nexport class Report {\n constructor(\n public readonly type: ReportType,\n public readonly value: bigint,\n public readonly uncertainty: number = 0,\n public readonly scale: bigint = 1n,\n ) {}\n valueOf() {\n return Number(div(this.value, this.scale));\n }\n toString() {\n const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';\n\n const value = this.valueOf();\n if (this.type === 'ops') {\n return `${smartFixed(value)} ops/s${uncertainty}`;\n }\n if (this.type === 'rme') {\n return `${smartFixed(value)}%`;\n }\n if (this.type === 'variance') {\n let display = value;\n let unit = 'ns²';\n const varianceUnits = [\n { unit: 'ns²', factor: 1 },\n { unit: 'µs²', factor: 1e6 },\n { unit: 'ms²', factor: 1e12 },\n ];\n for (const { unit: u, factor } of varianceUnits) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}`;\n }\n let display = value;\n let unit = 'ns';\n\n for (const { unit: u, factor } of units) {\n const candidate = value / factor;\n if (candidate < 1000) {\n display = candidate;\n unit = u;\n break;\n }\n }\n return `${smartFixed(display)} ${unit}${uncertainty}`;\n }\n}\n\nconst SQRT_SCALE = 1_000_000n;\nconst SQRT_SCALE_SQ = SQRT_SCALE * SQRT_SCALE;\nconst Z95_NUM = 196n;\nconst Z95_DENOM = 100n;\n\nconst computeStats = (durations: BigUint64Array) => {\n let sum = 0n;\n for (const d of durations) sum += d;\n const n = BigInt(durations.length);\n const mean = sum / n;\n let ssd = 0n;\n for (const d of durations) {\n const diff = d - mean;\n ssd += diff * diff;\n }\n return { sum, mean, ssd, n };\n};\n\nexport const createReport = (durations: BigUint64Array, type: ReportType): Report => {\n const n = durations.length;\n if (n === 0) {\n return new Report(type, 0n);\n }\n switch (type) {\n case 'min': {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n case 'max': {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n case 'median': {\n const mid = Math.floor(n / 2);\n const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];\n return new Report(type, med, 0, DURATION_SCALE);\n }\n\n case 'mode': {\n const freq = new Map<bigint, bigint>();\n let maxCount = 0n;\n let modeVal = durations[0];\n for (const d of durations) {\n const count = (freq.get(d) || 0n) + 1n;\n freq.set(d, count);\n if (count > maxCount) {\n maxCount = count;\n modeVal = d;\n }\n }\n let lower = modeVal;\n let upper = modeVal;\n const firstIdx = durations.indexOf(modeVal);\n const lastIdx = durations.lastIndexOf(modeVal);\n if (firstIdx > 0) lower = durations[firstIdx - 1];\n if (lastIdx < n - 1) upper = durations[lastIdx + 1];\n const gap = max(modeVal - lower, upper - modeVal);\n const uncertainty = modeVal > 0 ? Number(((gap / 2n) * 100n) / modeVal) : 0;\n return new Report(type, modeVal, uncertainty, DURATION_SCALE);\n }\n\n case 'ops': {\n const { mean: avgScaled, ssd, n: nBig } = computeStats(durations);\n const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;\n const raw = Number(nsPerSecScaled) / Number(avgScaled);\n const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;\n\n const exp = raw > 100 ? 0 : 2 + extra;\n\n const scale = 10n ** BigInt(exp);\n\n const value = avgScaled > 0n ? (nsPerSecScaled * scale) / avgScaled : 0n;\n let uncertainty = 0;\n if (n >= 2 && avgScaled > 0n) {\n const RME_PRECISION = 1_000_000n;\n const semOverMeanSqScaled = (ssd * RME_PRECISION * RME_PRECISION) / (BigInt(n - 1) * nBig * avgScaled * avgScaled);\n const semOverMeanScaled = isqrt(semOverMeanSqScaled);\n uncertainty = Number(Z95_NUM * semOverMeanScaled) / Number(RME_PRECISION);\n }\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n const { sum } = computeStats(durations);\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_SCALE);\n }\n\n case 'variance': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);\n const { ssd } = computeStats(durations);\n const variance = ssd / BigInt(n - 1);\n return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);\n }\n\n case 'sd': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { ssd } = computeStats(durations);\n const scaledVariance = (ssd * SQRT_SCALE_SQ) / BigInt(n - 1);\n const sdScaled = isqrt(scaledVariance);\n return new Report(type, sdScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n return new Report(type, semScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n return new Report(type, moeScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n const { mean, ssd, n: nBig } = computeStats(durations);\n if (mean === 0n) return new Report(type, 0n);\n const RME_PRECISION = 1_000_000n;\n const semOverMeanSqScaled = (ssd * RME_PRECISION * RME_PRECISION) / (BigInt(n - 1) * nBig * mean * mean);\n const semOverMeanScaled = isqrt(semOverMeanSqScaled);\n const rmeScaled = (Z95_NUM * semOverMeanScaled * 100n) / RME_PRECISION;\n return new Report(type, rmeScaled, 0, 100n);\n }\n\n case 'mad': {\n const medianIdx = Math.floor(n / 2);\n const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;\n const deviations = new BigUint64Array(n);\n for (let i = 0; i < n; i++) {\n const diff = durations[i] > median ? durations[i] - median : median - durations[i];\n deviations[i] = diff;\n }\n deviations.sort();\n const madIdx = Math.floor(n / 2);\n const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;\n return new Report(type, mad, 0, DURATION_SCALE);\n }\n\n case 'iqr': {\n const q1Idx = Math.floor(n * 0.25);\n const q3Idx = Math.floor(n * 0.75);\n const q1 = durations[q1Idx];\n const q3 = durations[q3Idx];\n const iqr = q3 - q1;\n return new Report(type, iqr, 0, DURATION_SCALE);\n }\n\n case 'ci_lower': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { mean, ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n const ciLowerScaled = mean * SQRT_SCALE - moeScaled;\n return new Report(type, ciLowerScaled > 0n ? ciLowerScaled : 0n, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n case 'ci_upper': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n const { mean, ssd, n: nBig } = computeStats(durations);\n const semSqScaled = (ssd * SQRT_SCALE_SQ) / (BigInt(n - 1) * nBig);\n const semScaled = isqrt(semSqScaled);\n const moeScaled = (Z95_NUM * semScaled) / Z95_DENOM;\n const ciUpperScaled = mean * SQRT_SCALE + moeScaled;\n return new Report(type, ciUpperScaled, 0, DURATION_SCALE * SQRT_SCALE);\n }\n\n default: {\n const p = Number(type.slice(1));\n if (p === 0) {\n return new Report(type, durations[0], 0, DURATION_SCALE);\n }\n if (p === 100) {\n return new Report(type, durations[n - 1], 0, DURATION_SCALE);\n }\n const idx = Math.ceil((p / 100) * n) - 1;\n const value = durations[Math.min(Math.max(idx, 0), n - 1)];\n const prev = idx > 0 ? durations[idx - 1] : value;\n const next = idx < n - 1 ? durations[idx + 1] : value;\n const gap = max(value - prev, next - value);\n const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;\n\n return new Report(type, value, uncertainty, DURATION_SCALE);\n }\n }\n};\n"],"names":["Report","createReport","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","type","value","uncertainty","scale","valueOf","Number","div","toString","display","varianceUnits","u","candidate","SQRT_SCALE","SQRT_SCALE_SQ","Z95_NUM","Z95_DENOM","computeStats","durations","sum","d","BigInt","length","mean","ssd","diff","DURATION_SCALE","mid","Math","floor","med","freq","Map","maxCount","modeVal","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","max","avgScaled","nBig","nsPerSecScaled","raw","extra","ceil","log10","exp","RME_PRECISION","semOverMeanSqScaled","semOverMeanScaled","isqrt","divs","variance","scaledVariance","sdScaled","semSqScaled","semScaled","moeScaled","rmeScaled","medianIdx","median","deviations","BigUint64Array","i","sort","madIdx","mad","q1Idx","q3Idx","q1","q3","iqr","ciLowerScaled","ciUpperScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
package/build/reporter.js
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { div, max, divs, isqrt } from "./utils.js";
|
|
2
|
-
import { DURATION_SCALE } from "./types.js";
|
|
3
|
-
const units = [
|
|
4
|
-
{
|
|
5
|
-
unit: 'ns',
|
|
6
|
-
factor: 1
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
unit: 'µs',
|
|
10
|
-
factor: 1e3
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
unit: 'ms',
|
|
14
|
-
factor: 1e6
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
unit: 's',
|
|
18
|
-
factor: 1e9
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
unit: 'm',
|
|
22
|
-
factor: 60 * 1e9
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
unit: 'h',
|
|
26
|
-
factor: 3600 * 1e9
|
|
27
|
-
}
|
|
28
|
-
];
|
|
29
|
-
function smartFixed(n) {
|
|
30
|
-
return n.toLocaleString(undefined, {
|
|
31
|
-
minimumFractionDigits: 0,
|
|
32
|
-
maximumFractionDigits: 2,
|
|
33
|
-
useGrouping: true
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
export class Report {
|
|
37
|
-
type;
|
|
38
|
-
value;
|
|
39
|
-
uncertainty;
|
|
40
|
-
scale;
|
|
41
|
-
constructor(type, value, uncertainty = 0, scale = 1n){
|
|
42
|
-
this.type = type;
|
|
43
|
-
this.value = value;
|
|
44
|
-
this.uncertainty = uncertainty;
|
|
45
|
-
this.scale = scale;
|
|
46
|
-
}
|
|
47
|
-
valueOf() {
|
|
48
|
-
return Number(div(this.value, this.scale));
|
|
49
|
-
}
|
|
50
|
-
toString() {
|
|
51
|
-
const uncertainty = this.uncertainty ? ` ± ${smartFixed(this.uncertainty)}%` : '';
|
|
52
|
-
const value = this.valueOf();
|
|
53
|
-
if (this.type === 'ops') {
|
|
54
|
-
return `${smartFixed(value)} ops/s${uncertainty}`;
|
|
55
|
-
}
|
|
56
|
-
if (this.type === 'rme') {
|
|
57
|
-
return `${smartFixed(value)}%`;
|
|
58
|
-
}
|
|
59
|
-
if (this.type === 'variance') {
|
|
60
|
-
let display = value;
|
|
61
|
-
let unit = 'ns²';
|
|
62
|
-
const varianceUnits = [
|
|
63
|
-
{
|
|
64
|
-
unit: 'ns²',
|
|
65
|
-
factor: 1
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
unit: 'µs²',
|
|
69
|
-
factor: 1e6
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
unit: 'ms²',
|
|
73
|
-
factor: 1e12
|
|
74
|
-
}
|
|
75
|
-
];
|
|
76
|
-
for (const { unit: u, factor } of varianceUnits){
|
|
77
|
-
const candidate = value / factor;
|
|
78
|
-
if (candidate < 1000) {
|
|
79
|
-
display = candidate;
|
|
80
|
-
unit = u;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return `${smartFixed(display)} ${unit}`;
|
|
85
|
-
}
|
|
86
|
-
let display = value;
|
|
87
|
-
let unit = 'ns';
|
|
88
|
-
for (const { unit: u, factor } of units){
|
|
89
|
-
const candidate = value / factor;
|
|
90
|
-
if (candidate < 1000) {
|
|
91
|
-
display = candidate;
|
|
92
|
-
unit = u;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return `${smartFixed(display)} ${unit}${uncertainty}`;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const SQRT_SCALE = 1_000_000n;
|
|
100
|
-
const SQRT_SCALE_SQ = SQRT_SCALE * SQRT_SCALE;
|
|
101
|
-
const Z95_NUM = 196n;
|
|
102
|
-
const Z95_DENOM = 100n;
|
|
103
|
-
const computeStats = (durations)=>{
|
|
104
|
-
let sum = 0n;
|
|
105
|
-
for (const d of durations)sum += d;
|
|
106
|
-
const n = BigInt(durations.length);
|
|
107
|
-
const mean = sum / n;
|
|
108
|
-
let ssd = 0n;
|
|
109
|
-
for (const d of durations){
|
|
110
|
-
const diff = d - mean;
|
|
111
|
-
ssd += diff * diff;
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
sum,
|
|
115
|
-
mean,
|
|
116
|
-
ssd,
|
|
117
|
-
n
|
|
118
|
-
};
|
|
119
|
-
};
|
|
120
|
-
export const createReport = (durations, type)=>{
|
|
121
|
-
const n = durations.length;
|
|
122
|
-
if (n === 0) {
|
|
123
|
-
return new Report(type, 0n);
|
|
124
|
-
}
|
|
125
|
-
switch(type){
|
|
126
|
-
case 'min':
|
|
127
|
-
{
|
|
128
|
-
return new Report(type, durations[0], 0, DURATION_SCALE);
|
|
129
|
-
}
|
|
130
|
-
case 'max':
|
|
131
|
-
{
|
|
132
|
-
return new Report(type, durations[n - 1], 0, DURATION_SCALE);
|
|
133
|
-
}
|
|
134
|
-
case 'median':
|
|
135
|
-
{
|
|
136
|
-
const mid = Math.floor(n / 2);
|
|
137
|
-
const med = n % 2 === 0 ? (durations[mid - 1] + durations[mid]) / 2n : durations[mid];
|
|
138
|
-
return new Report(type, med, 0, DURATION_SCALE);
|
|
139
|
-
}
|
|
140
|
-
case 'mode':
|
|
141
|
-
{
|
|
142
|
-
const freq = new Map();
|
|
143
|
-
let maxCount = 0n;
|
|
144
|
-
let modeVal = durations[0];
|
|
145
|
-
for (const d of durations){
|
|
146
|
-
const count = (freq.get(d) || 0n) + 1n;
|
|
147
|
-
freq.set(d, count);
|
|
148
|
-
if (count > maxCount) {
|
|
149
|
-
maxCount = count;
|
|
150
|
-
modeVal = d;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
let lower = modeVal;
|
|
154
|
-
let upper = modeVal;
|
|
155
|
-
const firstIdx = durations.indexOf(modeVal);
|
|
156
|
-
const lastIdx = durations.lastIndexOf(modeVal);
|
|
157
|
-
if (firstIdx > 0) lower = durations[firstIdx - 1];
|
|
158
|
-
if (lastIdx < n - 1) upper = durations[lastIdx + 1];
|
|
159
|
-
const gap = max(modeVal - lower, upper - modeVal);
|
|
160
|
-
const uncertainty = modeVal > 0 ? Number(gap / 2n * 100n / modeVal) : 0;
|
|
161
|
-
return new Report(type, modeVal, uncertainty, DURATION_SCALE);
|
|
162
|
-
}
|
|
163
|
-
case 'ops':
|
|
164
|
-
{
|
|
165
|
-
const { mean: avgScaled, ssd, n: nBig } = computeStats(durations);
|
|
166
|
-
const nsPerSecScaled = 1_000_000_000n * DURATION_SCALE;
|
|
167
|
-
const raw = Number(nsPerSecScaled) / Number(avgScaled);
|
|
168
|
-
const extra = raw < 1 ? Math.ceil(-Math.log10(raw)) : 0;
|
|
169
|
-
const exp = raw > 100 ? 0 : 2 + extra;
|
|
170
|
-
const scale = 10n ** BigInt(exp);
|
|
171
|
-
const value = avgScaled > 0n ? nsPerSecScaled * scale / avgScaled : 0n;
|
|
172
|
-
let uncertainty = 0;
|
|
173
|
-
if (n >= 2 && avgScaled > 0n) {
|
|
174
|
-
const RME_PRECISION = 1_000_000n;
|
|
175
|
-
const semOverMeanSqScaled = ssd * RME_PRECISION * RME_PRECISION / (BigInt(n - 1) * nBig * avgScaled * avgScaled);
|
|
176
|
-
const semOverMeanScaled = isqrt(semOverMeanSqScaled);
|
|
177
|
-
uncertainty = Number(Z95_NUM * semOverMeanScaled) / Number(RME_PRECISION);
|
|
178
|
-
}
|
|
179
|
-
return new Report(type, value, uncertainty, scale);
|
|
180
|
-
}
|
|
181
|
-
case 'mean':
|
|
182
|
-
{
|
|
183
|
-
const { sum } = computeStats(durations);
|
|
184
|
-
const value = divs(sum, BigInt(n), 1n);
|
|
185
|
-
return new Report(type, value, 0, DURATION_SCALE);
|
|
186
|
-
}
|
|
187
|
-
case 'variance':
|
|
188
|
-
{
|
|
189
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);
|
|
190
|
-
const { ssd } = computeStats(durations);
|
|
191
|
-
const variance = ssd / BigInt(n - 1);
|
|
192
|
-
return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);
|
|
193
|
-
}
|
|
194
|
-
case 'sd':
|
|
195
|
-
{
|
|
196
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
197
|
-
const { ssd } = computeStats(durations);
|
|
198
|
-
const scaledVariance = ssd * SQRT_SCALE_SQ / BigInt(n - 1);
|
|
199
|
-
const sdScaled = isqrt(scaledVariance);
|
|
200
|
-
return new Report(type, sdScaled, 0, DURATION_SCALE * SQRT_SCALE);
|
|
201
|
-
}
|
|
202
|
-
case 'sem':
|
|
203
|
-
{
|
|
204
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
205
|
-
const { ssd, n: nBig } = computeStats(durations);
|
|
206
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
207
|
-
const semScaled = isqrt(semSqScaled);
|
|
208
|
-
return new Report(type, semScaled, 0, DURATION_SCALE * SQRT_SCALE);
|
|
209
|
-
}
|
|
210
|
-
case 'moe':
|
|
211
|
-
{
|
|
212
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
213
|
-
const { ssd, n: nBig } = computeStats(durations);
|
|
214
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
215
|
-
const semScaled = isqrt(semSqScaled);
|
|
216
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
217
|
-
return new Report(type, moeScaled, 0, DURATION_SCALE * SQRT_SCALE);
|
|
218
|
-
}
|
|
219
|
-
case 'rme':
|
|
220
|
-
{
|
|
221
|
-
if (n < 2) return new Report(type, 0n);
|
|
222
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
223
|
-
if (mean === 0n) return new Report(type, 0n);
|
|
224
|
-
const RME_PRECISION = 1_000_000n;
|
|
225
|
-
const semOverMeanSqScaled = ssd * RME_PRECISION * RME_PRECISION / (BigInt(n - 1) * nBig * mean * mean);
|
|
226
|
-
const semOverMeanScaled = isqrt(semOverMeanSqScaled);
|
|
227
|
-
const rmeScaled = Z95_NUM * semOverMeanScaled * 100n / RME_PRECISION;
|
|
228
|
-
return new Report(type, rmeScaled, 0, 100n);
|
|
229
|
-
}
|
|
230
|
-
case 'mad':
|
|
231
|
-
{
|
|
232
|
-
const medianIdx = Math.floor(n / 2);
|
|
233
|
-
const median = n % 2 === 1 ? durations[medianIdx] : (durations[medianIdx - 1] + durations[medianIdx]) / 2n;
|
|
234
|
-
const deviations = new BigUint64Array(n);
|
|
235
|
-
for(let i = 0; i < n; i++){
|
|
236
|
-
const diff = durations[i] > median ? durations[i] - median : median - durations[i];
|
|
237
|
-
deviations[i] = diff;
|
|
238
|
-
}
|
|
239
|
-
deviations.sort();
|
|
240
|
-
const madIdx = Math.floor(n / 2);
|
|
241
|
-
const mad = n % 2 === 1 ? deviations[madIdx] : (deviations[madIdx - 1] + deviations[madIdx]) / 2n;
|
|
242
|
-
return new Report(type, mad, 0, DURATION_SCALE);
|
|
243
|
-
}
|
|
244
|
-
case 'iqr':
|
|
245
|
-
{
|
|
246
|
-
const q1Idx = Math.floor(n * 0.25);
|
|
247
|
-
const q3Idx = Math.floor(n * 0.75);
|
|
248
|
-
const q1 = durations[q1Idx];
|
|
249
|
-
const q3 = durations[q3Idx];
|
|
250
|
-
const iqr = q3 - q1;
|
|
251
|
-
return new Report(type, iqr, 0, DURATION_SCALE);
|
|
252
|
-
}
|
|
253
|
-
case 'ci_lower':
|
|
254
|
-
{
|
|
255
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
256
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
257
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
258
|
-
const semScaled = isqrt(semSqScaled);
|
|
259
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
260
|
-
const ciLowerScaled = mean * SQRT_SCALE - moeScaled;
|
|
261
|
-
return new Report(type, ciLowerScaled > 0n ? ciLowerScaled : 0n, 0, DURATION_SCALE * SQRT_SCALE);
|
|
262
|
-
}
|
|
263
|
-
case 'ci_upper':
|
|
264
|
-
{
|
|
265
|
-
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
266
|
-
const { mean, ssd, n: nBig } = computeStats(durations);
|
|
267
|
-
const semSqScaled = ssd * SQRT_SCALE_SQ / (BigInt(n - 1) * nBig);
|
|
268
|
-
const semScaled = isqrt(semSqScaled);
|
|
269
|
-
const moeScaled = Z95_NUM * semScaled / Z95_DENOM;
|
|
270
|
-
const ciUpperScaled = mean * SQRT_SCALE + moeScaled;
|
|
271
|
-
return new Report(type, ciUpperScaled, 0, DURATION_SCALE * SQRT_SCALE);
|
|
272
|
-
}
|
|
273
|
-
default:
|
|
274
|
-
{
|
|
275
|
-
const p = Number(type.slice(1));
|
|
276
|
-
if (p === 0) {
|
|
277
|
-
return new Report(type, durations[0], 0, DURATION_SCALE);
|
|
278
|
-
}
|
|
279
|
-
if (p === 100) {
|
|
280
|
-
return new Report(type, durations[n - 1], 0, DURATION_SCALE);
|
|
281
|
-
}
|
|
282
|
-
const idx = Math.ceil(p / 100 * n) - 1;
|
|
283
|
-
const value = durations[Math.min(Math.max(idx, 0), n - 1)];
|
|
284
|
-
const prev = idx > 0 ? durations[idx - 1] : value;
|
|
285
|
-
const next = idx < n - 1 ? durations[idx + 1] : value;
|
|
286
|
-
const gap = max(value - prev, next - value);
|
|
287
|
-
const uncertainty = value > 0 ? Number(div(divs(gap, 2n, 100_00n), value)) / 100 : 0;
|
|
288
|
-
return new Report(type, value, uncertainty, DURATION_SCALE);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
//# sourceMappingURL=reporter.js.map
|