deepbox 0.1.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/LICENSE +21 -0
- package/README.md +344 -0
- package/dist/CSRMatrix-CwGwQRea.d.cts +219 -0
- package/dist/CSRMatrix-KzNt6QpS.d.ts +219 -0
- package/dist/Tensor-BQLk1ltW.d.cts +147 -0
- package/dist/Tensor-g8mUClel.d.ts +147 -0
- package/dist/chunk-4S73VUBD.js +677 -0
- package/dist/chunk-4S73VUBD.js.map +1 -0
- package/dist/chunk-5R4S63PF.js +2925 -0
- package/dist/chunk-5R4S63PF.js.map +1 -0
- package/dist/chunk-6AE5FKKQ.cjs +9264 -0
- package/dist/chunk-6AE5FKKQ.cjs.map +1 -0
- package/dist/chunk-AD436M45.js +3854 -0
- package/dist/chunk-AD436M45.js.map +1 -0
- package/dist/chunk-ALS7ETWZ.cjs +4263 -0
- package/dist/chunk-ALS7ETWZ.cjs.map +1 -0
- package/dist/chunk-AU7XHGKJ.js +2092 -0
- package/dist/chunk-AU7XHGKJ.js.map +1 -0
- package/dist/chunk-B5TNKUEY.js +1481 -0
- package/dist/chunk-B5TNKUEY.js.map +1 -0
- package/dist/chunk-BCR7G3A6.js +9136 -0
- package/dist/chunk-BCR7G3A6.js.map +1 -0
- package/dist/chunk-C4PKXY74.cjs +1917 -0
- package/dist/chunk-C4PKXY74.cjs.map +1 -0
- package/dist/chunk-DWZY6PIP.cjs +6400 -0
- package/dist/chunk-DWZY6PIP.cjs.map +1 -0
- package/dist/chunk-E3EU5FZO.cjs +2113 -0
- package/dist/chunk-E3EU5FZO.cjs.map +1 -0
- package/dist/chunk-F3JWBINJ.js +1054 -0
- package/dist/chunk-F3JWBINJ.js.map +1 -0
- package/dist/chunk-FJYLIGJX.js +1940 -0
- package/dist/chunk-FJYLIGJX.js.map +1 -0
- package/dist/chunk-JSCDE774.cjs +729 -0
- package/dist/chunk-JSCDE774.cjs.map +1 -0
- package/dist/chunk-LWECRCW2.cjs +2412 -0
- package/dist/chunk-LWECRCW2.cjs.map +1 -0
- package/dist/chunk-MLBMYKCG.js +6379 -0
- package/dist/chunk-MLBMYKCG.js.map +1 -0
- package/dist/chunk-OX6QXFMV.cjs +3874 -0
- package/dist/chunk-OX6QXFMV.cjs.map +1 -0
- package/dist/chunk-PHV2DKRS.cjs +1072 -0
- package/dist/chunk-PHV2DKRS.cjs.map +1 -0
- package/dist/chunk-PL7TAYKI.js +4056 -0
- package/dist/chunk-PL7TAYKI.js.map +1 -0
- package/dist/chunk-PR647I7R.js +1898 -0
- package/dist/chunk-PR647I7R.js.map +1 -0
- package/dist/chunk-QERHVCHC.cjs +2960 -0
- package/dist/chunk-QERHVCHC.cjs.map +1 -0
- package/dist/chunk-XEG44RF6.cjs +1514 -0
- package/dist/chunk-XEG44RF6.cjs.map +1 -0
- package/dist/chunk-XMWVME2W.js +2377 -0
- package/dist/chunk-XMWVME2W.js.map +1 -0
- package/dist/chunk-ZB75FESB.cjs +1979 -0
- package/dist/chunk-ZB75FESB.cjs.map +1 -0
- package/dist/chunk-ZLW62TJG.cjs +4061 -0
- package/dist/chunk-ZLW62TJG.cjs.map +1 -0
- package/dist/chunk-ZXKBDFP3.js +4235 -0
- package/dist/chunk-ZXKBDFP3.js.map +1 -0
- package/dist/core/index.cjs +204 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +2 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/dataframe/index.cjs +22 -0
- package/dist/dataframe/index.cjs.map +1 -0
- package/dist/dataframe/index.d.cts +3 -0
- package/dist/dataframe/index.d.ts +3 -0
- package/dist/dataframe/index.js +5 -0
- package/dist/dataframe/index.js.map +1 -0
- package/dist/datasets/index.cjs +134 -0
- package/dist/datasets/index.cjs.map +1 -0
- package/dist/datasets/index.d.cts +3 -0
- package/dist/datasets/index.d.ts +3 -0
- package/dist/datasets/index.js +5 -0
- package/dist/datasets/index.js.map +1 -0
- package/dist/index-74AB8Cyh.d.cts +1126 -0
- package/dist/index-9oQx1HgV.d.cts +1180 -0
- package/dist/index-BJY2SI4i.d.ts +483 -0
- package/dist/index-BWGhrDlr.d.ts +733 -0
- package/dist/index-B_DK4FKY.d.cts +242 -0
- package/dist/index-BbA2Gxfl.d.ts +456 -0
- package/dist/index-BgHYAoSS.d.cts +837 -0
- package/dist/index-BndMbqsM.d.ts +1439 -0
- package/dist/index-C1mfVYoo.d.ts +2517 -0
- package/dist/index-CCvlwAmL.d.cts +809 -0
- package/dist/index-CDw5CnOU.d.ts +785 -0
- package/dist/index-Cn3SdB0O.d.ts +1126 -0
- package/dist/index-CrqLlS-a.d.ts +776 -0
- package/dist/index-D61yaSMY.d.cts +483 -0
- package/dist/index-D9Loo1_A.d.cts +2517 -0
- package/dist/index-DIT_OO9C.d.cts +785 -0
- package/dist/index-DIp_RrRt.d.ts +242 -0
- package/dist/index-DbultU6X.d.cts +1427 -0
- package/dist/index-DmEg_LCm.d.cts +776 -0
- package/dist/index-DoPWVxPo.d.cts +1439 -0
- package/dist/index-DuCxd-8d.d.ts +837 -0
- package/dist/index-Dx42TZaY.d.ts +809 -0
- package/dist/index-DyZ4QQf5.d.cts +456 -0
- package/dist/index-GFAVyOWO.d.ts +1427 -0
- package/dist/index-WHQLn0e8.d.cts +733 -0
- package/dist/index-ZtI1Iy4L.d.ts +1180 -0
- package/dist/index-eJgeni9c.d.cts +1911 -0
- package/dist/index-tk4lSYod.d.ts +1911 -0
- package/dist/index.cjs +72 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/linalg/index.cjs +86 -0
- package/dist/linalg/index.cjs.map +1 -0
- package/dist/linalg/index.d.cts +3 -0
- package/dist/linalg/index.d.ts +3 -0
- package/dist/linalg/index.js +5 -0
- package/dist/linalg/index.js.map +1 -0
- package/dist/metrics/index.cjs +158 -0
- package/dist/metrics/index.cjs.map +1 -0
- package/dist/metrics/index.d.cts +3 -0
- package/dist/metrics/index.d.ts +3 -0
- package/dist/metrics/index.js +5 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/ml/index.cjs +87 -0
- package/dist/ml/index.cjs.map +1 -0
- package/dist/ml/index.d.cts +3 -0
- package/dist/ml/index.d.ts +3 -0
- package/dist/ml/index.js +6 -0
- package/dist/ml/index.js.map +1 -0
- package/dist/ndarray/index.cjs +501 -0
- package/dist/ndarray/index.cjs.map +1 -0
- package/dist/ndarray/index.d.cts +5 -0
- package/dist/ndarray/index.d.ts +5 -0
- package/dist/ndarray/index.js +4 -0
- package/dist/ndarray/index.js.map +1 -0
- package/dist/nn/index.cjs +142 -0
- package/dist/nn/index.cjs.map +1 -0
- package/dist/nn/index.d.cts +6 -0
- package/dist/nn/index.d.ts +6 -0
- package/dist/nn/index.js +5 -0
- package/dist/nn/index.js.map +1 -0
- package/dist/optim/index.cjs +77 -0
- package/dist/optim/index.cjs.map +1 -0
- package/dist/optim/index.d.cts +4 -0
- package/dist/optim/index.d.ts +4 -0
- package/dist/optim/index.js +4 -0
- package/dist/optim/index.js.map +1 -0
- package/dist/plot/index.cjs +114 -0
- package/dist/plot/index.cjs.map +1 -0
- package/dist/plot/index.d.cts +6 -0
- package/dist/plot/index.d.ts +6 -0
- package/dist/plot/index.js +5 -0
- package/dist/plot/index.js.map +1 -0
- package/dist/preprocess/index.cjs +82 -0
- package/dist/preprocess/index.cjs.map +1 -0
- package/dist/preprocess/index.d.cts +4 -0
- package/dist/preprocess/index.d.ts +4 -0
- package/dist/preprocess/index.js +5 -0
- package/dist/preprocess/index.js.map +1 -0
- package/dist/random/index.cjs +74 -0
- package/dist/random/index.cjs.map +1 -0
- package/dist/random/index.d.cts +3 -0
- package/dist/random/index.d.ts +3 -0
- package/dist/random/index.js +5 -0
- package/dist/random/index.js.map +1 -0
- package/dist/stats/index.cjs +142 -0
- package/dist/stats/index.cjs.map +1 -0
- package/dist/stats/index.d.cts +3 -0
- package/dist/stats/index.d.ts +3 -0
- package/dist/stats/index.js +5 -0
- package/dist/stats/index.js.map +1 -0
- package/dist/tensor-B96jjJLQ.d.cts +205 -0
- package/dist/tensor-B96jjJLQ.d.ts +205 -0
- package/package.json +226 -0
|
@@ -0,0 +1,2412 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk6AE5FKKQ_cjs = require('./chunk-6AE5FKKQ.cjs');
|
|
4
|
+
var chunkJSCDE774_cjs = require('./chunk-JSCDE774.cjs');
|
|
5
|
+
|
|
6
|
+
// src/stats/index.ts
|
|
7
|
+
var stats_exports = {};
|
|
8
|
+
chunkJSCDE774_cjs.__export(stats_exports, {
|
|
9
|
+
anderson: () => anderson,
|
|
10
|
+
bartlett: () => bartlett,
|
|
11
|
+
chisquare: () => chisquare,
|
|
12
|
+
corrcoef: () => corrcoef,
|
|
13
|
+
cov: () => cov,
|
|
14
|
+
f_oneway: () => f_oneway,
|
|
15
|
+
friedmanchisquare: () => friedmanchisquare,
|
|
16
|
+
geometricMean: () => geometricMean,
|
|
17
|
+
harmonicMean: () => harmonicMean,
|
|
18
|
+
kendalltau: () => kendalltau,
|
|
19
|
+
kruskal: () => kruskal,
|
|
20
|
+
kstest: () => kstest,
|
|
21
|
+
kurtosis: () => kurtosis,
|
|
22
|
+
levene: () => levene,
|
|
23
|
+
mannwhitneyu: () => mannwhitneyu,
|
|
24
|
+
mean: () => mean,
|
|
25
|
+
median: () => median,
|
|
26
|
+
mode: () => mode,
|
|
27
|
+
moment: () => moment,
|
|
28
|
+
normaltest: () => normaltest,
|
|
29
|
+
pearsonr: () => pearsonr,
|
|
30
|
+
percentile: () => percentile,
|
|
31
|
+
quantile: () => quantile,
|
|
32
|
+
shapiro: () => shapiro,
|
|
33
|
+
skewness: () => skewness,
|
|
34
|
+
spearmanr: () => spearmanr,
|
|
35
|
+
std: () => std,
|
|
36
|
+
trimMean: () => trimMean,
|
|
37
|
+
ttest_1samp: () => ttest_1samp,
|
|
38
|
+
ttest_ind: () => ttest_ind,
|
|
39
|
+
ttest_rel: () => ttest_rel,
|
|
40
|
+
variance: () => variance,
|
|
41
|
+
wilcoxon: () => wilcoxon
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/stats/_internal.ts
|
|
45
|
+
function normalizeAxes(axis, ndim) {
|
|
46
|
+
if (axis === void 0) return [];
|
|
47
|
+
const axesInput = Array.isArray(axis) ? [...axis] : [axis];
|
|
48
|
+
const seen = /* @__PURE__ */ new Set();
|
|
49
|
+
const result = [];
|
|
50
|
+
for (const ax of axesInput) {
|
|
51
|
+
const norm = chunkJSCDE774_cjs.normalizeAxis(ax, ndim);
|
|
52
|
+
if (!seen.has(norm)) {
|
|
53
|
+
seen.add(norm);
|
|
54
|
+
result.push(norm);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result.sort((a, b) => a - b);
|
|
58
|
+
}
|
|
59
|
+
function reducedShape(shape, axes, keepdims) {
|
|
60
|
+
if (axes.length === 0) {
|
|
61
|
+
return keepdims ? new Array(shape.length).fill(1) : [];
|
|
62
|
+
}
|
|
63
|
+
const reduce = new Set(axes);
|
|
64
|
+
const out = [];
|
|
65
|
+
for (let i = 0; i < shape.length; i++) {
|
|
66
|
+
const d = shape[i];
|
|
67
|
+
if (d === void 0) throw new chunkJSCDE774_cjs.ShapeError("Internal error: missing shape dimension");
|
|
68
|
+
if (reduce.has(i)) {
|
|
69
|
+
if (keepdims) out.push(1);
|
|
70
|
+
} else {
|
|
71
|
+
out.push(d);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
chunkJSCDE774_cjs.validateShape(out);
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function computeStrides(shape) {
|
|
78
|
+
const strides = new Array(shape.length);
|
|
79
|
+
let stride = 1;
|
|
80
|
+
for (let i = shape.length - 1; i >= 0; i--) {
|
|
81
|
+
strides[i] = stride;
|
|
82
|
+
stride *= shape[i] ?? 0;
|
|
83
|
+
}
|
|
84
|
+
return strides;
|
|
85
|
+
}
|
|
86
|
+
function assertSameSize(a, b, name) {
|
|
87
|
+
if (a.size !== b.size) {
|
|
88
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
89
|
+
`${name}: tensors must have the same number of elements; got ${a.size} and ${b.size}`,
|
|
90
|
+
"size",
|
|
91
|
+
{ a: a.size, b: b.size }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function getNumberAt(t, offset) {
|
|
96
|
+
if (t.dtype === "string" || Array.isArray(t.data)) {
|
|
97
|
+
throw new chunkJSCDE774_cjs.DTypeError("operation not supported for string dtype");
|
|
98
|
+
}
|
|
99
|
+
return chunkJSCDE774_cjs.getElementAsNumber(t.data, offset);
|
|
100
|
+
}
|
|
101
|
+
function rankData(values) {
|
|
102
|
+
const n = values.length;
|
|
103
|
+
const ranks = new Float64Array(n);
|
|
104
|
+
if (n === 0) return { ranks, tieSum: 0 };
|
|
105
|
+
const sorted = Array.from(values, (v, i) => ({ v, i })).sort((a, b) => a.v - b.v);
|
|
106
|
+
let tieSum = 0;
|
|
107
|
+
for (let i = 0; i < sorted.length; ) {
|
|
108
|
+
let j = i + 1;
|
|
109
|
+
while (j < sorted.length && sorted[j]?.v === sorted[i]?.v) {
|
|
110
|
+
j++;
|
|
111
|
+
}
|
|
112
|
+
const t = j - i;
|
|
113
|
+
const avgRank = (i + 1 + j) / 2;
|
|
114
|
+
for (let k = i; k < j; k++) {
|
|
115
|
+
const idx = sorted[k]?.i;
|
|
116
|
+
if (idx !== void 0) {
|
|
117
|
+
ranks[idx] = avgRank;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (t > 1) tieSum += t * t * t - t;
|
|
121
|
+
i = j;
|
|
122
|
+
}
|
|
123
|
+
return { ranks, tieSum };
|
|
124
|
+
}
|
|
125
|
+
function forEachIndexOffset(t, fn) {
|
|
126
|
+
if (t.size === 0) return;
|
|
127
|
+
if (t.ndim === 0) {
|
|
128
|
+
fn(t.offset, []);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const shape = t.shape;
|
|
132
|
+
const strides = t.strides;
|
|
133
|
+
const idx = new Array(t.ndim).fill(0);
|
|
134
|
+
let offset = t.offset;
|
|
135
|
+
while (true) {
|
|
136
|
+
fn(offset, idx);
|
|
137
|
+
let axis = t.ndim - 1;
|
|
138
|
+
for (; ; ) {
|
|
139
|
+
idx[axis] = (idx[axis] ?? 0) + 1;
|
|
140
|
+
offset += strides[axis] ?? 0;
|
|
141
|
+
const dim = shape[axis] ?? 0;
|
|
142
|
+
if ((idx[axis] ?? 0) < dim) break;
|
|
143
|
+
offset -= (idx[axis] ?? 0) * (strides[axis] ?? 0);
|
|
144
|
+
idx[axis] = 0;
|
|
145
|
+
axis--;
|
|
146
|
+
if (axis < 0) return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function reduceMean(t, axis, keepdims) {
|
|
151
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
152
|
+
if (axes.length === 0) {
|
|
153
|
+
if (t.size === 0) {
|
|
154
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("mean() requires at least one element", "size", t.size);
|
|
155
|
+
}
|
|
156
|
+
let sum = 0;
|
|
157
|
+
forEachIndexOffset(t, (off) => {
|
|
158
|
+
sum += getNumberAt(t, off);
|
|
159
|
+
});
|
|
160
|
+
const out = new Float64Array(1);
|
|
161
|
+
out[0] = sum / t.size;
|
|
162
|
+
const outShape2 = keepdims ? new Array(t.ndim).fill(1) : [];
|
|
163
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
164
|
+
data: out,
|
|
165
|
+
shape: outShape2,
|
|
166
|
+
dtype: "float64",
|
|
167
|
+
device: t.device
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const outShape = reducedShape(t.shape, axes, keepdims);
|
|
171
|
+
const outStrides = computeStrides(outShape);
|
|
172
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
173
|
+
const sums = new Float64Array(outSize);
|
|
174
|
+
const reduce = new Set(axes);
|
|
175
|
+
const reduceCount = axes.reduce((acc, ax) => acc * (t.shape[ax] ?? 0), 1);
|
|
176
|
+
if (reduceCount === 0) {
|
|
177
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
178
|
+
"mean() reduction over empty axis is undefined",
|
|
179
|
+
"reduceCount",
|
|
180
|
+
reduceCount
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
184
|
+
let outFlat = 0;
|
|
185
|
+
if (keepdims) {
|
|
186
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
187
|
+
const s = outStrides[i] ?? 0;
|
|
188
|
+
const v = reduce.has(i) ? 0 : idx[i] ?? 0;
|
|
189
|
+
outFlat += v * s;
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
let oi = 0;
|
|
193
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
194
|
+
if (reduce.has(i)) continue;
|
|
195
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
196
|
+
oi++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
sums[outFlat] = (sums[outFlat] ?? 0) + getNumberAt(t, off);
|
|
200
|
+
});
|
|
201
|
+
for (let i = 0; i < sums.length; i++) {
|
|
202
|
+
sums[i] = (sums[i] ?? 0) / reduceCount;
|
|
203
|
+
}
|
|
204
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
205
|
+
data: sums,
|
|
206
|
+
shape: outShape,
|
|
207
|
+
dtype: "float64",
|
|
208
|
+
device: t.device
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function reduceVariance(t, axis, keepdims, ddof) {
|
|
212
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
213
|
+
if (t.dtype === "string") {
|
|
214
|
+
throw new chunkJSCDE774_cjs.DTypeError("variance() not supported for string dtype");
|
|
215
|
+
}
|
|
216
|
+
if (axes.length === 0) {
|
|
217
|
+
if (t.size === 0) {
|
|
218
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("variance() requires at least one element", "size", t.size);
|
|
219
|
+
}
|
|
220
|
+
if (ddof < 0) {
|
|
221
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ddof must be non-negative", "ddof", ddof);
|
|
222
|
+
}
|
|
223
|
+
if (t.size <= ddof) {
|
|
224
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
225
|
+
`ddof=${ddof} >= size=${t.size}, variance undefined`,
|
|
226
|
+
"ddof",
|
|
227
|
+
ddof
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
let mean2 = 0;
|
|
231
|
+
let m2 = 0;
|
|
232
|
+
let n = 0;
|
|
233
|
+
forEachIndexOffset(t, (off) => {
|
|
234
|
+
const x = getNumberAt(t, off);
|
|
235
|
+
n++;
|
|
236
|
+
const delta = x - mean2;
|
|
237
|
+
mean2 += delta / n;
|
|
238
|
+
const delta2 = x - mean2;
|
|
239
|
+
m2 += delta * delta2;
|
|
240
|
+
});
|
|
241
|
+
const out2 = new Float64Array(1);
|
|
242
|
+
out2[0] = m2 / (n - ddof);
|
|
243
|
+
const outShape2 = keepdims ? new Array(t.ndim).fill(1) : [];
|
|
244
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
245
|
+
data: out2,
|
|
246
|
+
shape: outShape2,
|
|
247
|
+
dtype: "float64",
|
|
248
|
+
device: t.device
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const outShape = reducedShape(t.shape, axes, keepdims);
|
|
252
|
+
const outStrides = computeStrides(outShape);
|
|
253
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
254
|
+
const reduce = new Set(axes);
|
|
255
|
+
const reduceCount = axes.reduce((acc, ax) => acc * (t.shape[ax] ?? 0), 1);
|
|
256
|
+
if (reduceCount === 0) {
|
|
257
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
258
|
+
"variance() reduction over empty axis is undefined",
|
|
259
|
+
"reduceCount",
|
|
260
|
+
reduceCount
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
if (ddof < 0) {
|
|
264
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ddof must be non-negative", "ddof", ddof);
|
|
265
|
+
}
|
|
266
|
+
if (reduceCount <= ddof) {
|
|
267
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
268
|
+
`ddof=${ddof} >= reduced size=${reduceCount}, variance undefined`,
|
|
269
|
+
"ddof",
|
|
270
|
+
ddof
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
const means = new Float64Array(outSize);
|
|
274
|
+
const m2s = new Float64Array(outSize);
|
|
275
|
+
const counts = new Int32Array(outSize);
|
|
276
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
277
|
+
let outFlat = 0;
|
|
278
|
+
if (keepdims) {
|
|
279
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
280
|
+
const s = outStrides[i] ?? 0;
|
|
281
|
+
const v = reduce.has(i) ? 0 : idx[i] ?? 0;
|
|
282
|
+
outFlat += v * s;
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
let oi = 0;
|
|
286
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
287
|
+
if (reduce.has(i)) continue;
|
|
288
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
289
|
+
oi++;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const x = getNumberAt(t, off);
|
|
293
|
+
const n = (counts[outFlat] ?? 0) + 1;
|
|
294
|
+
counts[outFlat] = n;
|
|
295
|
+
const mean2 = means[outFlat] ?? 0;
|
|
296
|
+
const delta = x - mean2;
|
|
297
|
+
const nextMean = mean2 + delta / n;
|
|
298
|
+
means[outFlat] = nextMean;
|
|
299
|
+
const delta2 = x - nextMean;
|
|
300
|
+
m2s[outFlat] = (m2s[outFlat] ?? 0) + delta * delta2;
|
|
301
|
+
});
|
|
302
|
+
const out = new Float64Array(outSize);
|
|
303
|
+
for (let i = 0; i < outSize; i++) {
|
|
304
|
+
const n = counts[i] ?? 0;
|
|
305
|
+
out[i] = (m2s[i] ?? 0) / (n - ddof);
|
|
306
|
+
}
|
|
307
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
308
|
+
data: out,
|
|
309
|
+
shape: outShape,
|
|
310
|
+
dtype: "float64",
|
|
311
|
+
device: t.device
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
var LANCZOS_COEFFS = [
|
|
315
|
+
0.9999999999998099,
|
|
316
|
+
676.5203681218851,
|
|
317
|
+
-1259.1392167224028,
|
|
318
|
+
771.3234287776531,
|
|
319
|
+
-176.6150291621406,
|
|
320
|
+
12.507343278686905,
|
|
321
|
+
-0.13857109526572012,
|
|
322
|
+
9984369578019572e-21,
|
|
323
|
+
15056327351493116e-23
|
|
324
|
+
];
|
|
325
|
+
function logGamma(z) {
|
|
326
|
+
if (z < 0.5) {
|
|
327
|
+
return Math.log(Math.PI) - Math.log(Math.sin(Math.PI * z)) - logGamma(1 - z);
|
|
328
|
+
}
|
|
329
|
+
z -= 1;
|
|
330
|
+
let x = LANCZOS_COEFFS[0];
|
|
331
|
+
for (let i = 1; i < LANCZOS_COEFFS.length; i++) {
|
|
332
|
+
x += (LANCZOS_COEFFS[i] ?? 0) / (z + i);
|
|
333
|
+
}
|
|
334
|
+
const t = z + 7.5;
|
|
335
|
+
return 0.5 * Math.log(2 * Math.PI) + (z + 0.5) * Math.log(t) - t + Math.log(x);
|
|
336
|
+
}
|
|
337
|
+
function betacf(a, b, x) {
|
|
338
|
+
const MAX_ITER = 200;
|
|
339
|
+
const EPS = 3e-14;
|
|
340
|
+
const FPMIN = 1e-300;
|
|
341
|
+
const qab = a + b;
|
|
342
|
+
const qap = a + 1;
|
|
343
|
+
const qam = a - 1;
|
|
344
|
+
let c = 1;
|
|
345
|
+
let d = 1 - qab * x / qap;
|
|
346
|
+
if (Math.abs(d) < FPMIN) d = FPMIN;
|
|
347
|
+
d = 1 / d;
|
|
348
|
+
let h = d;
|
|
349
|
+
for (let m = 1; m <= MAX_ITER; m++) {
|
|
350
|
+
const m2 = 2 * m;
|
|
351
|
+
let aa = m * (b - m) * x / ((qam + m2) * (a + m2));
|
|
352
|
+
d = 1 + aa * d;
|
|
353
|
+
if (Math.abs(d) < FPMIN) d = FPMIN;
|
|
354
|
+
c = 1 + aa / c;
|
|
355
|
+
if (Math.abs(c) < FPMIN) c = FPMIN;
|
|
356
|
+
d = 1 / d;
|
|
357
|
+
h *= d * c;
|
|
358
|
+
aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
|
|
359
|
+
d = 1 + aa * d;
|
|
360
|
+
if (Math.abs(d) < FPMIN) d = FPMIN;
|
|
361
|
+
c = 1 + aa / c;
|
|
362
|
+
if (Math.abs(c) < FPMIN) c = FPMIN;
|
|
363
|
+
d = 1 / d;
|
|
364
|
+
const del = d * c;
|
|
365
|
+
h *= del;
|
|
366
|
+
if (Math.abs(del - 1) < EPS) break;
|
|
367
|
+
}
|
|
368
|
+
return h;
|
|
369
|
+
}
|
|
370
|
+
function regularizedIncompleteBeta(a, b, x) {
|
|
371
|
+
if (!Number.isFinite(a) || a <= 0) {
|
|
372
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("a must be > 0", "a", a);
|
|
373
|
+
}
|
|
374
|
+
if (!Number.isFinite(b) || b <= 0) {
|
|
375
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("b must be > 0", "b", b);
|
|
376
|
+
}
|
|
377
|
+
if (x < 0 || x > 1) {
|
|
378
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("x must be in [0,1]", "x", x);
|
|
379
|
+
}
|
|
380
|
+
if (x === 0) return 0;
|
|
381
|
+
if (x === 1) return 1;
|
|
382
|
+
const lnBt = logGamma(a + b) - logGamma(a) - logGamma(b) + a * Math.log(x) + b * Math.log(1 - x);
|
|
383
|
+
const bt = Math.exp(lnBt);
|
|
384
|
+
if (x < (a + 1) / (a + b + 2)) {
|
|
385
|
+
return bt * betacf(a, b, x) / a;
|
|
386
|
+
}
|
|
387
|
+
return 1 - bt * betacf(b, a, 1 - x) / b;
|
|
388
|
+
}
|
|
389
|
+
function regularizedLowerIncompleteGamma(s, x) {
|
|
390
|
+
if (!Number.isFinite(s) || s <= 0) {
|
|
391
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("s must be > 0", "s", s);
|
|
392
|
+
}
|
|
393
|
+
if (x < 0) throw new chunkJSCDE774_cjs.InvalidParameterError("x must be >= 0", "x", x);
|
|
394
|
+
if (x === 0) return 0;
|
|
395
|
+
const ITMAX = 200;
|
|
396
|
+
const EPS = 3e-14;
|
|
397
|
+
const FPMIN = 1e-300;
|
|
398
|
+
if (x < s + 1) {
|
|
399
|
+
let sum = 1 / s;
|
|
400
|
+
let del = sum;
|
|
401
|
+
let ap = s;
|
|
402
|
+
for (let n = 1; n <= ITMAX; n++) {
|
|
403
|
+
ap += 1;
|
|
404
|
+
del *= x / ap;
|
|
405
|
+
sum += del;
|
|
406
|
+
if (Math.abs(del) < Math.abs(sum) * EPS) break;
|
|
407
|
+
}
|
|
408
|
+
return sum * Math.exp(-x + s * Math.log(x) - logGamma(s));
|
|
409
|
+
}
|
|
410
|
+
let b = x + 1 - s;
|
|
411
|
+
let c = 1 / FPMIN;
|
|
412
|
+
let d = 1 / b;
|
|
413
|
+
let h = d;
|
|
414
|
+
for (let i = 1; i <= ITMAX; i++) {
|
|
415
|
+
const an = -i * (i - s);
|
|
416
|
+
b += 2;
|
|
417
|
+
d = an * d + b;
|
|
418
|
+
if (Math.abs(d) < FPMIN) d = FPMIN;
|
|
419
|
+
c = b + an / c;
|
|
420
|
+
if (Math.abs(c) < FPMIN) c = FPMIN;
|
|
421
|
+
d = 1 / d;
|
|
422
|
+
const del = d * c;
|
|
423
|
+
h *= del;
|
|
424
|
+
if (Math.abs(del - 1) < EPS) break;
|
|
425
|
+
}
|
|
426
|
+
const q = Math.exp(-x + s * Math.log(x) - logGamma(s)) * h;
|
|
427
|
+
return 1 - q;
|
|
428
|
+
}
|
|
429
|
+
function normalCdf(x) {
|
|
430
|
+
const a = 0.147;
|
|
431
|
+
const sign = x < 0 ? -1 : 1;
|
|
432
|
+
const ax = Math.abs(x) / Math.SQRT2;
|
|
433
|
+
const t = 1 + a * ax * ax;
|
|
434
|
+
const erf = sign * Math.sqrt(1 - Math.exp(-ax * ax * ((4 / Math.PI + a * ax * ax) / t)));
|
|
435
|
+
return 0.5 * (1 + erf);
|
|
436
|
+
}
|
|
437
|
+
function studentTCdf(t, df) {
|
|
438
|
+
if (!Number.isFinite(df) || df <= 0) {
|
|
439
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("df must be > 0", "df", df);
|
|
440
|
+
}
|
|
441
|
+
if (Number.isNaN(t)) return NaN;
|
|
442
|
+
if (!Number.isFinite(t)) return t < 0 ? 0 : 1;
|
|
443
|
+
const x = df / (df + t * t);
|
|
444
|
+
const a = df / 2;
|
|
445
|
+
const b = 0.5;
|
|
446
|
+
const ib = regularizedIncompleteBeta(a, b, x);
|
|
447
|
+
const p = 0.5 * ib;
|
|
448
|
+
return t >= 0 ? 1 - p : p;
|
|
449
|
+
}
|
|
450
|
+
function chiSquareCdf(x, k) {
|
|
451
|
+
if (!Number.isFinite(k) || k <= 0) {
|
|
452
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("degrees of freedom must be > 0", "k", k);
|
|
453
|
+
}
|
|
454
|
+
if (Number.isNaN(x)) return NaN;
|
|
455
|
+
if (x === Infinity) return 1;
|
|
456
|
+
if (x <= 0) return 0;
|
|
457
|
+
return regularizedLowerIncompleteGamma(k / 2, x / 2);
|
|
458
|
+
}
|
|
459
|
+
function fCdf(x, dfn, dfd) {
|
|
460
|
+
if (!Number.isFinite(dfn) || dfn <= 0) {
|
|
461
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("degrees of freedom (dfn) must be > 0", "dfn", dfn);
|
|
462
|
+
}
|
|
463
|
+
if (!Number.isFinite(dfd) || dfd <= 0) {
|
|
464
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("degrees of freedom (dfd) must be > 0", "dfd", dfd);
|
|
465
|
+
}
|
|
466
|
+
if (Number.isNaN(x)) return NaN;
|
|
467
|
+
if (x === Infinity) return 1;
|
|
468
|
+
if (x <= 0) return 0;
|
|
469
|
+
const xx = dfn * x / (dfn * x + dfd);
|
|
470
|
+
return regularizedIncompleteBeta(dfn / 2, dfd / 2, xx);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/stats/correlation.ts
|
|
474
|
+
function toDenseFlatArray(t) {
|
|
475
|
+
const out = new Float64Array(t.size);
|
|
476
|
+
let i = 0;
|
|
477
|
+
forEachIndexOffset(t, (off) => {
|
|
478
|
+
out[i] = getNumberAt(t, off);
|
|
479
|
+
i++;
|
|
480
|
+
});
|
|
481
|
+
return out;
|
|
482
|
+
}
|
|
483
|
+
function pearsonFromDense(x, y) {
|
|
484
|
+
const n = x.length;
|
|
485
|
+
let sumX = 0;
|
|
486
|
+
let sumY = 0;
|
|
487
|
+
for (let i = 0; i < n; i++) {
|
|
488
|
+
sumX += x[i] ?? 0;
|
|
489
|
+
sumY += y[i] ?? 0;
|
|
490
|
+
}
|
|
491
|
+
const meanX = sumX / n;
|
|
492
|
+
const meanY = sumY / n;
|
|
493
|
+
let num = 0;
|
|
494
|
+
let denX = 0;
|
|
495
|
+
let denY = 0;
|
|
496
|
+
for (let i = 0; i < n; i++) {
|
|
497
|
+
const dx = (x[i] ?? 0) - meanX;
|
|
498
|
+
const dy = (y[i] ?? 0) - meanY;
|
|
499
|
+
num += dx * dy;
|
|
500
|
+
denX += dx * dx;
|
|
501
|
+
denY += dy * dy;
|
|
502
|
+
}
|
|
503
|
+
const den = Math.sqrt(denX * denY);
|
|
504
|
+
if (den === 0) {
|
|
505
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
506
|
+
"pearsonr() is undefined for constant input",
|
|
507
|
+
"input",
|
|
508
|
+
"constant"
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
return num / den;
|
|
512
|
+
}
|
|
513
|
+
function pearsonr(x, y) {
|
|
514
|
+
assertSameSize(x, y, "pearsonr");
|
|
515
|
+
const n = x.size;
|
|
516
|
+
if (n < 2) {
|
|
517
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("pearsonr() requires at least 2 paired samples", "n", n);
|
|
518
|
+
}
|
|
519
|
+
const xd = toDenseFlatArray(x);
|
|
520
|
+
const yd = toDenseFlatArray(y);
|
|
521
|
+
const r = pearsonFromDense(xd, yd);
|
|
522
|
+
const df = n - 2;
|
|
523
|
+
if (df <= 0) {
|
|
524
|
+
return [r, NaN];
|
|
525
|
+
}
|
|
526
|
+
const tStat = r * Math.sqrt(df / (1 - r * r));
|
|
527
|
+
const pValue = 2 * (1 - studentTCdf(Math.abs(tStat), df));
|
|
528
|
+
return [r, pValue];
|
|
529
|
+
}
|
|
530
|
+
function spearmanr(x, y) {
|
|
531
|
+
assertSameSize(x, y, "spearmanr");
|
|
532
|
+
const n = x.size;
|
|
533
|
+
if (n < 2) {
|
|
534
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("spearmanr() requires at least 2 paired samples", "n", n);
|
|
535
|
+
}
|
|
536
|
+
const xd = toDenseFlatArray(x);
|
|
537
|
+
const yd = toDenseFlatArray(y);
|
|
538
|
+
const rankX = rankData(xd).ranks;
|
|
539
|
+
const rankY = rankData(yd).ranks;
|
|
540
|
+
const rho = pearsonFromDense(rankX, rankY);
|
|
541
|
+
const df = n - 2;
|
|
542
|
+
const tStat = rho * Math.sqrt(df / (1 - rho * rho));
|
|
543
|
+
const pValue = df > 0 ? 2 * (1 - studentTCdf(Math.abs(tStat), df)) : NaN;
|
|
544
|
+
return [rho, pValue];
|
|
545
|
+
}
|
|
546
|
+
function kendalltau(x, y) {
|
|
547
|
+
assertSameSize(x, y, "kendalltau");
|
|
548
|
+
const n = x.size;
|
|
549
|
+
if (n < 2) {
|
|
550
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("kendalltau() requires at least 2 paired samples", "n", n);
|
|
551
|
+
}
|
|
552
|
+
const xd = toDenseFlatArray(x);
|
|
553
|
+
const yd = toDenseFlatArray(y);
|
|
554
|
+
let concordant = 0;
|
|
555
|
+
let discordant = 0;
|
|
556
|
+
for (let i = 0; i < n - 1; i++) {
|
|
557
|
+
const xi = xd[i] ?? 0;
|
|
558
|
+
const yi = yd[i] ?? 0;
|
|
559
|
+
for (let j = i + 1; j < n; j++) {
|
|
560
|
+
const signX = Math.sign((xd[j] ?? 0) - xi);
|
|
561
|
+
const signY = Math.sign((yd[j] ?? 0) - yi);
|
|
562
|
+
if (signX === 0 || signY === 0) continue;
|
|
563
|
+
if (signX === signY) concordant++;
|
|
564
|
+
else discordant++;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
const n0 = n * (n - 1) / 2;
|
|
568
|
+
const tieSums = (vals) => {
|
|
569
|
+
const sorted = Array.from(vals).sort((a, b) => a - b);
|
|
570
|
+
let sumT = 0;
|
|
571
|
+
let sumT2 = 0;
|
|
572
|
+
let sumT3 = 0;
|
|
573
|
+
for (let i = 0; i < sorted.length; ) {
|
|
574
|
+
let j = i + 1;
|
|
575
|
+
while (j < sorted.length && sorted[j] === sorted[i]) j++;
|
|
576
|
+
const t = j - i;
|
|
577
|
+
if (t > 1) {
|
|
578
|
+
sumT += t * (t - 1);
|
|
579
|
+
sumT2 += t * (t - 1) * (2 * t + 5);
|
|
580
|
+
sumT3 += t * (t - 1) * (t - 2);
|
|
581
|
+
}
|
|
582
|
+
i = j;
|
|
583
|
+
}
|
|
584
|
+
return { nTies: sumT / 2, sumT, sumT2, sumT3 };
|
|
585
|
+
};
|
|
586
|
+
const tieX = tieSums(xd);
|
|
587
|
+
const tieY = tieSums(yd);
|
|
588
|
+
const denom = Math.sqrt((n0 - tieX.nTies) * (n0 - tieY.nTies));
|
|
589
|
+
const s = concordant - discordant;
|
|
590
|
+
const tau = denom === 0 ? NaN : s / denom;
|
|
591
|
+
let varS = (n * (n - 1) * (2 * n + 5) - tieX.sumT2 - tieY.sumT2) / 18 + tieX.sumT * tieY.sumT / (2 * n * (n - 1));
|
|
592
|
+
if (n > 2) {
|
|
593
|
+
varS += tieX.sumT3 * tieY.sumT3 / (9 * n * (n - 1) * (n - 2));
|
|
594
|
+
}
|
|
595
|
+
const pValue = varS <= 0 ? NaN : 2 * (1 - normalCdf(Math.abs(s / Math.sqrt(varS))));
|
|
596
|
+
return [tau, pValue];
|
|
597
|
+
}
|
|
598
|
+
function corrcoef(x, y) {
|
|
599
|
+
if (y) {
|
|
600
|
+
const [r] = pearsonr(x, y);
|
|
601
|
+
return chunk6AE5FKKQ_cjs.tensor([
|
|
602
|
+
[1, r],
|
|
603
|
+
[r, 1]
|
|
604
|
+
]);
|
|
605
|
+
}
|
|
606
|
+
if (x.ndim === 1) {
|
|
607
|
+
if (x.size < 2) {
|
|
608
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
609
|
+
"corrcoef() requires at least 2 observations",
|
|
610
|
+
"nObs",
|
|
611
|
+
x.size
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
return chunk6AE5FKKQ_cjs.tensor([[1]]);
|
|
615
|
+
}
|
|
616
|
+
if (x.ndim !== 2) {
|
|
617
|
+
throw new chunkJSCDE774_cjs.ShapeError("corrcoef() expects a 1D or 2D tensor");
|
|
618
|
+
}
|
|
619
|
+
const nObs = x.shape[0] ?? 0;
|
|
620
|
+
const nVar = x.shape[1] ?? 0;
|
|
621
|
+
if (nObs < 2) {
|
|
622
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("corrcoef() requires at least 2 observations", "nObs", nObs);
|
|
623
|
+
}
|
|
624
|
+
const s0 = x.strides[0] ?? 0;
|
|
625
|
+
const s1 = x.strides[1] ?? 0;
|
|
626
|
+
const xOff = x.offset;
|
|
627
|
+
const xData = x.data;
|
|
628
|
+
const directAccess = !Array.isArray(xData) && !(xData instanceof BigInt64Array);
|
|
629
|
+
const means = new Float64Array(nVar);
|
|
630
|
+
if (directAccess) {
|
|
631
|
+
for (let j = 0; j < nVar; j++) {
|
|
632
|
+
let s = 0;
|
|
633
|
+
for (let i = 0; i < nObs; i++) {
|
|
634
|
+
s += xData[xOff + i * s0 + j * s1];
|
|
635
|
+
}
|
|
636
|
+
means[j] = s / nObs;
|
|
637
|
+
}
|
|
638
|
+
} else {
|
|
639
|
+
for (let j = 0; j < nVar; j++) {
|
|
640
|
+
let s = 0;
|
|
641
|
+
for (let i = 0; i < nObs; i++) {
|
|
642
|
+
s += getNumberAt(x, xOff + i * s0 + j * s1);
|
|
643
|
+
}
|
|
644
|
+
means[j] = s / nObs;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const cov2 = new Float64Array(nVar * nVar);
|
|
648
|
+
const ddof = 1;
|
|
649
|
+
if (directAccess) {
|
|
650
|
+
for (let a = 0; a < nVar; a++) {
|
|
651
|
+
const ma = means[a];
|
|
652
|
+
for (let b = a; b < nVar; b++) {
|
|
653
|
+
const mb = means[b];
|
|
654
|
+
let s = 0;
|
|
655
|
+
for (let i = 0; i < nObs; i++) {
|
|
656
|
+
const base = xOff + i * s0;
|
|
657
|
+
s += (xData[base + a * s1] - ma) * (xData[base + b * s1] - mb);
|
|
658
|
+
}
|
|
659
|
+
const v = s / (nObs - ddof);
|
|
660
|
+
cov2[a * nVar + b] = v;
|
|
661
|
+
cov2[b * nVar + a] = v;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
} else {
|
|
665
|
+
for (let a = 0; a < nVar; a++) {
|
|
666
|
+
for (let b = a; b < nVar; b++) {
|
|
667
|
+
let s = 0;
|
|
668
|
+
for (let i = 0; i < nObs; i++) {
|
|
669
|
+
const offA = xOff + i * s0 + a * s1;
|
|
670
|
+
const offB = xOff + i * s0 + b * s1;
|
|
671
|
+
s += (getNumberAt(x, offA) - (means[a] ?? 0)) * (getNumberAt(x, offB) - (means[b] ?? 0));
|
|
672
|
+
}
|
|
673
|
+
const v = s / (nObs - ddof);
|
|
674
|
+
cov2[a * nVar + b] = v;
|
|
675
|
+
cov2[b * nVar + a] = v;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
const corr = new Float64Array(nVar * nVar);
|
|
680
|
+
for (let i = 0; i < nVar; i++) {
|
|
681
|
+
for (let j = 0; j < nVar; j++) {
|
|
682
|
+
const v = cov2[i * nVar + j] ?? 0;
|
|
683
|
+
const vi = cov2[i * nVar + i] ?? 0;
|
|
684
|
+
const vj = cov2[j * nVar + j] ?? 0;
|
|
685
|
+
const den = Math.sqrt(vi * vj);
|
|
686
|
+
corr[i * nVar + j] = den === 0 ? NaN : v / den;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
690
|
+
data: corr,
|
|
691
|
+
shape: [nVar, nVar],
|
|
692
|
+
dtype: "float64",
|
|
693
|
+
device: x.device
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
function cov(x, y, ddof = 1) {
|
|
697
|
+
if (!Number.isFinite(ddof) || ddof < 0) {
|
|
698
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ddof must be a non-negative finite number", "ddof", ddof);
|
|
699
|
+
}
|
|
700
|
+
if (y) {
|
|
701
|
+
assertSameSize(x, y, "cov");
|
|
702
|
+
const n = x.size;
|
|
703
|
+
if (n === 0) throw new chunkJSCDE774_cjs.InvalidParameterError("cov() requires at least one element", "n", n);
|
|
704
|
+
if (n <= ddof)
|
|
705
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
706
|
+
`ddof=${ddof} >= size=${n}, covariance undefined`,
|
|
707
|
+
"ddof",
|
|
708
|
+
ddof
|
|
709
|
+
);
|
|
710
|
+
const xd = toDenseFlatArray(x);
|
|
711
|
+
const yd = toDenseFlatArray(y);
|
|
712
|
+
let meanX = 0;
|
|
713
|
+
let meanY = 0;
|
|
714
|
+
for (let i = 0; i < n; i++) {
|
|
715
|
+
meanX += xd[i] ?? 0;
|
|
716
|
+
meanY += yd[i] ?? 0;
|
|
717
|
+
}
|
|
718
|
+
meanX /= n;
|
|
719
|
+
meanY /= n;
|
|
720
|
+
let varX = 0;
|
|
721
|
+
let varY = 0;
|
|
722
|
+
let covXY = 0;
|
|
723
|
+
for (let i = 0; i < n; i++) {
|
|
724
|
+
const dx = (xd[i] ?? 0) - meanX;
|
|
725
|
+
const dy = (yd[i] ?? 0) - meanY;
|
|
726
|
+
varX += dx * dx;
|
|
727
|
+
varY += dy * dy;
|
|
728
|
+
covXY += dx * dy;
|
|
729
|
+
}
|
|
730
|
+
varX /= n - ddof;
|
|
731
|
+
varY /= n - ddof;
|
|
732
|
+
covXY /= n - ddof;
|
|
733
|
+
return chunk6AE5FKKQ_cjs.tensor([
|
|
734
|
+
[varX, covXY],
|
|
735
|
+
[covXY, varY]
|
|
736
|
+
]);
|
|
737
|
+
}
|
|
738
|
+
if (x.ndim === 1) {
|
|
739
|
+
const n = x.size;
|
|
740
|
+
if (n === 0) throw new chunkJSCDE774_cjs.InvalidParameterError("cov() requires at least one element", "n", n);
|
|
741
|
+
if (ddof < 0) {
|
|
742
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ddof must be non-negative", "ddof", ddof);
|
|
743
|
+
}
|
|
744
|
+
if (n <= ddof)
|
|
745
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
746
|
+
`ddof=${ddof} >= size=${n}, covariance undefined`,
|
|
747
|
+
"ddof",
|
|
748
|
+
ddof
|
|
749
|
+
);
|
|
750
|
+
const xd = toDenseFlatArray(x);
|
|
751
|
+
let meanX = 0;
|
|
752
|
+
for (let i = 0; i < n; i++) meanX += xd[i] ?? 0;
|
|
753
|
+
meanX /= n;
|
|
754
|
+
let varX = 0;
|
|
755
|
+
for (let i = 0; i < n; i++) {
|
|
756
|
+
const dx = (xd[i] ?? 0) - meanX;
|
|
757
|
+
varX += dx * dx;
|
|
758
|
+
}
|
|
759
|
+
varX /= n - ddof;
|
|
760
|
+
return chunk6AE5FKKQ_cjs.tensor([[varX]]);
|
|
761
|
+
}
|
|
762
|
+
if (x.ndim !== 2) {
|
|
763
|
+
throw new chunkJSCDE774_cjs.ShapeError("cov() expects a 1D or 2D tensor");
|
|
764
|
+
}
|
|
765
|
+
const nObs = x.shape[0] ?? 0;
|
|
766
|
+
const nVar = x.shape[1] ?? 0;
|
|
767
|
+
if (nObs === 0)
|
|
768
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("cov() requires at least one observation", "nObs", nObs);
|
|
769
|
+
if (ddof < 0) {
|
|
770
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ddof must be non-negative", "ddof", ddof);
|
|
771
|
+
}
|
|
772
|
+
if (nObs <= ddof)
|
|
773
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
774
|
+
`ddof=${ddof} >= nObs=${nObs}, covariance undefined`,
|
|
775
|
+
"ddof",
|
|
776
|
+
ddof
|
|
777
|
+
);
|
|
778
|
+
const means = new Float64Array(nVar);
|
|
779
|
+
for (let j = 0; j < nVar; j++) {
|
|
780
|
+
let s = 0;
|
|
781
|
+
for (let i = 0; i < nObs; i++) {
|
|
782
|
+
const off = x.offset + i * (x.strides[0] ?? 0) + j * (x.strides[1] ?? 0);
|
|
783
|
+
s += getNumberAt(x, off);
|
|
784
|
+
}
|
|
785
|
+
means[j] = s / nObs;
|
|
786
|
+
}
|
|
787
|
+
const out = new Float64Array(nVar * nVar);
|
|
788
|
+
for (let a = 0; a < nVar; a++) {
|
|
789
|
+
for (let b = a; b < nVar; b++) {
|
|
790
|
+
let s = 0;
|
|
791
|
+
for (let i = 0; i < nObs; i++) {
|
|
792
|
+
const offA = x.offset + i * (x.strides[0] ?? 0) + a * (x.strides[1] ?? 0);
|
|
793
|
+
const offB = x.offset + i * (x.strides[0] ?? 0) + b * (x.strides[1] ?? 0);
|
|
794
|
+
s += (getNumberAt(x, offA) - (means[a] ?? 0)) * (getNumberAt(x, offB) - (means[b] ?? 0));
|
|
795
|
+
}
|
|
796
|
+
const v = s / (nObs - ddof);
|
|
797
|
+
out[a * nVar + b] = v;
|
|
798
|
+
out[b * nVar + a] = v;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
802
|
+
data: out,
|
|
803
|
+
shape: [nVar, nVar],
|
|
804
|
+
dtype: "float64",
|
|
805
|
+
device: x.device
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// src/stats/descriptive.ts
|
|
810
|
+
function mean(t, axis, _keepdims = false) {
|
|
811
|
+
return reduceMean(t, axis, _keepdims);
|
|
812
|
+
}
|
|
813
|
+
function median(t, axis, _keepdims = false) {
|
|
814
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
815
|
+
if (axes.length === 0) {
|
|
816
|
+
if (t.size === 0) {
|
|
817
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("median() requires at least one element", "size", t.size);
|
|
818
|
+
}
|
|
819
|
+
const values = [];
|
|
820
|
+
let hasNaN = false;
|
|
821
|
+
forEachIndexOffset(t, (off) => {
|
|
822
|
+
const v = getNumberAt(t, off);
|
|
823
|
+
if (Number.isNaN(v)) hasNaN = true;
|
|
824
|
+
values.push(v);
|
|
825
|
+
});
|
|
826
|
+
const outShape2 = _keepdims ? new Array(t.ndim).fill(1) : [];
|
|
827
|
+
if (hasNaN) {
|
|
828
|
+
const out3 = new Float64Array(1);
|
|
829
|
+
out3[0] = Number.NaN;
|
|
830
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
831
|
+
data: out3,
|
|
832
|
+
shape: outShape2,
|
|
833
|
+
dtype: "float64",
|
|
834
|
+
device: t.device
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
values.sort((a, b) => a - b);
|
|
838
|
+
const mid = Math.floor(values.length / 2);
|
|
839
|
+
const result = values.length % 2 === 0 ? ((values[mid - 1] ?? 0) + (values[mid] ?? 0)) / 2 : values[mid] ?? 0;
|
|
840
|
+
const out2 = new Float64Array(1);
|
|
841
|
+
out2[0] = result;
|
|
842
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
843
|
+
data: out2,
|
|
844
|
+
shape: outShape2,
|
|
845
|
+
dtype: "float64",
|
|
846
|
+
device: t.device
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
const outShape = reducedShape(t.shape, axes, _keepdims);
|
|
850
|
+
const outStrides = computeStrides(outShape);
|
|
851
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
852
|
+
const buckets = new Array(outSize);
|
|
853
|
+
const nanFlags = new Array(outSize).fill(false);
|
|
854
|
+
const reduce = new Set(axes);
|
|
855
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
856
|
+
let outFlat = 0;
|
|
857
|
+
if (_keepdims) {
|
|
858
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
859
|
+
const s = outStrides[i] ?? 0;
|
|
860
|
+
const v = reduce.has(i) ? 0 : idx[i] ?? 0;
|
|
861
|
+
outFlat += v * s;
|
|
862
|
+
}
|
|
863
|
+
} else {
|
|
864
|
+
let oi = 0;
|
|
865
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
866
|
+
if (reduce.has(i)) continue;
|
|
867
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
868
|
+
oi++;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
const val = getNumberAt(t, off);
|
|
872
|
+
if (Number.isNaN(val)) {
|
|
873
|
+
nanFlags[outFlat] = true;
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
const arr = buckets[outFlat] ?? [];
|
|
877
|
+
arr.push(val);
|
|
878
|
+
buckets[outFlat] = arr;
|
|
879
|
+
});
|
|
880
|
+
const out = new Float64Array(outSize);
|
|
881
|
+
for (let i = 0; i < outSize; i++) {
|
|
882
|
+
if (nanFlags[i]) {
|
|
883
|
+
out[i] = Number.NaN;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
const arr = buckets[i] ?? [];
|
|
887
|
+
if (arr.length === 0) {
|
|
888
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
889
|
+
"median() reduction over empty axis is undefined",
|
|
890
|
+
"axis",
|
|
891
|
+
arr.length
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
arr.sort((a, b) => a - b);
|
|
895
|
+
const mid = Math.floor(arr.length / 2);
|
|
896
|
+
out[i] = arr.length % 2 === 0 ? ((arr[mid - 1] ?? 0) + (arr[mid] ?? 0)) / 2 : arr[mid] ?? 0;
|
|
897
|
+
}
|
|
898
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
899
|
+
data: out,
|
|
900
|
+
shape: outShape,
|
|
901
|
+
dtype: "float64",
|
|
902
|
+
device: t.device
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
function mode(t, axis) {
|
|
906
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
907
|
+
if (axes.length === 0) {
|
|
908
|
+
if (t.size === 0) {
|
|
909
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("mode() requires at least one element", "size", t.size);
|
|
910
|
+
}
|
|
911
|
+
const freq = /* @__PURE__ */ new Map();
|
|
912
|
+
let maxFreq = 0;
|
|
913
|
+
let modeVal = Number.POSITIVE_INFINITY;
|
|
914
|
+
let hasNaN = false;
|
|
915
|
+
forEachIndexOffset(t, (off) => {
|
|
916
|
+
const val = getNumberAt(t, off);
|
|
917
|
+
if (Number.isNaN(val)) {
|
|
918
|
+
hasNaN = true;
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
const count = (freq.get(val) ?? 0) + 1;
|
|
922
|
+
freq.set(val, count);
|
|
923
|
+
if (count > maxFreq || count === maxFreq && val < modeVal) {
|
|
924
|
+
maxFreq = count;
|
|
925
|
+
modeVal = val;
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
if (hasNaN) {
|
|
929
|
+
return chunk6AE5FKKQ_cjs.tensor([Number.NaN]);
|
|
930
|
+
}
|
|
931
|
+
return chunk6AE5FKKQ_cjs.tensor([modeVal]);
|
|
932
|
+
}
|
|
933
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
934
|
+
const outStrides = computeStrides(outShape);
|
|
935
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
936
|
+
const maps = new Array(outSize);
|
|
937
|
+
const bestCounts = new Int32Array(outSize);
|
|
938
|
+
const bestValues = new Float64Array(outSize);
|
|
939
|
+
const nanFlags = new Array(outSize).fill(false);
|
|
940
|
+
const reduce = new Set(axes);
|
|
941
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
942
|
+
let outFlat = 0;
|
|
943
|
+
let oi = 0;
|
|
944
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
945
|
+
if (reduce.has(i)) continue;
|
|
946
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
947
|
+
oi++;
|
|
948
|
+
}
|
|
949
|
+
const val = getNumberAt(t, off);
|
|
950
|
+
if (Number.isNaN(val)) {
|
|
951
|
+
nanFlags[outFlat] = true;
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const m = maps[outFlat] ?? /* @__PURE__ */ new Map();
|
|
955
|
+
const next = (m.get(val) ?? 0) + 1;
|
|
956
|
+
m.set(val, next);
|
|
957
|
+
maps[outFlat] = m;
|
|
958
|
+
const currentBestCount = bestCounts[outFlat] ?? 0;
|
|
959
|
+
const currentBestValue = bestValues[outFlat] ?? Number.POSITIVE_INFINITY;
|
|
960
|
+
if (next > currentBestCount || next === currentBestCount && val < currentBestValue) {
|
|
961
|
+
bestCounts[outFlat] = next;
|
|
962
|
+
bestValues[outFlat] = val;
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
const out = new Float64Array(outSize);
|
|
966
|
+
for (let i = 0; i < outSize; i++) {
|
|
967
|
+
if (nanFlags[i]) {
|
|
968
|
+
out[i] = Number.NaN;
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
if ((bestCounts[i] ?? 0) === 0) {
|
|
972
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
973
|
+
"mode() reduction over empty axis is undefined",
|
|
974
|
+
"axis",
|
|
975
|
+
bestCounts[i] ?? 0
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
out[i] = bestValues[i] ?? Number.NaN;
|
|
979
|
+
}
|
|
980
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
981
|
+
data: out,
|
|
982
|
+
shape: outShape,
|
|
983
|
+
dtype: "float64",
|
|
984
|
+
device: t.device
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
function std(t, axis, _keepdims = false, ddof = 0) {
|
|
988
|
+
const v = reduceVariance(t, axis, _keepdims, ddof);
|
|
989
|
+
const out = new Float64Array(v.size);
|
|
990
|
+
for (let i = 0; i < v.size; i++) {
|
|
991
|
+
out[i] = Math.sqrt(getNumberAt(v, v.offset + i));
|
|
992
|
+
}
|
|
993
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
994
|
+
data: out,
|
|
995
|
+
shape: v.shape,
|
|
996
|
+
dtype: "float64",
|
|
997
|
+
device: v.device
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
function variance(t, axis, _keepdims = false, ddof = 0) {
|
|
1001
|
+
return reduceVariance(t, axis, _keepdims, ddof);
|
|
1002
|
+
}
|
|
1003
|
+
function skewness(t, axis, bias = true) {
|
|
1004
|
+
const mu = reduceMean(t, axis, false);
|
|
1005
|
+
const sigma2 = reduceVariance(t, axis, false, 0);
|
|
1006
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1007
|
+
const reduce = new Set(axes);
|
|
1008
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1009
|
+
const outStrides = computeStrides(outShape);
|
|
1010
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1011
|
+
const sumCube = new Float64Array(outSize);
|
|
1012
|
+
const counts = new Int32Array(outSize);
|
|
1013
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1014
|
+
let outFlat = 0;
|
|
1015
|
+
let oi = 0;
|
|
1016
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1017
|
+
if (reduce.has(i)) continue;
|
|
1018
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1019
|
+
oi++;
|
|
1020
|
+
}
|
|
1021
|
+
const m = getNumberAt(mu, mu.offset + outFlat);
|
|
1022
|
+
const v = Math.sqrt(getNumberAt(sigma2, sigma2.offset + outFlat));
|
|
1023
|
+
const x = getNumberAt(t, off);
|
|
1024
|
+
if (!Number.isFinite(v) || v === 0) {
|
|
1025
|
+
sumCube[outFlat] = NaN;
|
|
1026
|
+
} else {
|
|
1027
|
+
const z = (x - m) / v;
|
|
1028
|
+
sumCube[outFlat] = (sumCube[outFlat] ?? 0) + z * z * z;
|
|
1029
|
+
}
|
|
1030
|
+
counts[outFlat] = (counts[outFlat] ?? 0) + 1;
|
|
1031
|
+
});
|
|
1032
|
+
const out = new Float64Array(outSize);
|
|
1033
|
+
for (let i = 0; i < outSize; i++) {
|
|
1034
|
+
const n = counts[i] ?? 0;
|
|
1035
|
+
if (n === 0) {
|
|
1036
|
+
out[i] = NaN;
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
1039
|
+
let g1 = (sumCube[i] ?? NaN) / n;
|
|
1040
|
+
if (!bias) {
|
|
1041
|
+
if (n < 3) {
|
|
1042
|
+
g1 = NaN;
|
|
1043
|
+
} else {
|
|
1044
|
+
g1 *= Math.sqrt(n * (n - 1)) / (n - 2);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
out[i] = g1;
|
|
1048
|
+
}
|
|
1049
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1050
|
+
data: out,
|
|
1051
|
+
shape: outShape,
|
|
1052
|
+
dtype: "float64",
|
|
1053
|
+
device: t.device
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
function kurtosis(t, axis, fisher = true, bias = true) {
|
|
1057
|
+
const mu = reduceMean(t, axis, false);
|
|
1058
|
+
const sigma2 = reduceVariance(t, axis, false, 0);
|
|
1059
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1060
|
+
const reduce = new Set(axes);
|
|
1061
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1062
|
+
const outStrides = computeStrides(outShape);
|
|
1063
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1064
|
+
const sumQuad = new Float64Array(outSize);
|
|
1065
|
+
const counts = new Int32Array(outSize);
|
|
1066
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1067
|
+
let outFlat = 0;
|
|
1068
|
+
let oi = 0;
|
|
1069
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1070
|
+
if (reduce.has(i)) continue;
|
|
1071
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1072
|
+
oi++;
|
|
1073
|
+
}
|
|
1074
|
+
const m = getNumberAt(mu, mu.offset + outFlat);
|
|
1075
|
+
const v = Math.sqrt(getNumberAt(sigma2, sigma2.offset + outFlat));
|
|
1076
|
+
const x = getNumberAt(t, off);
|
|
1077
|
+
if (!Number.isFinite(v) || v === 0) {
|
|
1078
|
+
sumQuad[outFlat] = NaN;
|
|
1079
|
+
} else {
|
|
1080
|
+
const z = (x - m) / v;
|
|
1081
|
+
sumQuad[outFlat] = (sumQuad[outFlat] ?? 0) + z ** 4;
|
|
1082
|
+
}
|
|
1083
|
+
counts[outFlat] = (counts[outFlat] ?? 0) + 1;
|
|
1084
|
+
});
|
|
1085
|
+
const out = new Float64Array(outSize);
|
|
1086
|
+
for (let i = 0; i < outSize; i++) {
|
|
1087
|
+
const n = counts[i] ?? 0;
|
|
1088
|
+
if (n === 0) {
|
|
1089
|
+
out[i] = NaN;
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
let g2 = (sumQuad[i] ?? NaN) / n;
|
|
1093
|
+
if (!bias) {
|
|
1094
|
+
if (n < 4) {
|
|
1095
|
+
g2 = NaN;
|
|
1096
|
+
} else {
|
|
1097
|
+
const excess = g2 - 3;
|
|
1098
|
+
const adj = ((n + 1) * excess + 6) * ((n - 1) / ((n - 2) * (n - 3)));
|
|
1099
|
+
g2 = adj + 3;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
out[i] = fisher ? g2 - 3 : g2;
|
|
1103
|
+
}
|
|
1104
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1105
|
+
data: out,
|
|
1106
|
+
shape: outShape,
|
|
1107
|
+
dtype: "float64",
|
|
1108
|
+
device: t.device
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
function quantile(t, q, axis) {
|
|
1112
|
+
const qVals = Array.isArray(q) ? q : [q];
|
|
1113
|
+
for (const v of qVals) {
|
|
1114
|
+
if (!Number.isFinite(v) || v < 0 || v > 1) {
|
|
1115
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("q must be in [0, 1]", "q", v);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1119
|
+
const reduce = new Set(axes);
|
|
1120
|
+
if (axes.length === 0) {
|
|
1121
|
+
if (t.size === 0) {
|
|
1122
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("quantile() requires at least one element", "size", t.size);
|
|
1123
|
+
}
|
|
1124
|
+
const arr = [];
|
|
1125
|
+
let hasNaN = false;
|
|
1126
|
+
forEachIndexOffset(t, (off) => {
|
|
1127
|
+
const v = getNumberAt(t, off);
|
|
1128
|
+
if (Number.isNaN(v)) hasNaN = true;
|
|
1129
|
+
arr.push(v);
|
|
1130
|
+
});
|
|
1131
|
+
if (hasNaN) {
|
|
1132
|
+
return chunk6AE5FKKQ_cjs.tensor(qVals.map(() => Number.NaN));
|
|
1133
|
+
}
|
|
1134
|
+
arr.sort((a, b) => a - b);
|
|
1135
|
+
const results = [];
|
|
1136
|
+
for (const qVal of qVals) {
|
|
1137
|
+
const idx = qVal * (arr.length - 1);
|
|
1138
|
+
const lower = Math.floor(idx);
|
|
1139
|
+
const upper = Math.ceil(idx);
|
|
1140
|
+
const weight = idx - lower;
|
|
1141
|
+
results.push((arr[lower] ?? 0) * (1 - weight) + (arr[upper] ?? 0) * weight);
|
|
1142
|
+
}
|
|
1143
|
+
return chunk6AE5FKKQ_cjs.tensor(results);
|
|
1144
|
+
}
|
|
1145
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1146
|
+
const outStrides = computeStrides(outShape);
|
|
1147
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1148
|
+
const buckets = new Array(outSize);
|
|
1149
|
+
const nanFlags = new Array(outSize).fill(false);
|
|
1150
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1151
|
+
let outFlat = 0;
|
|
1152
|
+
let oi = 0;
|
|
1153
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1154
|
+
if (reduce.has(i)) continue;
|
|
1155
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1156
|
+
oi++;
|
|
1157
|
+
}
|
|
1158
|
+
const val = getNumberAt(t, off);
|
|
1159
|
+
if (Number.isNaN(val)) {
|
|
1160
|
+
nanFlags[outFlat] = true;
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const arr = buckets[outFlat] ?? [];
|
|
1164
|
+
arr.push(val);
|
|
1165
|
+
buckets[outFlat] = arr;
|
|
1166
|
+
});
|
|
1167
|
+
const finalShape = [qVals.length, ...outShape];
|
|
1168
|
+
const finalSize = qVals.length * outSize;
|
|
1169
|
+
const out = new Float64Array(finalSize);
|
|
1170
|
+
for (let g = 0; g < outSize; g++) {
|
|
1171
|
+
if (nanFlags[g]) {
|
|
1172
|
+
for (let qi = 0; qi < qVals.length; qi++) {
|
|
1173
|
+
out[qi * outSize + g] = Number.NaN;
|
|
1174
|
+
}
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
const arr = buckets[g] ?? [];
|
|
1178
|
+
if (arr.length === 0) {
|
|
1179
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1180
|
+
"quantile() reduction over empty axis is undefined",
|
|
1181
|
+
"axis",
|
|
1182
|
+
arr.length
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
arr.sort((a, b) => a - b);
|
|
1186
|
+
for (let qi = 0; qi < qVals.length; qi++) {
|
|
1187
|
+
const qVal = qVals[qi] ?? 0;
|
|
1188
|
+
const idx = qVal * (arr.length - 1);
|
|
1189
|
+
const lower = Math.floor(idx);
|
|
1190
|
+
const upper = Math.ceil(idx);
|
|
1191
|
+
const weight = idx - lower;
|
|
1192
|
+
out[qi * outSize + g] = (arr[lower] ?? 0) * (1 - weight) + (arr[upper] ?? 0) * weight;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1196
|
+
data: out,
|
|
1197
|
+
shape: finalShape,
|
|
1198
|
+
dtype: "float64",
|
|
1199
|
+
device: t.device
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
function percentile(t, q, axis) {
|
|
1203
|
+
const qArr = Array.isArray(q) ? q : [q];
|
|
1204
|
+
for (const v of qArr) {
|
|
1205
|
+
if (!Number.isFinite(v) || v < 0 || v > 100) {
|
|
1206
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("q must be in [0, 100]", "q", v);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
const qVals = Array.isArray(q) ? q.map((v) => v / 100) : q / 100;
|
|
1210
|
+
return quantile(t, qVals, axis);
|
|
1211
|
+
}
|
|
1212
|
+
function moment(t, n, axis) {
|
|
1213
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
|
|
1214
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("n must be a non-negative integer", "n", n);
|
|
1215
|
+
}
|
|
1216
|
+
const mu = reduceMean(t, axis, false);
|
|
1217
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1218
|
+
const reduce = new Set(axes);
|
|
1219
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1220
|
+
const outStrides = computeStrides(outShape);
|
|
1221
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1222
|
+
const sums = new Float64Array(outSize);
|
|
1223
|
+
const counts = new Int32Array(outSize);
|
|
1224
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1225
|
+
let outFlat = 0;
|
|
1226
|
+
let oi = 0;
|
|
1227
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1228
|
+
if (reduce.has(i)) continue;
|
|
1229
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1230
|
+
oi++;
|
|
1231
|
+
}
|
|
1232
|
+
const m = getNumberAt(mu, mu.offset + outFlat);
|
|
1233
|
+
const x = getNumberAt(t, off);
|
|
1234
|
+
sums[outFlat] = (sums[outFlat] ?? 0) + (x - m) ** n;
|
|
1235
|
+
counts[outFlat] = (counts[outFlat] ?? 0) + 1;
|
|
1236
|
+
});
|
|
1237
|
+
const out = new Float64Array(outSize);
|
|
1238
|
+
for (let i = 0; i < outSize; i++) {
|
|
1239
|
+
const c = counts[i] ?? 0;
|
|
1240
|
+
out[i] = c === 0 ? NaN : (sums[i] ?? 0) / c;
|
|
1241
|
+
}
|
|
1242
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1243
|
+
data: out,
|
|
1244
|
+
shape: outShape,
|
|
1245
|
+
dtype: "float64",
|
|
1246
|
+
device: t.device
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
function geometricMean(t, axis) {
|
|
1250
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1251
|
+
if (axes.length === 0 && t.size === 0) {
|
|
1252
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1253
|
+
"geometricMean() requires at least one element",
|
|
1254
|
+
"size",
|
|
1255
|
+
t.size
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
const reduce = new Set(axes);
|
|
1259
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1260
|
+
const outStrides = computeStrides(outShape);
|
|
1261
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1262
|
+
const sums = new Float64Array(outSize);
|
|
1263
|
+
const counts = new Int32Array(outSize);
|
|
1264
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1265
|
+
let outFlat = 0;
|
|
1266
|
+
let oi = 0;
|
|
1267
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1268
|
+
if (reduce.has(i)) continue;
|
|
1269
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1270
|
+
oi++;
|
|
1271
|
+
}
|
|
1272
|
+
const x = getNumberAt(t, off);
|
|
1273
|
+
if (x <= 0)
|
|
1274
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("geometricMean() requires all values to be > 0", "value", x);
|
|
1275
|
+
sums[outFlat] = (sums[outFlat] ?? 0) + Math.log(x);
|
|
1276
|
+
counts[outFlat] = (counts[outFlat] ?? 0) + 1;
|
|
1277
|
+
});
|
|
1278
|
+
const out = new Float64Array(outSize);
|
|
1279
|
+
for (let i = 0; i < outSize; i++) {
|
|
1280
|
+
const c = counts[i] ?? 0;
|
|
1281
|
+
if (c === 0) {
|
|
1282
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1283
|
+
"geometricMean() reduction over empty axis is undefined",
|
|
1284
|
+
"axis",
|
|
1285
|
+
c
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
out[i] = Math.exp((sums[i] ?? 0) / c);
|
|
1289
|
+
}
|
|
1290
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1291
|
+
data: out,
|
|
1292
|
+
shape: outShape,
|
|
1293
|
+
dtype: "float64",
|
|
1294
|
+
device: t.device
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
function harmonicMean(t, axis) {
|
|
1298
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1299
|
+
if (axes.length === 0 && t.size === 0) {
|
|
1300
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("harmonicMean() requires at least one element", "size", t.size);
|
|
1301
|
+
}
|
|
1302
|
+
const reduce = new Set(axes);
|
|
1303
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1304
|
+
const outStrides = computeStrides(outShape);
|
|
1305
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1306
|
+
const sums = new Float64Array(outSize);
|
|
1307
|
+
const counts = new Int32Array(outSize);
|
|
1308
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1309
|
+
let outFlat = 0;
|
|
1310
|
+
let oi = 0;
|
|
1311
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1312
|
+
if (reduce.has(i)) continue;
|
|
1313
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1314
|
+
oi++;
|
|
1315
|
+
}
|
|
1316
|
+
const x = getNumberAt(t, off);
|
|
1317
|
+
if (x <= 0) {
|
|
1318
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("harmonicMean() requires all values to be > 0", "value", x);
|
|
1319
|
+
}
|
|
1320
|
+
sums[outFlat] = (sums[outFlat] ?? 0) + 1 / x;
|
|
1321
|
+
counts[outFlat] = (counts[outFlat] ?? 0) + 1;
|
|
1322
|
+
});
|
|
1323
|
+
const out = new Float64Array(outSize);
|
|
1324
|
+
for (let i = 0; i < outSize; i++) {
|
|
1325
|
+
const c = counts[i] ?? 0;
|
|
1326
|
+
if (c === 0) {
|
|
1327
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1328
|
+
"harmonicMean() reduction over empty axis is undefined",
|
|
1329
|
+
"axis",
|
|
1330
|
+
c
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
out[i] = c / (sums[i] ?? NaN);
|
|
1334
|
+
}
|
|
1335
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1336
|
+
data: out,
|
|
1337
|
+
shape: outShape,
|
|
1338
|
+
dtype: "float64",
|
|
1339
|
+
device: t.device
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1342
|
+
function trimMean(t, proportiontocut, axis) {
|
|
1343
|
+
if (!Number.isFinite(proportiontocut) || proportiontocut < 0 || proportiontocut >= 0.5) {
|
|
1344
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1345
|
+
"proportiontocut must be a finite number in range [0, 0.5)",
|
|
1346
|
+
"proportiontocut",
|
|
1347
|
+
proportiontocut
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
const axes = normalizeAxes(axis, t.ndim);
|
|
1351
|
+
const reduce = new Set(axes);
|
|
1352
|
+
if (axes.length === 0) {
|
|
1353
|
+
const arr = [];
|
|
1354
|
+
let hasNaN = false;
|
|
1355
|
+
forEachIndexOffset(t, (off) => {
|
|
1356
|
+
const v = getNumberAt(t, off);
|
|
1357
|
+
if (Number.isNaN(v)) hasNaN = true;
|
|
1358
|
+
arr.push(v);
|
|
1359
|
+
});
|
|
1360
|
+
if (arr.length === 0)
|
|
1361
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1362
|
+
"trimMean() requires at least one element",
|
|
1363
|
+
"size",
|
|
1364
|
+
arr.length
|
|
1365
|
+
);
|
|
1366
|
+
if (hasNaN) {
|
|
1367
|
+
return chunk6AE5FKKQ_cjs.tensor([Number.NaN]);
|
|
1368
|
+
}
|
|
1369
|
+
arr.sort((a, b) => a - b);
|
|
1370
|
+
const nTrim = Math.floor(arr.length * proportiontocut);
|
|
1371
|
+
const trimmed = arr.slice(nTrim, arr.length - nTrim);
|
|
1372
|
+
const sum = trimmed.reduce((a, b) => a + b, 0);
|
|
1373
|
+
return chunk6AE5FKKQ_cjs.tensor([sum / trimmed.length]);
|
|
1374
|
+
}
|
|
1375
|
+
const outShape = reducedShape(t.shape, axes, false);
|
|
1376
|
+
const outStrides = computeStrides(outShape);
|
|
1377
|
+
const outSize = outShape.reduce((a, b) => a * b, 1);
|
|
1378
|
+
const buckets = new Array(outSize);
|
|
1379
|
+
const nanFlags = new Array(outSize).fill(false);
|
|
1380
|
+
forEachIndexOffset(t, (off, idx) => {
|
|
1381
|
+
let outFlat = 0;
|
|
1382
|
+
let oi = 0;
|
|
1383
|
+
for (let i = 0; i < t.ndim; i++) {
|
|
1384
|
+
if (reduce.has(i)) continue;
|
|
1385
|
+
outFlat += (idx[i] ?? 0) * (outStrides[oi] ?? 0);
|
|
1386
|
+
oi++;
|
|
1387
|
+
}
|
|
1388
|
+
const val = getNumberAt(t, off);
|
|
1389
|
+
if (Number.isNaN(val)) {
|
|
1390
|
+
nanFlags[outFlat] = true;
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const arr = buckets[outFlat] ?? [];
|
|
1394
|
+
arr.push(val);
|
|
1395
|
+
buckets[outFlat] = arr;
|
|
1396
|
+
});
|
|
1397
|
+
const out = new Float64Array(outSize);
|
|
1398
|
+
for (let i = 0; i < outSize; i++) {
|
|
1399
|
+
if (nanFlags[i]) {
|
|
1400
|
+
out[i] = Number.NaN;
|
|
1401
|
+
continue;
|
|
1402
|
+
}
|
|
1403
|
+
const arr = buckets[i] ?? [];
|
|
1404
|
+
if (arr.length === 0) {
|
|
1405
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1406
|
+
"trimMean() reduction over empty axis is undefined",
|
|
1407
|
+
"axis",
|
|
1408
|
+
arr.length
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
arr.sort((a, b) => a - b);
|
|
1412
|
+
const nTrim = Math.floor(arr.length * proportiontocut);
|
|
1413
|
+
const trimmed = arr.slice(nTrim, arr.length - nTrim);
|
|
1414
|
+
const sum = trimmed.reduce((a, b) => a + b, 0);
|
|
1415
|
+
out[i] = sum / trimmed.length;
|
|
1416
|
+
}
|
|
1417
|
+
return chunk6AE5FKKQ_cjs.Tensor.fromTypedArray({
|
|
1418
|
+
data: out,
|
|
1419
|
+
shape: outShape,
|
|
1420
|
+
dtype: "float64",
|
|
1421
|
+
device: t.device
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// src/stats/tests.ts
|
|
1426
|
+
function toDenseSortedArray1D(x) {
|
|
1427
|
+
if (x.size < 1) {
|
|
1428
|
+
return new Float64Array(0);
|
|
1429
|
+
}
|
|
1430
|
+
const out = new Float64Array(x.size);
|
|
1431
|
+
let i = 0;
|
|
1432
|
+
forEachIndexOffset(x, (off) => {
|
|
1433
|
+
out[i] = getNumberAt(x, off);
|
|
1434
|
+
i++;
|
|
1435
|
+
});
|
|
1436
|
+
out.sort((a, b) => a - b);
|
|
1437
|
+
return out;
|
|
1438
|
+
}
|
|
1439
|
+
function toDenseArray1D(x) {
|
|
1440
|
+
const out = new Float64Array(x.size);
|
|
1441
|
+
let i = 0;
|
|
1442
|
+
forEachIndexOffset(x, (off) => {
|
|
1443
|
+
out[i] = getNumberAt(x, off);
|
|
1444
|
+
i++;
|
|
1445
|
+
});
|
|
1446
|
+
return out;
|
|
1447
|
+
}
|
|
1448
|
+
function meanAndM2(x) {
|
|
1449
|
+
if (x.length === 0) {
|
|
1450
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("expected at least one element", "length", x.length);
|
|
1451
|
+
}
|
|
1452
|
+
let mean2 = 0;
|
|
1453
|
+
let m2 = 0;
|
|
1454
|
+
for (let i = 0; i < x.length; i++) {
|
|
1455
|
+
const v = x[i] ?? 0;
|
|
1456
|
+
const n = i + 1;
|
|
1457
|
+
const delta = v - mean2;
|
|
1458
|
+
mean2 += delta / n;
|
|
1459
|
+
const delta2 = v - mean2;
|
|
1460
|
+
m2 += delta * delta2;
|
|
1461
|
+
}
|
|
1462
|
+
return { mean: mean2, m2 };
|
|
1463
|
+
}
|
|
1464
|
+
function shapiroWilk(x) {
|
|
1465
|
+
const n = x.length;
|
|
1466
|
+
if (n < 3 || n > 5e3) {
|
|
1467
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("shapiro() sample size must be between 3 and 5000", "n", n);
|
|
1468
|
+
}
|
|
1469
|
+
const range = (x[n - 1] ?? 0) - (x[0] ?? 0);
|
|
1470
|
+
if (range === 0) {
|
|
1471
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("shapiro() all x values are identical", "range", range);
|
|
1472
|
+
}
|
|
1473
|
+
const small = 1e-19;
|
|
1474
|
+
if (range < small) {
|
|
1475
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("shapiro() range is too small", "range", range);
|
|
1476
|
+
}
|
|
1477
|
+
const nn2 = Math.floor(n / 2);
|
|
1478
|
+
const a = new Float64Array(nn2 + 1);
|
|
1479
|
+
const g = [-2.273, 0.459];
|
|
1480
|
+
const c1 = [0, 0.221157, -0.147981, -2.07119, 4.434685, -2.706056];
|
|
1481
|
+
const c2 = [0, 0.042981, -0.293762, -1.752461, 5.682633, -3.582633];
|
|
1482
|
+
const c3 = [0.544, -0.39978, 0.025054, -6714e-7];
|
|
1483
|
+
const c4 = [1.3822, -0.77857, 0.062767, -20322e-7];
|
|
1484
|
+
const c5 = [-1.5861, -0.31082, -0.083751, 38915e-7];
|
|
1485
|
+
const c6 = [-0.4803, -0.082676, 30302e-7];
|
|
1486
|
+
const poly = (cc, x0) => {
|
|
1487
|
+
let p = cc[cc.length - 1] ?? 0;
|
|
1488
|
+
for (let j = cc.length - 2; j >= 0; j--) {
|
|
1489
|
+
p = p * x0 + (cc[j] ?? 0);
|
|
1490
|
+
}
|
|
1491
|
+
return p;
|
|
1492
|
+
};
|
|
1493
|
+
const sign = (v) => v === 0 ? 0 : v > 0 ? 1 : -1;
|
|
1494
|
+
const an = n;
|
|
1495
|
+
if (n === 3) {
|
|
1496
|
+
a[1] = Math.SQRT1_2;
|
|
1497
|
+
} else {
|
|
1498
|
+
const an25 = an + 0.25;
|
|
1499
|
+
let summ2 = 0;
|
|
1500
|
+
for (let i = 1; i <= nn2; i++) {
|
|
1501
|
+
const p = (i - 0.375) / an25;
|
|
1502
|
+
let lo = -10;
|
|
1503
|
+
let hi = 10;
|
|
1504
|
+
for (let it = 0; it < 80; it++) {
|
|
1505
|
+
const mid = (lo + hi) / 2;
|
|
1506
|
+
const cdf = normalCdf(mid);
|
|
1507
|
+
if (cdf < p) lo = mid;
|
|
1508
|
+
else hi = mid;
|
|
1509
|
+
}
|
|
1510
|
+
const z2 = (lo + hi) / 2;
|
|
1511
|
+
a[i] = z2;
|
|
1512
|
+
summ2 += z2 * z2;
|
|
1513
|
+
}
|
|
1514
|
+
summ2 *= 2;
|
|
1515
|
+
const ssumm2 = Math.sqrt(summ2);
|
|
1516
|
+
const rsn = 1 / Math.sqrt(an);
|
|
1517
|
+
const a1 = poly(c1, rsn) - (a[1] ?? 0) / ssumm2;
|
|
1518
|
+
let i1;
|
|
1519
|
+
let fac;
|
|
1520
|
+
if (n > 5) {
|
|
1521
|
+
i1 = 3;
|
|
1522
|
+
const a2 = -((a[2] ?? 0) / ssumm2) + poly(c2, rsn);
|
|
1523
|
+
fac = Math.sqrt(
|
|
1524
|
+
(summ2 - 2 * (a[1] ?? 0) * (a[1] ?? 0) - 2 * (a[2] ?? 0) * (a[2] ?? 0)) / (1 - 2 * a1 * a1 - 2 * a2 * a2)
|
|
1525
|
+
);
|
|
1526
|
+
a[2] = a2;
|
|
1527
|
+
} else {
|
|
1528
|
+
i1 = 2;
|
|
1529
|
+
fac = Math.sqrt((summ2 - 2 * (a[1] ?? 0) * (a[1] ?? 0)) / (1 - 2 * a1 * a1));
|
|
1530
|
+
}
|
|
1531
|
+
a[1] = a1;
|
|
1532
|
+
for (let i = i1; i <= nn2; i++) {
|
|
1533
|
+
a[i] = -((a[i] ?? 0) / fac);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
let xx = (x[0] ?? 0) / range;
|
|
1537
|
+
let sx = xx;
|
|
1538
|
+
let sa = -(a[1] ?? 0);
|
|
1539
|
+
for (let i = 1, j = n - 1; i < n; j--) {
|
|
1540
|
+
const xi = (x[i] ?? 0) / range;
|
|
1541
|
+
if (xx - xi > small) {
|
|
1542
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("shapiro() data is not sorted", "data", "unsorted");
|
|
1543
|
+
}
|
|
1544
|
+
sx += xi;
|
|
1545
|
+
i++;
|
|
1546
|
+
if (i !== j) {
|
|
1547
|
+
sa += sign(i - j) * (a[Math.min(i, j)] ?? 0);
|
|
1548
|
+
}
|
|
1549
|
+
xx = xi;
|
|
1550
|
+
}
|
|
1551
|
+
sa /= n;
|
|
1552
|
+
sx /= n;
|
|
1553
|
+
let ssa = 0;
|
|
1554
|
+
let ssx = 0;
|
|
1555
|
+
let sax = 0;
|
|
1556
|
+
for (let i = 0, j = n - 1; i < n; i++, j--) {
|
|
1557
|
+
const asa = i !== j ? sign(i - j) * (a[1 + Math.min(i, j)] ?? 0) - sa : -sa;
|
|
1558
|
+
const xsx = (x[i] ?? 0) / range - sx;
|
|
1559
|
+
ssa += asa * asa;
|
|
1560
|
+
ssx += xsx * xsx;
|
|
1561
|
+
sax += asa * xsx;
|
|
1562
|
+
}
|
|
1563
|
+
const ssassx = Math.sqrt(ssa * ssx);
|
|
1564
|
+
const w1 = (ssassx - sax) * (ssassx + sax) / (ssa * ssx);
|
|
1565
|
+
const w = 1 - w1;
|
|
1566
|
+
if (n === 3) {
|
|
1567
|
+
const pi6 = 1.90985931710274;
|
|
1568
|
+
const stqr = 1.0471975511966;
|
|
1569
|
+
let pw = pi6 * (Math.asin(Math.sqrt(w)) - stqr);
|
|
1570
|
+
if (pw < 0) pw = 0;
|
|
1571
|
+
if (pw > 1) pw = 1;
|
|
1572
|
+
return { statistic: w, pvalue: pw };
|
|
1573
|
+
}
|
|
1574
|
+
const y = Math.log(w1);
|
|
1575
|
+
const lnN = Math.log(an);
|
|
1576
|
+
let m;
|
|
1577
|
+
let s;
|
|
1578
|
+
if (n <= 11) {
|
|
1579
|
+
const gamma = poly(g, an);
|
|
1580
|
+
if (y >= gamma) {
|
|
1581
|
+
return { statistic: w, pvalue: 0 };
|
|
1582
|
+
}
|
|
1583
|
+
const yy = -Math.log(gamma - y);
|
|
1584
|
+
m = poly(c3, an);
|
|
1585
|
+
s = Math.exp(poly(c4, an));
|
|
1586
|
+
const z2 = (yy - m) / s;
|
|
1587
|
+
return { statistic: w, pvalue: normalCdf(z2) };
|
|
1588
|
+
}
|
|
1589
|
+
m = poly(c5, lnN);
|
|
1590
|
+
s = Math.exp(poly(c6, lnN));
|
|
1591
|
+
const z = (y - m) / s;
|
|
1592
|
+
return { statistic: w, pvalue: normalCdf(z) };
|
|
1593
|
+
}
|
|
1594
|
+
function ttest_1samp(a, popmean) {
|
|
1595
|
+
const x = toDenseSortedArray1D(a);
|
|
1596
|
+
const n = x.length;
|
|
1597
|
+
if (n < 2) {
|
|
1598
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ttest_1samp() requires at least 2 samples", "n", n);
|
|
1599
|
+
}
|
|
1600
|
+
let mean2 = 0;
|
|
1601
|
+
for (let i = 0; i < n; i++) mean2 += x[i] ?? 0;
|
|
1602
|
+
mean2 /= n;
|
|
1603
|
+
let m2 = 0;
|
|
1604
|
+
for (let i = 0; i < n; i++) {
|
|
1605
|
+
const d = (x[i] ?? 0) - mean2;
|
|
1606
|
+
m2 += d * d;
|
|
1607
|
+
}
|
|
1608
|
+
const variance2 = m2 / (n - 1);
|
|
1609
|
+
const std2 = Math.sqrt(variance2);
|
|
1610
|
+
if (std2 === 0) {
|
|
1611
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ttest_1samp() is undefined for constant input", "std", std2);
|
|
1612
|
+
}
|
|
1613
|
+
const tstat = (mean2 - popmean) / (std2 / Math.sqrt(n));
|
|
1614
|
+
const df = n - 1;
|
|
1615
|
+
const pvalue = 2 * (1 - studentTCdf(Math.abs(tstat), df));
|
|
1616
|
+
return { statistic: tstat, pvalue };
|
|
1617
|
+
}
|
|
1618
|
+
function ttest_ind(a, b, equalVar = true) {
|
|
1619
|
+
const xa = toDenseSortedArray1D(a);
|
|
1620
|
+
const xb = toDenseSortedArray1D(b);
|
|
1621
|
+
const na = xa.length;
|
|
1622
|
+
const nb = xb.length;
|
|
1623
|
+
if (na < 2 || nb < 2) {
|
|
1624
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ttest_ind() requires at least 2 samples in each group", "n", {
|
|
1625
|
+
na,
|
|
1626
|
+
nb
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
let meanA = 0;
|
|
1630
|
+
let meanB = 0;
|
|
1631
|
+
for (let i = 0; i < na; i++) meanA += xa[i] ?? 0;
|
|
1632
|
+
for (let i = 0; i < nb; i++) meanB += xb[i] ?? 0;
|
|
1633
|
+
meanA /= na;
|
|
1634
|
+
meanB /= nb;
|
|
1635
|
+
let ssa = 0;
|
|
1636
|
+
let ssb = 0;
|
|
1637
|
+
for (let i = 0; i < na; i++) {
|
|
1638
|
+
const d = (xa[i] ?? 0) - meanA;
|
|
1639
|
+
ssa += d * d;
|
|
1640
|
+
}
|
|
1641
|
+
for (let i = 0; i < nb; i++) {
|
|
1642
|
+
const d = (xb[i] ?? 0) - meanB;
|
|
1643
|
+
ssb += d * d;
|
|
1644
|
+
}
|
|
1645
|
+
const varA = ssa / (na - 1);
|
|
1646
|
+
const varB = ssb / (nb - 1);
|
|
1647
|
+
let tstat;
|
|
1648
|
+
let df;
|
|
1649
|
+
if (equalVar) {
|
|
1650
|
+
const pooledVar = ((na - 1) * varA + (nb - 1) * varB) / (na + nb - 2);
|
|
1651
|
+
const denom = Math.sqrt(pooledVar * (1 / na + 1 / nb));
|
|
1652
|
+
if (denom === 0)
|
|
1653
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1654
|
+
"ttest_ind() is undefined for constant input",
|
|
1655
|
+
"denom",
|
|
1656
|
+
denom
|
|
1657
|
+
);
|
|
1658
|
+
tstat = (meanA - meanB) / denom;
|
|
1659
|
+
df = na + nb - 2;
|
|
1660
|
+
} else {
|
|
1661
|
+
const denom = Math.sqrt(varA / na + varB / nb);
|
|
1662
|
+
if (denom === 0)
|
|
1663
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1664
|
+
"ttest_ind() is undefined for constant input",
|
|
1665
|
+
"denom",
|
|
1666
|
+
denom
|
|
1667
|
+
);
|
|
1668
|
+
tstat = (meanA - meanB) / denom;
|
|
1669
|
+
df = (varA / na + varB / nb) ** 2 / ((varA / na) ** 2 / (na - 1) + (varB / nb) ** 2 / (nb - 1));
|
|
1670
|
+
}
|
|
1671
|
+
const pvalue = 2 * (1 - studentTCdf(Math.abs(tstat), df));
|
|
1672
|
+
return { statistic: tstat, pvalue };
|
|
1673
|
+
}
|
|
1674
|
+
function ttest_rel(a, b) {
|
|
1675
|
+
if (a.size !== b.size) {
|
|
1676
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ttest_rel() requires paired samples of equal length", "size", {
|
|
1677
|
+
a: a.size,
|
|
1678
|
+
b: b.size
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
const n = a.size;
|
|
1682
|
+
if (n < 2) {
|
|
1683
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("ttest_rel() requires at least 2 paired samples", "n", n);
|
|
1684
|
+
}
|
|
1685
|
+
const diffs = new Float64Array(n);
|
|
1686
|
+
let i = 0;
|
|
1687
|
+
forEachIndexOffset(a, (offA) => {
|
|
1688
|
+
diffs[i] = getNumberAt(a, offA);
|
|
1689
|
+
i++;
|
|
1690
|
+
});
|
|
1691
|
+
const bd = new Float64Array(n);
|
|
1692
|
+
i = 0;
|
|
1693
|
+
forEachIndexOffset(b, (offB) => {
|
|
1694
|
+
bd[i] = getNumberAt(b, offB);
|
|
1695
|
+
i++;
|
|
1696
|
+
});
|
|
1697
|
+
for (let k = 0; k < n; k++) {
|
|
1698
|
+
diffs[k] = (diffs[k] ?? 0) - (bd[k] ?? 0);
|
|
1699
|
+
}
|
|
1700
|
+
let mean2 = 0;
|
|
1701
|
+
for (let k = 0; k < n; k++) mean2 += diffs[k] ?? 0;
|
|
1702
|
+
mean2 /= n;
|
|
1703
|
+
let ss = 0;
|
|
1704
|
+
for (let k = 0; k < n; k++) {
|
|
1705
|
+
const d = (diffs[k] ?? 0) - mean2;
|
|
1706
|
+
ss += d * d;
|
|
1707
|
+
}
|
|
1708
|
+
const varDiff = ss / (n - 1);
|
|
1709
|
+
const stdDiff = Math.sqrt(varDiff);
|
|
1710
|
+
if (stdDiff === 0) {
|
|
1711
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1712
|
+
"ttest_rel() is undefined for constant differences",
|
|
1713
|
+
"stdDiff",
|
|
1714
|
+
stdDiff
|
|
1715
|
+
);
|
|
1716
|
+
}
|
|
1717
|
+
const tstat = mean2 / (stdDiff / Math.sqrt(n));
|
|
1718
|
+
const df = n - 1;
|
|
1719
|
+
const pvalue = 2 * (1 - studentTCdf(Math.abs(tstat), df));
|
|
1720
|
+
return { statistic: tstat, pvalue };
|
|
1721
|
+
}
|
|
1722
|
+
function chisquare(f_obs, f_exp) {
|
|
1723
|
+
const obs = toDenseArray1D(f_obs);
|
|
1724
|
+
const n = obs.length;
|
|
1725
|
+
if (n < 1) {
|
|
1726
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("chisquare() requires at least one observed value", "n", n);
|
|
1727
|
+
}
|
|
1728
|
+
let chiSq = 0;
|
|
1729
|
+
let sumObs = 0;
|
|
1730
|
+
for (let i = 0; i < n; i++) {
|
|
1731
|
+
const v = obs[i] ?? 0;
|
|
1732
|
+
if (!Number.isFinite(v) || v < 0) {
|
|
1733
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1734
|
+
"chisquare() observed frequencies must be finite and >= 0",
|
|
1735
|
+
"f_obs",
|
|
1736
|
+
v
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
sumObs += v;
|
|
1740
|
+
}
|
|
1741
|
+
if (f_exp && f_obs.size !== f_exp.size) {
|
|
1742
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1743
|
+
"Observed and expected frequency arrays must have the same length",
|
|
1744
|
+
"size",
|
|
1745
|
+
{ f_obs: f_obs.size, f_exp: f_exp.size }
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
if (!f_exp) {
|
|
1749
|
+
const expected = sumObs / n;
|
|
1750
|
+
if (!Number.isFinite(expected) || expected <= 0) {
|
|
1751
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1752
|
+
"chisquare() expected frequencies must be finite and > 0",
|
|
1753
|
+
"expected",
|
|
1754
|
+
expected
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1757
|
+
for (let i = 0; i < n; i++) {
|
|
1758
|
+
const v = obs[i] ?? 0;
|
|
1759
|
+
chiSq += (v - expected) ** 2 / expected;
|
|
1760
|
+
}
|
|
1761
|
+
} else {
|
|
1762
|
+
const exp = toDenseArray1D(f_exp);
|
|
1763
|
+
let sumExp = 0;
|
|
1764
|
+
for (let i = 0; i < n; i++) {
|
|
1765
|
+
const v = exp[i] ?? 0;
|
|
1766
|
+
if (!Number.isFinite(v) || v <= 0) {
|
|
1767
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1768
|
+
"chisquare() expected frequencies must be finite and > 0",
|
|
1769
|
+
"f_exp",
|
|
1770
|
+
v
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
sumExp += v;
|
|
1774
|
+
}
|
|
1775
|
+
const rtol = Math.sqrt(Number.EPSILON);
|
|
1776
|
+
const denom = Math.max(Math.abs(sumObs), Math.abs(sumExp));
|
|
1777
|
+
if (Math.abs(sumObs - sumExp) > rtol * denom) {
|
|
1778
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1779
|
+
"chisquare() expected and observed frequencies must sum to the same value",
|
|
1780
|
+
"sum",
|
|
1781
|
+
{ f_obs: sumObs, f_exp: sumExp }
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
for (let i = 0; i < n; i++) {
|
|
1785
|
+
const vObs = obs[i] ?? 0;
|
|
1786
|
+
const vExp = exp[i] ?? 0;
|
|
1787
|
+
chiSq += (vObs - vExp) ** 2 / vExp;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
const df = n - 1;
|
|
1791
|
+
if (df < 1) {
|
|
1792
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1793
|
+
"chisquare() requires at least 2 categories (df must be >= 1)",
|
|
1794
|
+
"df",
|
|
1795
|
+
df
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
const pvalue = 1 - chiSquareCdf(chiSq, df);
|
|
1799
|
+
return { statistic: chiSq, pvalue };
|
|
1800
|
+
}
|
|
1801
|
+
function kstest(data, cdf) {
|
|
1802
|
+
const x = toDenseSortedArray1D(data);
|
|
1803
|
+
const n = x.length;
|
|
1804
|
+
if (n === 0) {
|
|
1805
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("kstest() requires at least one element", "n", n);
|
|
1806
|
+
}
|
|
1807
|
+
if (typeof cdf === "string" && cdf !== "norm") {
|
|
1808
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1809
|
+
`Unsupported distribution: '${cdf}'. Supported distributions: 'norm'`,
|
|
1810
|
+
"cdf",
|
|
1811
|
+
cdf
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
const F = typeof cdf === "string" ? (v) => normalCdf(v) : cdf;
|
|
1815
|
+
let d = 0;
|
|
1816
|
+
for (let i = 0; i < n; i++) {
|
|
1817
|
+
const xi = x[i] ?? 0;
|
|
1818
|
+
const fi = F(xi);
|
|
1819
|
+
const dPlus = (i + 1) / n - fi;
|
|
1820
|
+
const dMinus = fi - i / n;
|
|
1821
|
+
d = Math.max(d, dPlus, dMinus);
|
|
1822
|
+
}
|
|
1823
|
+
let p = 0;
|
|
1824
|
+
for (let k = 1; k < 200; k++) {
|
|
1825
|
+
const term = Math.exp(-2 * k * k * d * d * n);
|
|
1826
|
+
p += (k % 2 === 1 ? 1 : -1) * term;
|
|
1827
|
+
if (term < 1e-12) break;
|
|
1828
|
+
}
|
|
1829
|
+
p = Math.max(0, Math.min(1, 2 * p));
|
|
1830
|
+
return { statistic: d, pvalue: p };
|
|
1831
|
+
}
|
|
1832
|
+
function normaltest(a) {
|
|
1833
|
+
const x = toDenseSortedArray1D(a);
|
|
1834
|
+
const n = x.length;
|
|
1835
|
+
if (n < 8) {
|
|
1836
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("normaltest() requires at least 8 samples", "n", n);
|
|
1837
|
+
}
|
|
1838
|
+
const { mean: mean2, m2 } = meanAndM2(x);
|
|
1839
|
+
const m2n = m2 / n;
|
|
1840
|
+
const std2 = Math.sqrt(m2n);
|
|
1841
|
+
if (!Number.isFinite(std2) || std2 === 0) {
|
|
1842
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("normaltest() is undefined for constant input", "std", std2);
|
|
1843
|
+
}
|
|
1844
|
+
let m3 = 0;
|
|
1845
|
+
let m4 = 0;
|
|
1846
|
+
for (let i = 0; i < n; i++) {
|
|
1847
|
+
const d = (x[i] ?? 0) - mean2;
|
|
1848
|
+
m3 += d * d * d;
|
|
1849
|
+
m4 += d * d * d * d;
|
|
1850
|
+
}
|
|
1851
|
+
const skew = m3 / n / m2n ** 1.5;
|
|
1852
|
+
const kurt = m4 / n / (m2n * m2n);
|
|
1853
|
+
const y = skew * Math.sqrt((n + 1) * (n + 3) / (6 * (n - 2)));
|
|
1854
|
+
const beta2 = 3 * (n * n + 27 * n - 70) * (n + 1) * (n + 3) / ((n - 2) * (n + 5) * (n + 7) * (n + 9));
|
|
1855
|
+
const w2 = -1 + Math.sqrt(2 * (beta2 - 1));
|
|
1856
|
+
const delta = 1 / Math.sqrt(0.5 * Math.log(w2));
|
|
1857
|
+
const alpha = Math.sqrt(2 / (w2 - 1));
|
|
1858
|
+
const yScaled = y / alpha;
|
|
1859
|
+
const z1 = delta * Math.log(yScaled + Math.sqrt(yScaled * yScaled + 1));
|
|
1860
|
+
const e = 3 * (n - 1) / (n + 1);
|
|
1861
|
+
const varb2 = 24 * n * (n - 2) * (n - 3) / ((n + 1) * (n + 1) * (n + 3) * (n + 5));
|
|
1862
|
+
const xval = (kurt - e) / Math.sqrt(varb2);
|
|
1863
|
+
const sqrtbeta1 = 6 * (n * n - 5 * n + 2) / ((n + 7) * (n + 9)) * Math.sqrt(6 * (n + 3) * (n + 5) / (n * (n - 2) * (n - 3)));
|
|
1864
|
+
const aTerm = 6 + 8 / sqrtbeta1 * (2 / sqrtbeta1 + Math.sqrt(1 + 4 / (sqrtbeta1 * sqrtbeta1)));
|
|
1865
|
+
const term1 = 1 - 2 / (9 * aTerm);
|
|
1866
|
+
const denom = 1 + xval * Math.sqrt(2 / (aTerm - 4));
|
|
1867
|
+
const term2 = denom === 0 ? Number.NaN : Math.sign(denom) * ((1 - 2 / aTerm) / Math.abs(denom)) ** (1 / 3);
|
|
1868
|
+
const z2 = (term1 - term2) / Math.sqrt(2 / (9 * aTerm));
|
|
1869
|
+
const k2 = z1 * z1 + z2 * z2;
|
|
1870
|
+
const pvalue = 1 - chiSquareCdf(k2, 2);
|
|
1871
|
+
return { statistic: k2, pvalue };
|
|
1872
|
+
}
|
|
1873
|
+
function shapiro(x) {
|
|
1874
|
+
const sorted = toDenseSortedArray1D(x);
|
|
1875
|
+
return shapiroWilk(sorted);
|
|
1876
|
+
}
|
|
1877
|
+
function anderson(x) {
|
|
1878
|
+
const sorted = toDenseSortedArray1D(x);
|
|
1879
|
+
const n = sorted.length;
|
|
1880
|
+
if (n < 1) {
|
|
1881
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("anderson() requires at least one element", "n", n);
|
|
1882
|
+
}
|
|
1883
|
+
const { mean: mean2, m2 } = meanAndM2(sorted);
|
|
1884
|
+
const variance2 = n > 1 ? m2 / (n - 1) : NaN;
|
|
1885
|
+
let std2 = Math.sqrt(variance2);
|
|
1886
|
+
if (!Number.isFinite(std2) || std2 === 0) {
|
|
1887
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("anderson() is undefined for constant input", "std", std2);
|
|
1888
|
+
}
|
|
1889
|
+
if (n < 10) {
|
|
1890
|
+
const quantile2 = (q) => {
|
|
1891
|
+
if (n === 1) return sorted[0] ?? 0;
|
|
1892
|
+
const pos = (n - 1) * q;
|
|
1893
|
+
const lo = Math.floor(pos);
|
|
1894
|
+
const hi = Math.ceil(pos);
|
|
1895
|
+
const v0 = sorted[lo] ?? 0;
|
|
1896
|
+
const v1 = sorted[hi] ?? v0;
|
|
1897
|
+
return v0 + (pos - lo) * (v1 - v0);
|
|
1898
|
+
};
|
|
1899
|
+
const q1 = quantile2(0.25);
|
|
1900
|
+
const q3 = quantile2(0.75);
|
|
1901
|
+
const iqr = q3 - q1;
|
|
1902
|
+
const robust = iqr / 1.349;
|
|
1903
|
+
if (Number.isFinite(robust) && robust > 0) {
|
|
1904
|
+
std2 = robust;
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
let A2 = 0;
|
|
1908
|
+
for (let i = 0; i < n; i++) {
|
|
1909
|
+
const zi = ((sorted[i] ?? 0) - mean2) / std2;
|
|
1910
|
+
const zj = ((sorted[n - 1 - i] ?? 0) - mean2) / std2;
|
|
1911
|
+
const PhiI = Math.max(1e-300, Math.min(1 - 1e-16, normalCdf(zi)));
|
|
1912
|
+
const PhiJ = Math.max(1e-300, Math.min(1 - 1e-16, normalCdf(zj)));
|
|
1913
|
+
A2 += (2 * (i + 1) - 1) * (Math.log(PhiI) + Math.log(1 - PhiJ));
|
|
1914
|
+
}
|
|
1915
|
+
A2 = -n - A2 / n;
|
|
1916
|
+
const baseCritical = [0.576, 0.656, 0.787, 0.918, 1.092];
|
|
1917
|
+
const factor = 1 + 4 / n - 25 / (n * n);
|
|
1918
|
+
const critical_values = baseCritical.map((v) => Math.round(v / factor * 1e3) / 1e3);
|
|
1919
|
+
return {
|
|
1920
|
+
statistic: A2,
|
|
1921
|
+
critical_values,
|
|
1922
|
+
significance_level: [0.15, 0.1, 0.05, 0.025, 0.01]
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
function mannwhitneyu(x, y) {
|
|
1926
|
+
const nx = x.size;
|
|
1927
|
+
const ny = y.size;
|
|
1928
|
+
if (nx < 1 || ny < 1) {
|
|
1929
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("Both samples must be non-empty", "size", {
|
|
1930
|
+
x: nx,
|
|
1931
|
+
y: ny
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
const xVals = toDenseArray1D(x);
|
|
1935
|
+
const yVals = toDenseArray1D(y);
|
|
1936
|
+
const n = nx + ny;
|
|
1937
|
+
const combined = new Float64Array(n);
|
|
1938
|
+
combined.set(xVals, 0);
|
|
1939
|
+
combined.set(yVals, nx);
|
|
1940
|
+
const { ranks, tieSum } = rankData(combined);
|
|
1941
|
+
let R1 = 0;
|
|
1942
|
+
for (let i = 0; i < nx; i++) {
|
|
1943
|
+
R1 += ranks[i] ?? 0;
|
|
1944
|
+
}
|
|
1945
|
+
const U1 = R1 - nx * (nx + 1) / 2;
|
|
1946
|
+
const U2 = nx * ny - U1;
|
|
1947
|
+
const U = Math.min(U1, U2);
|
|
1948
|
+
const meanU = nx * ny / 2;
|
|
1949
|
+
const tieAdj = n > 1 ? tieSum / (n * (n - 1)) : 0;
|
|
1950
|
+
const varU = nx * ny * (n + 1 - tieAdj) / 12;
|
|
1951
|
+
if (varU <= 0) {
|
|
1952
|
+
return { statistic: U, pvalue: NaN };
|
|
1953
|
+
}
|
|
1954
|
+
const stdU = Math.sqrt(varU);
|
|
1955
|
+
const useContinuity = nx + ny > 20;
|
|
1956
|
+
const continuity = useContinuity ? U < meanU ? 0.5 : U > meanU ? -0.5 : 0 : 0;
|
|
1957
|
+
const z = (U - meanU + continuity) / stdU;
|
|
1958
|
+
const pvalue = 2 * (1 - normalCdf(Math.abs(z)));
|
|
1959
|
+
return { statistic: U, pvalue };
|
|
1960
|
+
}
|
|
1961
|
+
function wilcoxon(x, y) {
|
|
1962
|
+
const n = x.size;
|
|
1963
|
+
const diffs = [];
|
|
1964
|
+
if (y) {
|
|
1965
|
+
if (x.size !== y.size) {
|
|
1966
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("Paired samples must have equal length", "size", {
|
|
1967
|
+
x: x.size,
|
|
1968
|
+
y: y.size
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
const xd = toDenseArray1D(x);
|
|
1972
|
+
const yd = toDenseArray1D(y);
|
|
1973
|
+
for (let i = 0; i < n; i++) {
|
|
1974
|
+
const diff = (xd[i] ?? 0) - (yd[i] ?? 0);
|
|
1975
|
+
if (diff !== 0) diffs.push(diff);
|
|
1976
|
+
}
|
|
1977
|
+
} else {
|
|
1978
|
+
const xd = toDenseArray1D(x);
|
|
1979
|
+
for (let i = 0; i < n; i++) {
|
|
1980
|
+
const val = xd[i] ?? 0;
|
|
1981
|
+
if (val !== 0) diffs.push(val);
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
if (diffs.length === 0) {
|
|
1985
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
1986
|
+
"wilcoxon() is undefined when all differences are zero",
|
|
1987
|
+
"diffs",
|
|
1988
|
+
diffs.length
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1991
|
+
const absDiffs = new Float64Array(diffs.length);
|
|
1992
|
+
for (let i = 0; i < diffs.length; i++) {
|
|
1993
|
+
absDiffs[i] = Math.abs(diffs[i] ?? 0);
|
|
1994
|
+
}
|
|
1995
|
+
const { ranks, tieSum } = rankData(absDiffs);
|
|
1996
|
+
let Wplus = 0;
|
|
1997
|
+
for (let i = 0; i < diffs.length; i++) {
|
|
1998
|
+
if ((diffs[i] ?? 0) > 0) {
|
|
1999
|
+
Wplus += ranks[i] ?? 0;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
const nEff = diffs.length;
|
|
2003
|
+
const meanW = nEff * (nEff + 1) / 4;
|
|
2004
|
+
const varW = nEff * (nEff + 1) * (2 * nEff + 1) / 24 - tieSum / 48;
|
|
2005
|
+
if (varW <= 0) {
|
|
2006
|
+
return { statistic: Wplus, pvalue: NaN };
|
|
2007
|
+
}
|
|
2008
|
+
const stdW = Math.sqrt(varW);
|
|
2009
|
+
const useContinuity = nEff > 20;
|
|
2010
|
+
const continuity = useContinuity ? Wplus < meanW ? 0.5 : Wplus > meanW ? -0.5 : 0 : 0;
|
|
2011
|
+
const z = (Wplus - meanW + continuity) / stdW;
|
|
2012
|
+
const pvalue = 2 * (1 - normalCdf(Math.abs(z)));
|
|
2013
|
+
return { statistic: Wplus, pvalue };
|
|
2014
|
+
}
|
|
2015
|
+
function kruskal(...samples) {
|
|
2016
|
+
const k = samples.length;
|
|
2017
|
+
if (k < 2) {
|
|
2018
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("kruskal() requires at least 2 groups", "k", k);
|
|
2019
|
+
}
|
|
2020
|
+
let N = 0;
|
|
2021
|
+
const sizes = new Array(k);
|
|
2022
|
+
const validatedSamples = new Array(k);
|
|
2023
|
+
for (let g = 0; g < k; g++) {
|
|
2024
|
+
const sample = samples[g];
|
|
2025
|
+
if (!sample || sample.size < 1) {
|
|
2026
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("kruskal() requires non-empty samples", "size", {
|
|
2027
|
+
group: g,
|
|
2028
|
+
size: sample?.size ?? 0
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
validatedSamples[g] = sample;
|
|
2032
|
+
sizes[g] = sample.size;
|
|
2033
|
+
N += sample.size;
|
|
2034
|
+
}
|
|
2035
|
+
const combined = new Float64Array(N);
|
|
2036
|
+
const groupIndex = new Int32Array(N);
|
|
2037
|
+
let idx = 0;
|
|
2038
|
+
for (let g = 0; g < k; g++) {
|
|
2039
|
+
const sample = validatedSamples[g];
|
|
2040
|
+
if (!sample) {
|
|
2041
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("kruskal() requires non-empty samples", "sample", g);
|
|
2042
|
+
}
|
|
2043
|
+
const vals = toDenseArray1D(sample);
|
|
2044
|
+
for (let i = 0; i < vals.length; i++) {
|
|
2045
|
+
combined[idx] = vals[i] ?? 0;
|
|
2046
|
+
groupIndex[idx] = g;
|
|
2047
|
+
idx++;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
const { ranks, tieSum } = rankData(combined);
|
|
2051
|
+
const rankSums = new Float64Array(k);
|
|
2052
|
+
for (let i = 0; i < N; i++) {
|
|
2053
|
+
const group = groupIndex[i] ?? 0;
|
|
2054
|
+
const rank = ranks[i] ?? 0;
|
|
2055
|
+
rankSums[group] = (rankSums[group] ?? 0) + rank;
|
|
2056
|
+
}
|
|
2057
|
+
let H = 0;
|
|
2058
|
+
for (let g = 0; g < k; g++) {
|
|
2059
|
+
const rs = rankSums[g] ?? 0;
|
|
2060
|
+
const sz = sizes[g] ?? 1;
|
|
2061
|
+
H += rs * rs / sz;
|
|
2062
|
+
}
|
|
2063
|
+
H = 12 / (N * (N + 1)) * H - 3 * (N + 1);
|
|
2064
|
+
const tieCorrection = N > 1 ? 1 - tieSum / (N * N * N - N) : 1;
|
|
2065
|
+
if (tieCorrection <= 0) {
|
|
2066
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2067
|
+
"kruskal() is undefined when all numbers are identical",
|
|
2068
|
+
"tieCorrection",
|
|
2069
|
+
tieCorrection
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2072
|
+
H /= tieCorrection;
|
|
2073
|
+
const df = k - 1;
|
|
2074
|
+
const pvalue = 1 - chiSquareCdf(H, df);
|
|
2075
|
+
return { statistic: H, pvalue };
|
|
2076
|
+
}
|
|
2077
|
+
function friedmanchisquare(...samples) {
|
|
2078
|
+
const k = samples.length;
|
|
2079
|
+
if (k < 3) {
|
|
2080
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2081
|
+
"friedmanchisquare() requires at least 3 related samples",
|
|
2082
|
+
"k",
|
|
2083
|
+
k
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
2086
|
+
const n = samples[0]?.size ?? 0;
|
|
2087
|
+
if (n < 1) {
|
|
2088
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2089
|
+
"friedmanchisquare() requires all samples to be non-empty",
|
|
2090
|
+
"n",
|
|
2091
|
+
n
|
|
2092
|
+
);
|
|
2093
|
+
}
|
|
2094
|
+
for (let i = 1; i < k; i++) {
|
|
2095
|
+
const sample = samples[i];
|
|
2096
|
+
if (sample && sample.size !== n) {
|
|
2097
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2098
|
+
"All samples must have the same length for Friedman test",
|
|
2099
|
+
"size",
|
|
2100
|
+
{ expected: n, got: sample.size, sampleIndex: i }
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
const denseSamples = samples.map(
|
|
2105
|
+
(sample) => sample ? toDenseArray1D(sample) : new Float64Array(0)
|
|
2106
|
+
);
|
|
2107
|
+
const rankSums = new Float64Array(k);
|
|
2108
|
+
let tieSum = 0;
|
|
2109
|
+
for (let i = 0; i < n; i++) {
|
|
2110
|
+
const block = new Float64Array(k);
|
|
2111
|
+
for (let j = 0; j < k; j++) {
|
|
2112
|
+
const arr = denseSamples[j];
|
|
2113
|
+
block[j] = arr?.[i] ?? 0;
|
|
2114
|
+
}
|
|
2115
|
+
const ranked = rankData(block);
|
|
2116
|
+
tieSum += ranked.tieSum;
|
|
2117
|
+
for (let j = 0; j < k; j++) {
|
|
2118
|
+
const rank = ranked.ranks[j] ?? 0;
|
|
2119
|
+
rankSums[j] = (rankSums[j] ?? 0) + rank;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
let chiSq = 0;
|
|
2123
|
+
for (let j = 0; j < k; j++) {
|
|
2124
|
+
const rs = rankSums[j] ?? 0;
|
|
2125
|
+
chiSq += rs * rs;
|
|
2126
|
+
}
|
|
2127
|
+
chiSq = 12 / (n * k * (k + 1)) * chiSq - 3 * n * (k + 1);
|
|
2128
|
+
const tieCorrection = n > 0 ? 1 - tieSum / (n * k * (k * k - 1)) : 1;
|
|
2129
|
+
if (tieCorrection <= 0) {
|
|
2130
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2131
|
+
"friedmanchisquare() is undefined when all numbers are identical within blocks",
|
|
2132
|
+
"tieCorrection",
|
|
2133
|
+
tieCorrection
|
|
2134
|
+
);
|
|
2135
|
+
}
|
|
2136
|
+
chiSq /= tieCorrection;
|
|
2137
|
+
const df = k - 1;
|
|
2138
|
+
const pvalue = 1 - chiSquareCdf(chiSq, df);
|
|
2139
|
+
return { statistic: chiSq, pvalue };
|
|
2140
|
+
}
|
|
2141
|
+
function levene(center, ...samples) {
|
|
2142
|
+
const k = samples.length;
|
|
2143
|
+
if (k < 2) {
|
|
2144
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("levene() requires at least 2 groups", "k", k);
|
|
2145
|
+
}
|
|
2146
|
+
const groups = [];
|
|
2147
|
+
const centers = [];
|
|
2148
|
+
for (let g = 0; g < k; g++) {
|
|
2149
|
+
const sample = samples[g];
|
|
2150
|
+
if (!sample || sample.size === 0) {
|
|
2151
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("levene() requires all groups to be non-empty", "groupSize", {
|
|
2152
|
+
group: g,
|
|
2153
|
+
size: sample?.size ?? 0
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
const arr = toDenseSortedArray1D(sample);
|
|
2157
|
+
if (arr.length < 2) {
|
|
2158
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2159
|
+
"levene() requires at least 2 samples per group",
|
|
2160
|
+
"groupSize",
|
|
2161
|
+
arr.length
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
groups.push(arr);
|
|
2165
|
+
if (center === "mean") {
|
|
2166
|
+
let sum = 0;
|
|
2167
|
+
for (let i = 0; i < arr.length; i++) sum += arr[i] ?? 0;
|
|
2168
|
+
centers.push(sum / arr.length);
|
|
2169
|
+
} else if (center === "median") {
|
|
2170
|
+
const mid = Math.floor(arr.length / 2);
|
|
2171
|
+
if (arr.length % 2 === 0) {
|
|
2172
|
+
centers.push(((arr[mid - 1] ?? 0) + (arr[mid] ?? 0)) / 2);
|
|
2173
|
+
} else {
|
|
2174
|
+
centers.push(arr[mid] ?? 0);
|
|
2175
|
+
}
|
|
2176
|
+
} else {
|
|
2177
|
+
const trimCount = Math.floor(arr.length * 0.1);
|
|
2178
|
+
let sum = 0;
|
|
2179
|
+
const n = arr.length - 2 * trimCount;
|
|
2180
|
+
for (let i = trimCount; i < arr.length - trimCount; i++) {
|
|
2181
|
+
sum += arr[i] ?? 0;
|
|
2182
|
+
}
|
|
2183
|
+
centers.push(sum / n);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
const Z = [];
|
|
2187
|
+
const groupMeansZ = [];
|
|
2188
|
+
let N = 0;
|
|
2189
|
+
let grandSumZ = 0;
|
|
2190
|
+
for (let g = 0; g < groups.length; g++) {
|
|
2191
|
+
const arr = groups[g];
|
|
2192
|
+
if (!arr) continue;
|
|
2193
|
+
const c = centers[g] ?? 0;
|
|
2194
|
+
const zArr = new Float64Array(arr.length);
|
|
2195
|
+
let sumZ = 0;
|
|
2196
|
+
for (let i = 0; i < arr.length; i++) {
|
|
2197
|
+
const absVal = Math.abs((arr[i] ?? 0) - c);
|
|
2198
|
+
zArr[i] = absVal;
|
|
2199
|
+
sumZ += absVal;
|
|
2200
|
+
}
|
|
2201
|
+
Z.push(zArr);
|
|
2202
|
+
groupMeansZ.push(sumZ / arr.length);
|
|
2203
|
+
N += arr.length;
|
|
2204
|
+
grandSumZ += sumZ;
|
|
2205
|
+
}
|
|
2206
|
+
const grandMeanZ = grandSumZ / N;
|
|
2207
|
+
let SSB = 0;
|
|
2208
|
+
let SSW = 0;
|
|
2209
|
+
for (let g = 0; g < Z.length; g++) {
|
|
2210
|
+
const zArr = Z[g];
|
|
2211
|
+
if (!zArr) continue;
|
|
2212
|
+
const n = zArr.length;
|
|
2213
|
+
SSB += n * ((groupMeansZ[g] ?? 0) - grandMeanZ) ** 2;
|
|
2214
|
+
for (let i = 0; i < n; i++) {
|
|
2215
|
+
SSW += ((zArr[i] ?? 0) - (groupMeansZ[g] ?? 0)) ** 2;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
const dfB = k - 1;
|
|
2219
|
+
const dfW = N - k;
|
|
2220
|
+
if (dfW <= 0) {
|
|
2221
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2222
|
+
"levene() requires more total observations than groups",
|
|
2223
|
+
"dfW",
|
|
2224
|
+
dfW
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2227
|
+
if (SSW === 0) {
|
|
2228
|
+
return { statistic: Infinity, pvalue: 0 };
|
|
2229
|
+
}
|
|
2230
|
+
const W = SSB / dfB / (SSW / dfW);
|
|
2231
|
+
const pvalue = 1 - fCdf(W, dfB, dfW);
|
|
2232
|
+
return { statistic: W, pvalue };
|
|
2233
|
+
}
|
|
2234
|
+
function bartlett(...samples) {
|
|
2235
|
+
const k = samples.length;
|
|
2236
|
+
if (k < 2) {
|
|
2237
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("bartlett() requires at least 2 groups", "k", k);
|
|
2238
|
+
}
|
|
2239
|
+
const variances = [];
|
|
2240
|
+
const sizes = [];
|
|
2241
|
+
let N = 0;
|
|
2242
|
+
for (let g = 0; g < k; g++) {
|
|
2243
|
+
const sample = samples[g];
|
|
2244
|
+
if (!sample || sample.size === 0) {
|
|
2245
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2246
|
+
"bartlett() requires all groups to be non-empty",
|
|
2247
|
+
"groupSize",
|
|
2248
|
+
{ group: g, size: sample?.size ?? 0 }
|
|
2249
|
+
);
|
|
2250
|
+
}
|
|
2251
|
+
const arr = toDenseSortedArray1D(sample);
|
|
2252
|
+
const n = arr.length;
|
|
2253
|
+
if (n < 2) {
|
|
2254
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2255
|
+
"bartlett() requires at least 2 samples per group",
|
|
2256
|
+
"groupSize",
|
|
2257
|
+
n
|
|
2258
|
+
);
|
|
2259
|
+
}
|
|
2260
|
+
let mean2 = 0;
|
|
2261
|
+
for (let i = 0; i < n; i++) mean2 += arr[i] ?? 0;
|
|
2262
|
+
mean2 /= n;
|
|
2263
|
+
let ss = 0;
|
|
2264
|
+
for (let i = 0; i < n; i++) {
|
|
2265
|
+
const d = (arr[i] ?? 0) - mean2;
|
|
2266
|
+
ss += d * d;
|
|
2267
|
+
}
|
|
2268
|
+
const variance2 = ss / (n - 1);
|
|
2269
|
+
variances.push(variance2);
|
|
2270
|
+
sizes.push(n);
|
|
2271
|
+
N += n;
|
|
2272
|
+
}
|
|
2273
|
+
for (let g = 0; g < k; g++) {
|
|
2274
|
+
if ((variances[g] ?? 0) === 0) {
|
|
2275
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2276
|
+
"bartlett() is undefined when a group has zero variance",
|
|
2277
|
+
"variance",
|
|
2278
|
+
variances[g]
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
let pooledNumerator = 0;
|
|
2283
|
+
for (let g = 0; g < k; g++) {
|
|
2284
|
+
pooledNumerator += ((sizes[g] ?? 1) - 1) * (variances[g] ?? 1);
|
|
2285
|
+
}
|
|
2286
|
+
const pooledVariance = pooledNumerator / (N - k);
|
|
2287
|
+
let sumLogVar = 0;
|
|
2288
|
+
for (let g = 0; g < k; g++) {
|
|
2289
|
+
sumLogVar += ((sizes[g] ?? 1) - 1) * Math.log(variances[g] ?? 1);
|
|
2290
|
+
}
|
|
2291
|
+
const T = (N - k) * Math.log(pooledVariance) - sumLogVar;
|
|
2292
|
+
let sumInvDf = 0;
|
|
2293
|
+
for (let g = 0; g < k; g++) {
|
|
2294
|
+
sumInvDf += 1 / ((sizes[g] ?? 1) - 1);
|
|
2295
|
+
}
|
|
2296
|
+
const C = 1 + 1 / (3 * (k - 1)) * (sumInvDf - 1 / (N - k));
|
|
2297
|
+
const chiSq = T / C;
|
|
2298
|
+
const df = k - 1;
|
|
2299
|
+
const pvalue = 1 - chiSquareCdf(chiSq, df);
|
|
2300
|
+
return { statistic: chiSq, pvalue };
|
|
2301
|
+
}
|
|
2302
|
+
function f_oneway(...samples) {
|
|
2303
|
+
const k = samples.length;
|
|
2304
|
+
if (k < 2) {
|
|
2305
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError("f_oneway() requires at least 2 groups", "groups", k);
|
|
2306
|
+
}
|
|
2307
|
+
for (let g = 0; g < k; g++) {
|
|
2308
|
+
const sample = samples[g];
|
|
2309
|
+
if (!sample || sample.size === 0) {
|
|
2310
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2311
|
+
"f_oneway() requires all groups to be non-empty",
|
|
2312
|
+
"groupSize",
|
|
2313
|
+
{ group: g, size: sample?.size ?? 0 }
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
let N = 0;
|
|
2318
|
+
const means = [];
|
|
2319
|
+
const sizes = [];
|
|
2320
|
+
const groups = [];
|
|
2321
|
+
for (let g = 0; g < k; g++) {
|
|
2322
|
+
const sample = samples[g];
|
|
2323
|
+
if (!sample) {
|
|
2324
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2325
|
+
"f_oneway() requires all groups to be non-empty",
|
|
2326
|
+
"groupSize",
|
|
2327
|
+
{ group: g, size: 0 }
|
|
2328
|
+
);
|
|
2329
|
+
}
|
|
2330
|
+
const arr = toDenseArray1D(sample);
|
|
2331
|
+
const n = arr.length;
|
|
2332
|
+
groups.push(arr);
|
|
2333
|
+
sizes.push(n);
|
|
2334
|
+
N += n;
|
|
2335
|
+
let sum = 0;
|
|
2336
|
+
for (let i = 0; i < n; i++) {
|
|
2337
|
+
sum += arr[i] ?? 0;
|
|
2338
|
+
}
|
|
2339
|
+
means.push(sum / n);
|
|
2340
|
+
}
|
|
2341
|
+
let grandSum = 0;
|
|
2342
|
+
for (let g = 0; g < k; g++) {
|
|
2343
|
+
grandSum += (means[g] ?? 0) * (sizes[g] ?? 0);
|
|
2344
|
+
}
|
|
2345
|
+
const grandMean = grandSum / N;
|
|
2346
|
+
let SSB = 0;
|
|
2347
|
+
let SSW = 0;
|
|
2348
|
+
for (let g = 0; g < groups.length; g++) {
|
|
2349
|
+
const arr = groups[g];
|
|
2350
|
+
if (!arr) continue;
|
|
2351
|
+
const n = arr.length;
|
|
2352
|
+
SSB += n * ((means[g] ?? 0) - grandMean) ** 2;
|
|
2353
|
+
for (let i = 0; i < n; i++) {
|
|
2354
|
+
SSW += ((arr[i] ?? 0) - (means[g] ?? 0)) ** 2;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
const dfB = k - 1;
|
|
2358
|
+
const dfW = N - k;
|
|
2359
|
+
if (dfW <= 0) {
|
|
2360
|
+
throw new chunkJSCDE774_cjs.InvalidParameterError(
|
|
2361
|
+
"f_oneway() requires at least one group with more than one sample",
|
|
2362
|
+
"dfW",
|
|
2363
|
+
dfW
|
|
2364
|
+
);
|
|
2365
|
+
}
|
|
2366
|
+
const MSB = SSB / dfB;
|
|
2367
|
+
const MSW = SSW / dfW;
|
|
2368
|
+
if (MSW === 0) {
|
|
2369
|
+
const F2 = MSB === 0 ? NaN : Infinity;
|
|
2370
|
+
return { statistic: F2, pvalue: MSB === 0 ? NaN : 0 };
|
|
2371
|
+
}
|
|
2372
|
+
const F = MSB / MSW;
|
|
2373
|
+
const pvalue = 1 - fCdf(F, dfB, dfW);
|
|
2374
|
+
return { statistic: F, pvalue };
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
exports.anderson = anderson;
|
|
2378
|
+
exports.bartlett = bartlett;
|
|
2379
|
+
exports.chisquare = chisquare;
|
|
2380
|
+
exports.corrcoef = corrcoef;
|
|
2381
|
+
exports.cov = cov;
|
|
2382
|
+
exports.f_oneway = f_oneway;
|
|
2383
|
+
exports.friedmanchisquare = friedmanchisquare;
|
|
2384
|
+
exports.geometricMean = geometricMean;
|
|
2385
|
+
exports.harmonicMean = harmonicMean;
|
|
2386
|
+
exports.kendalltau = kendalltau;
|
|
2387
|
+
exports.kruskal = kruskal;
|
|
2388
|
+
exports.kstest = kstest;
|
|
2389
|
+
exports.kurtosis = kurtosis;
|
|
2390
|
+
exports.levene = levene;
|
|
2391
|
+
exports.mannwhitneyu = mannwhitneyu;
|
|
2392
|
+
exports.mean = mean;
|
|
2393
|
+
exports.median = median;
|
|
2394
|
+
exports.mode = mode;
|
|
2395
|
+
exports.moment = moment;
|
|
2396
|
+
exports.normaltest = normaltest;
|
|
2397
|
+
exports.pearsonr = pearsonr;
|
|
2398
|
+
exports.percentile = percentile;
|
|
2399
|
+
exports.quantile = quantile;
|
|
2400
|
+
exports.shapiro = shapiro;
|
|
2401
|
+
exports.skewness = skewness;
|
|
2402
|
+
exports.spearmanr = spearmanr;
|
|
2403
|
+
exports.stats_exports = stats_exports;
|
|
2404
|
+
exports.std = std;
|
|
2405
|
+
exports.trimMean = trimMean;
|
|
2406
|
+
exports.ttest_1samp = ttest_1samp;
|
|
2407
|
+
exports.ttest_ind = ttest_ind;
|
|
2408
|
+
exports.ttest_rel = ttest_rel;
|
|
2409
|
+
exports.variance = variance;
|
|
2410
|
+
exports.wilcoxon = wilcoxon;
|
|
2411
|
+
//# sourceMappingURL=chunk-LWECRCW2.cjs.map
|
|
2412
|
+
//# sourceMappingURL=chunk-LWECRCW2.cjs.map
|