@zukhruf/statistics 0.8.6 → 0.8.8

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/NOTICE CHANGED
@@ -3,8 +3,10 @@ Copyright 2026 ezzabuzaid
3
3
 
4
4
  This package ports the semantics of the methods lower, higher, linear and
5
5
  inverted_cdf of numpy.quantile in NumPy 2.5.4, including the _lerp of its
6
- linear method, Copyright (c) NumPy Developers, BSD 3-Clause License,
6
+ linear method, and of numpy.sum and numpy.mean, Copyright (c) NumPy Developers, BSD 3-Clause License,
7
7
  https://github.com/numpy/numpy. The package does not include NumPy's code.
8
8
  The names of the percentile bootstrap follow SciPy (scipy.stats.bootstrap)
9
9
  and arch (arch.bootstrap.IIDBootstrap); the package includes no code of
10
10
  either.
11
+ The pairwise sum comes from @stdlib/blas-ext-base-gsumpw, a dependency
12
+ (Apache-2.0, https://github.com/stdlib-js/stdlib).
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @zukhruf/statistics
2
2
 
3
- The percentile bootstrap and the quantile methods of NumPy in JavaScript, to the last bit. Use it when a TypeScript eval must give the same interval as a Python program, such as the summary of a benchmark or the comparison of two models.
3
+ The percentile bootstrap, the quantile methods of NumPy and `numpy.sum` and `numpy.mean` in JavaScript, to the last bit. Use it when a TypeScript eval must give the same interval as a Python program, such as the summary of a benchmark or the comparison of two models.
4
4
 
5
5
  The package is public on npm. Until 2026-11-07 it was private and reached through a workspace path (ADR 0001); it became public with `@zukhruf/evals`, which depends on it (backlog #3888).
6
6
 
@@ -9,7 +9,13 @@ The package is public on npm. Until 2026-11-07 it was private and reached throug
9
9
  ```ts
10
10
  import { Random } from 'python-random';
11
11
 
12
- import { IidBootstrap, Linear, PercentileInterval } from '@zukhruf/statistics';
12
+ import {
13
+ IidBootstrap,
14
+ Linear,
15
+ PercentileInterval,
16
+ mean,
17
+ sum,
18
+ } from '@zukhruf/statistics';
13
19
 
14
20
  const random = new Random(42);
15
21
  const bootstrap = new IidBootstrap({
@@ -26,19 +32,24 @@ interval.low; // the 2.5% quantile of the 1000 means, as numpy.percentile
26
32
  interval.isAbove(0); // true when the whole interval lies above 0
27
33
 
28
34
  new Linear().of([1, 2, 3, 4], 0.5); // 2.5, as numpy.quantile(a, 0.5)
35
+ sum([0.1, 0.2, 0.3]); // 0.6000000000000001, as numpy.sum(a)
36
+ mean([1, 2, 3, 4]); // 2.5, as numpy.mean(a)
29
37
  ```
30
38
 
31
- | Export | NumPy, SciPy or arch | What it does |
32
- | -------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
- | `QuantileMethod` | the `method` of `numpy.quantile` | A rule that gives the value at the quantile `q` of sorted values: `of(sorted, q)`. `q` is from 0 to 1. A `q` out of that range, or no values, throws a `RangeError`. |
34
- | `Lower` | `method='lower'` | The value at the index `floor((n − 1)q)`. |
35
- | `Higher` | `method='higher'` | The value at the index `ceil((n − 1)q)`. |
36
- | `Linear` | `method='linear'`, the default of NumPy | The line between the two values around the index `(n − 1)q`, computed as NumPy's `_lerp` computes it, so the bits are NumPy's. d3-array's `quantileSorted` gives other bits for 1 value of 10. |
37
- | `InvertedCdf` | `method='inverted_cdf'` | The nearest rank: the value at the index `ceil(nq) − 1`, and the first value when `q` is 0. |
38
- | `ConfidenceInterval` | the `ConfidenceInterval` of `scipy.stats.bootstrap` | `low` and `high`. `isAbove(value)` is true when `low > value`, and `isBelow(value)` is true when `high < value`: the whole interval lies on one side of the value. |
39
- | `ConfidenceIntervalMethod` | the `method` of `scipy.stats.bootstrap` | A rule that gives the confidence interval of a bootstrap distribution: `of(distribution)`. `PercentileInterval` is one. A caller with a rule of its own writes another. |
40
- | `PercentileInterval` | `method='percentile'` of `scipy.stats.bootstrap` | The `low` and the `high` quantile of a bootstrap distribution, both read with one quantile method, as `numpy.percentile` reads them. It sorts a copy, so the distribution does not change. |
41
- | `IidBootstrap` | `arch.bootstrap.IIDBootstrap`; `n_resamples` and `bootstrap_distribution` of SciPy | Draws `nResamples` resamples of the data, with replacement. `distribution(data, statistic)` gives the statistic of each resample. `interval(data, statistic, method)` gives the interval that a `ConfidenceIntervalMethod` reads from that distribution. Data with no items throws a `RangeError`. |
39
+ | Export | NumPy, SciPy or arch | What it does |
40
+ | -------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
+ | `sum` | `numpy.sum` of a 1-D float64 array | The pairwise sum of NumPy: blocks of up to 128 values in 8 accumulators, and two halves for more values. It starts from 0, so values of −0 give 0. No values give 0. |
42
+ | `mean` | `numpy.mean` of a 1-D float64 array | `sum` divided by the number of values. No values give NaN. |
43
+ | `QuantileMethod` | the `method` of `numpy.quantile` | A rule that gives the value at the quantile `q` of sorted values: `of(sorted, q)`. `q` is from 0 to 1. A `q` out of that range, or no values, throws a `RangeError`. |
44
+ | `Lower` | `method='lower'` | The value at the index `floor((n − 1)q)`. |
45
+ | `Higher` | `method='higher'` | The value at the index `ceil((n − 1)q)`. |
46
+ | `Linear` | `method='linear'`, the default of NumPy | The line between the two values around the index `(n − 1)q`, computed as NumPy's `_lerp` computes it, so the bits are NumPy's. d3-array's `quantileSorted` gives other bits for 1 value of 10. |
47
+ | `InvertedCdf` | `method='inverted_cdf'` | The nearest rank: the value at the index `ceil(nq) − 1`, and the first value when `q` is 0. |
48
+ | `ConfidenceInterval` | the `ConfidenceInterval` of `scipy.stats.bootstrap` | `low` and `high`. `isAbove(value)` is true when `low > value`, and `isBelow(value)` is true when `high < value`: the whole interval lies on one side of the value. |
49
+ | `DifferenceInterval` | the `ConfidenceInterval` of `scipy.stats.bootstrap`, with the observed statistic | A `ConfidenceInterval` of (change − baseline) with `observed`: the difference that the data gives. `new DifferenceInterval(low, high, observed)` makes one. It is data only: it has no verdict. mteb's `ChangeVerdict`, the `Interval` of relevance-filtering and the `Interval` of event-detection hold the same three values. `@zukhruf/evals` gives it in each verdict of two runs. |
50
+ | `ConfidenceIntervalMethod` | the `method` of `scipy.stats.bootstrap` | A rule that gives the confidence interval of a bootstrap distribution: `of(distribution)`. `PercentileInterval` is one. A caller with a rule of its own writes another. |
51
+ | `PercentileInterval` | `method='percentile'` of `scipy.stats.bootstrap` | The `low` and the `high` quantile of a bootstrap distribution, both read with one quantile method, as `numpy.percentile` reads them. It sorts a copy, so the distribution does not change. |
52
+ | `IidBootstrap` | `arch.bootstrap.IIDBootstrap`; `n_resamples` and `bootstrap_distribution` of SciPy | Draws `nResamples` resamples of the data, with replacement. `distribution(data, statistic)` gives the statistic of each resample. `interval(data, statistic, method)` gives the interval that a `ConfidenceIntervalMethod` reads from that distribution. Data with no items throws a `RangeError`. |
42
53
 
43
54
  The random generator is an input. `randomIndex(n)` gives an index from 0 to n − 1. Each item of a resample takes one call, in order, resample by resample, as a Python loop over the same generator does. So `(n) => random.randrange(n)` of python-random draws as CPython's `random.Random`, and a port of NumPy's `default_rng` draws as `integers(0, n, n)` when it draws one index for each call. An index out of range throws a `RangeError`.
44
55
 
@@ -52,3 +63,4 @@ These parts stay with each caller, because each caller has its own rule:
52
63
  ## Documentation
53
64
 
54
65
  - [ADR 0001: one home for the percentile bootstrap that six places copied, reached through a workspace path](docs/adr/0001-one-home-for-the-percentile-bootstrap-that-six-places-copied.md)
66
+ - [ADR 0002: one home for the pairwise sum of NumPy that four places copied](docs/adr/0002-one-home-for-the-pairwise-sum-of-numpy-that-four-places-copied.md)
package/dist/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  export { IidBootstrap } from './bootstrap/iid-bootstrap.ts';
2
2
  export { ConfidenceInterval } from './interval/confidence-interval.ts';
3
3
  export type { ConfidenceIntervalMethod } from './interval/confidence-interval-method.ts';
4
+ export { DifferenceInterval } from './interval/difference-interval.ts';
4
5
  export { PercentileInterval } from './interval/percentile-interval.ts';
5
6
  export { Higher } from './quantile/higher.ts';
6
7
  export { InvertedCdf } from './quantile/inverted-cdf.ts';
7
8
  export { Linear } from './quantile/linear.ts';
8
9
  export { Lower } from './quantile/lower.ts';
9
10
  export { QuantileMethod } from './quantile/quantile-method.ts';
11
+ export { mean } from './sum/mean.ts';
12
+ export { sum } from './sum/sum.ts';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  export { IidBootstrap } from "./bootstrap/iid-bootstrap.js";
2
2
  export { ConfidenceInterval } from "./interval/confidence-interval.js";
3
+ export { DifferenceInterval } from "./interval/difference-interval.js";
3
4
  export { PercentileInterval } from "./interval/percentile-interval.js";
4
5
  export { Higher } from "./quantile/higher.js";
5
6
  export { InvertedCdf } from "./quantile/inverted-cdf.js";
6
7
  export { Linear } from "./quantile/linear.js";
7
8
  export { Lower } from "./quantile/lower.js";
8
9
  export { QuantileMethod } from "./quantile/quantile-method.js";
10
+ export { mean } from "./sum/mean.js";
11
+ export { sum } from "./sum/sum.js";
9
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ConfidenceInterval } from './confidence-interval.ts';
2
+ export declare class DifferenceInterval extends ConfidenceInterval {
3
+ readonly observed: number;
4
+ constructor(low: number, high: number, observed: number);
5
+ }
6
+ //# sourceMappingURL=difference-interval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"difference-interval.d.ts","sourceRoot":"","sources":["../../src/interval/difference-interval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAK9D,qBAAa,kBAAmB,SAAQ,kBAAkB;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAIxD"}
@@ -0,0 +1,12 @@
1
+ import { ConfidenceInterval } from "./confidence-interval.js";
2
+ // The confidence interval of (change − baseline), with the observed
3
+ // difference: the difference that the data gives. It is data only. Each
4
+ // caller reads its own verdict from isAbove and isBelow (ADR 0001).
5
+ export class DifferenceInterval extends ConfidenceInterval {
6
+ observed;
7
+ constructor(low, high, observed) {
8
+ super(low, high);
9
+ this.observed = observed;
10
+ }
11
+ }
12
+ //# sourceMappingURL=difference-interval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"difference-interval.js","sourceRoot":"","sources":["../../src/interval/difference-interval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,oEAAoE;AACpE,wEAAwE;AACxE,oEAAoE;AACpE,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAC/C,QAAQ,CAAS;IAE1B,YAAY,GAAW,EAAE,IAAY,EAAE,QAAgB;QACrD,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare function mean(values: ArrayLike<number>): number;
2
+ //# sourceMappingURL=mean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mean.d.ts","sourceRoot":"","sources":["../../src/sum/mean.ts"],"names":[],"mappings":"AAIA,wBAAgB,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,7 @@
1
+ import { sum } from "./sum.js";
2
+ // numpy.mean of a 1-D float64 array: numpy.sum divided by the number of
3
+ // values. The mean of no values is NaN, as NumPy gives it.
4
+ export function mean(values) {
5
+ return sum(values) / values.length;
6
+ }
7
+ //# sourceMappingURL=mean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mean.js","sourceRoot":"","sources":["../../src/sum/mean.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,wEAAwE;AACxE,2DAA2D;AAC3D,MAAM,UAAU,IAAI,CAAC,MAAyB;IAC5C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;AACrC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function sum(values: ArrayLike<number>): number;
2
+ //# sourceMappingURL=sum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sum.d.ts","sourceRoot":"","sources":["../../src/sum/sum.ts"],"names":[],"mappings":"AAOA,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAErD"}
@@ -0,0 +1,10 @@
1
+ import gsumpw from '@stdlib/blas-ext-base-gsumpw';
2
+ // numpy.sum of a 1-D float64 array: the identity 0 plus numpy's pairwise sum
3
+ // (pairwise_sum of loops_utils.h), which gsumpw of stdlib gives in the same
4
+ // order: blocks of up to 128 values in 8 accumulators, larger arrays cut in
5
+ // two halves, the first a multiple of 8. The identity makes a sum of -0.0
6
+ // values 0.0, as NumPy gives it.
7
+ export function sum(values) {
8
+ return 0 + gsumpw(values.length, values, 1);
9
+ }
10
+ //# sourceMappingURL=sum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sum.js","sourceRoot":"","sources":["../../src/sum/sum.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,8BAA8B,CAAC;AAElD,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,iCAAiC;AACjC,MAAM,UAAU,GAAG,CAAC,MAAyB;IAC3C,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zukhruf/statistics",
3
- "version": "0.8.6",
4
- "description": "The percentile bootstrap and the quantile methods of NumPy in JavaScript, to the last bit: resamples of a dataset with a random generator that the caller gives, the percentile interval of their statistic, and NumPy's quantile methods.",
3
+ "version": "0.8.8",
4
+ "description": "The percentile bootstrap, NumPy's quantile methods, and numpy.sum and numpy.mean in JavaScript, to the last bit: resamples with a random generator that the caller gives, the percentile interval of their statistic, and NumPy's pairwise sum.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -38,5 +38,8 @@
38
38
  ],
39
39
  "publishConfig": {
40
40
  "access": "public"
41
+ },
42
+ "dependencies": {
43
+ "@stdlib/blas-ext-base-gsumpw": "^0.3.1"
41
44
  }
42
45
  }