@numero-uno-jpn/rstats 0.0.0-stage → 0.5.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.
Files changed (159) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +21 -0
  3. package/README.ja.md +181 -0
  4. package/README.md +172 -2
  5. package/THIRD_PARTY_NOTICES.md +297 -0
  6. package/dist/distributions/beta.d.ts +62 -0
  7. package/dist/distributions/beta.js +246 -0
  8. package/dist/distributions/binomial.d.ts +41 -0
  9. package/dist/distributions/binomial.js +136 -0
  10. package/dist/distributions/cauchy.d.ts +34 -0
  11. package/dist/distributions/cauchy.js +139 -0
  12. package/dist/distributions/chisq.d.ts +42 -0
  13. package/dist/distributions/chisq.js +60 -0
  14. package/dist/distributions/exponential.d.ts +34 -0
  15. package/dist/distributions/exponential.js +93 -0
  16. package/dist/distributions/f.d.ts +47 -0
  17. package/dist/distributions/f.js +214 -0
  18. package/dist/distributions/gamma.d.ts +61 -0
  19. package/dist/distributions/gamma.js +188 -0
  20. package/dist/distributions/geometric.d.ts +38 -0
  21. package/dist/distributions/geometric.js +116 -0
  22. package/dist/distributions/hypergeometric.d.ts +38 -0
  23. package/dist/distributions/hypergeometric.js +234 -0
  24. package/dist/distributions/logistic.d.ts +36 -0
  25. package/dist/distributions/logistic.js +94 -0
  26. package/dist/distributions/lognormal.d.ts +39 -0
  27. package/dist/distributions/lognormal.js +158 -0
  28. package/dist/distributions/nbeta.d.ts +7 -0
  29. package/dist/distributions/nbeta.js +312 -0
  30. package/dist/distributions/nchisq.d.ts +3 -0
  31. package/dist/distributions/nchisq.js +217 -0
  32. package/dist/distributions/negbinomial.d.ts +54 -0
  33. package/dist/distributions/negbinomial.js +325 -0
  34. package/dist/distributions/normal.d.ts +66 -0
  35. package/dist/distributions/normal.js +184 -0
  36. package/dist/distributions/nt.d.ts +3 -0
  37. package/dist/distributions/nt.js +491 -0
  38. package/dist/distributions/poisson.d.ts +41 -0
  39. package/dist/distributions/poisson.js +104 -0
  40. package/dist/distributions/signrank.d.ts +38 -0
  41. package/dist/distributions/signrank.js +216 -0
  42. package/dist/distributions/t.d.ts +49 -0
  43. package/dist/distributions/t.js +235 -0
  44. package/dist/distributions/tukey.d.ts +43 -0
  45. package/dist/distributions/tukey.js +985 -0
  46. package/dist/distributions/uniform.d.ts +36 -0
  47. package/dist/distributions/uniform.js +90 -0
  48. package/dist/distributions/weibull.d.ts +37 -0
  49. package/dist/distributions/weibull.js +125 -0
  50. package/dist/distributions/wilcox.d.ts +47 -0
  51. package/dist/distributions/wilcox.js +270 -0
  52. package/dist/htest/chisqTest.d.ts +55 -0
  53. package/dist/htest/chisqTest.js +160 -0
  54. package/dist/htest/cor.d.ts +81 -0
  55. package/dist/htest/cor.js +436 -0
  56. package/dist/htest/fisherTest.d.ts +48 -0
  57. package/dist/htest/fisherTest.js +468 -0
  58. package/dist/htest/pAdjust.d.ts +34 -0
  59. package/dist/htest/pAdjust.js +147 -0
  60. package/dist/htest/tTest.d.ts +57 -0
  61. package/dist/htest/tTest.js +153 -0
  62. package/dist/htest/types.d.ts +49 -0
  63. package/dist/htest/types.js +20 -0
  64. package/dist/htest/wilcoxTest.d.ts +61 -0
  65. package/dist/htest/wilcoxTest.js +471 -0
  66. package/dist/index.d.ts +50 -0
  67. package/dist/index.js +50 -0
  68. package/dist/internal/ddexp.d.ts +19 -0
  69. package/dist/internal/ddexp.js +94 -0
  70. package/dist/internal/discrete.d.ts +14 -0
  71. package/dist/internal/discrete.js +85 -0
  72. package/dist/internal/dpq.d.ts +43 -0
  73. package/dist/internal/dpq.js +54 -0
  74. package/dist/internal/integer.d.ts +4 -0
  75. package/dist/internal/integer.js +17 -0
  76. package/dist/internal/invert.d.ts +36 -0
  77. package/dist/internal/invert.js +124 -0
  78. package/dist/internal/noncentral.d.ts +12 -0
  79. package/dist/internal/noncentral.js +2 -0
  80. package/dist/internal/poissonMixture.d.ts +31 -0
  81. package/dist/internal/poissonMixture.js +401 -0
  82. package/dist/internal/summary.d.ts +21 -0
  83. package/dist/internal/summary.js +125 -0
  84. package/dist/internal/uniroot.d.ts +11 -0
  85. package/dist/internal/uniroot.js +75 -0
  86. package/dist/internal/vectorize.d.ts +12 -0
  87. package/dist/internal/vectorize.js +7 -0
  88. package/dist/linalg/basic.d.ts +95 -0
  89. package/dist/linalg/basic.js +152 -0
  90. package/dist/linalg/chol.d.ts +83 -0
  91. package/dist/linalg/chol.js +200 -0
  92. package/dist/linalg/eigen.d.ts +52 -0
  93. package/dist/linalg/eigen.js +753 -0
  94. package/dist/linalg/kappa.d.ts +51 -0
  95. package/dist/linalg/kappa.js +199 -0
  96. package/dist/linalg/matrix.d.ts +29 -0
  97. package/dist/linalg/matrix.js +65 -0
  98. package/dist/linalg/norm.d.ts +32 -0
  99. package/dist/linalg/norm.js +92 -0
  100. package/dist/linalg/qr.d.ts +264 -0
  101. package/dist/linalg/qr.js +494 -0
  102. package/dist/linalg/solve.d.ts +123 -0
  103. package/dist/linalg/solve.js +380 -0
  104. package/dist/linalg/svd.d.ts +38 -0
  105. package/dist/linalg/svd.js +275 -0
  106. package/dist/random/as241.d.ts +2 -0
  107. package/dist/random/as241.js +58 -0
  108. package/dist/random/beta.d.ts +14 -0
  109. package/dist/random/beta.js +117 -0
  110. package/dist/random/binomial.d.ts +25 -0
  111. package/dist/random/binomial.js +224 -0
  112. package/dist/random/common.d.ts +4 -0
  113. package/dist/random/common.js +35 -0
  114. package/dist/random/continuous.d.ts +91 -0
  115. package/dist/random/continuous.js +138 -0
  116. package/dist/random/gamma.d.ts +52 -0
  117. package/dist/random/gamma.js +217 -0
  118. package/dist/random/hyper.d.ts +12 -0
  119. package/dist/random/hyper.js +240 -0
  120. package/dist/random/mt.d.ts +16 -0
  121. package/dist/random/mt.js +97 -0
  122. package/dist/random/poisson.d.ts +33 -0
  123. package/dist/random/poisson.js +204 -0
  124. package/dist/random/rank.d.ts +19 -0
  125. package/dist/random/rank.js +62 -0
  126. package/dist/random/rng.d.ts +46 -0
  127. package/dist/random/rng.js +148 -0
  128. package/dist/random/sample.d.ts +45 -0
  129. package/dist/random/sample.js +255 -0
  130. package/dist/rstats.js +2 -0
  131. package/dist/special/beta.d.ts +30 -0
  132. package/dist/special/beta.js +152 -0
  133. package/dist/special/constants.d.ts +16 -0
  134. package/dist/special/constants.js +19 -0
  135. package/dist/special/dd.d.ts +29 -0
  136. package/dist/special/dd.js +693 -0
  137. package/dist/special/erf.d.ts +9 -0
  138. package/dist/special/erf.js +85 -0
  139. package/dist/special/gamma.d.ts +32 -0
  140. package/dist/special/gamma.js +270 -0
  141. package/dist/special/igam.d.ts +11 -0
  142. package/dist/special/igam.js +291 -0
  143. package/dist/special/igamAsympCoeff.d.ts +4 -0
  144. package/dist/special/igamAsympCoeff.js +233 -0
  145. package/dist/special/igami.d.ts +2 -0
  146. package/dist/special/igami.js +135 -0
  147. package/dist/special/incbet.d.ts +25 -0
  148. package/dist/special/incbet.js +326 -0
  149. package/dist/special/lgammaDiff.d.ts +2 -0
  150. package/dist/special/lgammaDiff.js +34 -0
  151. package/dist/special/loader.d.ts +43 -0
  152. package/dist/special/loader.js +456 -0
  153. package/dist/special/log1pmx.d.ts +2 -0
  154. package/dist/special/log1pmx.js +20 -0
  155. package/dist/special/ndtri.d.ts +4 -0
  156. package/dist/special/ndtri.js +82 -0
  157. package/dist/special/polevl.d.ts +4 -0
  158. package/dist/special/polevl.js +17 -0
  159. package/package.json +68 -4
@@ -0,0 +1,234 @@
1
+ // Hypergeometric distribution dhyper / phyper / qhyper (same arguments as R: k balls drawn from m white and n black).
2
+ //
3
+ // Probabilities use Loader's (2000) decomposition into binomial probabilities:
4
+ // p(x) = b(x; m, p) b(k - x; n, p) / b(k; m + n, p), p = k / (m + n)
5
+ // The exponents of the three binomial probabilities are added and subtracted in double-double before taking exp.
6
+ // The distribution function sums the tail far from the mean directly as p(x) × Σ (products of ratios of adjacent
7
+ // probabilities) (products and sums in double-double). Quantiles use an integer search on the distribution function.
8
+ import { vectorize } from "../internal/vectorize.js";
9
+ import { d0, dt0, dt1, quantileBoundaries } from "../internal/dpq.js";
10
+ import { discreteQuantile } from "../internal/discrete.js";
11
+ import { nonInt, roundHalfEven } from "../internal/integer.js";
12
+ import { bd0dd, dbinomExponent } from "../special/loader.js";
13
+ import { ddAdd, ddDiv, ddLog, ddMul, ddNeg, ddSub, twoProd } from "../special/dd.js";
14
+ import { qnorm } from "./normal.js";
15
+ /**
16
+ * Binomial probability b(x; x + nmx, p) as an ExpForm (0 <= x, 0 <= nmx, 0 < p < 1).
17
+ * At the ends (x = 0 or nmx = 0), q^n / p^n is represented by the exponent alone.
18
+ */
19
+ function binomForm(x, nmx, p, q) {
20
+ if (x === 0 && nmx === 0)
21
+ return { e: [0, 0], logDenom: 0 };
22
+ if (x === 0 || nmx === 0) {
23
+ // q^n (x = 0) or p^n (nmx = 0)
24
+ const n = x + nmx;
25
+ const [a, b] = x === 0 ? [q, p] : [p, q];
26
+ // When the base is close to 1 (the other side b is small), avoid cancellation with n log a = -bd0(n, n a) - n b
27
+ const e = b[0] < 0.1 ? ddAdd(bd0dd(n, ddMul([n, 0], a)), ddMul([n, 0], b)) : ddNeg(ddMul([n, 0], ddLog(a)));
28
+ return { e, logDenom: 0 };
29
+ }
30
+ return dbinomExponent(x, nmx, p, q);
31
+ }
32
+ /** ExpForm of p(x) (x an integer in the support, 0 < k < m + n) */
33
+ function hyperForm(x, m, n, k) {
34
+ const N = m + n;
35
+ const p = ddDiv([k, 0], [N, 0]);
36
+ const q = ddDiv([N - k, 0], [N, 0]);
37
+ const f1 = binomForm(x, m - x, p, q);
38
+ const f2 = binomForm(k - x, n - k + x, p, q);
39
+ const f3 = binomForm(k, N - k, p, q);
40
+ return {
41
+ e: ddSub(ddAdd(f1.e, f2.e), f3.e),
42
+ logDenom: f1.logDenom + f2.logDenom - f3.logDenom,
43
+ };
44
+ }
45
+ /** exp(-e) / sqrt(exp(logDenom)) × s. Rounding happens once at the end even for results near subnormal */
46
+ function evalForm(f, s) {
47
+ const [eh, el] = f.e;
48
+ const scale = s * Math.exp(-0.5 * f.logDenom);
49
+ if (eh < 700)
50
+ return Math.exp(-eh) * (1 - el) * scale;
51
+ return Math.exp(700 - eh) * (1 - el) * scale * Math.exp(-700);
52
+ }
53
+ function logForm(f) {
54
+ return -f.e[0] - f.e[1] - 0.5 * f.logDenom;
55
+ }
56
+ /** Support [lo, hi] */
57
+ function support(m, n, k) {
58
+ return [Math.max(0, k - n), Math.min(k, m)];
59
+ }
60
+ export function dhyper1(x, m, n, k, log) {
61
+ if ([x, m, n, k].some(Number.isNaN))
62
+ return NaN;
63
+ if (![m, n, k].every(Number.isFinite) || nonInt(m) || nonInt(n) || nonInt(k))
64
+ return NaN;
65
+ m = roundHalfEven(m);
66
+ n = roundHalfEven(n);
67
+ k = roundHalfEven(k);
68
+ if (m < 0 || n < 0 || k < 0 || k > m + n)
69
+ return NaN;
70
+ if (nonInt(x))
71
+ return d0(log);
72
+ x = roundHalfEven(x);
73
+ const [lo, hi] = support(m, n, k);
74
+ if (x < lo || x > hi)
75
+ return d0(log);
76
+ if (k === 0 || k === m + n)
77
+ return log ? 0 : 1;
78
+ const f = hyperForm(x, m, n, k);
79
+ return log ? logForm(f) : evalForm(f, 1);
80
+ }
81
+ /** a b / (c d) in double-double (a..d integers) */
82
+ function ratio(a, b, c, d) {
83
+ return ddDiv(twoProd(a, b), twoProd(c, d));
84
+ }
85
+ /**
86
+ * Sum of the tail far from the mean. If lower, P[X <= x] = p(x) Σ_{j>=0} p(x-j)/p(x);
87
+ * otherwise P[X >= x] = p(x) Σ p(x+j)/p(x). Returns the sum S = Σ p(x∓j)/p(x).
88
+ */
89
+ function tailSum(x, m, n, k, lower, lo, hi) {
90
+ let t = [1, 0];
91
+ let s = [1, 0];
92
+ let y = x;
93
+ for (;;) {
94
+ if (lower ? y <= lo : y >= hi)
95
+ break;
96
+ // Ratio p(y-1)/p(y) = y (n - k + y) / ((m - y + 1)(k - y + 1))
97
+ // p(y+1)/p(y) = (m - y)(k - y) / ((y + 1)(n - k + y + 1))
98
+ const r = lower ? ratio(y, n - k + y, m - y + 1, k - y + 1) : ratio(m - y, k - y, y + 1, n - k + y + 1);
99
+ t = ddMul(t, r);
100
+ s = ddAdd(s, t);
101
+ y += lower ? -1 : 1;
102
+ // Moving away from the mean, the ratio decreases monotonically. The remaining sum is bounded by t r / (1 - r)
103
+ const rr = r[0];
104
+ if (rr < 1 && (t[0] * rr) / (1 - rr) < s[0] * 2 ** -60)
105
+ break;
106
+ }
107
+ return s[0] + s[1];
108
+ }
109
+ /** P[X <= x] (lowerTail) / P[X > x] at an integer x inside the support (lo <= x < hi) */
110
+ function phyperRaw(x, m, n, k, lowerTail, logP) {
111
+ const [lo, hi] = support(m, n, k);
112
+ const N = m + n;
113
+ // Below the mean k m / N sum the lower tail directly; otherwise the upper tail P[X >= x + 1]
114
+ let lowerSide = x * N < k * m;
115
+ let tail = directTail(x, m, n, k, lowerSide, lo, hi);
116
+ if (tail.value > 0.5) {
117
+ // When the mean is near an end of the support, even the side far from the mean can exceed 1/2. Sum the other
118
+ // side directly too and use the smaller (so that the log of a value near 1 is formed from 1 - (other side))
119
+ const other = directTail(x, m, n, k, !lowerSide, lo, hi);
120
+ if (other.value < tail.value) {
121
+ tail = other;
122
+ lowerSide = !lowerSide;
123
+ }
124
+ }
125
+ if (lowerSide === lowerTail) {
126
+ if (!logP)
127
+ return tail.value;
128
+ return tail.value > 1e-300 ? Math.log(tail.value) : logForm(tail.form) + Math.log(tail.sum);
129
+ }
130
+ return logP ? Math.log1p(-tail.value) : 1 - tail.value;
131
+ }
132
+ /** P[X <= x] (lowerSide) or P[X >= x + 1], computed directly as the probability at the tail's end × the sum of ratios */
133
+ function directTail(x, m, n, k, lowerSide, lo, hi) {
134
+ const start = lowerSide ? x : x + 1;
135
+ const form = hyperForm(start, m, n, k);
136
+ const sum = tailSum(start, m, n, k, lowerSide, lo, hi);
137
+ return { form, sum, value: evalForm(form, sum) };
138
+ }
139
+ /** Check and round the parameters of phyper / qhyper. undefined if invalid */
140
+ function hyperParams(m, n, k) {
141
+ if (![m, n, k].every(Number.isFinite))
142
+ return undefined;
143
+ m = roundHalfEven(m);
144
+ n = roundHalfEven(n);
145
+ k = roundHalfEven(k);
146
+ if (m < 0 || n < 0 || k < 0 || k > m + n)
147
+ return undefined;
148
+ return [m, n, k];
149
+ }
150
+ export function phyper1(q, m, n, k, lowerTail, logP) {
151
+ if ([q, m, n, k].some(Number.isNaN))
152
+ return NaN;
153
+ const params = hyperParams(m, n, k);
154
+ if (params === undefined)
155
+ return NaN;
156
+ [m, n, k] = params;
157
+ const x = Math.floor(q + 1e-7);
158
+ const [lo, hi] = support(m, n, k);
159
+ if (x < lo)
160
+ return dt0(lowerTail, logP);
161
+ if (x >= hi)
162
+ return dt1(lowerTail, logP);
163
+ return phyperRaw(x, m, n, k, lowerTail, logP);
164
+ }
165
+ export function qhyper1(p, m, n, k, lowerTail, logP) {
166
+ if ([p, m, n, k].some(Number.isNaN))
167
+ return NaN;
168
+ const params = hyperParams(m, n, k);
169
+ if (params === undefined)
170
+ return NaN;
171
+ [m, n, k] = params;
172
+ const [lo, hi] = support(m, n, k);
173
+ const b = quantileBoundaries(p, lo, hi, lowerTail, logP);
174
+ if (b !== undefined)
175
+ return b;
176
+ if (lo === hi)
177
+ return lo;
178
+ const N = m + n;
179
+ const mu = (k * m) / N;
180
+ const sigma = Math.sqrt((((k * m) / N) * (n / N) * (N - k)) / Math.max(N - 1, 1));
181
+ const z = qnorm(p, { lowerTail, logP });
182
+ const y0 = mu + sigma * z;
183
+ return discreteQuantile({
184
+ p,
185
+ lowerTail,
186
+ logP,
187
+ cdf: (y, l, lg) => (y < lo ? dt0(l, lg) : y >= hi ? dt1(l, lg) : phyperRaw(y, m, n, k, l, lg)),
188
+ y0: Number.isFinite(y0) ? y0 : mu,
189
+ lo,
190
+ hi,
191
+ });
192
+ }
193
+ /**
194
+ * Probability mass function of the hypergeometric distribution (number of white balls among `k` drawn without replacement from an urn of `m` white and `n` black balls). Equivalent to R's `dhyper(x, m, n, k, log = FALSE)`.
195
+ *
196
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
197
+ * @param m - Number of white balls in the urn.
198
+ * @param n - Number of black balls in the urn.
199
+ * @param k - Number of balls drawn.
200
+ * @param options - `log` (see {@link DensityOptions}).
201
+ * @returns The probability (or log probability).
202
+ */
203
+ export function dhyper(x, m, n, k, options = {}) {
204
+ const log = options.log ?? false;
205
+ return vectorize(x, (v) => dhyper1(v, m, n, k, log));
206
+ }
207
+ /**
208
+ * Distribution function of the hypergeometric distribution (number of white balls among `k` drawn without replacement from an urn of `m` white and `n` black balls). Equivalent to R's `phyper(q, m, n, k, lower.tail = TRUE, log.p = FALSE)`.
209
+ *
210
+ * @param q - Quantile(s): a number, `number[]` or `Float64Array`. The result has the same shape.
211
+ * @param m - Number of white balls in the urn.
212
+ * @param n - Number of black balls in the urn.
213
+ * @param k - Number of balls drawn.
214
+ * @param options - `lowerTail` and `logP` (see {@link TailOptions}).
215
+ * @returns The probability (or log probability).
216
+ */
217
+ export function phyper(q, m, n, k, options = {}) {
218
+ const { lowerTail = true, logP = false } = options;
219
+ return vectorize(q, (v) => phyper1(v, m, n, k, lowerTail, logP));
220
+ }
221
+ /**
222
+ * Quantile function of the hypergeometric distribution (number of white balls among `k` drawn without replacement from an urn of `m` white and `n` black balls). Equivalent to R's `qhyper(p, m, n, k, lower.tail = TRUE, log.p = FALSE)`.
223
+ *
224
+ * @param p - Probability (or log probability with `logP`): a number, `number[]` or `Float64Array`. The result has the same shape.
225
+ * @param m - Number of white balls in the urn.
226
+ * @param n - Number of black balls in the urn.
227
+ * @param k - Number of balls drawn.
228
+ * @param options - `lowerTail` and `logP` (see {@link TailOptions}).
229
+ * @returns The quantile(s).
230
+ */
231
+ export function qhyper(p, m, n, k, options = {}) {
232
+ const { lowerTail = true, logP = false } = options;
233
+ return vectorize(p, (v) => qhyper1(v, m, n, k, lowerTail, logP));
234
+ }
@@ -0,0 +1,36 @@
1
+ import { type Vectorizable, type VectorResult } from "../internal/vectorize.js";
2
+ import { type DensityOptions, type TailOptions } from "../internal/dpq.js";
3
+ /** Location and scale parameters, used by the logistic and Cauchy distributions. */
4
+ export interface LocationScaleParams {
5
+ /** Location. Default `0`. */
6
+ location?: number;
7
+ /** Scale. Default `1`. */
8
+ scale?: number;
9
+ }
10
+ export declare function dlogis1(x: number, location: number, scale: number, log: boolean): number;
11
+ export declare function plogis1(q: number, location: number, scale: number, lowerTail: boolean, logP: boolean): number;
12
+ export declare function qlogis1(p: number, location: number, scale: number, lowerTail: boolean, logP: boolean): number;
13
+ /**
14
+ * Density of the logistic distribution. Equivalent to R's `dlogis(x, location = 0, scale = 1, log = FALSE)`.
15
+ *
16
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
17
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}) and `log` (see {@link DensityOptions}).
18
+ * @returns The density (or log density).
19
+ */
20
+ export declare function dlogis<T extends Vectorizable>(x: T, options?: LocationScaleParams & DensityOptions): VectorResult<T>;
21
+ /**
22
+ * Distribution function of the logistic distribution. Equivalent to R's `plogis(q, location = 0, scale = 1, lower.tail = TRUE, log.p = FALSE)`.
23
+ *
24
+ * @param q - Quantile(s): a number, `number[]` or `Float64Array`. The result has the same shape.
25
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}), `lowerTail` and `logP` (see {@link TailOptions}).
26
+ * @returns The probability (or log probability).
27
+ */
28
+ export declare function plogis<T extends Vectorizable>(q: T, options?: LocationScaleParams & TailOptions): VectorResult<T>;
29
+ /**
30
+ * Quantile function of the logistic distribution. Equivalent to R's `qlogis(p, location = 0, scale = 1, lower.tail = TRUE, log.p = FALSE)`.
31
+ *
32
+ * @param p - Probability (or log probability with `logP`): a number, `number[]` or `Float64Array`. The result has the same shape.
33
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}), `lowerTail` and `logP` (see {@link TailOptions}).
34
+ * @returns The quantile(s).
35
+ */
36
+ export declare function qlogis<T extends Vectorizable>(p: T, options?: LocationScaleParams & TailOptions): VectorResult<T>;
@@ -0,0 +1,94 @@
1
+ // Logistic distribution dlogis / plogis / qlogis.
2
+ //
3
+ // With z = (x - location) / scale, a = |z|, e = exp(-a),
4
+ // f(x) = e / (scale (1 + e)^2), probability of the larger side 1 / (1 + e), of the smaller side e / (1 + e)
5
+ // z is formed in double-double (the relative error of exp(-a) equals the absolute error of a).
6
+ // Quantiles compute logit(p) = log(p / (1 - p)) in a cancellation-free form.
7
+ import { vectorize } from "../internal/vectorize.js";
8
+ import { quantileBoundaries } from "../internal/dpq.js";
9
+ import { expNeg, locationScale, log1mExp, standardizeDD } from "../internal/ddexp.js";
10
+ export function dlogis1(x, location, scale, log) {
11
+ if (Number.isNaN(x) || Number.isNaN(location) || Number.isNaN(scale))
12
+ return NaN;
13
+ if (!(scale > 0))
14
+ return NaN;
15
+ const z = standardizeDD(x, location, scale);
16
+ if (Number.isNaN(z[0]))
17
+ return NaN;
18
+ const a = z[0] < 0 ? [-z[0], -z[1]] : [z[0], z[1]];
19
+ const e = expNeg(a);
20
+ if (log)
21
+ return -a[0] - a[1] - Math.log(scale) - 2 * Math.log1p(e);
22
+ return e / (scale * (1 + e) * (1 + e));
23
+ }
24
+ export function plogis1(q, location, scale, lowerTail, logP) {
25
+ if (Number.isNaN(q) || Number.isNaN(location) || Number.isNaN(scale))
26
+ return NaN;
27
+ if (!(scale > 0))
28
+ return NaN;
29
+ const z = standardizeDD(q, location, scale);
30
+ if (Number.isNaN(z[0]))
31
+ return NaN;
32
+ const a = z[0] < 0 ? [-z[0], -z[1]] : [z[0], z[1]];
33
+ const e = expNeg(a);
34
+ // The lower probability is the larger side when z >= 0
35
+ const big = lowerTail === z[0] >= 0;
36
+ if (big)
37
+ return logP ? -Math.log1p(e) : 1 / (1 + e);
38
+ return logP ? -a[0] - a[1] - Math.log1p(e) : e / (1 + e);
39
+ }
40
+ /** logit(p) = log(p / (1 - p)). p is a log if logP */
41
+ function logit(p, logP) {
42
+ if (logP)
43
+ return p - log1mExp(p);
44
+ if (p < 0.25)
45
+ return Math.log(p / (1 - p));
46
+ // 2p - 1 is exact. Avoids cancellation in log near 1/2
47
+ return Math.log1p((2 * p - 1) / (1 - p));
48
+ }
49
+ export function qlogis1(p, location, scale, lowerTail, logP) {
50
+ if (Number.isNaN(p) || Number.isNaN(location) || Number.isNaN(scale))
51
+ return NaN;
52
+ const b = quantileBoundaries(p, -Infinity, Infinity, lowerTail, logP);
53
+ if (b !== undefined)
54
+ return b;
55
+ if (scale < 0)
56
+ return NaN;
57
+ if (scale === 0)
58
+ return location;
59
+ const l = logit(p, logP);
60
+ return locationScale(location, scale, lowerTail ? l : -l);
61
+ }
62
+ /**
63
+ * Density of the logistic distribution. Equivalent to R's `dlogis(x, location = 0, scale = 1, log = FALSE)`.
64
+ *
65
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
66
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}) and `log` (see {@link DensityOptions}).
67
+ * @returns The density (or log density).
68
+ */
69
+ export function dlogis(x, options = {}) {
70
+ const { location = 0, scale = 1, log = false } = options;
71
+ return vectorize(x, (v) => dlogis1(v, location, scale, log));
72
+ }
73
+ /**
74
+ * Distribution function of the logistic distribution. Equivalent to R's `plogis(q, location = 0, scale = 1, lower.tail = TRUE, log.p = FALSE)`.
75
+ *
76
+ * @param q - Quantile(s): a number, `number[]` or `Float64Array`. The result has the same shape.
77
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}), `lowerTail` and `logP` (see {@link TailOptions}).
78
+ * @returns The probability (or log probability).
79
+ */
80
+ export function plogis(q, options = {}) {
81
+ const { location = 0, scale = 1, lowerTail = true, logP = false } = options;
82
+ return vectorize(q, (v) => plogis1(v, location, scale, lowerTail, logP));
83
+ }
84
+ /**
85
+ * Quantile function of the logistic distribution. Equivalent to R's `qlogis(p, location = 0, scale = 1, lower.tail = TRUE, log.p = FALSE)`.
86
+ *
87
+ * @param p - Probability (or log probability with `logP`): a number, `number[]` or `Float64Array`. The result has the same shape.
88
+ * @param options - `location` and `scale` (see {@link LocationScaleParams}), `lowerTail` and `logP` (see {@link TailOptions}).
89
+ * @returns The quantile(s).
90
+ */
91
+ export function qlogis(p, options = {}) {
92
+ const { location = 0, scale = 1, lowerTail = true, logP = false } = options;
93
+ return vectorize(p, (v) => qlogis1(v, location, scale, lowerTail, logP));
94
+ }
@@ -0,0 +1,39 @@
1
+ import { type Vectorizable, type VectorResult } from "../internal/vectorize.js";
2
+ import { type DensityOptions, type TailOptions } from "../internal/dpq.js";
3
+ import { type DD } from "../special/dd.js";
4
+ /** Parameters of the log-normal distribution (mean and standard deviation on the log scale). */
5
+ export interface LognormalParams {
6
+ /** Mean of the distribution on the log scale. Default `0`. */
7
+ meanlog?: number;
8
+ /** Standard deviation of the distribution on the log scale. Default `1`. */
9
+ sdlog?: number;
10
+ }
11
+ /** P[Z <= t] of the standard normal. t is double-double (finite) */
12
+ export declare function pnormDD(t: DD, logP: boolean): number;
13
+ export declare function dlnorm1(x: number, meanlog: number, sdlog: number, log: boolean): number;
14
+ export declare function plnorm1(q: number, meanlog: number, sdlog: number, lowerTail: boolean, logP: boolean): number;
15
+ export declare function qlnorm1(p: number, meanlog: number, sdlog: number, lowerTail: boolean, logP: boolean): number;
16
+ /**
17
+ * Density of the log-normal distribution. Equivalent to R's `dlnorm(x, meanlog = 0, sdlog = 1, log = FALSE)`.
18
+ *
19
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
20
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}) and `log` (see {@link DensityOptions}).
21
+ * @returns The density (or log density).
22
+ */
23
+ export declare function dlnorm<T extends Vectorizable>(x: T, options?: LognormalParams & DensityOptions): VectorResult<T>;
24
+ /**
25
+ * Distribution function of the log-normal distribution. Equivalent to R's `plnorm(q, meanlog = 0, sdlog = 1, lower.tail = TRUE, log.p = FALSE)`.
26
+ *
27
+ * @param q - Quantile(s): a number, `number[]` or `Float64Array`. The result has the same shape.
28
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}), `lowerTail` and `logP` (see {@link TailOptions}).
29
+ * @returns The probability (or log probability).
30
+ */
31
+ export declare function plnorm<T extends Vectorizable>(q: T, options?: LognormalParams & TailOptions): VectorResult<T>;
32
+ /**
33
+ * Quantile function of the log-normal distribution. Equivalent to R's `qlnorm(p, meanlog = 0, sdlog = 1, lower.tail = TRUE, log.p = FALSE)`.
34
+ *
35
+ * @param p - Probability (or log probability with `logP`): a number, `number[]` or `Float64Array`. The result has the same shape.
36
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}), `lowerTail` and `logP` (see {@link TailOptions}).
37
+ * @returns The quantile(s).
38
+ */
39
+ export declare function qlnorm<T extends Vectorizable>(p: T, options?: LognormalParams & TailOptions): VectorResult<T>;
@@ -0,0 +1,158 @@
1
+ // Log-normal distribution dlnorm / plnorm / qlnorm.
2
+ //
3
+ // log X ~ N(meanlog, sdlog^2). z = (log x - meanlog) / sdlog is formed in double-double, and z^2 in
4
+ // exp(-z^2/2) is also computed in double-double (for large |log x|, the rounding of log x becomes an absolute
5
+ // error in z^2/2 and hence a relative error in the density and tail probabilities).
6
+ // Tail probabilities use Φ(-a) = erfcx(a/√2) exp(-a^2/2) / 2 (xsf's erfcx, src/special/erf.ts).
7
+ import { vectorize } from "../internal/vectorize.js";
8
+ import { d0, dt0 } from "../internal/dpq.js";
9
+ import { expNeg, mulDD } from "../internal/ddexp.js";
10
+ import { ddAdd, ddDiv, ddLog, ddMul, ddSub, twoSum } from "../special/dd.js";
11
+ import { erfcxNonNegative } from "../special/erf.js";
12
+ import { pnorm, qnorm } from "./normal.js";
13
+ const LN_SQRT_2PI = 0.918938533204672741780329736406;
14
+ const INV_SQRT_2PI = 0.398942280401432677939946059934;
15
+ /** z = (log x - meanlog) / sdlog (x > 0, finite parameters, sdlog > 0) */
16
+ function zOf(x, meanlog, sdlog) {
17
+ const d = ddSub(ddLog([x, 0]), [meanlog, 0]);
18
+ if (sdlog === 1)
19
+ return d;
20
+ const hi = d[0] / sdlog;
21
+ return Number.isFinite(hi) && Math.abs(hi) < 1e300 ? ddDiv(d, [sdlog, 0]) : [hi, 0];
22
+ }
23
+ /** z^2 / 2 in double-double */
24
+ function halfSquare(z) {
25
+ if (Math.abs(z[0]) > 1e150)
26
+ return [(z[0] * z[0]) / 2, 0];
27
+ const s = ddMul(z, z);
28
+ return [s[0] / 2, s[1] / 2];
29
+ }
30
+ /** P[Z <= t] of the standard normal. t is double-double (finite) */
31
+ export function pnormDD(t, logP) {
32
+ if (t[0] > -Math.SQRT2) {
33
+ if (t[0] < Math.SQRT2)
34
+ return pnorm(t[0] + t[1], { logP });
35
+ // Side close to 1: 1 - Φ(-t)
36
+ const other = smallTail(t[0], [t[0], t[1]], false);
37
+ return logP ? Math.log1p(-other) : 1 - other;
38
+ }
39
+ return smallTail(-t[0], [-t[0], -t[1]], logP);
40
+ }
41
+ /** Φ(-a) (a >= √2) */
42
+ function smallTail(a, ad, logP) {
43
+ const c = 0.5 * erfcxNonNegative(a * Math.SQRT1_2);
44
+ const h = halfSquare(ad);
45
+ if (logP)
46
+ return Math.log(c) - h[0] - h[1];
47
+ return c * expNeg(h);
48
+ }
49
+ const SQRT_2PI = 2.506628274631000502415765284811;
50
+ /**
51
+ * Attach a double-double low-order term to the standard normal quantile z0 (the double value from qnorm).
52
+ * In exp(meanlog + sdlog z) the rounding of z (1e-16 relative) is amplified sdlog |z| times, so compute one
53
+ * Newton correction δ from the residual of the distribution function and set z = z0 + δ.
54
+ * In the tails use φ(s) / Φ(s) = 1 / (√(2π) c) (c = erfcx(|s|/√2) / 2) to avoid dividing probabilities.
55
+ */
56
+ function refineStdQuantile(z0, p, lowerTail, logP) {
57
+ // s is the point corresponding to the probability p on that side (P[Z <= s] = p)
58
+ const s = lowerTail ? z0 : -z0;
59
+ let delta;
60
+ // Residual r = log(Φ(-a) / target) = log c - a^2/2 - log target. Subtract the large terms from each other first
61
+ const residual = (c, h, lt) => -h[0] - lt[0] + (-h[1] - lt[1]) + Math.log(c);
62
+ if (s <= -Math.SQRT2) {
63
+ const c = 0.5 * erfcxNonNegative(-s * Math.SQRT1_2);
64
+ const lt = logP ? [p, 0] : ddLog([p, 0]);
65
+ delta = -residual(c, halfSquare([-s, 0]), lt) * SQRT_2PI * c;
66
+ }
67
+ else if (s >= Math.SQRT2) {
68
+ // Measure the residual with the other side G = P[Z > s] (1 - p is exact for p >= 1/2)
69
+ const c = 0.5 * erfcxNonNegative(s * Math.SQRT1_2);
70
+ const target = logP ? -Math.expm1(p) : 1 - p;
71
+ delta = residual(c, halfSquare([s, 0]), ddLog([target, 0])) * SQRT_2PI * c;
72
+ }
73
+ else {
74
+ const F = pnorm(s);
75
+ const phi = Math.exp((-s * s) / 2) / SQRT_2PI;
76
+ delta = ((logP ? Math.exp(p) : p) - F) / phi;
77
+ }
78
+ if (!Number.isFinite(delta))
79
+ return [z0, 0];
80
+ return twoSum(z0, lowerTail ? delta : -delta);
81
+ }
82
+ export function dlnorm1(x, meanlog, sdlog, log) {
83
+ if (Number.isNaN(x) || Number.isNaN(meanlog) || Number.isNaN(sdlog))
84
+ return NaN;
85
+ if (sdlog < 0)
86
+ return NaN;
87
+ if (x <= 0)
88
+ return d0(log);
89
+ if (sdlog === 0)
90
+ return Math.log(x) === meanlog ? Infinity : d0(log);
91
+ if (!Number.isFinite(x) || !Number.isFinite(meanlog) || !Number.isFinite(sdlog)) {
92
+ const y = (Math.log(x) - meanlog) / sdlog;
93
+ return Number.isNaN(y) ? NaN : d0(log);
94
+ }
95
+ const z = zOf(x, meanlog, sdlog);
96
+ const h = halfSquare(z);
97
+ if (log)
98
+ return -(LN_SQRT_2PI + h[0] + h[1] + Math.log(sdlog) + Math.log(x));
99
+ return (INV_SQRT_2PI * expNeg(h)) / sdlog / x;
100
+ }
101
+ export function plnorm1(q, meanlog, sdlog, lowerTail, logP) {
102
+ if (Number.isNaN(q) || Number.isNaN(meanlog) || Number.isNaN(sdlog))
103
+ return NaN;
104
+ if (sdlog < 0)
105
+ return NaN;
106
+ if (q <= 0)
107
+ return dt0(lowerTail, logP);
108
+ if (sdlog === 0 || !Number.isFinite(q) || !Number.isFinite(meanlog) || !Number.isFinite(sdlog)) {
109
+ return pnorm(Math.log(q), { mean: meanlog, sd: sdlog, lowerTail, logP });
110
+ }
111
+ const z = zOf(q, meanlog, sdlog);
112
+ return pnormDD(lowerTail ? z : [-z[0], -z[1]], logP);
113
+ }
114
+ export function qlnorm1(p, meanlog, sdlog, lowerTail, logP) {
115
+ if (Number.isNaN(p) || Number.isNaN(meanlog) || Number.isNaN(sdlog))
116
+ return NaN;
117
+ const z = qnorm(p, { lowerTail, logP });
118
+ if (!Number.isFinite(z) || !(sdlog > 0) || !Number.isFinite(sdlog) || !Number.isFinite(meanlog)) {
119
+ return Math.exp(qnorm(p, { mean: meanlog, sd: sdlog, lowerTail, logP }));
120
+ }
121
+ // exp(meanlog + sdlog z). Form the exponent in double-double and apply the low-order term to first order
122
+ const zd = refineStdQuantile(z, p, lowerTail, logP);
123
+ const e = ddAdd(ddAdd(mulDD(sdlog, zd[0]), [sdlog * zd[1], 0]), [meanlog, 0]);
124
+ return Math.exp(e[0]) * (1 + e[1]);
125
+ }
126
+ /**
127
+ * Density of the log-normal distribution. Equivalent to R's `dlnorm(x, meanlog = 0, sdlog = 1, log = FALSE)`.
128
+ *
129
+ * @param x - Value(s) at which to evaluate: a number, `number[]` or `Float64Array`. The result has the same shape.
130
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}) and `log` (see {@link DensityOptions}).
131
+ * @returns The density (or log density).
132
+ */
133
+ export function dlnorm(x, options = {}) {
134
+ const { meanlog = 0, sdlog = 1, log = false } = options;
135
+ return vectorize(x, (v) => dlnorm1(v, meanlog, sdlog, log));
136
+ }
137
+ /**
138
+ * Distribution function of the log-normal distribution. Equivalent to R's `plnorm(q, meanlog = 0, sdlog = 1, lower.tail = TRUE, log.p = FALSE)`.
139
+ *
140
+ * @param q - Quantile(s): a number, `number[]` or `Float64Array`. The result has the same shape.
141
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}), `lowerTail` and `logP` (see {@link TailOptions}).
142
+ * @returns The probability (or log probability).
143
+ */
144
+ export function plnorm(q, options = {}) {
145
+ const { meanlog = 0, sdlog = 1, lowerTail = true, logP = false } = options;
146
+ return vectorize(q, (v) => plnorm1(v, meanlog, sdlog, lowerTail, logP));
147
+ }
148
+ /**
149
+ * Quantile function of the log-normal distribution. Equivalent to R's `qlnorm(p, meanlog = 0, sdlog = 1, lower.tail = TRUE, log.p = FALSE)`.
150
+ *
151
+ * @param p - Probability (or log probability with `logP`): a number, `number[]` or `Float64Array`. The result has the same shape.
152
+ * @param options - `meanlog` and `sdlog` (see {@link LognormalParams}), `lowerTail` and `logP` (see {@link TailOptions}).
153
+ * @returns The quantile(s).
154
+ */
155
+ export function qlnorm(p, options = {}) {
156
+ const { meanlog = 0, sdlog = 1, lowerTail = true, logP = false } = options;
157
+ return vectorize(p, (v) => qlnorm1(v, meanlog, sdlog, lowerTail, logP));
158
+ }
@@ -0,0 +1,7 @@
1
+ export declare function dnbeta1(x: number, a: number, b: number, ncp: number, log: boolean): number;
2
+ export declare function pnbeta1(q: number, a: number, b: number, ncp: number, lowerTail: boolean, logP: boolean): number;
3
+ export declare function qnbeta1(p: number, a: number, b: number, ncp: number, lowerTail: boolean, logP: boolean): number;
4
+ export declare function pnfRaw(q: number, m: number, n: number, ncp: number, lower: boolean, log: boolean): number;
5
+ export declare function dnf1(x: number, m: number, n: number, ncp: number, log: boolean): number;
6
+ export declare function pnf1(q: number, m: number, n: number, ncp: number, lowerTail: boolean, logP: boolean): number;
7
+ export declare function qnf1(p: number, m: number, n: number, ncp: number, lowerTail: boolean, logP: boolean): number;