overtake 1.2.0 → 1.2.1
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/build/reporter.cjs +125 -0
- package/build/reporter.cjs.map +1 -1
- package/build/reporter.js +126 -1
- package/build/reporter.js.map +1 -1
- package/build/types.cjs +6 -1
- package/build/types.cjs.map +1 -1
- package/build/types.d.ts +1 -1
- package/build/types.js +6 -1
- package/build/types.js.map +1 -1
- package/package.json +1 -1
- package/src/reporter.ts +117 -1
- package/src/types.ts +14 -2
package/build/reporter.cjs
CHANGED
|
@@ -71,6 +71,36 @@ class Report {
|
|
|
71
71
|
if (this.type === 'ops') {
|
|
72
72
|
return `${smartFixed(value)} ops/s${uncertainty}`;
|
|
73
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
|
+
}
|
|
74
104
|
let display = value;
|
|
75
105
|
let unit = 'ns';
|
|
76
106
|
for (const { unit: u, factor } of units){
|
|
@@ -153,6 +183,101 @@ const createReport = (durations, type)=>{
|
|
|
153
183
|
const value = (0, _utilscjs.divs)(sum, BigInt(n), 1n);
|
|
154
184
|
return new Report(type, value, 0, _typescjs.DURATION_SCALE);
|
|
155
185
|
}
|
|
186
|
+
case 'variance':
|
|
187
|
+
{
|
|
188
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE * _typescjs.DURATION_SCALE);
|
|
189
|
+
let sum = 0n;
|
|
190
|
+
for (const duration of durations){
|
|
191
|
+
sum += duration;
|
|
192
|
+
}
|
|
193
|
+
const mean = sum / BigInt(n);
|
|
194
|
+
let sumSquaredDiff = 0n;
|
|
195
|
+
for (const duration of durations){
|
|
196
|
+
const diff = duration - mean;
|
|
197
|
+
sumSquaredDiff += diff * diff;
|
|
198
|
+
}
|
|
199
|
+
const variance = sumSquaredDiff / BigInt(n - 1);
|
|
200
|
+
return new Report(type, variance, 0, _typescjs.DURATION_SCALE * _typescjs.DURATION_SCALE);
|
|
201
|
+
}
|
|
202
|
+
case 'sd':
|
|
203
|
+
{
|
|
204
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
205
|
+
let sum = 0n;
|
|
206
|
+
for (const duration of durations){
|
|
207
|
+
sum += duration;
|
|
208
|
+
}
|
|
209
|
+
const mean = sum / BigInt(n);
|
|
210
|
+
let sumSquaredDiff = 0n;
|
|
211
|
+
for (const duration of durations){
|
|
212
|
+
const diff = duration - mean;
|
|
213
|
+
sumSquaredDiff += diff * diff;
|
|
214
|
+
}
|
|
215
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
216
|
+
const sd = Math.sqrt(variance);
|
|
217
|
+
const sdScaled = BigInt(Math.round(sd));
|
|
218
|
+
return new Report(type, sdScaled, 0, _typescjs.DURATION_SCALE);
|
|
219
|
+
}
|
|
220
|
+
case 'sem':
|
|
221
|
+
{
|
|
222
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
223
|
+
let sum = 0n;
|
|
224
|
+
for (const duration of durations){
|
|
225
|
+
sum += duration;
|
|
226
|
+
}
|
|
227
|
+
const mean = sum / BigInt(n);
|
|
228
|
+
let sumSquaredDiff = 0n;
|
|
229
|
+
for (const duration of durations){
|
|
230
|
+
const diff = duration - mean;
|
|
231
|
+
sumSquaredDiff += diff * diff;
|
|
232
|
+
}
|
|
233
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
234
|
+
const sd = Math.sqrt(variance);
|
|
235
|
+
const sem = sd / Math.sqrt(n);
|
|
236
|
+
const semScaled = BigInt(Math.round(sem));
|
|
237
|
+
return new Report(type, semScaled, 0, _typescjs.DURATION_SCALE);
|
|
238
|
+
}
|
|
239
|
+
case 'moe':
|
|
240
|
+
{
|
|
241
|
+
if (n < 2) return new Report(type, 0n, 0, _typescjs.DURATION_SCALE);
|
|
242
|
+
let sum = 0n;
|
|
243
|
+
for (const duration of durations){
|
|
244
|
+
sum += duration;
|
|
245
|
+
}
|
|
246
|
+
const mean = sum / BigInt(n);
|
|
247
|
+
let sumSquaredDiff = 0n;
|
|
248
|
+
for (const duration of durations){
|
|
249
|
+
const diff = duration - mean;
|
|
250
|
+
sumSquaredDiff += diff * diff;
|
|
251
|
+
}
|
|
252
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
253
|
+
const sd = Math.sqrt(variance);
|
|
254
|
+
const sem = sd / Math.sqrt(n);
|
|
255
|
+
const moe = _typescjs.Z95 * sem;
|
|
256
|
+
const moeScaled = BigInt(Math.round(moe));
|
|
257
|
+
return new Report(type, moeScaled, 0, _typescjs.DURATION_SCALE);
|
|
258
|
+
}
|
|
259
|
+
case 'rme':
|
|
260
|
+
{
|
|
261
|
+
if (n < 2) return new Report(type, 0n);
|
|
262
|
+
let sum = 0n;
|
|
263
|
+
for (const duration of durations){
|
|
264
|
+
sum += duration;
|
|
265
|
+
}
|
|
266
|
+
const mean = Number(sum) / n;
|
|
267
|
+
if (mean === 0) return new Report(type, 0n);
|
|
268
|
+
let sumSquaredDiff = 0;
|
|
269
|
+
for (const duration of durations){
|
|
270
|
+
const diff = Number(duration) - mean;
|
|
271
|
+
sumSquaredDiff += diff * diff;
|
|
272
|
+
}
|
|
273
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
274
|
+
const sd = Math.sqrt(variance);
|
|
275
|
+
const sem = sd / Math.sqrt(n);
|
|
276
|
+
const moe = _typescjs.Z95 * sem;
|
|
277
|
+
const rme = moe / mean * 100;
|
|
278
|
+
const rmeScaled = BigInt(Math.round(rme * 100));
|
|
279
|
+
return new Report(type, rmeScaled, 0, 100n);
|
|
280
|
+
}
|
|
156
281
|
default:
|
|
157
282
|
{
|
|
158
283
|
const p = Number(type.slice(1));
|
package/build/reporter.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } 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 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\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\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 const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_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","u","candidate","durations","length","DURATION_SCALE","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","max","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","divs","p","slice","idx","min","prev","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } 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\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\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 const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / 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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\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","durations","length","DURATION_SCALE","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","max","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","divs","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","Z95","moeScaled","rme","rmeScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
package/build/reporter.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { div, max, divs } from "./utils.js";
|
|
2
|
-
import { DURATION_SCALE } from "./types.js";
|
|
2
|
+
import { DURATION_SCALE, Z95 } from "./types.js";
|
|
3
3
|
const units = [
|
|
4
4
|
{
|
|
5
5
|
unit: 'ns',
|
|
@@ -53,6 +53,36 @@ export class Report {
|
|
|
53
53
|
if (this.type === 'ops') {
|
|
54
54
|
return `${smartFixed(value)} ops/s${uncertainty}`;
|
|
55
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
|
+
}
|
|
56
86
|
let display = value;
|
|
57
87
|
let unit = 'ns';
|
|
58
88
|
for (const { unit: u, factor } of units){
|
|
@@ -135,6 +165,101 @@ export const createReport = (durations, type)=>{
|
|
|
135
165
|
const value = divs(sum, BigInt(n), 1n);
|
|
136
166
|
return new Report(type, value, 0, DURATION_SCALE);
|
|
137
167
|
}
|
|
168
|
+
case 'variance':
|
|
169
|
+
{
|
|
170
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);
|
|
171
|
+
let sum = 0n;
|
|
172
|
+
for (const duration of durations){
|
|
173
|
+
sum += duration;
|
|
174
|
+
}
|
|
175
|
+
const mean = sum / BigInt(n);
|
|
176
|
+
let sumSquaredDiff = 0n;
|
|
177
|
+
for (const duration of durations){
|
|
178
|
+
const diff = duration - mean;
|
|
179
|
+
sumSquaredDiff += diff * diff;
|
|
180
|
+
}
|
|
181
|
+
const variance = sumSquaredDiff / BigInt(n - 1);
|
|
182
|
+
return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);
|
|
183
|
+
}
|
|
184
|
+
case 'sd':
|
|
185
|
+
{
|
|
186
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
187
|
+
let sum = 0n;
|
|
188
|
+
for (const duration of durations){
|
|
189
|
+
sum += duration;
|
|
190
|
+
}
|
|
191
|
+
const mean = sum / BigInt(n);
|
|
192
|
+
let sumSquaredDiff = 0n;
|
|
193
|
+
for (const duration of durations){
|
|
194
|
+
const diff = duration - mean;
|
|
195
|
+
sumSquaredDiff += diff * diff;
|
|
196
|
+
}
|
|
197
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
198
|
+
const sd = Math.sqrt(variance);
|
|
199
|
+
const sdScaled = BigInt(Math.round(sd));
|
|
200
|
+
return new Report(type, sdScaled, 0, DURATION_SCALE);
|
|
201
|
+
}
|
|
202
|
+
case 'sem':
|
|
203
|
+
{
|
|
204
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
205
|
+
let sum = 0n;
|
|
206
|
+
for (const duration of durations){
|
|
207
|
+
sum += duration;
|
|
208
|
+
}
|
|
209
|
+
const mean = sum / BigInt(n);
|
|
210
|
+
let sumSquaredDiff = 0n;
|
|
211
|
+
for (const duration of durations){
|
|
212
|
+
const diff = duration - mean;
|
|
213
|
+
sumSquaredDiff += diff * diff;
|
|
214
|
+
}
|
|
215
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
216
|
+
const sd = Math.sqrt(variance);
|
|
217
|
+
const sem = sd / Math.sqrt(n);
|
|
218
|
+
const semScaled = BigInt(Math.round(sem));
|
|
219
|
+
return new Report(type, semScaled, 0, DURATION_SCALE);
|
|
220
|
+
}
|
|
221
|
+
case 'moe':
|
|
222
|
+
{
|
|
223
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
224
|
+
let sum = 0n;
|
|
225
|
+
for (const duration of durations){
|
|
226
|
+
sum += duration;
|
|
227
|
+
}
|
|
228
|
+
const mean = sum / BigInt(n);
|
|
229
|
+
let sumSquaredDiff = 0n;
|
|
230
|
+
for (const duration of durations){
|
|
231
|
+
const diff = duration - mean;
|
|
232
|
+
sumSquaredDiff += diff * diff;
|
|
233
|
+
}
|
|
234
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
235
|
+
const sd = Math.sqrt(variance);
|
|
236
|
+
const sem = sd / Math.sqrt(n);
|
|
237
|
+
const moe = Z95 * sem;
|
|
238
|
+
const moeScaled = BigInt(Math.round(moe));
|
|
239
|
+
return new Report(type, moeScaled, 0, DURATION_SCALE);
|
|
240
|
+
}
|
|
241
|
+
case 'rme':
|
|
242
|
+
{
|
|
243
|
+
if (n < 2) return new Report(type, 0n);
|
|
244
|
+
let sum = 0n;
|
|
245
|
+
for (const duration of durations){
|
|
246
|
+
sum += duration;
|
|
247
|
+
}
|
|
248
|
+
const mean = Number(sum) / n;
|
|
249
|
+
if (mean === 0) return new Report(type, 0n);
|
|
250
|
+
let sumSquaredDiff = 0;
|
|
251
|
+
for (const duration of durations){
|
|
252
|
+
const diff = Number(duration) - mean;
|
|
253
|
+
sumSquaredDiff += diff * diff;
|
|
254
|
+
}
|
|
255
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
256
|
+
const sd = Math.sqrt(variance);
|
|
257
|
+
const sem = sd / Math.sqrt(n);
|
|
258
|
+
const moe = Z95 * sem;
|
|
259
|
+
const rme = moe / mean * 100;
|
|
260
|
+
const rmeScaled = BigInt(Math.round(rme * 100));
|
|
261
|
+
return new Report(type, rmeScaled, 0, 100n);
|
|
262
|
+
}
|
|
138
263
|
default:
|
|
139
264
|
{
|
|
140
265
|
const p = Number(type.slice(1));
|
package/build/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } 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 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\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\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 const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const value = divs(sum, BigInt(n), 1n);\n return new Report(type, value, 0, DURATION_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":["div","max","divs","DURATION_SCALE","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","Report","type","value","uncertainty","scale","valueOf","Number","toString","display","u","candidate","createReport","durations","length","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","p","slice","idx","min","prev","next"],"mappings":"AAAA,SAASA,GAAG,EAAEC,GAAG,EAAEC,IAAI,QAAQ,aAAa;AAC5C,SAAqBC,cAAc,QAAQ,aAAa;AAExD,MAAMC,QAAQ;IACZ;QAAEC,MAAM;QAAMC,QAAQ;IAAE;IACxB;QAAED,MAAM;QAAMC,QAAQ;IAAI;IAC1B;QAAED,MAAM;QAAMC,QAAQ;IAAI;IAC1B;QAAED,MAAM;QAAKC,QAAQ;IAAI;IACzB;QAAED,MAAM;QAAKC,QAAQ,KAAK;IAAI;IAC9B;QAAED,MAAM;QAAKC,QAAQ,OAAO;IAAI;CACjC;AAED,SAASC,WAAWC,CAAS;IAC3B,OAAOA,EAAEC,cAAc,CAACC,WAAW;QACjCC,uBAAuB;QACvBC,uBAAuB;QACvBC,aAAa;IACf;AACF;AACA,OAAO,MAAMC;;;;;IACX,YACE,AAAgBC,IAAgB,EAChC,AAAgBC,KAAa,EAC7B,AAAgBC,cAAsB,CAAC,EACvC,AAAgBC,QAAgB,EAAE,CAClC;aAJgBH,OAAAA;aACAC,QAAAA;aACAC,cAAAA;aACAC,QAAAA;IACf;IACHC,UAAU;QACR,OAAOC,OAAOpB,IAAI,IAAI,CAACgB,KAAK,EAAE,IAAI,CAACE,KAAK;IAC1C;IACAG,WAAW;QACT,MAAMJ,cAAc,IAAI,CAACA,WAAW,GAAG,CAAC,GAAG,EAAEV,WAAW,IAAI,CAACU,WAAW,EAAE,CAAC,CAAC,GAAG;QAE/E,MAAMD,QAAQ,IAAI,CAACG,OAAO;QAC1B,IAAI,IAAI,CAACJ,IAAI,KAAK,OAAO;YACvB,OAAO,GAAGR,WAAWS,OAAO,MAAM,EAAEC,aAAa;QACnD;QACA,IAAIK,UAAUN;QACd,IAAIX,OAAO;QAEX,KAAK,MAAM,EAAEA,MAAMkB,CAAC,EAAEjB,MAAM,EAAE,IAAIF,MAAO;YACvC,MAAMoB,YAAYR,QAAQV;YAC1B,IAAIkB,YAAY,MAAM;gBACpBF,UAAUE;gBACVnB,OAAOkB;gBACP;YACF;QACF;QACA,OAAO,GAAGhB,WAAWe,SAAS,CAAC,EAAEjB,OAAOY,aAAa;IACvD;AACF;AAEA,OAAO,MAAMQ,eAAe,CAACC,WAA2BX;IACtD,MAAMP,IAAIkB,UAAUC,MAAM;IAC1B,IAAInB,MAAM,GAAG;QACX,OAAO,IAAIM,OAAOC,MAAM,EAAE;IAC5B;IACA,OAAQA;QACN,KAAK;YAAO;gBACV,OAAO,IAAID,OAAOC,MAAMW,SAAS,CAAC,EAAE,EAAE,GAAGvB;YAC3C;QACA,KAAK;YAAO;gBACV,OAAO,IAAIW,OAAOC,MAAMW,SAAS,CAAClB,IAAI,EAAE,EAAE,GAAGL;YAC/C;QACA,KAAK;YAAU;gBACb,MAAMyB,MAAMC,KAAKC,KAAK,CAACtB,IAAI;gBAC3B,MAAMuB,MAAMvB,IAAI,MAAM,IAAI,AAACkB,CAAAA,SAAS,CAACE,MAAM,EAAE,GAAGF,SAAS,CAACE,IAAI,AAAD,IAAK,EAAE,GAAGF,SAAS,CAACE,IAAI;gBACrF,OAAO,IAAId,OAAOC,MAAMgB,KAAK,GAAG5B;YAClC;QAEA,KAAK;YAAQ;gBACX,MAAM6B,OAAO,IAAIC;gBACjB,IAAIC,WAAW,EAAE;gBACjB,IAAIC,UAAUT,SAAS,CAAC,EAAE;gBAC1B,KAAK,MAAMU,KAAKV,UAAW;oBACzB,MAAMW,QAAQ,AAACL,CAAAA,KAAKM,GAAG,CAACF,MAAM,EAAE,AAAD,IAAK,EAAE;oBACtCJ,KAAKO,GAAG,CAACH,GAAGC;oBACZ,IAAIA,QAAQH,UAAU;wBACpBA,WAAWG;wBACXF,UAAUC;oBACZ;gBACF;gBACA,IAAII,QAAQL;gBACZ,IAAIM,QAAQN;gBACZ,MAAMO,WAAWhB,UAAUiB,OAAO,CAACR;gBACnC,MAAMS,UAAUlB,UAAUmB,WAAW,CAACV;gBACtC,IAAIO,WAAW,GAAGF,QAAQd,SAAS,CAACgB,WAAW,EAAE;gBACjD,IAAIE,UAAUpC,IAAI,GAAGiC,QAAQf,SAAS,CAACkB,UAAU,EAAE;gBACnD,MAAME,MAAM7C,IAAIkC,UAAUK,OAAOC,QAAQN;gBACzC,MAAMlB,cAAckB,UAAU,IAAIf,OAAO,AAAE0B,MAAM,EAAE,GAAI,IAAI,GAAIX,WAAW;gBAC1E,OAAO,IAAIrB,OAAOC,MAAMoB,SAASlB,aAAad;YAChD;QAEA,KAAK;YAAO;gBACV,IAAI4C,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMC,YAAYF,MAAMG,OAAO1C;gBAC/B,MAAM2C,iBAAiB,cAAc,GAAGhD;gBACxC,MAAMiD,MAAMhC,OAAO+B,kBAAkB/B,OAAO6B;gBAC5C,MAAMI,QAAQD,MAAM,IAAIvB,KAAKyB,IAAI,CAAC,CAACzB,KAAK0B,KAAK,CAACH,QAAQ;gBAEtD,MAAMI,MAAMJ,MAAM,MAAM,IAAI,IAAIC;gBAEhC,MAAMnC,QAAQ,GAAG,IAAIgC,OAAOM;gBAE5B,MAAMxC,QAAQiC,YAAY,EAAE,GAAG,AAACE,iBAAiBjC,QAAS+B,YAAY,EAAE;gBACxE,MAAMQ,YAAY/B,SAAS,CAAClB,IAAI,EAAE,GAAGkB,SAAS,CAAC,EAAE;gBACjD,MAAMT,cAAcgC,YAAY,IAAI7B,OAAOpB,IAAIyD,YAAYvC,OAAO,EAAE,GAAG+B,cAAc;gBACrF,OAAO,IAAInC,OAAOC,MAAMC,OAAOC,aAAaC;YAC9C;QACA,KAAK;YAAQ;gBACX,IAAI6B,MAAM,EAAE;gBACZ,KAAK,MAAMC,YAAYtB,UAAW;oBAChCqB,OAAOC;gBACT;gBACA,MAAMhC,QAAQd,KAAK6C,KAAKG,OAAO1C,IAAI,EAAE;gBACrC,OAAO,IAAIM,OAAOC,MAAMC,OAAO,GAAGb;YACpC;QAEA;YAAS;gBACP,MAAMuD,IAAItC,OAAOL,KAAK4C,KAAK,CAAC;gBAC5B,IAAID,MAAM,GAAG;oBACX,OAAO,IAAI5C,OAAOC,MAAMW,SAAS,CAAC,EAAE,EAAE,GAAGvB;gBAC3C;gBACA,IAAIuD,MAAM,KAAK;oBACb,OAAO,IAAI5C,OAAOC,MAAMW,SAAS,CAAClB,IAAI,EAAE,EAAE,GAAGL;gBAC/C;gBACA,MAAMyD,MAAM/B,KAAKyB,IAAI,CAAC,AAACI,IAAI,MAAOlD,KAAK;gBACvC,MAAMQ,QAAQU,SAAS,CAACG,KAAKgC,GAAG,CAAChC,KAAK5B,GAAG,CAAC2D,KAAK,IAAIpD,IAAI,GAAG;gBAC1D,MAAMsD,OAAOF,MAAM,IAAIlC,SAAS,CAACkC,MAAM,EAAE,GAAG5C;gBAC5C,MAAM+C,OAAOH,MAAMpD,IAAI,IAAIkB,SAAS,CAACkC,MAAM,EAAE,GAAG5C;gBAChD,MAAM8B,MAAM7C,IAAIe,QAAQ8C,MAAMC,OAAO/C;gBACrC,MAAMC,cAAcD,QAAQ,IAAII,OAAOpB,IAAIE,KAAK4C,KAAK,EAAE,EAAE,OAAO,GAAG9B,UAAU,MAAM;gBAEnF,OAAO,IAAIF,OAAOC,MAAMC,OAAOC,aAAad;YAC9C;IACF;AACF,EAAE"}
|
|
1
|
+
{"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["import { div, max, divs } from './utils.js';\nimport { ReportType, DURATION_SCALE, Z95 } 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\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const avgScaled = sum / BigInt(n);\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 const deviation = durations[n - 1] - durations[0];\n const uncertainty = avgScaled > 0 ? Number(div(deviation * scale, 2n * avgScaled)) : 0;\n return new Report(type, value, uncertainty, scale);\n }\n case 'mean': {\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / 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 let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sdScaled = BigInt(Math.round(sd));\n return new Report(type, sdScaled, 0, DURATION_SCALE);\n }\n\n case 'sem': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const semScaled = BigInt(Math.round(sem));\n return new Report(type, semScaled, 0, DURATION_SCALE);\n }\n\n case 'moe': {\n if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = sum / BigInt(n);\n let sumSquaredDiff = 0n;\n for (const duration of durations) {\n const diff = duration - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = Number(sumSquaredDiff) / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const moeScaled = BigInt(Math.round(moe));\n return new Report(type, moeScaled, 0, DURATION_SCALE);\n }\n\n case 'rme': {\n if (n < 2) return new Report(type, 0n);\n let sum = 0n;\n for (const duration of durations) {\n sum += duration;\n }\n const mean = Number(sum) / n;\n if (mean === 0) return new Report(type, 0n);\n let sumSquaredDiff = 0;\n for (const duration of durations) {\n const diff = Number(duration) - mean;\n sumSquaredDiff += diff * diff;\n }\n const variance = sumSquaredDiff / (n - 1);\n const sd = Math.sqrt(variance);\n const sem = sd / Math.sqrt(n);\n const moe = Z95 * sem;\n const rme = (moe / mean) * 100;\n const rmeScaled = BigInt(Math.round(rme * 100));\n return new Report(type, rmeScaled, 0, 100n);\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":["div","max","divs","DURATION_SCALE","Z95","units","unit","factor","smartFixed","n","toLocaleString","undefined","minimumFractionDigits","maximumFractionDigits","useGrouping","Report","type","value","uncertainty","scale","valueOf","Number","toString","display","varianceUnits","u","candidate","createReport","durations","length","mid","Math","floor","med","freq","Map","maxCount","modeVal","d","count","get","set","lower","upper","firstIdx","indexOf","lastIdx","lastIndexOf","gap","sum","duration","avgScaled","BigInt","nsPerSecScaled","raw","extra","ceil","log10","exp","deviation","mean","sumSquaredDiff","diff","variance","sd","sqrt","sdScaled","round","sem","semScaled","moe","moeScaled","rme","rmeScaled","p","slice","idx","min","prev","next"],"mappings":"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"}
|
package/build/types.cjs
CHANGED
package/build/types.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<unknown>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops'
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<unknown>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | 'variance' | 'sd' | 'sem' | 'moe' | 'rme' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat([\n 'ops',\n 'mean',\n 'min',\n 'max',\n 'median',\n 'mode',\n 'variance',\n 'sd',\n 'sem',\n 'moe',\n 'rme',\n]);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n}\n\nexport interface RunOptions<TContext, TInput> {\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface ExecutorRunOptions<TContext, TInput> extends RunOptions<TContext, TInput> {\n id?: string;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n benchmarkUrl?: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\nexport const DURATION_SCALE = 1000n;\nexport const COMPLETE_VALUE = 100_00;\n\nexport interface ProgressInfo {\n id: string;\n progress: number;\n}\n\nexport type ProgressCallback = (info: ProgressInfo) => void;\n"],"names":["COMPLETE_VALUE","CONTROL_SLOTS","Control","DEFAULT_CYCLES","DURATION_SCALE","REPORT_TYPES","Z95","Array","from","length","_","idx","concat","Object","values"],"mappings":";;;;;;;;;;;QA2FaA;eAAAA;;QAJAC;eAAAA;;QANDC;eAAAA;;QAOCC;eAAAA;;QAEAC;eAAAA;;QAlEAC;eAAAA;;QAiEAC;eAAAA;;;AAjEN,MAAMD,eAA+BE,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IACrH;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AA6CM,IAAA,AAAKV,iCAAAA;;;;WAAAA;;AAML,MAAMD,gBAAgBY,OAAOC,MAAM,CAACZ,SAASO,MAAM,GAAG;AACtD,MAAMN,iBAAiB;AACvB,MAAMG,MAAM;AACZ,MAAMF,iBAAiB,KAAK;AAC5B,MAAMJ,iBAAiB"}
|
package/build/types.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface FeedFn<TInput> {
|
|
|
14
14
|
type _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;
|
|
15
15
|
export type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;
|
|
16
16
|
export type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;
|
|
17
|
-
export type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;
|
|
17
|
+
export type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | 'variance' | 'sd' | 'sem' | 'moe' | 'rme' | `p${Between<1, 100>}`;
|
|
18
18
|
export type ReportTypeList = readonly ReportType[];
|
|
19
19
|
export declare const REPORT_TYPES: ReportTypeList;
|
|
20
20
|
export interface ReportOptions<R extends ReportTypeList> {
|
package/build/types.js
CHANGED
package/build/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<unknown>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat(['ops'
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface SetupFn<TContext> {\n (): MaybePromise<TContext>;\n}\n\nexport interface TeardownFn<TContext> {\n (ctx: TContext): MaybePromise<void>;\n}\n\nexport interface StepFn<TContext, TInput> {\n (ctx: TContext, input: TInput): MaybePromise<unknown>;\n}\n\nexport interface FeedFn<TInput> {\n (): MaybePromise<TInput>;\n}\n\ntype _Sequence<To extends number, R extends unknown[]> = R['length'] extends To ? R[number] : _Sequence<To, [R['length'], ...R]>;\nexport type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;\nexport type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;\n\nexport type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | 'variance' | 'sd' | 'sem' | 'moe' | 'rme' | `p${Between<1, 100>}`;\nexport type ReportTypeList = readonly ReportType[];\nexport const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat([\n 'ops',\n 'mean',\n 'min',\n 'max',\n 'median',\n 'mode',\n 'variance',\n 'sd',\n 'sem',\n 'moe',\n 'rme',\n]);\n\nexport interface ReportOptions<R extends ReportTypeList> {\n reportTypes: R;\n}\n\nexport interface BenchmarkOptions {\n warmupCycles?: number;\n minCycles?: number;\n absThreshold?: number; // ns\n relThreshold?: number; // %\n gcObserver?: boolean;\n}\n\nexport interface RunOptions<TContext, TInput> {\n setup?: SetupFn<TContext>;\n teardown?: TeardownFn<TContext>;\n pre?: StepFn<TContext, TInput>;\n run: StepFn<TContext, TInput>;\n post?: StepFn<TContext, TInput>;\n data?: TInput;\n}\n\nexport interface ExecutorRunOptions<TContext, TInput> extends RunOptions<TContext, TInput> {\n id?: string;\n}\n\nexport interface WorkerOptions extends Required<BenchmarkOptions> {\n benchmarkUrl?: string;\n setupCode?: string;\n teardownCode?: string;\n preCode?: string;\n runCode: string;\n postCode?: string;\n data?: unknown;\n\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport interface Options<TContext, TInput> extends RunOptions<TContext, TInput>, BenchmarkOptions {\n durationsSAB: SharedArrayBuffer;\n controlSAB: SharedArrayBuffer;\n}\n\nexport enum Control {\n INDEX,\n PROGRESS,\n COMPLETE,\n}\n\nexport const CONTROL_SLOTS = Object.values(Control).length / 2;\nexport const DEFAULT_CYCLES = 1_000;\nexport const Z95 = 1.96;\nexport const DURATION_SCALE = 1000n;\nexport const COMPLETE_VALUE = 100_00;\n\nexport interface ProgressInfo {\n id: string;\n progress: number;\n}\n\nexport type ProgressCallback = (info: ProgressInfo) => void;\n"],"names":["REPORT_TYPES","Array","from","length","_","idx","concat","Control","CONTROL_SLOTS","Object","values","DEFAULT_CYCLES","Z95","DURATION_SCALE","COMPLETE_VALUE"],"mappings":"AAwBA,OAAO,MAAMA,eAA+BC,MAAMC,IAAI,CAAC;IAAEC,QAAQ;AAAG,GAAG,CAACC,GAAGC,MAAQ,CAAC,CAAC,EAAEA,MAAM,GAAG,EAAgBC,MAAM,CAAC;IACrH;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,EAAE;AA6CH,OAAO,IAAA,AAAKC,iCAAAA;;;;WAAAA;MAIX;AAED,OAAO,MAAMC,gBAAgBC,OAAOC,MAAM,CAACH,SAASJ,MAAM,GAAG,EAAE;AAC/D,OAAO,MAAMQ,iBAAiB,MAAM;AACpC,OAAO,MAAMC,MAAM,KAAK;AACxB,OAAO,MAAMC,iBAAiB,KAAK,CAAC;AACpC,OAAO,MAAMC,iBAAiB,OAAO"}
|
package/package.json
CHANGED
package/src/reporter.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { div, max, divs } from './utils.js';
|
|
2
|
-
import { ReportType, DURATION_SCALE } from './types.js';
|
|
2
|
+
import { ReportType, DURATION_SCALE, Z95 } from './types.js';
|
|
3
3
|
|
|
4
4
|
const units = [
|
|
5
5
|
{ unit: 'ns', factor: 1 },
|
|
@@ -34,6 +34,27 @@ export class Report {
|
|
|
34
34
|
if (this.type === 'ops') {
|
|
35
35
|
return `${smartFixed(value)} ops/s${uncertainty}`;
|
|
36
36
|
}
|
|
37
|
+
if (this.type === 'rme') {
|
|
38
|
+
return `${smartFixed(value)}%`;
|
|
39
|
+
}
|
|
40
|
+
if (this.type === 'variance') {
|
|
41
|
+
let display = value;
|
|
42
|
+
let unit = 'ns²';
|
|
43
|
+
const varianceUnits = [
|
|
44
|
+
{ unit: 'ns²', factor: 1 },
|
|
45
|
+
{ unit: 'µs²', factor: 1e6 },
|
|
46
|
+
{ unit: 'ms²', factor: 1e12 },
|
|
47
|
+
];
|
|
48
|
+
for (const { unit: u, factor } of varianceUnits) {
|
|
49
|
+
const candidate = value / factor;
|
|
50
|
+
if (candidate < 1000) {
|
|
51
|
+
display = candidate;
|
|
52
|
+
unit = u;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return `${smartFixed(display)} ${unit}`;
|
|
57
|
+
}
|
|
37
58
|
let display = value;
|
|
38
59
|
let unit = 'ns';
|
|
39
60
|
|
|
@@ -118,6 +139,101 @@ export const createReport = (durations: BigUint64Array, type: ReportType): Repor
|
|
|
118
139
|
return new Report(type, value, 0, DURATION_SCALE);
|
|
119
140
|
}
|
|
120
141
|
|
|
142
|
+
case 'variance': {
|
|
143
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE * DURATION_SCALE);
|
|
144
|
+
let sum = 0n;
|
|
145
|
+
for (const duration of durations) {
|
|
146
|
+
sum += duration;
|
|
147
|
+
}
|
|
148
|
+
const mean = sum / BigInt(n);
|
|
149
|
+
let sumSquaredDiff = 0n;
|
|
150
|
+
for (const duration of durations) {
|
|
151
|
+
const diff = duration - mean;
|
|
152
|
+
sumSquaredDiff += diff * diff;
|
|
153
|
+
}
|
|
154
|
+
const variance = sumSquaredDiff / BigInt(n - 1);
|
|
155
|
+
return new Report(type, variance, 0, DURATION_SCALE * DURATION_SCALE);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case 'sd': {
|
|
159
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
160
|
+
let sum = 0n;
|
|
161
|
+
for (const duration of durations) {
|
|
162
|
+
sum += duration;
|
|
163
|
+
}
|
|
164
|
+
const mean = sum / BigInt(n);
|
|
165
|
+
let sumSquaredDiff = 0n;
|
|
166
|
+
for (const duration of durations) {
|
|
167
|
+
const diff = duration - mean;
|
|
168
|
+
sumSquaredDiff += diff * diff;
|
|
169
|
+
}
|
|
170
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
171
|
+
const sd = Math.sqrt(variance);
|
|
172
|
+
const sdScaled = BigInt(Math.round(sd));
|
|
173
|
+
return new Report(type, sdScaled, 0, DURATION_SCALE);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case 'sem': {
|
|
177
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
178
|
+
let sum = 0n;
|
|
179
|
+
for (const duration of durations) {
|
|
180
|
+
sum += duration;
|
|
181
|
+
}
|
|
182
|
+
const mean = sum / BigInt(n);
|
|
183
|
+
let sumSquaredDiff = 0n;
|
|
184
|
+
for (const duration of durations) {
|
|
185
|
+
const diff = duration - mean;
|
|
186
|
+
sumSquaredDiff += diff * diff;
|
|
187
|
+
}
|
|
188
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
189
|
+
const sd = Math.sqrt(variance);
|
|
190
|
+
const sem = sd / Math.sqrt(n);
|
|
191
|
+
const semScaled = BigInt(Math.round(sem));
|
|
192
|
+
return new Report(type, semScaled, 0, DURATION_SCALE);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
case 'moe': {
|
|
196
|
+
if (n < 2) return new Report(type, 0n, 0, DURATION_SCALE);
|
|
197
|
+
let sum = 0n;
|
|
198
|
+
for (const duration of durations) {
|
|
199
|
+
sum += duration;
|
|
200
|
+
}
|
|
201
|
+
const mean = sum / BigInt(n);
|
|
202
|
+
let sumSquaredDiff = 0n;
|
|
203
|
+
for (const duration of durations) {
|
|
204
|
+
const diff = duration - mean;
|
|
205
|
+
sumSquaredDiff += diff * diff;
|
|
206
|
+
}
|
|
207
|
+
const variance = Number(sumSquaredDiff) / (n - 1);
|
|
208
|
+
const sd = Math.sqrt(variance);
|
|
209
|
+
const sem = sd / Math.sqrt(n);
|
|
210
|
+
const moe = Z95 * sem;
|
|
211
|
+
const moeScaled = BigInt(Math.round(moe));
|
|
212
|
+
return new Report(type, moeScaled, 0, DURATION_SCALE);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
case 'rme': {
|
|
216
|
+
if (n < 2) return new Report(type, 0n);
|
|
217
|
+
let sum = 0n;
|
|
218
|
+
for (const duration of durations) {
|
|
219
|
+
sum += duration;
|
|
220
|
+
}
|
|
221
|
+
const mean = Number(sum) / n;
|
|
222
|
+
if (mean === 0) return new Report(type, 0n);
|
|
223
|
+
let sumSquaredDiff = 0;
|
|
224
|
+
for (const duration of durations) {
|
|
225
|
+
const diff = Number(duration) - mean;
|
|
226
|
+
sumSquaredDiff += diff * diff;
|
|
227
|
+
}
|
|
228
|
+
const variance = sumSquaredDiff / (n - 1);
|
|
229
|
+
const sd = Math.sqrt(variance);
|
|
230
|
+
const sem = sd / Math.sqrt(n);
|
|
231
|
+
const moe = Z95 * sem;
|
|
232
|
+
const rme = (moe / mean) * 100;
|
|
233
|
+
const rmeScaled = BigInt(Math.round(rme * 100));
|
|
234
|
+
return new Report(type, rmeScaled, 0, 100n);
|
|
235
|
+
}
|
|
236
|
+
|
|
121
237
|
default: {
|
|
122
238
|
const p = Number(type.slice(1));
|
|
123
239
|
if (p === 0) {
|
package/src/types.ts
CHANGED
|
@@ -20,9 +20,21 @@ type _Sequence<To extends number, R extends unknown[]> = R['length'] extends To
|
|
|
20
20
|
export type Sequence<To extends number> = number extends To ? number : _Sequence<To, []>;
|
|
21
21
|
export type Between<From extends number, To extends number> = Exclude<Sequence<To>, Sequence<From>>;
|
|
22
22
|
|
|
23
|
-
export type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | `p${Between<1, 100>}`;
|
|
23
|
+
export type ReportType = 'ops' | 'min' | 'max' | 'mean' | 'median' | 'mode' | 'variance' | 'sd' | 'sem' | 'moe' | 'rme' | `p${Between<1, 100>}`;
|
|
24
24
|
export type ReportTypeList = readonly ReportType[];
|
|
25
|
-
export const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat([
|
|
25
|
+
export const REPORT_TYPES: ReportTypeList = Array.from({ length: 99 }, (_, idx) => `p${idx + 1}` as ReportType).concat([
|
|
26
|
+
'ops',
|
|
27
|
+
'mean',
|
|
28
|
+
'min',
|
|
29
|
+
'max',
|
|
30
|
+
'median',
|
|
31
|
+
'mode',
|
|
32
|
+
'variance',
|
|
33
|
+
'sd',
|
|
34
|
+
'sem',
|
|
35
|
+
'moe',
|
|
36
|
+
'rme',
|
|
37
|
+
]);
|
|
26
38
|
|
|
27
39
|
export interface ReportOptions<R extends ReportTypeList> {
|
|
28
40
|
reportTypes: R;
|