/** * Statistical Hypothesis Tests * * Provides common statistical tests returning test statistics and p-values: * - studentTTest: one-sample and two-sample t-test * - chiSquareTest: chi-square goodness of fit * - anova: one-way ANOVA * - kolmogorovSmirnovTest: Kolmogorov-Smirnov test * - mannWhitneyTest: Mann-Whitney U test * - shapiroWilkTest: Shapiro-Wilk normality test * - principalComponentAnalysis: PCA dimensionality reduction * * Worker-dispatch policy (Slice 3.10): * - chiSquareTest (1D): element-wise reduction via applyKernel2 + sum above threshold. * - kolmogorovSmirnovTest: sort on main thread; post-sort CDF-compare loop via * applyKernel (serialised normal-CDF) above threshold when no custom CDF is given. * - mannWhitneyTest: sort on main thread; rank-sum via parallel dot above threshold. * - shapiroWilkTest: sort on main thread; W-numerator dot-product via parallel dot * above threshold. * * Bootstrap fan-out (Slice 5.11): * - All four two-sample / goodness-of-fit tests accept `{ bootstrap: N }`. * - When set, N permuted resamples are drawn from the combined data pool and the * statistic is recomputed for each. The N tasks are fanned out via * `Promise.all` so the JS event-loop can interleave them (embarrassingly * parallel at the microtask level; each individual run uses the existing * Slice-3.10 worker dispatch if the resample is large enough). * - `bootstrapSeed` enables fully deterministic resampling via Mulberry32 PRNG. * * @packageDocumentation */ /** 64-bit float */ type f64 = number; /** * Result of `studentTTest` and `studentTTestPaired`: the t statistic, the p-value, and the * degrees of freedom. */ export interface TTestResult { statistic: f64; pValue: f64; degreesOfFreedom: f64; } /** * Result of `chiSquareTest` without bootstrap: the chi-squared statistic, the p-value, * and the degrees of freedom. */ export interface ChiSquareResult { statistic: f64; pValue: f64; degreesOfFreedom: f64; } /** * Result of `anova`: the F statistic, the p-value, and the between-group and within-group * degrees of freedom. */ export interface AnovaResult { fStatistic: f64; pValue: f64; dfBetween: f64; dfWithin: f64; } /** Result of a Kolmogorov-Smirnov test without bootstrap: the D statistic and the p-value. */ export interface KSTestResult { statistic: f64; pValue: f64; } /** Result of `mannWhitneyTest` without bootstrap: the U statistic and the p-value. */ export interface MannWhitneyResult { uStatistic: f64; pValue: f64; } /** Result of `shapiroWilkTest` without bootstrap: the W statistic and the p-value. */ export interface ShapiroWilkResult { statistic: f64; pValue: f64; } /** * Result of `principalComponentAnalysis`. * * `components` holds the principal directions, `explained` holds the fraction of the total * variance for each component, and `scores` holds the centered data projected onto the * components. */ export interface PCAResult { components: f64[][]; explained: f64[]; scores: f64[][]; } /** * Options for bootstrap resampling. When `bootstrap` is set, the test is run * on `bootstrap` independent permutations of the combined sample data, and the * results are aggregated into a `*BootstrapResult` object. * * @example * const r = await kolmogorovSmirnovTest(s1, s2, { bootstrap: 200, bootstrapSeed: 42 }); * // r.pValueEmpirical — fraction of permuted statistics ≥ base statistic */ export interface BootstrapOptions { /** * Number of permutation-resampled test runs to execute. * `0` or `undefined` = fall back to the ordinary (non-bootstrap) result. */ bootstrap?: number; /** * Integer seed for the Mulberry32 PRNG so that permutations are * deterministic across runs. When omitted Math.random() is used. */ bootstrapSeed?: number; } /** Result of `kolmogorovSmirnovTest` when the `bootstrap` option is set. */ export interface KSBootstrapResult { /** D statistic from the original (un-permuted) samples. */ statistic: f64; /** Fraction of permuted statistics ≥ original statistic (two-tailed). */ pValueEmpirical: f64; /** Raw permuted D statistics. */ bootstrapStatistics: Float64Array; bootstrapMean: f64; bootstrapStd: f64; } /** Result of `mannWhitneyTest` when the `bootstrap` option is set. */ export interface MWBootstrapResult { /** U statistic from the original (un-permuted) samples. */ uStatistic: f64; /** Fraction of permuted U statistics ≥ original U statistic. */ pValueEmpirical: f64; /** Raw permuted U statistics. */ bootstrapStatistics: Float64Array; bootstrapMean: f64; bootstrapStd: f64; } /** Result of `shapiroWilkTest` when the `bootstrap` option is set. */ export interface SWBootstrapResult { /** W statistic from the original (un-permuted) samples. */ statistic: f64; /** * Fraction of permuted W statistics ≤ original W statistic. * (Small W indicates non-normality, so we count ≤.) */ pValueEmpirical: f64; /** Raw permuted W statistics. */ bootstrapStatistics: Float64Array; bootstrapMean: f64; bootstrapStd: f64; } /** Result of `chiSquareTest` when the `bootstrap` option is set. */ export interface ChiSquareBootstrapResult { /** chi² statistic from the original (un-permuted) samples. */ statistic: f64; /** Fraction of permuted statistics ≥ original statistic. */ pValueEmpirical: f64; /** Raw permuted chi² statistics. */ bootstrapStatistics: Float64Array; bootstrapMean: f64; bootstrapStd: f64; } /** * Student's t-test. * * One-sample: test if sample mean differs from 0 (or provide second argument as null). * Two-sample: Welch's t-test (unequal variances) comparing two independent samples. * * @param sample1 - First sample * @param sample2 - Second sample (omit for one-sample test) * @returns Test result with statistic, pValue, degreesOfFreedom * * @example * studentTTest([1, 2, 3, 4, 5]) // one-sample test * studentTTest([1, 2, 3], [4, 5, 6]) // two-sample test */ export declare function studentTTest(sample1: f64[], sample2?: f64[]): TTestResult; /** * Chi-square goodness-of-fit test (1D) or independence test (2D contingency table). * * 1D form: tests whether observed frequencies match expected frequencies. * chi2 = sum((O_i - E_i)^2 / E_i), df = length - 1. * * 2D form: when called with a single 2D `observed` array (rows x cols), * tests independence of two categorical variables. Expected cell counts * are auto-computed from row totals * col totals / grand total. * chi2 = sum_{i,j} ((O_ij - E_ij)^2 / E_ij), df = (rows-1) * (cols-1). * * Worker dispatch (Slice 3.10): For the 1D form with ≥ 4096 categories the * element-wise reduction `(o-e)²/e` is computed via `applyKernel2` + `sum` * on the worker pool. The 2D form stays on the main thread (reduction over a * 2D grid — marshal cost dominates). * * Bootstrap (Slice 5.11): When `opts.bootstrap > 0`, the observed counts are * resampled with replacement from a multinomial distribution (preserving the * total count), the statistic is re-computed for each resample, and the * empirical p-value is the fraction of resampled statistics ≥ the base. * * Complementary to (NOT a duplicate of) `chi2Contingency` * (`stats/inference-extra.js`): this function's 2D form is a plain * independence test, while `chi2Contingency` is the * `scipy.stats.chi2_contingency`-parity contingency test, adding the Yates * continuity correction (2x2 tables), an expected-frequency table, and * Cramér's V effect size. * * @param observed - 1D observed counts, OR 2D contingency table (rows x cols) * @param expected - 1D expected counts (required for 1D form; omit for 2D) * @param opts - Optional bootstrap settings * @returns Chi-square test result (or bootstrap result when `opts.bootstrap > 0`) * * @example * chiSquareTest([10, 20, 30], [20, 20, 20]) // 1D goodness-of-fit * chiSquareTest([[10, 20], [30, 40]]) // 2D independence test * chiSquareTest([10, 20, 30], [20, 20, 20], { bootstrap: 500 }) // bootstrap */ export declare function chiSquareTest(observed: f64[] | f64[][], expected?: f64[], opts?: BootstrapOptions): Promise; /** * One-way ANOVA (Analysis of Variance). * * Tests whether the means of multiple groups are equal. * * @param groups - Array of sample arrays (at least 2 groups) * @returns ANOVA result with F-statistic and p-value * * @example * anova([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) */ export declare function anova(groups: f64[][]): AnovaResult; /** * Kolmogorov-Smirnov test for goodness of fit. * * One-sample test against the standard normal distribution (default), * or provide a custom CDF function. * * Worker dispatch (Slice 3.10): When no custom CDF is supplied and * `sample.length >= 4096`, the sort stays on the main thread but the * per-element normal-CDF evaluation is dispatched via `applyKernel`. * Max-reduction of |D+| and |D-| is done on the main thread from the * returned CDF values (O(n) but cheap vs. O(n log n) sort). * When a custom CDF closure is given, the parallel path is skipped * (closures cannot be serialised into worker threads). * * Bootstrap (Slice 5.11): When `opts.bootstrap > 0`, the sample is resampled * with replacement (parametric bootstrap from the empirical distribution), * and the D statistic is recomputed against the same CDF for each resample. * Empirical p-value = fraction of bootstrap D values ≥ base D. * * @param sample - Array of observations * @param cdfFn - CDF function to test against (default: standard normal) * @param opts - Optional bootstrap settings * @returns K-S test result * * @example * kolmogorovSmirnovTest([0.1, 0.5, 0.9], (x) => x) // test against uniform(0,1) * kolmogorovSmirnovTest(data, undefined, { bootstrap: 200, bootstrapSeed: 1 }) */ export declare function kolmogorovSmirnovTest(sample: f64[], cdfFn?: (x: f64) => f64, opts?: BootstrapOptions): Promise; /** * Mann-Whitney U test (Wilcoxon rank-sum test). * * Non-parametric test for whether two independent samples are drawn * from the same distribution. * * Worker dispatch (Slice 3.10): When the combined sample has ≥ 4096 elements, * the sort stays on the main thread but the rank-sum for group 1 is computed * via a parallel dot-product `dot(ranks, groupIndicator)` on the pool. * * @param sample1 - First sample * @param sample2 - Second sample * @param opts - Optional bootstrap settings * @returns Mann-Whitney test result * * @example * mannWhitneyTest([1, 2, 3], [4, 5, 6]) * mannWhitneyTest(s1, s2, { bootstrap: 200, bootstrapSeed: 7 }) */ export declare function mannWhitneyTest(sample1: f64[], sample2: f64[], opts?: BootstrapOptions): Promise; /** * Shapiro-Wilk test for normality. * * Tests the null hypothesis that the data is normally distributed. * Implementation uses the simplified algorithm for sample sizes up to 5000. * * Worker dispatch (Slice 3.10): When `sample.length >= 4096`, the sort stays * on the main thread but the W-statistic numerator dot-product * `dot(coefficients, sorted_values)` is computed via the pool. * * @param sample - Array of observations (3 to 5000 elements) * @param opts - Optional bootstrap settings * @returns Shapiro-Wilk test result * * @example * shapiroWilkTest([1, 2, 3, 4, 5]) * shapiroWilkTest(data, { bootstrap: 100, bootstrapSeed: 42 }) */ export declare function shapiroWilkTest(sample: f64[], opts?: BootstrapOptions): Promise; /** * Principal Component Analysis (PCA). * * Reduces dimensionality of data by finding the directions of maximum variance. * * @param data - 2D array where each row is an observation, each column a variable * @param k - Number of principal components to keep (default: all) * @returns PCA result with components, explained variance ratios, and scores * * @example * const result = principalComponentAnalysis([[1, 2], [3, 4], [5, 6]], 1); * result.components // [[0.707, 0.707]] * result.explained // [1.0] */ export declare function principalComponentAnalysis(data: f64[][], k?: number): PCAResult; /** Options for {@link kolmogorovSmirnov2Test}. */ export interface KS2Options { /** * `'asymp'` (default): large-sample `kstwobign` asymptotic p-value — * unchanged from the original implementation, so omitting `opts` entirely * preserves the exact prior behavior. * `'exact'`: exact lattice-path p-value (Kim & Jennrich), matching * `scipy.stats.ks_2samp(..., method='exact')`. * `'auto'`: exact when n1*n2 <= 10000, else asymptotic (scipy's own * threshold for switching to the asymptotic approximation). */ method?: 'auto' | 'exact' | 'asymp'; } /** * Two-sample Kolmogorov–Smirnov test: are two samples drawn from the same * continuous distribution? The statistic is the maximum gap between the two * empirical CDFs, D = maxₓ |F₁(x) − F₂(x)|. By default the p-value is the * large-sample asymptotic Q(√(n₁n₂/(n₁+n₂))·D) (the `kstwobign` survival * function, matching scipy's asymptotic method) — this default is unchanged * from before Phase 4. Pass `{ method: 'exact' }` to opt into the exact * lattice-path p-value instead (`scipy.stats.ks_2samp(..., method='exact')`). * Distinct from the one-sample {@link kolmogorovSmirnovTest}, which compares * one sample to a CDF *function*. * * @param sample1 - first sample (non-empty) * @param sample2 - second sample (non-empty) * @param opts - `{ method: 'auto' | 'exact' | 'asymp' }` (default 'asymp') * @returns `{ statistic: D, pValue }` * * @example * kolmogorovSmirnov2Test([0.1, 0.4, 0.6], [0.3, 0.5, 0.9]) // { statistic, pValue } (asymptotic) * kolmogorovSmirnov2Test(a, b, { method: 'exact' }) // exact lattice-path p-value */ export declare function kolmogorovSmirnov2Test(sample1: f64[], sample2: f64[], opts?: KS2Options): KSTestResult; /** Variance-homogeneity test result. `degreesOfFreedom` is `[d1, d2]` for the * F-based Levene test, a single number for the χ²-based Bartlett test. */ export interface VarianceTestResult { statistic: f64; pValue: f64; degreesOfFreedom: number | [number, number]; } /** * Levene's test for equality of variances across ≥2 groups (the ANOVA * prerequisite). Robust to non-normality — it runs a one-way ANOVA F-test on the * absolute deviations from each group's center. `center` defaults to `'median'` * (the Brown–Forsythe variant, scipy's default); `'mean'` gives the original * Levene test. Pinned to `scipy.stats.levene`. * * @example leveneTest([[8.1,8.3,7.9],[9.1,9.5,8.9]]) // { statistic, pValue, degreesOfFreedom } */ export declare function leveneTest(groups: f64[][], center?: 'median' | 'mean'): VarianceTestResult; /** * Bartlett's test for equality of variances across ≥2 groups. More powerful than * Levene when the data are normal, but sensitive to departures from normality. * Statistic is χ²-distributed with k−1 df. Pinned to `scipy.stats.bartlett`. * * @example bartlettTest([[8.1,8.3,7.9],[9.1,9.5,8.9]]) // { statistic, pValue, degreesOfFreedom } */ export declare function bartlettTest(groups: f64[][]): VarianceTestResult; /** * Paired (dependent-samples) t-test: tests whether the mean of the paired * differences x−y is zero. Distinct from the two-sample Welch test in * {@link studentTTest}, which assumes independent samples. Pinned to * `scipy.stats.ttest_rel`. * * @example studentTTestPaired([1.2,2.3,3.1], [1.0,2.0,3.5]) // { statistic, pValue, degreesOfFreedom } */ export declare function studentTTestPaired(sample1: f64[], sample2: f64[]): TTestResult; /** z-test result (statistic + two-tailed p-value). */ export interface ProportionZResult { statistic: f64; pValue: f64; } /** * Proportion z-test (large-sample, two-tailed). * - **One-sample**: `proportionZTest(successes, n, p0)` tests p̂ = successes/n * against a hypothesized proportion `p0`. * - **Two-sample**: `proportionZTest([s1, s2], [n1, n2])` tests p̂₁ = p̂₂ using * the pooled-variance z (equivalent to `statsmodels.proportions_ztest`). * * @example proportionZTest(40, 100, 0.5) // one-sample: z=-2, p≈0.0455 * @example proportionZTest([40, 30], [100, 100]) // two-sample: z≈1.482, p≈0.138 */ export declare function proportionZTest(count: number | [number, number], nobs: number | [number, number], value?: number): ProportionZResult; /** * Exact binomial test — is the observed success count consistent with success * probability `p`? The two-tailed p-value is the total probability of all * outcomes no more likely than the observed one (scipy's method-of-small-p). * Pinned to `scipy.stats.binomtest`. * * @example binomialTest(8, 20, 0.5) // { pValue: 0.5034446716 } */ export declare function binomialTest(successes: number, n: number, p?: f64): { statistic: f64; pValue: f64; }; /** Normality-test result (statistic + p-value). */ export interface NormalityTestResult { statistic: f64; pValue: f64; } /** * Anderson-Darling test for normality. Returns the A^2 statistic (matching * scipy.stats.anderson, standardized with the ddof=1 sample std) and a p-value * from the D'Agostino-Stephens approximation on the small-sample-corrected A^2*. */ export declare function andersonDarlingTest(data: f64[]): NormalityTestResult; /** * D'Agostino-Pearson omnibus normality test (scipy.stats.normaltest): * K2 = Z1^2 + Z2^2 (skew + kurtosis Z-tests), chi-square with 2 df, p = e^(-K2/2). */ export declare function dagostinoTest(data: f64[]): NormalityTestResult; /** * Friedman test - non-parametric repeated-measures ANOVA across k related * groups of the same n blocks. chi-square with k-1 df. scipy.stats.friedmanchisquare. */ export declare function friedmanTest(groups: f64[][]): { statistic: f64; pValue: f64; degreesOfFreedom: number; }; /** One factor's line in a two-way ANOVA table. */ export interface Anova2Effect { F: f64; pValue: f64; degreesOfFreedom: [number, number]; } /** Balanced two-way (with-replication) ANOVA result. */ export interface Anova2Result { factorA: Anova2Effect; factorB: Anova2Effect; interaction: Anova2Effect; } /** * Balanced two-way ANOVA with replication. data[i][j] holds the r replicates for * level i of factor A x level j of factor B (all cells equal size). Equivalent to * MATLAB anova2. */ export declare function anova2(data: f64[][][]): Anova2Result; /** * Multiple-comparison p-value correction: bonferroni, holm (step-down), or bh * (Benjamini-Hochberg FDR). Matches statsmodels multipletests. * * Same algorithm as {@link multipleTest} (`../stats/inference-extra.js`) — * an equivalent alias kept for backward-compatible naming; both names are * supported and always return identical results. */ export declare function multipleComparison(pValues: f64[], method?: 'bonferroni' | 'holm' | 'bh'): f64[]; /** A confidence interval with the point estimate it brackets. */ export interface ConfidenceInterval { estimate: f64; lower: f64; upper: f64; confidence: f64; } /** * Confidence interval for the population mean via the Student-t distribution * (`scipy.stats.t.interval`). `confidence` defaults to 0.95. */ export declare function meanCI(data: f64[], confidence?: number): ConfidenceInterval; /** * Wald confidence interval for a binomial proportion (normal approximation). * `confidence` defaults to 0.95. */ export declare function proportionCI(successes: number, n: number, confidence?: number): ConfidenceInterval; /** Options for `bootstrapCI`. */ export interface BootstrapCIOptions { confidence?: number; resamples?: number; seed?: number; } /** * Percentile bootstrap confidence interval for an arbitrary statistic of a * single sample (`scipy.stats.bootstrap`, percentile method). Resampling is * deterministic when `seed` is given. Returns the CI plus the observed estimate. */ export declare function bootstrapCI(data: f64[], statistic: (sample: f64[]) => f64, opts?: BootstrapCIOptions): ConfidenceInterval; /** Options for `permutationTest`. */ export interface PermutationOptions { resamples?: number; seed?: number; } /** * Two-sample permutation test for an arbitrary statistic `statistic(a, b)`. * The combined pool is repeatedly shuffled and re-split; the two-tailed p-value * is the fraction of permuted statistics at least as extreme (in absolute value) * as the observed one (`scipy.stats.permutation_test`). Deterministic with `seed`. */ export declare function permutationTest(a: f64[], b: f64[], statistic: (x: f64[], y: f64[]) => f64, opts?: PermutationOptions): { statistic: f64; pValue: f64; }; /** * Mahalanobis distance between two vectors `u` and `v` under covariance `cov`: * √((u−v)ᵀ Σ⁻¹ (u−v)). Matches `scipy.spatial.distance.mahalanobis(u, v, inv(cov))` * (this form takes the covariance directly and inverts it internally). * * @example mahalanobis([1,2], [2.5,1], [[2,0.5],[0.5,1]]) // 1.8126539343 */ export declare function mahalanobis(u: number[], v: number[], cov: number[][]): f64; /** One-sample Hotelling's T² result. */ export interface HotellingResult { statistic: f64; fStatistic: f64; pValue: f64; degreesOfFreedom: [number, number]; } /** * One-sample Hotelling's T² test — the multivariate generalization of the * one-sample t-test: is the mean vector of `data` (rows = observations, columns * = variables) equal to `mu0`? T² = n·(x̄−μ₀)ᵀ S⁻¹ (x̄−μ₀), and * F = (n−p)/(p(n−1))·T² ~ F(p, n−p) under H₀. * * @example hotellingT2(data, [5, 7]) // { statistic, fStatistic, pValue, degreesOfFreedom } */ export declare function hotellingT2(data: f64[][], mu0: f64[]): HotellingResult; export {}; //# sourceMappingURL=hypothesis.d.ts.map