@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,508 @@
1
+ // Bessel functions J and Y of real order: besselJ, besselY.
2
+ //
3
+ // Ported from Boost.Math include/boost/math/special_functions/detail/bessel_jy.hpp, detail/bessel_jy_series.hpp and
4
+ // detail/bessel_jy_asym.hpp (Boost.Math commit 0a0fb4e).
5
+ // Copyright (c) 2006 Xiaogang Zhang, (c) 2007 John Maddock. Boost Software License 1.0. See THIRD_PARTY_NOTICES.md.
6
+ //
7
+ // Changes from Boost
8
+ // - Integer orders go through the same algorithm (Boost dispatches them to bessel_jn / bessel_yn).
9
+ // - The series prefix (x/2)^v / Gamma(v + 1) uses Loader's Poisson term for large v, as in besselIK.ts.
10
+ // - Negative orders follow R's documentation (A&S 9.1.2):
11
+ // J_-v = cos(pi v) J_v - sin(pi v) Y_v, Y_-v = sin(pi v) J_v + cos(pi v) Y_v.
12
+ import { gamma, lgamma, lgamma1p, lgammaSign, sinpi } from "./gamma.js";
13
+ import { seriesTimesPrefix } from "./besselSeries.js";
14
+ import { ddDiv, ddMul, ddSub, twoSum } from "./dd.js";
15
+ const EPS = Number.EPSILON;
16
+ /** Multiply by 2^e without overflow in the intermediate power */
17
+ function ldexp(m, e) {
18
+ if (!Number.isFinite(e))
19
+ return e > 0 ? m * Infinity : m * 0;
20
+ while (e > 1000) {
21
+ m *= 2 ** 1000;
22
+ e -= 1000;
23
+ }
24
+ while (e < -1000) {
25
+ m *= 2 ** -1000;
26
+ e += 1000;
27
+ }
28
+ return m * 2 ** e;
29
+ }
30
+ /** Forward recurrence Y_(u+k+1) = 2 (u + k) / x Y_(u+k) - Y_(u+k-1) for k = 1..n, rescaling by powers of 2 (exact) */
31
+ function yForward(u, x, n, y0, y1) {
32
+ let prev = y0;
33
+ let current = y1;
34
+ let e2 = 0;
35
+ for (let k = 1; k <= n; k++) {
36
+ const fact = (2 * (u + k)) / x;
37
+ // the factor itself can be huge (2e300 at x = 1e-300), so look at the size of the product
38
+ const lg = Math.log2(Math.abs(current)) + Math.log2(fact);
39
+ if (lg > 900 && Number.isFinite(lg)) {
40
+ const s = Math.ceil(lg - 800);
41
+ prev = ldexp(prev, -s);
42
+ current = ldexp(current, -s);
43
+ e2 += s;
44
+ }
45
+ const next = fact * current - prev;
46
+ prev = current;
47
+ current = next;
48
+ }
49
+ return { y: prev, y1: current, e2 };
50
+ }
51
+ const MAX_ITER = 1_000_000;
52
+ const TINY = Math.sqrt(2.2250738585072014e-308);
53
+ const DBL_MAX = Number.MAX_VALUE;
54
+ function tgamma1pm1(v) {
55
+ return Math.expm1(lgamma1p(v));
56
+ }
57
+ /** cos(pi x), exact at half-integers */
58
+ function cospi(x) {
59
+ return sinpi(0.5 - Math.abs(x % 2));
60
+ }
61
+ /** J_v(x) by its power series (x small compared to v) */
62
+ function jSmallZ(v, x) {
63
+ const mult = -(x / 2) * (x / 2);
64
+ let term = 1;
65
+ let sum = 0;
66
+ for (let n = 1; n < MAX_ITER; n++) {
67
+ sum += term;
68
+ term *= mult / (n * (n + v));
69
+ if (Math.abs(term) <= EPS * Math.abs(sum))
70
+ break;
71
+ }
72
+ return seriesTimesPrefix(v, x, sum + term);
73
+ }
74
+ /**
75
+ * Y_v(x) by its power series for x small compared to v (non-integer v), as m 2^e2 (the prefix can overflow while
76
+ * the reflection formula still multiplies it by a small factor)
77
+ */
78
+ function ySmallZ(v, x) {
79
+ let p = Math.log(x / 2);
80
+ let e2 = 0;
81
+ const needLogs = v >= 170 || 709.78 / v < Math.abs(p);
82
+ let prefix;
83
+ if (!needLogs) {
84
+ let gam = gamma(v);
85
+ p = Math.pow(x / 2, v);
86
+ if (DBL_MAX * p < gam) {
87
+ gam *= 2 ** -1000;
88
+ e2 = 1000;
89
+ }
90
+ prefix = -gam / (Math.PI * p);
91
+ }
92
+ else {
93
+ const gam = lgamma(v);
94
+ p = v * p;
95
+ prefix = gam - Math.log(Math.PI) - p;
96
+ if (709.78 < prefix) {
97
+ const k = Math.ceil((prefix - 700) / Math.LN2);
98
+ prefix -= k * Math.LN2;
99
+ e2 = k;
100
+ }
101
+ prefix = -Math.exp(prefix);
102
+ }
103
+ const mult = -(x / 2) * (x / 2);
104
+ let term = 1;
105
+ let sum = 0;
106
+ for (let n = 1; n < MAX_ITER; n++) {
107
+ sum += term;
108
+ term *= mult / (n * (n - v));
109
+ if (Math.abs(term) <= EPS * Math.abs(sum))
110
+ break;
111
+ }
112
+ let result = (sum + term) * prefix;
113
+ let prefix2;
114
+ if (!needLogs) {
115
+ prefix2 = (gamma(-v) * cospi(v) * p) / Math.PI;
116
+ }
117
+ else {
118
+ const lg = lgammaSign(-v);
119
+ prefix2 = (Math.exp(lg.value + p) * lg.sign) / Math.PI;
120
+ }
121
+ term = 1;
122
+ let b = 0;
123
+ for (let n = 1; n < MAX_ITER; n++) {
124
+ b += term;
125
+ term *= mult / (n * (n + v));
126
+ if (Math.abs(term) <= EPS * Math.abs(b))
127
+ break;
128
+ }
129
+ b += term;
130
+ result -= ldexp(prefix2 * b, -e2);
131
+ return { m: result, e2 };
132
+ }
133
+ /** Hankel's asymptotic series P and Q (A&S 9.2.9, 9.2.10); false if it does not converge */
134
+ function hankelPQ(v, x) {
135
+ let p = 1;
136
+ let q = 0;
137
+ let k = 1;
138
+ const z8 = 8 * x;
139
+ let sq = 1;
140
+ const mu = 4 * v * v;
141
+ let term = 1;
142
+ let ok = true;
143
+ do {
144
+ term *= (mu - sq * sq) / (k * z8);
145
+ q += term;
146
+ k += 1;
147
+ sq += 2;
148
+ const mult = (sq * sq - mu) / (k * z8);
149
+ ok = Math.abs(mult) < 0.5;
150
+ term *= mult;
151
+ p += term;
152
+ k += 1;
153
+ sq += 2;
154
+ } while (Math.abs(term) > 2 * EPS * p && ok);
155
+ return ok ? { p, q } : undefined;
156
+ }
157
+ /** Y_u(x) and Y_(u+1)(x) by Temme's series (|u| <= 1/2, x <= 2) */
158
+ function temmeJY(u, x) {
159
+ const gp = tgamma1pm1(u);
160
+ const gm = tgamma1pm1(-u);
161
+ const spv = sinpi(u);
162
+ const spv2 = sinpi(u / 2);
163
+ const xp = Math.pow(x / 2, u);
164
+ const a = Math.log(x / 2);
165
+ const sigma = -a * u;
166
+ const d = Math.abs(sigma) < EPS ? 1 : Math.sinh(sigma) / sigma;
167
+ const e = Math.abs(u) < EPS ? (u * Math.PI * Math.PI) / 2 : (2 * spv2 * spv2) / u;
168
+ const g1 = u === 0 ? -0.5772156649015329 : (gp - gm) / ((1 + gp) * (1 + gm) * 2 * u);
169
+ const g2 = (2 + gp + gm) / ((1 + gp) * (1 + gm) * 2);
170
+ const vspv = Math.abs(u) < EPS ? 1 / Math.PI : u / spv;
171
+ let f = (g1 * Math.cosh(sigma) - g2 * a * d) * 2 * vspv;
172
+ let p = vspv / (xp * (1 + gm));
173
+ let q = (vspv * xp) / (1 + gp);
174
+ let g = f + e * q;
175
+ let h = p;
176
+ let coef = 1;
177
+ let sum = coef * g;
178
+ let sum1 = coef * h;
179
+ const v2 = u * u;
180
+ const coefMult = (-x * x) / 4;
181
+ for (let k = 1; k < MAX_ITER; k++) {
182
+ f = (k * f + p + q) / (k * k - v2);
183
+ p /= k - u;
184
+ q /= k + u;
185
+ g = f + e * q;
186
+ h = p - k * g;
187
+ coef *= coefMult / k;
188
+ sum += coef * g;
189
+ sum1 += coef * h;
190
+ if (Math.abs(coef * g) < Math.abs(sum) * EPS)
191
+ break;
192
+ }
193
+ return [-sum, (-2 * sum1) / x];
194
+ }
195
+ /**
196
+ * cf1JY in double-double, with b_k = 2 (v + k) / x formed from the exact v + k. For x ≫ v the continued fraction
197
+ * needs about x terms in the region where it oscillates, and the rounding of v + k (which repeats with k) and of the
198
+ * Lentz steps add up to 3e-13 relative at v = 575, x = 2211 even in double precision with exact b_k
199
+ */
200
+ function cf1JYDD(v, x) {
201
+ let C = [TINY, 0];
202
+ let f = [TINY, 0];
203
+ let D = [0, 0];
204
+ let s = 1;
205
+ const xd = [x, 0];
206
+ for (let k = 1; k < MAX_ITER * 100; k++) {
207
+ const vk = twoSum(v, k);
208
+ const b = ddDiv([2 * vk[0], 2 * vk[1]], xd);
209
+ C = ddSub(b, ddDiv([1, 0], C));
210
+ D = ddSub(b, D);
211
+ if (C[0] === 0)
212
+ C = [TINY, 0];
213
+ if (D[0] === 0)
214
+ D = [TINY, 0];
215
+ D = ddDiv([1, 0], D);
216
+ const delta = ddMul(C, D);
217
+ f = ddMul(f, delta);
218
+ if (D[0] < 0)
219
+ s = -s;
220
+ if (Math.abs(delta[0] - 1 + delta[1]) < EPS * EPS)
221
+ break;
222
+ }
223
+ return { fv: -(f[0] + f[1]), sign: s };
224
+ }
225
+ /** fv = J_(v+1) / J_v by continued fraction (A&S 9.1.73, modified Lentz), and the sign of the denominator */
226
+ function cf1JY(v, x) {
227
+ if (x > 30)
228
+ return cf1JYDD(v, x);
229
+ let C = TINY;
230
+ let f = TINY;
231
+ let D = 0;
232
+ let s = 1;
233
+ for (let k = 1; k < MAX_ITER * 100; k++) {
234
+ const b = (2 * (v + k)) / x;
235
+ C = b - 1 / C;
236
+ D = b - D;
237
+ if (C === 0)
238
+ C = TINY;
239
+ if (D === 0)
240
+ D = TINY;
241
+ D = 1 / D;
242
+ const delta = C * D;
243
+ f *= delta;
244
+ if (D < 0)
245
+ s = -s;
246
+ if (Math.abs(delta - 1) < 2 * EPS)
247
+ break;
248
+ }
249
+ return { fv: -f, sign: s };
250
+ }
251
+ /** p + iq = (J' + iY') / (J + iY) by Steed's complex continued fraction, in real arithmetic (x > 1) */
252
+ function cf2JY(v, x) {
253
+ let fr = -0.5 / x;
254
+ let fi = 1;
255
+ let Cr = fr;
256
+ let Ci = fi;
257
+ const v2 = v * v;
258
+ let a = (0.25 - v2) / x;
259
+ const br = 2 * x;
260
+ let bi = 2;
261
+ let temp = Cr * Cr + 1;
262
+ Ci = bi + (a * Cr) / temp;
263
+ Cr = br + a / temp;
264
+ let Dr = br;
265
+ let Di = bi;
266
+ if (Math.abs(Cr) + Math.abs(Ci) < TINY)
267
+ Cr = TINY;
268
+ if (Math.abs(Dr) + Math.abs(Di) < TINY)
269
+ Dr = TINY;
270
+ temp = Dr * Dr + Di * Di;
271
+ Dr = Dr / temp;
272
+ Di = -Di / temp;
273
+ let dr = Cr * Dr - Ci * Di;
274
+ let di = Ci * Dr + Cr * Di;
275
+ temp = fr;
276
+ fr = temp * dr - fi * di;
277
+ fi = temp * di + fi * dr;
278
+ for (let k = 2; k < MAX_ITER; k++) {
279
+ a = k - 0.5;
280
+ a *= a;
281
+ a -= v2;
282
+ bi += 2;
283
+ temp = Cr * Cr + Ci * Ci;
284
+ Cr = br + (a * Cr) / temp;
285
+ Ci = bi - (a * Ci) / temp;
286
+ Dr = br + a * Dr;
287
+ Di = bi + a * Di;
288
+ if (Math.abs(Cr) + Math.abs(Ci) < TINY)
289
+ Cr = TINY;
290
+ if (Math.abs(Dr) + Math.abs(Di) < TINY)
291
+ Dr = TINY;
292
+ temp = Dr * Dr + Di * Di;
293
+ Dr = Dr / temp;
294
+ Di = -Di / temp;
295
+ dr = Cr * Dr - Ci * Di;
296
+ di = Ci * Dr + Cr * Di;
297
+ temp = fr;
298
+ fr = temp * dr - fi * di;
299
+ fi = temp * di + fi * dr;
300
+ if (Math.abs(dr - 1) + Math.abs(di) < 2 * EPS)
301
+ break;
302
+ }
303
+ return { p: fr, q: fi };
304
+ }
305
+ /** Amplitude of J and Y for large x (A&S 9.2.28) */
306
+ function asymAmplitude(v, x) {
307
+ let s = 1;
308
+ const mu = 4 * v * v;
309
+ let txq = 2 * x;
310
+ txq *= txq;
311
+ s += (mu - 1) / (2 * txq);
312
+ s += (3 * (mu - 1) * (mu - 9)) / (txq * txq * 8);
313
+ s += (15 * (mu - 1) * (mu - 9) * (mu - 25)) / (txq * txq * txq * 8 * 6);
314
+ return Math.sqrt((s * 2) / (Math.PI * x));
315
+ }
316
+ /** Phase of J and Y for large x less (x - pi (v/2 + 1/4)) (A&S 9.2.29) */
317
+ function asymPhaseMx(v, x) {
318
+ const mu = 4 * v * v;
319
+ let denom = 4 * x;
320
+ const denomMult = denom * denom;
321
+ let s = 0;
322
+ s += (mu - 1) / (2 * denom);
323
+ denom *= denomMult;
324
+ s += ((mu - 1) * (mu - 25)) / (6 * denom);
325
+ denom *= denomMult;
326
+ s += ((mu - 1) * (mu * mu - 114 * mu + 1073)) / (5 * denom);
327
+ denom *= denomMult;
328
+ s += ((mu - 1) * (5 * mu * mu * mu - 1535 * mu * mu + 54703 * mu - 375733)) / (14 * denom);
329
+ return s;
330
+ }
331
+ /** J_v and Y_v for large x (A&S 9.2.19), with the phase factored by addition formulas */
332
+ function asymJY(v, x) {
333
+ const ampl = asymAmplitude(v, x);
334
+ const phase = asymPhaseMx(v, x);
335
+ const cx = Math.cos(x);
336
+ const sx = Math.sin(x);
337
+ const ci = cospi(v / 2 + 0.25);
338
+ const si = sinpi(v / 2 + 0.25);
339
+ const sp = Math.sin(phase);
340
+ const cp = Math.cos(phase);
341
+ const y = (sp * (cx * ci + sx * si) + cp * (sx * ci - cx * si)) * ampl;
342
+ const j = (cp * (cx * ci + sx * si) - sp * (sx * ci - cx * si)) * ampl;
343
+ return { j, y };
344
+ }
345
+ /**
346
+ * J_v(x) and Y_v(x) for v >= 0, x > 0 (Boost's bessel_jy without the reflection). Y is returned as y / yScale.
347
+ * needY: whether Y is wanted (J alone allows a cheaper series)
348
+ */
349
+ function besselJYPos(v, x, needY) {
350
+ const n = Math.round(v);
351
+ const u = v - n; // -1/2 < u <= 1/2
352
+ const W = 2 / (x * Math.PI); // Wronskian
353
+ if (!needY && (x < 5 || v > (x * x) / 4))
354
+ return { j: jSmallZ(v, x), y: { m: NaN, e2: 0 } };
355
+ if (x < 1 && u !== 0 && Math.log(EPS / 2) > v * Math.log(((x / 2) * (x / 2)) / v)) {
356
+ return { j: jSmallZ(v, x), y: ySmallZ(v, x) };
357
+ }
358
+ if (Math.max(v, 1) < x * 0.011048543456039806) {
359
+ // sqrt(forth root of epsilon)
360
+ const a = asymJY(v, x);
361
+ return { j: a.j, y: { m: a.y, e2: 0 } };
362
+ }
363
+ if (x > 8) {
364
+ const pq = hankelPQ(v, x);
365
+ if (pq !== undefined) {
366
+ const modV = (v / 2 + 0.25) % 2;
367
+ const sx = Math.sin(x);
368
+ const cx = Math.cos(x);
369
+ const sv = sinpi(modV);
370
+ const cv = cospi(modV);
371
+ const sc = sx * cv - sv * cx; // sin(chi)
372
+ const cc = cx * cv + sx * sv; // cos(chi)
373
+ const chi = Math.SQRT2 / (Math.sqrt(Math.PI) * Math.sqrt(x));
374
+ return { j: chi * (pq.p * cc - pq.q * sc), y: { m: chi * (pq.p * sc + pq.q * cc), e2: 0 } };
375
+ }
376
+ }
377
+ if (x <= 2) {
378
+ const [yu, yu1] = temmeJY(u, x);
379
+ const r = yForward(u, x, n, yu, yu1);
380
+ const { fv } = cf1JY(v, x);
381
+ // Wronskian: J_v = W / (Y_v fv - Y_(v+1))
382
+ const j = ldexp(W / (r.y * fv - r.y1), -r.e2);
383
+ return { j, y: { m: r.y, e2: r.e2 } };
384
+ }
385
+ // x > 2: backward recurrence for J from CF1, then CF2 for the normalisation and Y_u
386
+ const { fv, sign: s } = cf1JY(v, x);
387
+ if (x >= v && v > 2) {
388
+ // Beyond the turning point CF2 converges at order v itself, so Steed's method is applied there directly. Boost
389
+ // goes down to u = v - round(v) and back up by recurrence, whose error grows with the number of steps
390
+ // (1.2e-13 relative to the amplitude for Y at v = 575, x = 2211)
391
+ const { p, q } = cf2JY(v, x);
392
+ const t = v / x - fv; // J_v' / J_v
393
+ let g = (p - t) / q;
394
+ if (g === 0)
395
+ g = (v * EPS) / x;
396
+ const jv = s * Math.sqrt(W / (q + g * (p - t)));
397
+ return { j: jv, y: { m: g * jv, e2: 0 } };
398
+ }
399
+ // Boost stops this recurrence when it would overflow (large v) and then guesses J_u' / J_u and the sign of J_u,
400
+ // which gives Y the wrong sign (Y(5, 500) came out +Infinity); here it is rescaled by powers of 2 instead
401
+ const init = TINY;
402
+ let prev = fv * s * init;
403
+ let current = s * init;
404
+ let e2 = 0;
405
+ for (let k = n; k > 0; k--) {
406
+ const t = (2 * (u + k)) / x;
407
+ if (Math.abs(current) > 2 ** 900) {
408
+ prev *= 2 ** -900;
409
+ current *= 2 ** -900;
410
+ e2 += 900;
411
+ }
412
+ let next = t * current - prev;
413
+ if (next === 0)
414
+ next = (prev * EPS) / 2;
415
+ prev = current;
416
+ current = next;
417
+ }
418
+ const ratio = ldexp((s * init) / current, -e2); // J_v / J_u
419
+ const fu = prev / current;
420
+ const { p, q } = cf2JY(u, x);
421
+ const t = u / x - fu; // J'/J
422
+ let g = (p - t) / q;
423
+ if (g === 0)
424
+ g = (u * EPS) / x;
425
+ const ju = Math.sign(current) * Math.sqrt(W / (q + g * (p - t)));
426
+ const jv = ju * ratio;
427
+ const yu = g * ju;
428
+ const yu1 = yu * (u / x - p - q / g);
429
+ if (!needY)
430
+ return { j: jv, y: { m: NaN, e2: 0 } };
431
+ const r = yForward(u, x, n, yu, yu1);
432
+ return { j: jv, y: { m: r.y, e2: r.e2 } };
433
+ }
434
+ /**
435
+ * Bessel function of the first kind. Equivalent to R's `besselJ(x, nu)` for single numbers.
436
+ *
437
+ * @param x - Argument, `x >= 0` (`NaN` for negative `x`).
438
+ * @param nu - Order, any real number. For `nu < 0`, `J(x, -nu) = cos(pi nu) J(x, nu) - sin(pi nu) Y(x, nu)`
439
+ * (A&S 9.1.2, as in R).
440
+ * @returns J_nu(x).
441
+ *
442
+ * For `x` much larger than `nu` but below the range of the asymptotic expansion (`x < nu / 0.011`), the time grows
443
+ * with `x` (a continued fraction of about `x` terms): about 15 ms at `x = 5e4`, `nu = 1000`.
444
+ *
445
+ * @example
446
+ * ```ts
447
+ * besselJ(1, 0); // 0.7651976865579666
448
+ * besselJ(10, 2.5); // 0.1966584835818184
449
+ * ```
450
+ */
451
+ export function besselJ(x, nu) {
452
+ if (Number.isNaN(x) || Number.isNaN(nu) || x < 0 || !Number.isFinite(nu))
453
+ return NaN;
454
+ const v = Math.abs(nu);
455
+ const reflect = nu < 0 && nu !== Math.floor(nu);
456
+ if (x === 0) {
457
+ if (nu === 0)
458
+ return 1;
459
+ if (!reflect)
460
+ return 0;
461
+ // J_-v(0) = -sin(pi v) Y_v(0) with Y_v(0) = -Infinity
462
+ return sinpi(v) > 0 ? Infinity : -Infinity;
463
+ }
464
+ if (x === Infinity)
465
+ return 0;
466
+ if (!reflect) {
467
+ const j = besselJYPos(v, x, false).j;
468
+ return nu < 0 && v % 2 === 1 ? -j : j; // J_-n = (-1)^n J_n
469
+ }
470
+ const r = besselJYPos(v, x, true);
471
+ return cospi(v) * r.j - ldexp(sinpi(v) * r.y.m, r.y.e2);
472
+ }
473
+ /**
474
+ * Bessel function of the second kind. Equivalent to R's `besselY(x, nu)` for single numbers.
475
+ *
476
+ * @param x - Argument, `x >= 0` (`NaN` for negative `x`; `-Infinity` at 0).
477
+ * @param nu - Order, any real number. For `nu < 0`, `Y(x, -nu) = sin(pi nu) J(x, nu) + cos(pi nu) Y(x, nu)`
478
+ * (A&S 9.1.2, as in R).
479
+ * @returns Y_nu(x).
480
+ *
481
+ * @example
482
+ * ```ts
483
+ * besselY(1, 0); // 0.08825696421567694
484
+ * ```
485
+ */
486
+ export function besselY(x, nu) {
487
+ if (Number.isNaN(x) || Number.isNaN(nu) || x < 0 || !Number.isFinite(nu))
488
+ return NaN;
489
+ const v = Math.abs(nu);
490
+ const reflect = nu < 0;
491
+ if (x === 0) {
492
+ if (!reflect)
493
+ return -Infinity;
494
+ // Y_-v(0) = sin(pi v) J_v(0) + cos(pi v) Y_v(0)
495
+ const cp = cospi(v);
496
+ if (cp === 0)
497
+ return 0;
498
+ return cp > 0 ? -Infinity : Infinity;
499
+ }
500
+ if (x === Infinity)
501
+ return 0;
502
+ const r = besselJYPos(v, x, true);
503
+ if (!reflect)
504
+ return ldexp(r.y.m, r.y.e2);
505
+ const cp = cospi(v);
506
+ const sp = sinpi(v);
507
+ return (sp !== 0 ? sp * r.j : 0) + (cp === 0 ? 0 : ldexp(cp * r.y.m, r.y.e2));
508
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * (x/2)^v / Gamma(v + 1) * sum, the leading factor of the power series of I_v and J_v times the series sum.
3
+ * For v >= 10 the factor is Loader's Poisson term dpois(v; x/2) e^(x/2), which is accurate where pow / gamma loses
4
+ * 1e-14 (v = 32) and exp(v log(x/2) - lgamma(v + 1)) loses 7e-14 (v = 500). When the factor or the result is
5
+ * subnormal the logs are combined and exp taken once, so that a subnormal result is not built from a subnormal
6
+ * factor (the log of a value near 1e-308 carries an absolute error of 700 ε, which a subnormal result can afford)
7
+ */
8
+ export declare function seriesTimesPrefix(v: number, x: number, sum: number): number;
@@ -0,0 +1,24 @@
1
+ // The power-series prefix shared by the Bessel functions I and J (besselIK.ts, besselJY.ts).
2
+ import { gamma } from "./gamma.js";
3
+ import { dpoisRaw } from "./loader.js";
4
+ const DBL_MIN = 2.2250738585072014e-308;
5
+ /**
6
+ * (x/2)^v / Gamma(v + 1) * sum, the leading factor of the power series of I_v and J_v times the series sum.
7
+ * For v >= 10 the factor is Loader's Poisson term dpois(v; x/2) e^(x/2), which is accurate where pow / gamma loses
8
+ * 1e-14 (v = 32) and exp(v log(x/2) - lgamma(v + 1)) loses 7e-14 (v = 500). When the factor or the result is
9
+ * subnormal the logs are combined and exp taken once, so that a subnormal result is not built from a subnormal
10
+ * factor (the log of a value near 1e-308 carries an absolute error of 700 ε, which a subnormal result can afford)
11
+ */
12
+ export function seriesTimesPrefix(v, x, sum) {
13
+ if (v < 10)
14
+ return (Math.pow(x / 2, v) / gamma(v + 1)) * sum;
15
+ const lambda = x / 2;
16
+ const d = dpoisRaw(v, lambda, false);
17
+ if (d >= DBL_MIN && lambda < 700) {
18
+ const r = d * Math.exp(lambda) * sum;
19
+ if (Math.abs(r) >= DBL_MIN)
20
+ return r;
21
+ }
22
+ const ld = dpoisRaw(v, lambda, true) + lambda + Math.log(Math.abs(sum));
23
+ return Math.sign(sum) * Math.exp(ld);
24
+ }
@@ -3,7 +3,7 @@
3
3
  // xsf Copyright (c) 2024, SciPy. BSD-3-Clause. See THIRD_PARTY_NOTICES.md.
4
4
  import { MAXGAM } from "./constants.js";
5
5
  import { gamma, lgamma, lgammaSign } from "./gamma.js";
6
- import { lgammaDiff } from "./lgammaDiff.js";
6
+ import { lgammaDiff, lgammaDiffDD } from "./lgammaDiff.js";
7
7
  import { ddAdd, ddLog, ddMulNum, ddSub, twoSum } from "./dd.js";
8
8
  import { stirlerr } from "./loader.js";
9
9
  const ASYMP_FACTOR = 1e6;
@@ -35,9 +35,11 @@ export function beta(a, b) {
35
35
  const lo = Math.min(a, b);
36
36
  const hi = Math.max(a, b);
37
37
  // Smaller one below 1: B = Gamma(lo) Gamma(hi)/Gamma(lo + hi) = Gamma(lo) exp(-[lgamma(hi+lo) - lgamma(hi)])
38
- if (lo < 1)
39
- return gamma(lo) * Math.exp(-lgammaDiff(lo, hi));
40
- const e = lbetaDD(a, b);
38
+ if (lo < 1) {
39
+ const d = lgammaDiffDD(lo, hi);
40
+ return gamma(lo) * Math.exp(-d[0]) * (1 - d[1]);
41
+ }
42
+ const e = hi >= HUGE ? lbetaHuge(hi, lo) : lbetaDD(a, b);
41
43
  return Math.exp(e[0]) * (1 + e[1]);
42
44
  }
43
45
  let sign = 1;
@@ -102,7 +104,7 @@ export function lbeta(a, b) {
102
104
  // If the smaller one is below 1, lgamma(lo) is small and the difference form is accurate enough
103
105
  if (lo < 1)
104
106
  return lgamma(lo) - lgammaDiff(lo, hi);
105
- const e = lbetaDD(a, b);
107
+ const e = hi >= HUGE ? lbetaHuge(hi, lo) : lbetaDD(a, b);
106
108
  return e[0] + e[1];
107
109
  }
108
110
  if (a <= 0 && a === Math.floor(a))
@@ -131,6 +133,21 @@ function lbetaNegint(a, b) {
131
133
  return Infinity;
132
134
  }
133
135
  const LS2PI_DD = [0.91893853320467278, -3.8782941580672414e-17];
136
+ /** From here on lbetaDD is not used: it rounds a - 1/2 (off by 20 in log B(1e17, 31)) and its terms of size a log a lose all digits */
137
+ const HUGE = 2 ** 52;
138
+ /**
139
+ * log B(a, b) for a >= 2^52, a >= b >= 1, in double-double. Writing log(a + b) = log a + log1p(b/a) in the Stirling
140
+ * form of lbetaDD gives
141
+ * log B = b log(b/a) - log(b)/2 - (a + b - 1/2) log1p(b/a) + log sqrt(2 pi) + stirlerr(a) + stirlerr(b) - stirlerr(a + b)
142
+ * whose terms are all of the size of b log(a/b) or smaller, so nothing cancels. The leading b log(b/a) (hundreds) is
143
+ * formed in double-double, as exp would turn its rounding into a relative error of 1e-13 (beta(3.05e19, 11.96)); the
144
+ * rest is at most about b and rounds well below that
145
+ */
146
+ function lbetaHuge(a, b) {
147
+ const lead = ddMulNum(ddSub(ddLog([b, 0]), ddLog([a, 0])), b);
148
+ const rest = -0.5 * Math.log(b) - (a + b - 0.5) * Math.log1p(b / a) + (stirlerr(a) + stirlerr(b) - stirlerr(a + b));
149
+ return ddAdd(ddAdd(lead, LS2PI_DD), [rest, 0]);
150
+ }
134
151
  /**
135
152
  * log B(a, b) in double-double (a, b > 0).
136
153
  * Adding and subtracting three instances of lgamma(z) = (z - 1/2) log z - z + log sqrt(2 pi) + stirlerr(z) gives
@@ -0,0 +1,75 @@
1
+ import type { RCompatibleOptions } from "./rCompatible.js";
2
+ /**
3
+ * Binomial coefficient. Equivalent to R's `choose(n, k)` for single numbers.
4
+ *
5
+ * `n` may be any real number. `k` is rounded to the nearest integer (as R does, which also warns
6
+ * when `k` is not close to an integer); `choose(n, k)` is 0 for `k < 0` and 1 for `k = 0`.
7
+ * For integer `n` the result is an integer (exact up to 2^53).
8
+ *
9
+ * Edge cases where R differs from the mathematical value, followed by default (`rCompatible: false`
10
+ * returns the mathematical value instead):
11
+ * - `n` within 1e-9 max(1, |n|) of an integer is treated as that integer, so `choose(1e-10, 2)` is 0
12
+ * (mathematically -5e-11); for `n < 0` and `k >= 30` the tolerance is relative to `k - 1 - n`;
13
+ * - `choose(n, Infinity)` is 0 for `n >= 0` (otherwise `NaN`);
14
+ * - `choose(±Infinity, k)` is `NaN` for `k >= 30` (`±Infinity` below).
15
+ *
16
+ * @param n - Number of items (any real number).
17
+ * @param k - Number chosen (rounded to an integer).
18
+ * @param options - `rCompatible` (default `true`).
19
+ * @returns The binomial coefficient.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * choose(5, 2); // 10
24
+ * choose(0.5, 3); // 0.0625
25
+ * choose(-2, 3); // -4
26
+ * ```
27
+ */
28
+ export declare function choose(n: number, k: number, options?: RCompatibleOptions): number;
29
+ /**
30
+ * Logarithm of the absolute value of the binomial coefficient. Equivalent to R's `lchoose(n, k)`
31
+ * for single numbers: `log(abs(choose(n, k)))`, computed without overflow.
32
+ *
33
+ * Edge cases where R differs from the mathematical value, followed by default (`rCompatible: false`
34
+ * returns the mathematical value instead): `n` within 1e-9 max(1, |n|) of an integer is treated as that
35
+ * integer (for `k >= 2`; for `n < 0` the tolerance is relative to `k - 1 - n`); `lchoose(n, Infinity)` is `-Infinity` for `n >= 0` (otherwise `NaN`); `lchoose(±Infinity, k)`
36
+ * is `NaN` for `k >= 2` (`Infinity` for `k = 1`).
37
+ *
38
+ * @param n - Number of items (any real number).
39
+ * @param k - Number chosen (rounded to an integer).
40
+ * @param options - `rCompatible` (default `true`).
41
+ * @returns log|choose(n, k)| (`-Infinity` where `choose(n, k)` is 0).
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * lchoose(1000, 500); // 689.4672615678512
46
+ * ```
47
+ */
48
+ export declare function lchoose(n: number, k: number, options?: RCompatibleOptions): number;
49
+ /**
50
+ * Factorial. Equivalent to R's `factorial(x)` for a single number: `gamma(x + 1)`, defined for
51
+ * any real `x` that is not a negative integer.
52
+ *
53
+ * @param x - Argument.
54
+ * @returns x! = Gamma(x + 1) (`NaN` at negative integers, `Infinity` on overflow).
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * factorial(5); // 120
59
+ * factorial(0.5); // 0.8862269254527579
60
+ * ```
61
+ */
62
+ export declare function factorial(x: number): number;
63
+ /**
64
+ * Logarithm of the factorial. Equivalent to R's `lfactorial(x)` for a single number:
65
+ * `lgamma(x + 1)`, computed without forming `x + 1` near 0 so that small `x` keep their accuracy.
66
+ *
67
+ * @param x - Argument.
68
+ * @returns log|x!| = log|Gamma(x + 1)| (`Infinity` at negative integers).
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * lfactorial(100); // 363.73937555556347
73
+ * ```
74
+ */
75
+ export declare function lfactorial(x: number): number;