@numero-uno-jpn/rstats 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.ja.md +36 -20
  3. package/README.md +34 -18
  4. package/THIRD_PARTY_NOTICES.md +25 -5
  5. package/dist/chunks/chunk-2JCIB5H2.js +2 -0
  6. package/dist/chunks/chunk-7JVSDGQQ.js +2 -0
  7. package/dist/chunks/chunk-7NK4SA6B.js +2 -0
  8. package/dist/chunks/chunk-AJYQNFXK.js +2 -0
  9. package/dist/chunks/chunk-DRNMIEYH.js +2 -0
  10. package/dist/chunks/chunk-NAYDS7CL.js +2 -0
  11. package/dist/chunks/chunk-NOCEAM44.js +2 -0
  12. package/dist/chunks/chunk-QNAIK4PY.js +2 -0
  13. package/dist/chunks/chunk-TPC6MTYC.js +2 -0
  14. package/dist/chunks/chunk-UGUQYWRQ.js +2 -0
  15. package/dist/chunks/chunk-XM2TVD63.js +2 -0
  16. package/dist/chunks/chunk-Y4IZV7XK.js +2 -0
  17. package/dist/chunks/chunk-ZWJ42QN6.js +2 -0
  18. package/dist/descriptive/basic.d.ts +73 -0
  19. package/dist/descriptive/basic.js +256 -0
  20. package/dist/descriptive/cov.d.ts +39 -0
  21. package/dist/descriptive/cov.js +105 -0
  22. package/dist/descriptive/hist.d.ts +64 -0
  23. package/dist/descriptive/hist.js +304 -0
  24. package/dist/descriptive/moments.d.ts +63 -0
  25. package/dist/descriptive/moments.js +158 -0
  26. package/dist/descriptive/quantile.d.ts +50 -0
  27. package/dist/descriptive/quantile.js +131 -0
  28. package/dist/descriptive/rank.d.ts +23 -0
  29. package/dist/descriptive/rank.js +72 -0
  30. package/dist/descriptive/table.d.ts +54 -0
  31. package/dist/descriptive/table.js +160 -0
  32. package/dist/descriptive.js +2 -0
  33. package/dist/distributions/arcsine.d.ts +24 -0
  34. package/dist/distributions/arcsine.js +73 -0
  35. package/dist/distributions/invgamma.d.ts +29 -0
  36. package/dist/distributions/invgamma.js +85 -0
  37. package/dist/distributions/kumaraswamy.d.ts +17 -0
  38. package/dist/distributions/kumaraswamy.js +96 -0
  39. package/dist/distributions/laplace.d.ts +23 -0
  40. package/dist/distributions/laplace.js +69 -0
  41. package/dist/distributions/multinomial.d.ts +24 -0
  42. package/dist/distributions/multinomial.js +70 -0
  43. package/dist/distributions/nbeta.js +28 -10
  44. package/dist/distributions/nchisq.js +20 -3
  45. package/dist/distributions/pareto.d.ts +23 -0
  46. package/dist/distributions/pareto.js +76 -0
  47. package/dist/distributions/summary.d.ts +25 -0
  48. package/dist/distributions/summary.js +289 -0
  49. package/dist/distributions/triangular.d.ts +25 -0
  50. package/dist/distributions/triangular.js +87 -0
  51. package/dist/distributions.js +2 -0
  52. package/dist/entries/descriptive.d.ts +7 -0
  53. package/dist/entries/descriptive.js +8 -0
  54. package/dist/entries/distributions.d.ts +41 -0
  55. package/dist/entries/distributions.js +41 -0
  56. package/dist/entries/linalg.d.ts +11 -0
  57. package/dist/entries/linalg.js +11 -0
  58. package/dist/entries/numerics.d.ts +8 -0
  59. package/dist/entries/numerics.js +6 -0
  60. package/dist/entries/special.d.ts +9 -0
  61. package/dist/entries/special.js +9 -0
  62. package/dist/entries/tests.d.ts +21 -0
  63. package/dist/entries/tests.js +20 -0
  64. package/dist/htest/ansariTest.d.ts +13 -0
  65. package/dist/htest/ansariTest.js +80 -0
  66. package/dist/htest/aov.d.ts +85 -0
  67. package/dist/htest/aov.js +178 -0
  68. package/dist/htest/binomTest.d.ts +36 -0
  69. package/dist/htest/binomTest.js +121 -0
  70. package/dist/htest/cor.d.ts +14 -0
  71. package/dist/htest/cor.js +4 -3
  72. package/dist/htest/core/ansari.d.ts +18 -0
  73. package/dist/htest/core/ansari.js +121 -0
  74. package/dist/htest/core/kolmogorov.d.ts +26 -0
  75. package/dist/htest/core/kolmogorov.js +221 -0
  76. package/dist/htest/core/mantelhaen.d.ts +26 -0
  77. package/dist/htest/core/mantelhaen.js +145 -0
  78. package/dist/htest/core/shapiro.d.ts +24 -0
  79. package/dist/htest/core/shapiro.js +142 -0
  80. package/dist/htest/core/smirnov.d.ts +20 -0
  81. package/dist/htest/core/smirnov.js +75 -0
  82. package/dist/htest/fisherTest.js +134 -120
  83. package/dist/htest/groups.d.ts +20 -0
  84. package/dist/htest/groups.js +62 -0
  85. package/dist/htest/ksTest.d.ts +31 -0
  86. package/dist/htest/ksTest.js +106 -0
  87. package/dist/htest/mantelhaenTest.d.ts +26 -0
  88. package/dist/htest/mantelhaenTest.js +196 -0
  89. package/dist/htest/mcnemarTest.d.ts +26 -0
  90. package/dist/htest/mcnemarTest.js +99 -0
  91. package/dist/htest/onewayTest.d.ts +26 -0
  92. package/dist/htest/onewayTest.js +97 -0
  93. package/dist/htest/pairwise.d.ts +64 -0
  94. package/dist/htest/pairwise.js +152 -0
  95. package/dist/htest/poissonTest.d.ts +35 -0
  96. package/dist/htest/poissonTest.js +170 -0
  97. package/dist/htest/propTest.d.ts +37 -0
  98. package/dist/htest/propTest.js +164 -0
  99. package/dist/htest/rankTests.d.ts +52 -0
  100. package/dist/htest/rankTests.js +234 -0
  101. package/dist/htest/types.d.ts +2 -0
  102. package/dist/htest/types.js +6 -0
  103. package/dist/htest/varTest.d.ts +48 -0
  104. package/dist/htest/varTest.js +118 -0
  105. package/dist/htest/wilcoxTest.js +136 -174
  106. package/dist/index.d.ts +6 -50
  107. package/dist/index.js +8 -50
  108. package/dist/integrate/quadpack.d.ts +29 -0
  109. package/dist/integrate/quadpack.js +525 -0
  110. package/dist/internal/seq.d.ts +5 -0
  111. package/dist/internal/seq.js +14 -0
  112. package/dist/internal/uniroot.js +10 -71
  113. package/dist/linalg/lu.d.ts +45 -0
  114. package/dist/linalg/lu.js +88 -0
  115. package/dist/linalg/ops.d.ts +90 -0
  116. package/dist/linalg/ops.js +320 -0
  117. package/dist/linalg.js +2 -0
  118. package/dist/models/lm.d.ts +98 -0
  119. package/dist/models/lm.js +187 -0
  120. package/dist/numerics/deriv.d.ts +37 -0
  121. package/dist/numerics/deriv.js +150 -0
  122. package/dist/numerics/integrate.d.ts +91 -0
  123. package/dist/numerics/integrate.js +264 -0
  124. package/dist/numerics/interp.d.ts +103 -0
  125. package/dist/numerics/interp.js +581 -0
  126. package/dist/numerics/ode.d.ts +23 -0
  127. package/dist/numerics/ode.js +59 -0
  128. package/dist/numerics.js +2 -0
  129. package/dist/optim/localmin.d.ts +16 -0
  130. package/dist/optim/localmin.js +97 -0
  131. package/dist/random/beta.js +1 -1
  132. package/dist/random/binomial.js +1 -1
  133. package/dist/random/continuous.js +1 -1
  134. package/dist/random/extra.d.ts +33 -0
  135. package/dist/random/extra.js +62 -0
  136. package/dist/random/gamma.js +1 -1
  137. package/dist/random/hyper.js +1 -1
  138. package/dist/random/mt.js +0 -1
  139. package/dist/random/poisson.js +0 -1
  140. package/dist/random/rank.js +1 -1
  141. package/dist/random/rng.js +1 -1
  142. package/dist/random/sample.js +1 -1
  143. package/dist/rstats.js +2 -2
  144. package/dist/special/besselIK.d.ts +38 -0
  145. package/dist/special/besselIK.js +315 -0
  146. package/dist/special/besselJY.d.ts +32 -0
  147. package/dist/special/besselJY.js +508 -0
  148. package/dist/special/besselSeries.d.ts +8 -0
  149. package/dist/special/besselSeries.js +24 -0
  150. package/dist/special/beta.js +22 -5
  151. package/dist/special/choose.d.ts +75 -0
  152. package/dist/special/choose.js +233 -0
  153. package/dist/special/erf.d.ts +28 -2
  154. package/dist/special/erf.js +37 -10
  155. package/dist/special/extra.d.ts +47 -0
  156. package/dist/special/extra.js +220 -0
  157. package/dist/special/igam.d.ts +4 -0
  158. package/dist/special/igam.js +57 -2
  159. package/dist/special/incbet.js +77 -22
  160. package/dist/special/lgammaDiff.d.ts +7 -0
  161. package/dist/special/lgammaDiff.js +16 -3
  162. package/dist/special/psigamma.d.ts +48 -0
  163. package/dist/special/psigamma.js +318 -0
  164. package/dist/special/rCompatible.d.ts +8 -0
  165. package/dist/special/rCompatible.js +1 -0
  166. package/dist/special.js +2 -0
  167. package/dist/tests.js +2 -0
  168. package/package.json +26 -1
@@ -0,0 +1,50 @@
1
+ import { type NaRmOptions } from "./basic.js";
2
+ import type { Sample } from "../htest/types.js";
3
+ /** Options for {@link quantile}. */
4
+ export interface QuantileOptions extends NaRmOptions {
5
+ /** Hyndman and Fan's definition, 1 to 9. Default `7`. */
6
+ type?: number;
7
+ }
8
+ /**
9
+ * Sample quantiles. Equivalent to R's `quantile()` (with `names = FALSE`).
10
+ *
11
+ * @param x The data.
12
+ * @param probs Probabilities in [0, 1]. Default `[0, 0.25, 0.5, 0.75, 1]`. A single number gives a single number.
13
+ * @param options `type` (1 to 9, default 7) and `naRm`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * quantile([1, 2, 3, 4, 5, 6], 0.25); // 2.25 (type 7)
18
+ * quantile([1, 2, 3, 4, 5, 6], 0.25, { type: 9 }); // 1.9375 (jStat's quantiles)
19
+ * ```
20
+ */
21
+ export declare function quantile(x: Sample, probs: number, options?: QuantileOptions): number;
22
+ export declare function quantile(x: Sample, probs?: readonly number[], options?: QuantileOptions): number[];
23
+ /** Interquartile range, the difference of the 0.75 and 0.25 quantiles. Equivalent to R's `IQR()`. */
24
+ export declare function IQR(x: Sample, options?: QuantileOptions): number;
25
+ /**
26
+ * Tukey's five-number summary (minimum, lower hinge, median, upper hinge, maximum). Equivalent to R's `fivenum()`;
27
+ * `NaN` values are dropped.
28
+ */
29
+ export declare function fivenum(x: Sample): [number, number, number, number, number];
30
+ /** Options for {@link mad}. */
31
+ export interface MadOptions extends NaRmOptions {
32
+ /** Centre. Default: the median. */
33
+ center?: number;
34
+ /** Scale factor. Default `1.4826` (consistent for the normal standard deviation). */
35
+ constant?: number;
36
+ /** For an even count, take the lower of the two middle absolute deviations (the "lo-median"). */
37
+ low?: boolean;
38
+ /** For an even count, take the higher one (the "hi-median"). */
39
+ high?: boolean;
40
+ }
41
+ /**
42
+ * Median absolute deviation, scaled. Equivalent to R's `mad()`.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * mad([1, 2, 3, 4, 100]); // 1.4826
47
+ * mad([1, 2, 3, 4, 100], { constant: 1 }); // 1 (jStat's meddev)
48
+ * ```
49
+ */
50
+ export declare function mad(x: Sample, options?: MadOptions): number;
@@ -0,0 +1,131 @@
1
+ // Sample quantiles and robust summaries: R's quantile (types 1 to 9), IQR, fivenum and mad.
2
+ //
3
+ // Written for rStats.js. The nine quantile definitions are those of Hyndman and Fan, "Sample quantiles in
4
+ // statistical packages", The American Statistician 50, 1996, numbered as in that paper and in R's ?quantile. Details
5
+ // that the paper leaves open follow R's documented behaviour and observed output: type 7 interpolates at
6
+ // 1 + (n - 1) p only between order statistics that differ (so that equal infinite neighbours are not turned into
7
+ // NaN); the other types take the integer part of the position after enlarging it by a relative 4 eps, so that a
8
+ // position meant to be an integer is not lost to rounding, and treat a fractional part below 4 eps as 0. fivenum is
9
+ // Tukey's five-number summary; mad scales by 1.4826 by default.
10
+ import { median, values } from "./basic.js";
11
+ /** Relative fuzz for the positions of types 1 to 6, 8 and 9 */
12
+ const FUZZ = 4 * Number.EPSILON;
13
+ /** (a, b) of the continuous types 4 to 6, 8 and 9 (Hyndman and Fan's p(k) = (k - a) / (n + 1 - a - b)) */
14
+ const CONTINUOUS = {
15
+ 4: [0, 1],
16
+ 5: [0.5, 0.5],
17
+ 6: [0, 0],
18
+ 8: [1 / 3, 1 / 3],
19
+ 9: [3 / 8, 3 / 8],
20
+ };
21
+ /** Quantile of type `type` at probability `p` (in [0, 1]) of the ascending values `s` (non-empty) */
22
+ function quantileOfSorted(s, p, type) {
23
+ const n = s.length;
24
+ // order statistic j (1-based), extended by the end values outside 1..n
25
+ const at = (j) => s[Math.min(Math.max(j, 1), n) - 1];
26
+ if (type === 7) {
27
+ const m = 1 + (n - 1) * p;
28
+ const j = Math.floor(m);
29
+ const lower = at(j);
30
+ const upper = at(Math.ceil(m));
31
+ if (m > j && upper !== lower) {
32
+ const g = m - j;
33
+ return (1 - g) * lower + g * upper;
34
+ }
35
+ return lower;
36
+ }
37
+ let j;
38
+ let g;
39
+ if (type <= 3) {
40
+ const m = type === 3 ? n * p - 0.5 : n * p;
41
+ j = Math.floor(m * (1 + FUZZ));
42
+ if (type === 1)
43
+ g = m > j ? 1 : 0;
44
+ else if (type === 2)
45
+ g = m > j ? 1 : 0.5;
46
+ else
47
+ g = m !== j || Math.abs(j % 2) === 1 ? 1 : 0;
48
+ }
49
+ else {
50
+ const [a, b] = CONTINUOUS[type];
51
+ const m = a + p * (n + 1 - a - b);
52
+ j = Math.floor(m * (1 + FUZZ));
53
+ g = m - j;
54
+ if (Math.abs(g) < FUZZ)
55
+ g = 0;
56
+ }
57
+ const lower = at(j);
58
+ const upper = at(j + 1);
59
+ if (g === 1)
60
+ return upper;
61
+ if (g > 0 && g < 1 && lower !== upper)
62
+ return (1 - g) * lower + g * upper;
63
+ return lower;
64
+ }
65
+ export function quantile(x, probs = [0, 0.25, 0.5, 0.75, 1], options = {}) {
66
+ const type = options.type ?? 7;
67
+ if (!(Number.isInteger(type) && type >= 1 && type <= 9))
68
+ throw new RangeError("'type' must be an integer in 1..9");
69
+ const xs = values(x, options.naRm);
70
+ if (xs === undefined)
71
+ throw new RangeError("missing values and NaN's not allowed if 'na.rm' is FALSE");
72
+ const sorted = xs.sort((a, b) => a - b);
73
+ const ps = typeof probs === "number" ? [probs] : Array.from(probs);
74
+ const tol = 100 * Number.EPSILON;
75
+ if (ps.some((p) => p < -tol || p > 1 + tol))
76
+ throw new RangeError("'probs' outside [0,1]");
77
+ const out = ps.map((p) => {
78
+ if (Number.isNaN(p) || sorted.length === 0)
79
+ return NaN;
80
+ return quantileOfSorted(sorted, Math.min(Math.max(p, 0), 1), type);
81
+ });
82
+ return typeof probs === "number" ? out[0] : out;
83
+ }
84
+ /** Interquartile range, the difference of the 0.75 and 0.25 quantiles. Equivalent to R's `IQR()`. */
85
+ export function IQR(x, options = {}) {
86
+ const [a, b] = quantile(x, [0.25, 0.75], options);
87
+ return b - a;
88
+ }
89
+ /**
90
+ * Tukey's five-number summary (minimum, lower hinge, median, upper hinge, maximum). Equivalent to R's `fivenum()`;
91
+ * `NaN` values are dropped.
92
+ */
93
+ export function fivenum(x) {
94
+ const s = Array.from(x)
95
+ .filter((v) => !Number.isNaN(v))
96
+ .sort((a, b) => a - b);
97
+ const n = s.length;
98
+ if (n === 0)
99
+ return [NaN, NaN, NaN, NaN, NaN];
100
+ const n4 = Math.floor((n + 3) / 2) / 2;
101
+ const d = [1, n4, (n + 1) / 2, n + 1 - n4, n];
102
+ return d.map((v) => 0.5 * (s[Math.floor(v) - 1] + s[Math.ceil(v) - 1]));
103
+ }
104
+ /**
105
+ * Median absolute deviation, scaled. Equivalent to R's `mad()`.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * mad([1, 2, 3, 4, 100]); // 1.4826
110
+ * mad([1, 2, 3, 4, 100], { constant: 1 }); // 1 (jStat's meddev)
111
+ * ```
112
+ */
113
+ export function mad(x, options = {}) {
114
+ const xs = values(x, options.naRm);
115
+ if (xs === undefined)
116
+ return NaN;
117
+ const center = options.center ?? median(xs);
118
+ const constant = options.constant ?? 1.4826;
119
+ const low = options.low ?? false;
120
+ const high = options.high ?? false;
121
+ const dev = xs.map((v) => Math.abs(v - center));
122
+ const n = dev.length;
123
+ if ((low || high) && n % 2 === 0) {
124
+ if (low && high)
125
+ throw new RangeError("'low' and 'high' cannot be both TRUE");
126
+ const k = n / 2 + (high ? 1 : 0);
127
+ const s = dev.sort((a, b) => a - b);
128
+ return constant * s[k - 1];
129
+ }
130
+ return constant * median(dev);
131
+ }
@@ -0,0 +1,23 @@
1
+ import type { Sample } from "../htest/types.js";
2
+ /** How ties are ranked, as R's `ties.method`. */
3
+ export type TiesMethod = "average" | "first" | "last" | "random" | "max" | "min";
4
+ /** Options for {@link rank}. */
5
+ export interface RankOptions {
6
+ /** Ranks of tied values. Default `"average"`. */
7
+ tiesMethod?: TiesMethod;
8
+ /**
9
+ * Missing values: `"last"` (default, R's `na.last = TRUE`) ranks them after the others, `"first"` (`FALSE`) before
10
+ * them, `"keep"` leaves them `NaN`.
11
+ */
12
+ naLast?: "last" | "first" | "keep";
13
+ }
14
+ /**
15
+ * Sample ranks. Equivalent to R's `rank()`.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * rank([10, 20, 20, 30]); // [1, 2.5, 2.5, 4]
20
+ * rank([10, 20, 20, 30], { tiesMethod: "min" }); // [1, 2, 2, 4]
21
+ * ```
22
+ */
23
+ export declare function rank(x: Sample, options?: RankOptions): number[];
@@ -0,0 +1,72 @@
1
+ // Ranks with R's tie methods and placement of missing values (R's rank).
2
+ //
3
+ // Written for rStats.js (no ported code). Missing values (NaN) are ranked apart: kept as NaN, or given the ranks after
4
+ // (or before) all the others in their order of appearance. "random" breaks ties with R's uniform random numbers, one
5
+ // per non-missing value, so the result follows setSeed as R's follows set.seed.
6
+ import { runif } from "../random/continuous.js";
7
+ /** Ranks of values without NaN */
8
+ function rankValues(x, method) {
9
+ const n = x.length;
10
+ const r = new Array(n);
11
+ if (method === "first" || method === "last" || method === "random") {
12
+ const u = method === "random" ? runif(n) : [];
13
+ const idx = Array.from({ length: n }, (_, i) => i);
14
+ idx.sort((a, b) => {
15
+ const d = x[a] - x[b];
16
+ if (d !== 0)
17
+ return d;
18
+ if (method === "first")
19
+ return a - b;
20
+ if (method === "last")
21
+ return b - a;
22
+ return u[a] - u[b] || a - b;
23
+ });
24
+ idx.forEach((i, k) => (r[i] = k + 1));
25
+ return r;
26
+ }
27
+ const idx = Array.from({ length: n }, (_, i) => i).sort((a, b) => x[a] - x[b] || a - b);
28
+ let i = 0;
29
+ while (i < n) {
30
+ let j = i;
31
+ while (j + 1 < n && x[idx[j + 1]] === x[idx[i]])
32
+ j++;
33
+ const v = method === "average" ? (i + j + 2) / 2 : method === "min" ? i + 1 : j + 1;
34
+ for (let k = i; k <= j; k++)
35
+ r[idx[k]] = v;
36
+ i = j + 1;
37
+ }
38
+ return r;
39
+ }
40
+ /**
41
+ * Sample ranks. Equivalent to R's `rank()`.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * rank([10, 20, 20, 30]); // [1, 2.5, 2.5, 4]
46
+ * rank([10, 20, 20, 30], { tiesMethod: "min" }); // [1, 2, 2, 4]
47
+ * ```
48
+ */
49
+ export function rank(x, options = {}) {
50
+ const method = options.tiesMethod ?? "average";
51
+ if (!["average", "first", "last", "random", "max", "min"].includes(method)) {
52
+ throw new RangeError(`invalid tiesMethod "${method}"`);
53
+ }
54
+ const naLast = options.naLast ?? "last";
55
+ const xs = Array.from(x);
56
+ const present = xs.filter((v) => !Number.isNaN(v));
57
+ const r = rankValues(present, method);
58
+ const nMissing = xs.length - present.length;
59
+ const out = [];
60
+ let k = 0;
61
+ let m = 0;
62
+ for (const v of xs) {
63
+ if (Number.isNaN(v)) {
64
+ m++;
65
+ out.push(naLast === "keep" ? NaN : naLast === "last" ? present.length + m : m);
66
+ }
67
+ else {
68
+ out.push(naLast === "first" ? r[k++] + nMissing : r[k++]);
69
+ }
70
+ }
71
+ return out;
72
+ }
@@ -0,0 +1,54 @@
1
+ import type { Sample } from "../htest/types.js";
2
+ /**
3
+ * Counts of the integers 1..nbins in `bin` (values truncated towards 0; others and NaN are not counted).
4
+ * Equivalent to R's `tabulate()`; `nbins` defaults to max(1, bin).
5
+ */
6
+ export declare function tabulate(bin: Sample, nbins?: number): number[];
7
+ /** Options for {@link table}. */
8
+ export interface TableOptions {
9
+ /** Count missing values: `"no"` (default), `"ifany"` (when there are some) or `"always"`. */
10
+ useNA?: "no" | "ifany" | "always";
11
+ }
12
+ /**
13
+ * Frequency table of the distinct values. Equivalent to R's `table()` for one numeric vector: `values` in increasing
14
+ * order (NaN last when counted) with their `counts`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * table([3, 1, 3, 2, 3]); // { values: [1, 2, 3], counts: [1, 1, 3] }
19
+ * ```
20
+ */
21
+ export declare function table(x: Sample, options?: TableOptions): {
22
+ values: number[];
23
+ counts: number[];
24
+ };
25
+ /** Distinct values in order of first appearance (one NaN at most). Equivalent to R's `unique()`. */
26
+ export declare function unique(x: Sample): number[];
27
+ /** Options for {@link cut}. */
28
+ export interface CutOptions {
29
+ /** Intervals closed on the right, (a, b] (default `true`); otherwise [a, b). */
30
+ right?: boolean;
31
+ /** Close the first interval on the left (or the last on the right when `right` is false). Default `false`. */
32
+ includeLowest?: boolean;
33
+ }
34
+ /**
35
+ * Interval numbers (1-based) of the values, or NaN outside the breaks. Equivalent to R's `cut(..., labels = FALSE)`.
36
+ *
37
+ * @param breaks The break points, or a number of intervals (at least 2): then equal intervals over the range of `x`,
38
+ * widened by 1/1000 of the range at each end, as R does.
39
+ */
40
+ export declare function cut(x: Sample, breaks: number | readonly number[], options?: CutOptions): number[];
41
+ /** Options for {@link findInterval}. */
42
+ export interface FindIntervalOptions {
43
+ /** Treat the last interval as closed on the right (with `leftOpen`, the first as closed on the left). */
44
+ rightmostClosed?: boolean;
45
+ /** Map results below 1 to 1 and above N - 1 to N - 1. */
46
+ allInside?: boolean;
47
+ /** Intervals (v_i, v_(i+1)] instead of [v_i, v_(i+1)). */
48
+ leftOpen?: boolean;
49
+ }
50
+ /**
51
+ * For each value, the number of break points at or below it (the interval index). Equivalent to R's
52
+ * `findInterval()`; `vec` must be non-decreasing.
53
+ */
54
+ export declare function findInterval(x: Sample, vec: readonly number[], options?: FindIntervalOptions): number[];
@@ -0,0 +1,160 @@
1
+ // Counting and binning: R's tabulate, table (for one vector), unique, cut (codes) and findInterval.
2
+ //
3
+ // Written for rStats.js. cut's generation of breaks from a number of intervals follows R's behaviour: equal spacing
4
+ // over the range, ends widened by 1/1000 of the range, and a special case for a zero range. NaN stands for R's NA:
5
+ // unique keeps one NaN; table counts it according to `useNA`; cut and findInterval return NaN for it.
6
+ import { seqLength } from "../internal/seq.js";
7
+ /**
8
+ * Counts of the integers 1..nbins in `bin` (values truncated towards 0; others and NaN are not counted).
9
+ * Equivalent to R's `tabulate()`; `nbins` defaults to max(1, bin).
10
+ */
11
+ export function tabulate(bin, nbins) {
12
+ const b = Array.from(bin).map((v) => Math.trunc(v));
13
+ const nb = nbins ?? Math.max(1, ...b.filter((v) => !Number.isNaN(v)));
14
+ const out = new Array(Math.max(0, nb)).fill(0);
15
+ for (const v of b)
16
+ if (v >= 1 && v <= nb)
17
+ out[v - 1]++;
18
+ return out;
19
+ }
20
+ /**
21
+ * Frequency table of the distinct values. Equivalent to R's `table()` for one numeric vector: `values` in increasing
22
+ * order (NaN last when counted) with their `counts`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * table([3, 1, 3, 2, 3]); // { values: [1, 2, 3], counts: [1, 1, 3] }
27
+ * ```
28
+ */
29
+ export function table(x, options = {}) {
30
+ const useNA = options.useNA ?? "no";
31
+ const xs = Array.from(x);
32
+ const map = new Map();
33
+ let nas = 0;
34
+ for (const v of xs) {
35
+ if (Number.isNaN(v))
36
+ nas++;
37
+ else
38
+ map.set(v === 0 ? 0 : v, (map.get(v === 0 ? 0 : v) ?? 0) + 1);
39
+ }
40
+ const values = Array.from(map.keys()).sort((a, b) => a - b);
41
+ const counts = values.map((v) => map.get(v));
42
+ if (useNA === "always" || (useNA === "ifany" && nas > 0)) {
43
+ values.push(NaN);
44
+ counts.push(nas);
45
+ }
46
+ return { values, counts };
47
+ }
48
+ /** Distinct values in order of first appearance (one NaN at most). Equivalent to R's `unique()`. */
49
+ export function unique(x) {
50
+ const seen = new Set();
51
+ const out = [];
52
+ for (const v of Array.from(x)) {
53
+ const k = v === 0 ? 0 : v; // -0 and 0 are the same value
54
+ if (!seen.has(k)) {
55
+ seen.add(k);
56
+ out.push(v);
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+ /**
62
+ * Interval numbers (1-based) of the values, or NaN outside the breaks. Equivalent to R's `cut(..., labels = FALSE)`.
63
+ *
64
+ * @param breaks The break points, or a number of intervals (at least 2): then equal intervals over the range of `x`,
65
+ * widened by 1/1000 of the range at each end, as R does.
66
+ */
67
+ export function cut(x, breaks, options = {}) {
68
+ const right = options.right ?? true;
69
+ const includeLowest = options.includeLowest ?? false;
70
+ const xs = Array.from(x);
71
+ let br;
72
+ if (typeof breaks === "number" || breaks.length === 1) {
73
+ const k = typeof breaks === "number" ? breaks : breaks[0];
74
+ if (!(k >= 2))
75
+ throw new RangeError("invalid number of intervals");
76
+ const nb = Math.trunc(k + 1);
77
+ const finite = xs.filter((v) => !Number.isNaN(v));
78
+ const lo = Math.min(...finite);
79
+ const hi = Math.max(...finite);
80
+ let dx = hi - lo;
81
+ if (dx === 0) {
82
+ dx = lo !== 0 ? Math.abs(lo) : 1;
83
+ br = seqLength(lo - dx / 1000, hi + dx / 1000, nb);
84
+ }
85
+ else {
86
+ br = seqLength(lo, hi, nb);
87
+ br[0] = lo - dx / 1000;
88
+ br[nb - 1] = hi + dx / 1000;
89
+ }
90
+ }
91
+ else
92
+ br = [...breaks].sort((a, b) => a - b);
93
+ if (new Set(br).size < br.length)
94
+ throw new RangeError("'breaks' are not unique");
95
+ return binCode(xs, br, right, includeLowest);
96
+ }
97
+ /** Interval codes as R's .bincode */
98
+ function binCode(xs, br, right, includeLowest) {
99
+ const nb = br.length;
100
+ return xs.map((v) => {
101
+ if (Number.isNaN(v))
102
+ return NaN;
103
+ // first index i with br[i] >= v (right) or br[i] > v (left)
104
+ let lo = 0;
105
+ let hi = nb;
106
+ while (lo < hi) {
107
+ const mid = (lo + hi) >> 1;
108
+ if (right ? br[mid] < v : br[mid] <= v)
109
+ lo = mid + 1;
110
+ else
111
+ hi = mid;
112
+ }
113
+ let code = lo; // v in (br[code - 1], br[code]] (right) or [br[code - 1], br[code]) (left)
114
+ if (includeLowest) {
115
+ if (right && v === br[0])
116
+ code = 1;
117
+ if (!right && v === br[nb - 1])
118
+ code = nb - 1;
119
+ }
120
+ return code >= 1 && code <= nb - 1 ? code : NaN;
121
+ });
122
+ }
123
+ /**
124
+ * For each value, the number of break points at or below it (the interval index). Equivalent to R's
125
+ * `findInterval()`; `vec` must be non-decreasing.
126
+ */
127
+ export function findInterval(x, vec, options = {}) {
128
+ const n = vec.length;
129
+ for (let i = 1; i < n; i++) {
130
+ if (!(vec[i] >= vec[i - 1]))
131
+ throw new RangeError("'vec' must be sorted non-decreasingly and not contain NAs");
132
+ }
133
+ if (vec.some(Number.isNaN))
134
+ throw new RangeError("'vec' must be sorted non-decreasingly and not contain NAs");
135
+ const { rightmostClosed = false, allInside = false, leftOpen = false } = options;
136
+ return Array.from(x).map((v) => {
137
+ if (Number.isNaN(v))
138
+ return NaN;
139
+ // count of vec <= v (or < v when left-open)
140
+ let lo = 0;
141
+ let hi = n;
142
+ while (lo < hi) {
143
+ const mid = (lo + hi) >> 1;
144
+ if (leftOpen ? vec[mid] < v : vec[mid] <= v)
145
+ lo = mid + 1;
146
+ else
147
+ hi = mid;
148
+ }
149
+ let i = lo;
150
+ if (rightmostClosed && n > 0) {
151
+ if (!leftOpen && i === n && v === vec[n - 1])
152
+ i = n - 1;
153
+ if (leftOpen && i === 0 && v === vec[0])
154
+ i = 1;
155
+ }
156
+ if (allInside)
157
+ i = Math.min(Math.max(i, 1), n - 1);
158
+ return i;
159
+ });
160
+ }
@@ -0,0 +1,2 @@
1
+ /*! rStats.js 0.6.1 | MIT License | includes code ported from SciPy, Boost.Math, statsmodels, LAPACK and others: see THIRD_PARTY_NOTICES.md at https://github.com/numero-uno-jpn/rStats.js */
2
+ import{j as V}from"./chunks/chunk-NAYDS7CL.js";import{d as T,e as O}from"./chunks/chunk-AJYQNFXK.js";import"./chunks/chunk-XM2TVD63.js";import{a as q,b as Z,c as $,d as H,e as W,f as G,g as v,h as x,i as L,j as J,k as K,l as Y,m as ee,n as te,o as ne,p as re,q as oe,r as se,s as ie,t as ae,u as fe}from"./chunks/chunk-Y4IZV7XK.js";import{a as j,b as ce,c as le,d as ue,e as me,f as he}from"./chunks/chunk-NOCEAM44.js";import{d as P}from"./chunks/chunk-7NK4SA6B.js";import"./chunks/chunk-QNAIK4PY.js";import"./chunks/chunk-UGUQYWRQ.js";var B=4*Number.EPSILON,de={4:[0,1],5:[.5,.5],6:[0,0],8:[1/3,1/3],9:[3/8,3/8]};function Ne(t,e,r){let s=t.length,f=i=>t[Math.min(Math.max(i,1),s)-1];if(r===7){let i=1+(s-1)*e,d=Math.floor(i),u=f(d),w=f(Math.ceil(i));if(i>d&&w!==u){let b=i-d;return(1-b)*u+b*w}return u}let o,n;if(r<=3){let i=r===3?s*e-.5:s*e;o=Math.floor(i*(1+B)),r===1?n=i>o?1:0:r===2?n=i>o?1:.5:n=i!==o||Math.abs(o%2)===1?1:0}else{let[i,d]=de[r],u=i+e*(s+1-i-d);o=Math.floor(u*(1+B)),n=u-o,Math.abs(n)<B&&(n=0)}let a=f(o),c=f(o+1);return n===1?c:n>0&&n<1&&a!==c?(1-n)*a+n*c:a}function F(t,e=[0,.25,.5,.75,1],r={}){let s=r.type??7;if(!(Number.isInteger(s)&&s>=1&&s<=9))throw new RangeError("'type' must be an integer in 1..9");let f=q(t,r.naRm);if(f===void 0)throw new RangeError("missing values and NaN's not allowed if 'na.rm' is FALSE");let o=f.sort((i,d)=>i-d),n=typeof e=="number"?[e]:Array.from(e),a=100*Number.EPSILON;if(n.some(i=>i<-a||i>1+a))throw new RangeError("'probs' outside [0,1]");let c=n.map(i=>Number.isNaN(i)||o.length===0?NaN:Ne(o,Math.min(Math.max(i,0),1),s));return typeof e=="number"?c[0]:c}function D(t,e={}){let[r,s]=F(t,[.25,.75],e);return s-r}function pe(t){let e=Array.from(t).filter(o=>!Number.isNaN(o)).sort((o,n)=>o-n),r=e.length;if(r===0)return[NaN,NaN,NaN,NaN,NaN];let s=Math.floor((r+3)/2)/2;return[1,s,(r+1)/2,r+1-s,r].map(o=>.5*(e[Math.floor(o)-1]+e[Math.ceil(o)-1]))}function ge(t,e={}){let r=q(t,e.naRm);if(r===void 0)return NaN;let s=e.center??x(r),f=e.constant??1.4826,o=e.low??!1,n=e.high??!1,a=r.map(i=>Math.abs(i-s)),c=a.length;if((o||n)&&c%2===0){if(o&&n)throw new RangeError("'low' and 'high' cannot be both TRUE");let i=c/2+(n?1:0),d=a.sort((u,w)=>u-w);return f*d[i-1]}return f*x(a)}function we(t,e){let r=t.length,s=new Array(r);if(e==="first"||e==="last"||e==="random"){let n=e==="random"?V(r):[],a=Array.from({length:r},(c,i)=>i);return a.sort((c,i)=>{let d=t[c]-t[i];return d!==0?d:e==="first"?c-i:e==="last"?i-c:n[c]-n[i]||c-i}),a.forEach((c,i)=>s[c]=i+1),s}let f=Array.from({length:r},(n,a)=>a).sort((n,a)=>t[n]-t[a]||n-a),o=0;for(;o<r;){let n=o;for(;n+1<r&&t[f[n+1]]===t[f[o]];)n++;let a=e==="average"?(o+n+2)/2:e==="min"?o+1:n+1;for(let c=o;c<=n;c++)s[f[c]]=a;o=n+1}return s}function I(t,e={}){let r=e.tiesMethod??"average";if(!["average","first","last","random","max","min"].includes(r))throw new RangeError(`invalid tiesMethod "${r}"`);let s=e.naLast??"last",f=Array.from(t),o=f.filter(u=>!Number.isNaN(u)),n=we(o,r),a=f.length-o.length,c=[],i=0,d=0;for(let u of f)Number.isNaN(u)?(d++,c.push(s==="keep"?NaN:s==="last"?o.length+d:d)):c.push(s==="first"?n[i++]+a:n[i++]);return c}var be=["pearson","kendall","spearman"],Me=["all.obs","complete.obs","pairwise.complete.obs","everything","na.or.complete"];function C(t,e,r,s){if(t===void 0)return r;if(e.includes(t))return t;let f=e.filter(o=>o.startsWith(t));if(t.length===0||f.length!==1)throw new RangeError(`invalid '${s}' argument`);return f[0]}function R(t){return t.length>0&&Array.isArray(t[0])}function Q(t){if(!R(t))return[Array.from(t)];let e=t[0].length;return Array.from({length:e},(r,s)=>t.map(f=>f[s]))}function U(t,e,r,s){let f=C(r.method,be,"pearson","method"),o=C(r.use,Me,"everything","use");if(e===void 0&&!R(t))throw new TypeError("supply both 'x' and 'y' or a matrix-like 'x'");let n=Q(t),a=e===void 0?n:Q(e),c=n[0]?.length??0;if(a.some(h=>h.length!==c))throw new RangeError("incompatible dimensions");let i=[...n,...a];if(o==="all.obs"&&i.some(h=>h.some(Number.isNaN)))throw new RangeError("missing observations in cov/cor");if(!s&&o==="pairwise.complete.obs"&&f!=="pearson")throw new RangeError("cannot handle 'pairwise.complete.obs'");let d;if((o==="complete.obs"||o==="na.or.complete")&&(d=Array.from({length:c},(h,m)=>i.every(l=>!Number.isNaN(l[m]))),!d.some(Boolean))){if(o==="complete.obs")throw new RangeError("no complete element pairs");return e===void 0||R(t)||R(e)?n.map(()=>a.map(()=>NaN)):NaN}let u=h=>{let m=d===void 0?h:h.filter((l,N)=>d[N]);return f==="spearman"&&o!=="pairwise.complete.obs"?I(m,{naLast:"keep"}):m},w=n.map(u),b=e===void 0?w:a.map(u),y=(h,m)=>{let l=h,N=m;if(o==="pairwise.complete.obs"){let p=h.map((k,M)=>!Number.isNaN(k)&&!Number.isNaN(m[M]));l=h.filter((k,M)=>p[M]),N=m.filter((k,M)=>p[M]),f==="spearman"&&(l=I(l),N=I(N))}else if(l.some(Number.isNaN)||N.some(Number.isNaN))return NaN;return f==="kendall"?s?O(l,N).tau:2*O(l,N).s:s?T(l,N)[0]:P(l,N)},E=w.map(h=>b.map(m=>y(h,m)));return s&&e===void 0&&o!=="pairwise.complete.obs"&&E.forEach((h,m)=>h[m]=1),e!==void 0&&!R(t)&&!R(e)?E[0][0]:E}function ke(t,e,r={}){return e!==void 0&&!Array.isArray(e)&&!ArrayBuffer.isView(e)?U(t,void 0,e,!1):U(t,e,r,!1)}function ye(t,e,r={}){return e!==void 0&&!Array.isArray(e)&&!ArrayBuffer.isView(e)?U(t,void 0,e,!0):U(t,e,r,!0)}function z(t,e={}){let r=Array.from(t).filter(Number.isFinite);if(r.length===0)return[];let s=e.n??5,f=e.minN??Math.floor(s/3),o=e.shrinkSml??.75,n=e.highUBias??1.5,a=e.u5Bias??.5+1.5*n,c=1/0,i=-1/0;for(let g of r)g<c&&(c=g),g>i&&(i=g);let d=i-c,u,w;if(d===0&&i===0)u=1,w=!0;else{u=Math.max(Math.abs(c),Math.abs(i));let A=(1+(a>=1.5*n+.5?1/(1+n):1.5/(1+a)))*Math.max(1,s)*Number.EPSILON;w=d<u*A*3}w?(u>10&&(u=9+u/10),u*=o,f>1&&(u/=f)):(u=s>1?d/s:d,d===1/0&&s>=2&&(u=i/s-c/s));let b=2**-20*Ae;u<b?u=b:u>Number.MAX_VALUE/1.25&&(u=Number.MAX_VALUE/1.25);let y=10**Math.floor(Math.log10(u)),E=[[2*y,n],[5*y,a],[10*y,n]],h=y;for(let[g,A]of E)if(g-u<A*(u-h))h=g;else break;let m=1e-10,l=Math.floor(c/h+m);for(;l*h>c+m*h;)l--;for(;!Number.isFinite(l*h);)l++;let N=Math.ceil(i/h-m);for(;N*h<i-m*h;)N++;for(;!Number.isFinite(N*h);)N--;let p=Math.trunc(.5+N-l);if(p<f){let g=f-p,A=Math.floor(g/2),_=g%2;c===0&&l===0&&i!==0?N+=g:i===0&&N===0&&c!==0?l-=g:l>=0?(N+=A,l-=A+_):(l-=A,N+=A+_),p=f}let k=l*h<c?l*h:c,M=N*h>i?N*h:i;if(p<=0)return[k];let S;if(Number.isFinite(M-k))S=j(k,M,p+1);else{let g=M/p-k/p;S=Array.from({length:p+1},(A,_)=>k+_*g),S[p]=M}let X=M/p-k/p;return S.map(g=>Math.abs(g)<1e-14*X?0:g)}var Ae=22250738585072014e-324;function Ee(t){return t===0||!Number.isFinite(t)?t:Number(t.toPrecision(5))}function xe(t,e){let r=t.length,[s,f]=L(t),o=f-s;switch(e.toLowerCase()){case"sturges":return Math.ceil(Math.log2(r)+1);case"scott":{let n=3.5*v(t)*r**-.3333333333333333;return n>0?Math.max(1,Math.ceil(o/n)):1}case"fd":case"freedman-diaconis":{let n=t.map(Ee),a=2*D(n);for(let c=1/8;a===0&&c>=1/512;c/=2){let[i,d]=F(n,[c,1-c]);a=(d-i)/(1-2*c)}return a===0&&(a=3.5*v(t)),a>0?Math.ceil(o/a*r**(1/3)):1}default:throw new RangeError("unknown 'breaks' algorithm")}}function Re(t,e){let r=t.slice(1).map((s,f)=>s-t[f]);return t.length>5?x(r):t.length<=3?e:Math.min(...r.filter(s=>s>0))}function Le(t,e={}){let r=Array.from(t).filter(Number.isFinite),s=r.length,f=e.right??!0,o=e.includeLowest??!0,n=e.breaks??"Sturges",a;if(typeof n!="string"&&typeof n!="number"&&n.length>1)a=[...n].sort((m,l)=>m-l);else{o=!0;let m=typeof n=="string"?xe(r,n):typeof n=="number"?n:n[0];if(!Number.isFinite(m)||m<1)throw new RangeError("invalid number of 'breaks'");m=Math.min(m,1e6);let[l,N]=L(r);a=z([l,N],{n:m,minN:1});for(let p=1;p<a.length;p++)if(!(a[p]-a[p-1]>0))throw new RangeError("'breaks' are not strictly increasing")}let c=a.length,[i,d]=s>0?L(r):[0,0],u=1e-7*Re(a,d-i),w=a.map((m,l)=>f?l===0&&o?m-u:m+u:l<c-1?m-u:o?m+u:m-u),b=new Array(Math.max(0,c-1)).fill(0),y=0;for(let m of r){let l=Ie(m,w,f,o);l>=0&&(b[l]++,y++)}if(y<s)throw new RangeError("some 'x' not counted; maybe 'breaks' do not span range of 'x'");let E=b.map((m,l)=>m/(s*(a[l+1]-a[l]))),h=b.map((m,l)=>.5*(a[l+1]+a[l]));return{breaks:a,counts:b,density:E,mids:h}}function Ie(t,e,r,s){let f=e.length-1;if(f<1)return-1;if(r){if(t===e[0]&&s)return 0;if(!(t>e[0]&&t<=e[f]))return-1;let a=1,c=f;for(;a<c;){let i=a+c>>1;t<=e[i]?c=i:a=i+1}return a-1}if(t===e[f]&&s)return f-1;if(!(t>=e[0]&&t<e[f]))return-1;let o=0,n=f-1;for(;o<n;){let a=o+n+1>>1;e[a]<=t?o=a:n=a-1}return o}function Se(t){let e=Array.from(t).filter(s=>!Number.isNaN(s)).sort((s,f)=>s-f),r=e.length;if(r<1)throw new RangeError("'x' must have 1 or more non-missing values");return s=>{if(Number.isNaN(s))return NaN;let f=0,o=r;for(;f<o;){let n=f+o>>1;e[n]<=s?f=n+1:o=n}return f/r}}export{D as IQR,ye as cor,ke as cov,Y as cummax,ee as cummin,K as cumprod,J as cumsum,me as cut,ae as cv,te as diff,Se as ecdf,he as findInterval,pe as fivenum,oe as geometricMean,Le as hist,re as kurtosis,ge as mad,H as mean,ie as meanAD,x as median,se as modes,z as pretty,$ as prod,F as quantile,L as range,I as rank,fe as scale,v as sd,ne as skewness,Z as sum,le as table,ce as tabulate,ue as unique,G as variance,W as weightedMean};
@@ -0,0 +1,24 @@
1
+ import { type Vectorizable, type VectorResult } from "../internal/vectorize.js";
2
+ import { type DensityOptions, type TailOptions } from "../internal/dpq.js";
3
+ /** Limits of the arcsine distribution. */
4
+ export interface ArcsineParams {
5
+ /** Lower limit. Default `0`. */
6
+ a?: number;
7
+ /** Upper limit. Default `1`. */
8
+ b?: number;
9
+ }
10
+ export declare function darcsine1(x: number, a: number, b: number, log: boolean): number;
11
+ export declare function parcsine1(q: number, a: number, b: number, lowerTail: boolean, logP: boolean): number;
12
+ export declare function qarcsine1(p: number, a: number, b: number, lowerTail: boolean, logP: boolean): number;
13
+ /**
14
+ * Density of the arcsine distribution on (a, b), f(x) = 1 / (pi sqrt((x - a)(b - x))). R has no arcsine
15
+ * distribution; this equals `dbeta((x - a) / (b - a), 0.5, 0.5) / (b - a)`.
16
+ *
17
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
18
+ * @param options - `a` and `b` (see {@link ArcsineParams}) and `log` (see {@link DensityOptions}).
19
+ */
20
+ export declare function darcsine<T extends Vectorizable>(x: T, options?: ArcsineParams & DensityOptions): VectorResult<T>;
21
+ /** Distribution function of the arcsine distribution on (a, b): `pbeta((q - a) / (b - a), 0.5, 0.5)`. */
22
+ export declare function parcsine<T extends Vectorizable>(q: T, options?: ArcsineParams & TailOptions): VectorResult<T>;
23
+ /** Quantile function of the arcsine distribution on (a, b): `a + (b - a) qbeta(p, 0.5, 0.5)`. */
24
+ export declare function qarcsine<T extends Vectorizable>(p: T, options?: ArcsineParams & TailOptions): VectorResult<T>;
@@ -0,0 +1,73 @@
1
+ // Arcsine distribution darcsine / parcsine / qarcsine on (a, b): the beta(1/2, 1/2) distribution moved to (a, b).
2
+ //
3
+ // Written for rStats.js (no ported code). With z = (x - a) / (b - a): f(x) = dbeta(z, 1/2, 1/2) / (b - a)
4
+ // = 1 / (pi sqrt((x - a)(b - x))), P[X <= x] = pbeta(z, 1/2, 1/2) = (2/pi) asin(sqrt(z)), and
5
+ // q(p) = a + (b - a) qbeta(p, 1/2, 1/2).
6
+ // Near b, 1 - z would cancel once z is rounded, so the density takes x - a and b - x directly, and in the upper half
7
+ // the distribution function and the quantile use the mirrored variable (b - x) / (b - a) with the tails swapped
8
+ // (the beta(1/2, 1/2) distribution is symmetric).
9
+ import { vectorize } from "../internal/vectorize.js";
10
+ import { d0, dt0, dt1, quantileBoundaries } from "../internal/dpq.js";
11
+ import { ddAdd, ddLog, twoSum } from "../special/dd.js";
12
+ import { pbeta1, qbeta1 } from "./beta.js";
13
+ const valid = (a, b) => Number.isFinite(a) && Number.isFinite(b) && a < b;
14
+ export function darcsine1(x, a, b, log) {
15
+ if (Number.isNaN(x) || !valid(a, b))
16
+ return NaN;
17
+ if (x < a || x > b)
18
+ return d0(log);
19
+ if (x === a || x === b)
20
+ return Infinity;
21
+ if (!log)
22
+ return 1 / (Math.PI * Math.sqrt(x - a) * Math.sqrt(b - x)); // sqrt of each: the product can over- or underflow
23
+ // -log(pi) - (log(x - a) + log(b - x)) / 2 in double-double from the exact differences (the log of a density near 1
24
+ // would turn its rounding into a large relative error)
25
+ const l = ddAdd(ddLog(twoSum(x, -a)), ddLog(twoSum(b, -x)));
26
+ return -LOGPI_DD[0] - 0.5 * l[0] - (LOGPI_DD[1] + 0.5 * l[1]);
27
+ }
28
+ const LOGPI_DD = [1.1447298858494002, 1.0265951162707826e-17];
29
+ export function parcsine1(q, a, b, lowerTail, logP) {
30
+ if (Number.isNaN(q) || !valid(a, b))
31
+ return NaN;
32
+ if (q <= a)
33
+ return dt0(lowerTail, logP);
34
+ if (q >= b)
35
+ return dt1(lowerTail, logP);
36
+ const w = b - a;
37
+ if (q - a <= b - q)
38
+ return pbeta1((q - a) / w, 0.5, 0.5, lowerTail, logP);
39
+ return pbeta1((b - q) / w, 0.5, 0.5, !lowerTail, logP);
40
+ }
41
+ export function qarcsine1(p, a, b, lowerTail, logP) {
42
+ if (Number.isNaN(p) || !valid(a, b))
43
+ return NaN;
44
+ const bd = quantileBoundaries(p, a, b, lowerTail, logP);
45
+ if (bd !== undefined)
46
+ return bd;
47
+ const z = qbeta1(p, 0.5, 0.5, lowerTail, logP);
48
+ if (z <= 0.5)
49
+ return a + (b - a) * z;
50
+ // upper half: from b, with the mirrored probability (z near 1 has lost the digits of 1 - z)
51
+ return b - (b - a) * qbeta1(p, 0.5, 0.5, !lowerTail, logP);
52
+ }
53
+ /**
54
+ * Density of the arcsine distribution on (a, b), f(x) = 1 / (pi sqrt((x - a)(b - x))). R has no arcsine
55
+ * distribution; this equals `dbeta((x - a) / (b - a), 0.5, 0.5) / (b - a)`.
56
+ *
57
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
58
+ * @param options - `a` and `b` (see {@link ArcsineParams}) and `log` (see {@link DensityOptions}).
59
+ */
60
+ export function darcsine(x, options = {}) {
61
+ const { a = 0, b = 1, log = false } = options;
62
+ return vectorize(x, (v) => darcsine1(v, a, b, log));
63
+ }
64
+ /** Distribution function of the arcsine distribution on (a, b): `pbeta((q - a) / (b - a), 0.5, 0.5)`. */
65
+ export function parcsine(q, options = {}) {
66
+ const { a = 0, b = 1, lowerTail = true, logP = false } = options;
67
+ return vectorize(q, (v) => parcsine1(v, a, b, lowerTail, logP));
68
+ }
69
+ /** Quantile function of the arcsine distribution on (a, b): `a + (b - a) qbeta(p, 0.5, 0.5)`. */
70
+ export function qarcsine(p, options = {}) {
71
+ const { a = 0, b = 1, lowerTail = true, logP = false } = options;
72
+ return vectorize(p, (v) => qarcsine1(v, a, b, lowerTail, logP));
73
+ }
@@ -0,0 +1,29 @@
1
+ import { type Vectorizable, type VectorResult } from "../internal/vectorize.js";
2
+ import { type DensityOptions, type TailOptions } from "../internal/dpq.js";
3
+ /** Scale parameter of the inverse gamma distribution. */
4
+ export interface InvgammaParams {
5
+ /** Scale (the rate of the gamma distribution of 1/X). Default `1`. */
6
+ beta?: number;
7
+ }
8
+ export declare function dinvgamma1(x: number, alpha: number, beta: number, log: boolean): number;
9
+ export declare function pinvgamma1(q: number, alpha: number, beta: number, lowerTail: boolean, logP: boolean): number;
10
+ export declare function qinvgamma1(p: number, alpha: number, beta: number, lowerTail: boolean, logP: boolean): number;
11
+ /**
12
+ * Density of the inverse gamma distribution. Equivalent to `extraDistr::dinvgamma(x, alpha, beta = 1, log = FALSE)`:
13
+ * f(x) = beta^alpha x^(-alpha-1) exp(-beta/x) / Gamma(alpha).
14
+ *
15
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
16
+ * @param alpha - Shape parameter.
17
+ * @param options - `beta` (see {@link InvgammaParams}) and `log` (see {@link DensityOptions}).
18
+ */
19
+ export declare function dinvgamma<T extends Vectorizable>(x: T, alpha: number, options?: InvgammaParams & DensityOptions): VectorResult<T>;
20
+ /**
21
+ * Distribution function of the inverse gamma distribution. Equivalent to
22
+ * `extraDistr::pinvgamma(q, alpha, beta = 1, lower.tail = TRUE, log.p = FALSE)`.
23
+ */
24
+ export declare function pinvgamma<T extends Vectorizable>(q: T, alpha: number, options?: InvgammaParams & TailOptions): VectorResult<T>;
25
+ /**
26
+ * Quantile function of the inverse gamma distribution. Equivalent to
27
+ * `extraDistr::qinvgamma(p, alpha, beta = 1, lower.tail = TRUE, log.p = FALSE)`.
28
+ */
29
+ export declare function qinvgamma<T extends Vectorizable>(p: T, alpha: number, options?: InvgammaParams & TailOptions): VectorResult<T>;