@trebco/treb 30.12.0 → 30.16.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.
- package/dist/treb-export-worker.mjs +1 -1
- package/dist/treb-spreadsheet.mjs +12 -12
- package/dist/treb.d.ts +7 -1
- package/package.json +1 -1
- package/treb-calculator/src/complex-math.ts +39 -0
- package/treb-calculator/src/functions/base-functions.ts +55 -139
- package/treb-calculator/src/functions/beta.ts +244 -0
- package/treb-calculator/src/functions/statistics-functions.ts +388 -4
- package/treb-calculator/src/utilities.ts +10 -1
- package/treb-charts/src/chart-functions.ts +41 -4
- package/treb-charts/src/chart-types.ts +20 -1
- package/treb-charts/src/chart-utils.ts +86 -9
- package/treb-charts/src/default-chart-renderer.ts +40 -1
- package/treb-charts/src/renderer.ts +3 -3
- package/treb-embed/src/embedded-spreadsheet.ts +13 -0
- package/treb-grid/src/types/grid.ts +1 -1
package/dist/treb.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! API v30.
|
|
1
|
+
/*! API v30.16. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* add our tag to the map
|
|
@@ -515,6 +515,12 @@ export declare class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
515
515
|
*/
|
|
516
516
|
HideSheet(index?: number | string, hide?: boolean): void;
|
|
517
517
|
|
|
518
|
+
/** list sheets in the model */
|
|
519
|
+
ListSheets(): {
|
|
520
|
+
name: string;
|
|
521
|
+
hidden?: boolean;
|
|
522
|
+
}[];
|
|
523
|
+
|
|
518
524
|
/**
|
|
519
525
|
* Show or hide sheet. This method is deprecated because it's ambiguous.
|
|
520
526
|
* To set a sheet's visibility, use `HideSheet`. To activate a sheet, use
|
package/package.json
CHANGED
|
@@ -99,6 +99,24 @@ export const RectangularToPolar = (value: Complex): { r: number, theta: number }
|
|
|
99
99
|
return { r, theta };
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
+
export const TanH = (z: Complex): Complex => {
|
|
103
|
+
|
|
104
|
+
// tanh(a+bi) = (sinh a cos b + i cosh a sin b) / (cosh a cos b + i sinh a sin b)
|
|
105
|
+
|
|
106
|
+
const num: Complex = {
|
|
107
|
+
real: Math.sinh(z.real) * Math.cos(z.imaginary),
|
|
108
|
+
imaginary: Math.cosh(z.real) * Math.sin(z.imaginary),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const denom: Complex = {
|
|
112
|
+
real: Math.cosh(z.real) * Math.cos(z.imaginary),
|
|
113
|
+
imaginary: Math.sinh(z.real) * Math.sin(z.imaginary),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return Divide(num, denom);
|
|
117
|
+
|
|
118
|
+
};
|
|
119
|
+
|
|
102
120
|
export const Tan = (z: Complex) => {
|
|
103
121
|
|
|
104
122
|
// tan(a+bi) = (tan(a) + i tanh(b)) / (1 - i tan(a) tanh(b))
|
|
@@ -113,6 +131,17 @@ export const Tan = (z: Complex) => {
|
|
|
113
131
|
|
|
114
132
|
};
|
|
115
133
|
|
|
134
|
+
export const CosH = (z: Complex): Complex => {
|
|
135
|
+
|
|
136
|
+
// cosh(a+bi) = cosh a cos b + i sinh a sin b
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
real: Math.cosh(z.real) * Math.cos(z.imaginary),
|
|
140
|
+
imaginary: Math.sinh(z.real) * Math.sin(z.imaginary),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
};
|
|
144
|
+
|
|
116
145
|
export const Cos = (z: Complex) => {
|
|
117
146
|
|
|
118
147
|
// sin(a+bi) = cos(a) cosh(b) + i sin(a) sinh(b)
|
|
@@ -124,6 +153,16 @@ export const Cos = (z: Complex) => {
|
|
|
124
153
|
|
|
125
154
|
};
|
|
126
155
|
|
|
156
|
+
export const SinH = (z: Complex): Complex => {
|
|
157
|
+
|
|
158
|
+
// sinh(a+bi) = sinh a cos b + i cosh a sin b
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
real: Math.sinh(z.real) * Math.cos(z.imaginary),
|
|
162
|
+
imaginary: Math.cosh(z.real) * Math.sin(z.imaginary),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
};
|
|
127
166
|
|
|
128
167
|
export const Sin = (z: Complex) => {
|
|
129
168
|
|
|
@@ -62,56 +62,6 @@ import { ConstructDate } from './date-utils';
|
|
|
62
62
|
|
|
63
63
|
// OK, just one.
|
|
64
64
|
|
|
65
|
-
/** error function (for gaussian distribution) */
|
|
66
|
-
const erf = (x: number): number => {
|
|
67
|
-
|
|
68
|
-
const a1 = 0.254829592;
|
|
69
|
-
const a2 = -0.284496736;
|
|
70
|
-
const a3 = 1.421413741;
|
|
71
|
-
const a4 = -1.453152027;
|
|
72
|
-
const a5 = 1.061405429;
|
|
73
|
-
const p = 0.3275911;
|
|
74
|
-
|
|
75
|
-
x = Math.abs(x);
|
|
76
|
-
const t = 1 / (1 + p * x);
|
|
77
|
-
return 1 - ((((((a5 * t + a4) * t) + a3) * t + a2) * t) + a1) * t * Math.exp(-1 * x * x);
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const sqrt2pi = Math.sqrt(2 * Math.PI);
|
|
82
|
-
|
|
83
|
-
const norm_dist = (x: number, mean: number, stdev: number, cumulative: boolean) => {
|
|
84
|
-
|
|
85
|
-
let value = 0;
|
|
86
|
-
|
|
87
|
-
if (cumulative) {
|
|
88
|
-
const sign = (x < mean) ? -1 : 1;
|
|
89
|
-
value = 0.5 * (1.0 + sign * erf((Math.abs(x - mean)) / (stdev * Math.sqrt(2))));
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
value = Math.exp(-1/2 * Math.pow((x - mean) / stdev, 2)) / (stdev * sqrt2pi);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return value;
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** imprecise but reasonably fast normsinv function */
|
|
100
|
-
const inverse_normal = (q: number): number => {
|
|
101
|
-
|
|
102
|
-
if (q === 0.50) {
|
|
103
|
-
return 0;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const p = (q < 1.0 && q > 0.5) ? (1 - q) : q;
|
|
107
|
-
const t = Math.sqrt(Math.log(1.0 / Math.pow(p, 2.0)));
|
|
108
|
-
const x = t - (2.515517 + 0.802853 * t + 0.010328 * Math.pow(t, 2.0)) /
|
|
109
|
-
(1.0 + 1.432788 * t + 0.189269 * Math.pow(t, 2.0) + 0.001308 * Math.pow(t, 3.0));
|
|
110
|
-
|
|
111
|
-
return (q > 0.5 ? x : -x);
|
|
112
|
-
|
|
113
|
-
};
|
|
114
|
-
|
|
115
65
|
|
|
116
66
|
const edate_calc = (start: number, months: number) => {
|
|
117
67
|
|
|
@@ -2175,94 +2125,6 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
2175
2125
|
},
|
|
2176
2126
|
},
|
|
2177
2127
|
|
|
2178
|
-
Erf: {
|
|
2179
|
-
fn: (a: number): UnionValue => {
|
|
2180
|
-
return { type: ValueType.number, value: erf(a) };
|
|
2181
|
-
},
|
|
2182
|
-
},
|
|
2183
|
-
|
|
2184
|
-
'NormsInv': {
|
|
2185
|
-
|
|
2186
|
-
description: 'Inverse of the normal cumulative distribution',
|
|
2187
|
-
arguments: [
|
|
2188
|
-
{name: 'probability'},
|
|
2189
|
-
],
|
|
2190
|
-
|
|
2191
|
-
fn: (q: number): UnionValue => {
|
|
2192
|
-
return {
|
|
2193
|
-
type: ValueType.number,
|
|
2194
|
-
value: inverse_normal(q),
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
},
|
|
2198
|
-
|
|
2199
|
-
'Norm.Inv': {
|
|
2200
|
-
description: 'Inverse of the normal cumulative distribution',
|
|
2201
|
-
arguments: [
|
|
2202
|
-
{name: 'probability'},
|
|
2203
|
-
{name: 'mean', default: 0},
|
|
2204
|
-
{name: 'standard deviation', default: 1},
|
|
2205
|
-
],
|
|
2206
|
-
xlfn: true,
|
|
2207
|
-
fn: (q: number, mean = 0, stdev = 1): UnionValue => {
|
|
2208
|
-
return {
|
|
2209
|
-
type: ValueType.number,
|
|
2210
|
-
value: inverse_normal(q) * stdev + mean,
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
},
|
|
2214
|
-
|
|
2215
|
-
'Norm.S.Inv': {
|
|
2216
|
-
description: 'Inverse of the normal cumulative distribution',
|
|
2217
|
-
arguments: [
|
|
2218
|
-
{name: 'probability'},
|
|
2219
|
-
{name: 'mean', default: 0},
|
|
2220
|
-
{name: 'standard deviation', default: 1},
|
|
2221
|
-
],
|
|
2222
|
-
xlfn: true,
|
|
2223
|
-
fn: (q: number, mean = 0, stdev = 1): UnionValue => {
|
|
2224
|
-
return {
|
|
2225
|
-
type: ValueType.number,
|
|
2226
|
-
value: inverse_normal(q) * stdev + mean,
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
},
|
|
2230
|
-
|
|
2231
|
-
'Norm.Dist': {
|
|
2232
|
-
|
|
2233
|
-
description: 'Cumulative normal distribution',
|
|
2234
|
-
arguments: [
|
|
2235
|
-
{name: 'value'},
|
|
2236
|
-
{name: 'mean', default: 0},
|
|
2237
|
-
{name: 'standard deviation', default: 1},
|
|
2238
|
-
{name: 'cumulative', default: true},
|
|
2239
|
-
],
|
|
2240
|
-
|
|
2241
|
-
// this does need xlfn but it also requires four parameters
|
|
2242
|
-
// (we have three and they are not required).
|
|
2243
|
-
|
|
2244
|
-
xlfn: true,
|
|
2245
|
-
|
|
2246
|
-
fn: (x: number, mean = 0, stdev = 1, cumulative = true): UnionValue => {
|
|
2247
|
-
return { type: ValueType.number, value: norm_dist(x, mean, stdev, cumulative) };
|
|
2248
|
-
},
|
|
2249
|
-
},
|
|
2250
|
-
|
|
2251
|
-
'Norm.S.Dist': {
|
|
2252
|
-
|
|
2253
|
-
description: 'Cumulative normal distribution',
|
|
2254
|
-
arguments: [
|
|
2255
|
-
{name: 'value'},
|
|
2256
|
-
{name: 'cumulative', default: true},
|
|
2257
|
-
],
|
|
2258
|
-
|
|
2259
|
-
xlfn: true,
|
|
2260
|
-
|
|
2261
|
-
fn: (x: number, cumulative = true): UnionValue => {
|
|
2262
|
-
return { type: ValueType.number, value: norm_dist(x, 0, 1, cumulative) };
|
|
2263
|
-
},
|
|
2264
|
-
},
|
|
2265
|
-
|
|
2266
2128
|
Sqrt: {
|
|
2267
2129
|
description: 'Returns the square root of the argument',
|
|
2268
2130
|
arguments: [
|
|
@@ -2561,6 +2423,24 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
2561
2423
|
},
|
|
2562
2424
|
},
|
|
2563
2425
|
|
|
2426
|
+
SinH: {
|
|
2427
|
+
arguments: [
|
|
2428
|
+
{ name: 'number', boxed: true, unroll: true },
|
|
2429
|
+
],
|
|
2430
|
+
fn: (a: UnionValue) => {
|
|
2431
|
+
|
|
2432
|
+
if (a.type === ValueType.number) {
|
|
2433
|
+
return { type: ValueType.number, value: Math.sinh(a.value) };
|
|
2434
|
+
}
|
|
2435
|
+
if (a.type === ValueType.complex) {
|
|
2436
|
+
return { type: ValueType.complex, value: ComplexMath.SinH(a.value) };
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
return ArgumentError();
|
|
2440
|
+
|
|
2441
|
+
},
|
|
2442
|
+
},
|
|
2443
|
+
|
|
2564
2444
|
Sin: {
|
|
2565
2445
|
arguments: [
|
|
2566
2446
|
{ name: 'angle in radians', boxed: true, unroll: true, }
|
|
@@ -2579,6 +2459,24 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
2579
2459
|
},
|
|
2580
2460
|
},
|
|
2581
2461
|
|
|
2462
|
+
CosH: {
|
|
2463
|
+
arguments: [
|
|
2464
|
+
{ name: 'number', boxed: true, unroll: true },
|
|
2465
|
+
],
|
|
2466
|
+
fn: (a: UnionValue) => {
|
|
2467
|
+
|
|
2468
|
+
if (a.type === ValueType.number) {
|
|
2469
|
+
return { type: ValueType.number, value: Math.cosh(a.value) };
|
|
2470
|
+
}
|
|
2471
|
+
if (a.type === ValueType.complex) {
|
|
2472
|
+
return { type: ValueType.complex, value: ComplexMath.CosH(a.value) };
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
return ArgumentError();
|
|
2476
|
+
|
|
2477
|
+
},
|
|
2478
|
+
},
|
|
2479
|
+
|
|
2582
2480
|
Cos: {
|
|
2583
2481
|
arguments: [
|
|
2584
2482
|
{ name: 'angle in radians', boxed: true, unroll: true, }
|
|
@@ -2596,7 +2494,25 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
2596
2494
|
|
|
2597
2495
|
},
|
|
2598
2496
|
},
|
|
2599
|
-
|
|
2497
|
+
|
|
2498
|
+
TanH: {
|
|
2499
|
+
arguments: [
|
|
2500
|
+
{ name: 'number', boxed: true, unroll: true, }
|
|
2501
|
+
],
|
|
2502
|
+
fn: (a: UnionValue) => {
|
|
2503
|
+
|
|
2504
|
+
if (a.type === ValueType.number) {
|
|
2505
|
+
return { type: ValueType.number, value: Math.tanh(a.value) };
|
|
2506
|
+
}
|
|
2507
|
+
if (a.type === ValueType.complex) {
|
|
2508
|
+
return { type: ValueType.complex, value: ComplexMath.TanH(a.value) };
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
return ArgumentError();
|
|
2512
|
+
|
|
2513
|
+
},
|
|
2514
|
+
},
|
|
2515
|
+
|
|
2600
2516
|
Tan: {
|
|
2601
2517
|
arguments: [
|
|
2602
2518
|
{ name: 'angle in radians', boxed: true, unroll: true, }
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2024 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const EPSILON = 2.2204460492503131e-16;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* natural log of (1+x)
|
|
26
|
+
*/
|
|
27
|
+
const Log1p = (x: number) => {
|
|
28
|
+
const y = 1 + x;
|
|
29
|
+
return Math.log(y) - ((y - 1) - x) / y;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* continued fraction expansion
|
|
34
|
+
*/
|
|
35
|
+
const BetaContFrac = (a: number, b: number, x: number, epsabs: number) => {
|
|
36
|
+
|
|
37
|
+
const cutoff = 2.0 * Number.MIN_VALUE;
|
|
38
|
+
|
|
39
|
+
let cf = 0;
|
|
40
|
+
|
|
41
|
+
let numerator = 1.0;
|
|
42
|
+
let denominator = 1.0 - (a + b) * x / (a + 1.0);
|
|
43
|
+
|
|
44
|
+
if (Math.abs(denominator) < cutoff) {
|
|
45
|
+
denominator = Number.NaN;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
denominator = 1.0 / denominator;
|
|
49
|
+
cf = denominator;
|
|
50
|
+
|
|
51
|
+
for (let k = 1; k <= 512; k++) {
|
|
52
|
+
|
|
53
|
+
let coeff = k * (b - k) * x / (((a - 1.0) + 2 * k) * (a + 2 * k));
|
|
54
|
+
let delta_frac = 0;
|
|
55
|
+
|
|
56
|
+
denominator = 1.0 + coeff * denominator;
|
|
57
|
+
numerator = 1.0 + coeff / numerator;
|
|
58
|
+
|
|
59
|
+
if (Math.abs(denominator) < cutoff) {
|
|
60
|
+
denominator = Number.NaN;
|
|
61
|
+
}
|
|
62
|
+
if (Math.abs(numerator) < cutoff) {
|
|
63
|
+
numerator = Number.NaN;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
denominator = 1.0 / denominator;
|
|
67
|
+
|
|
68
|
+
delta_frac = denominator * numerator;
|
|
69
|
+
cf *= delta_frac;
|
|
70
|
+
|
|
71
|
+
coeff = -(a + k) * (a + b + k) * x / ((a + 2 * k) * (a + 2 * k + 1.0));
|
|
72
|
+
|
|
73
|
+
denominator = 1.0 + coeff * denominator;
|
|
74
|
+
numerator = 1.0 + coeff / numerator;
|
|
75
|
+
|
|
76
|
+
if (Math.abs(denominator) < cutoff) {
|
|
77
|
+
denominator = Number.NaN;
|
|
78
|
+
}
|
|
79
|
+
if (Math.abs(numerator) < cutoff) {
|
|
80
|
+
numerator = Number.NaN;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
denominator = 1.0 / denominator;
|
|
84
|
+
|
|
85
|
+
delta_frac = denominator * numerator;
|
|
86
|
+
cf *= delta_frac;
|
|
87
|
+
|
|
88
|
+
if ((Math.abs(delta_frac - 1.0) < 2.0 * EPSILON) || (cf * Math.abs(delta_frac - 1.0) < epsabs)) {
|
|
89
|
+
return cf;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return Number.NaN;
|
|
95
|
+
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* inverse beta function for beta (a, b)
|
|
100
|
+
*/
|
|
101
|
+
export const InverseBeta = (p: number, a: number, b: number): number => {
|
|
102
|
+
|
|
103
|
+
if (a < 0.0 || b < 0.0) {
|
|
104
|
+
return Number.NaN;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (p <= 0) {
|
|
108
|
+
return 0.0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (p >= 1) {
|
|
112
|
+
return 1.0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (p > 0.5) {
|
|
116
|
+
return 1 - InverseBeta(1 - p, b, a);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const mean = a / (a + b);
|
|
120
|
+
|
|
121
|
+
let x = 0;
|
|
122
|
+
|
|
123
|
+
if (p < 0.1) {
|
|
124
|
+
const lx = (Math.log(a) + LnGamma(a) + LnGamma(b) - LnGamma(a + b) + Math.log(p)) / a;
|
|
125
|
+
if (lx <= 0) {
|
|
126
|
+
x = Math.exp(lx);
|
|
127
|
+
x *= Math.pow(1 - x, -(b - 1) / a);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
x = mean;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (x > mean) {
|
|
134
|
+
x = mean;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
x = mean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for(let n = 0; n < 64; n++) {
|
|
142
|
+
|
|
143
|
+
const dP = p - BetaCDF(x, a, b);
|
|
144
|
+
const phi = BetaPDF(x, a, b);
|
|
145
|
+
|
|
146
|
+
if (dP === 0) {
|
|
147
|
+
return x;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const lambda = dP / Math.max(2 * Math.abs(dP / x), phi);
|
|
151
|
+
|
|
152
|
+
const step0 = lambda;
|
|
153
|
+
const step1 = -((a - 1) / x - (b - 1) / (1 - x)) * lambda * lambda / 2;
|
|
154
|
+
let step = step0;
|
|
155
|
+
|
|
156
|
+
if (Math.abs(step1) < Math.abs(step0)) {
|
|
157
|
+
step += step1;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
step *= 2 * Math.abs(step0 / step1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (x + step > 0 && x + step < 1) {
|
|
164
|
+
x += step;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
x = Math.sqrt(x) * Math.sqrt(mean);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (Math.abs(step0) <= 1e-10 * x) {
|
|
171
|
+
return x;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return x;
|
|
177
|
+
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* this is a faster approximation for real numbers
|
|
182
|
+
*/
|
|
183
|
+
export const LnGamma = (z: number) => {
|
|
184
|
+
|
|
185
|
+
let x = z - 1.0;
|
|
186
|
+
let y = x + 5.5;
|
|
187
|
+
y -= (x + 0.5) * Math.log(y);
|
|
188
|
+
let a = 1.0;
|
|
189
|
+
|
|
190
|
+
const coefficients = [
|
|
191
|
+
76.18009173,
|
|
192
|
+
-86.50532033,
|
|
193
|
+
24.01409822,
|
|
194
|
+
-1.231739516,
|
|
195
|
+
0.120858003e-2,
|
|
196
|
+
-0.536382e-5,
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
for (const coeff of coefficients) {
|
|
200
|
+
a += coeff / (++x);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return (-y + Math.log(2.50662827465 * a));
|
|
204
|
+
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** PDF of the beta distribution */
|
|
208
|
+
export const BetaPDF = (x: number, a: number, b: number) => {
|
|
209
|
+
if (x < 0 || x > 1) {
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
return Math.exp(LnGamma(a + b) - LnGamma(a) - LnGamma(b)) *
|
|
213
|
+
Math.pow(x, a - 1) * Math.pow(1 - x, b - 1);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/** CDF of the beta distribution */
|
|
217
|
+
export const BetaCDF = (x: number, a: number, b: number) => {
|
|
218
|
+
|
|
219
|
+
if (x <= 0.0) {
|
|
220
|
+
return 0.0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (x >= 1.0) {
|
|
224
|
+
return 1.0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const ln_beta = (LnGamma(a) + LnGamma(b) - LnGamma(a + b));
|
|
228
|
+
const ln_pre = -ln_beta + a * Math.log(x) + b * Log1p(-x);
|
|
229
|
+
const prefactor = Math.exp(ln_pre);
|
|
230
|
+
|
|
231
|
+
if (x < (a + 1.0) / (a + b + 2.0)) {
|
|
232
|
+
const cf = BetaContFrac(a, b, x, 0);
|
|
233
|
+
return (prefactor * cf / a);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const epsabs = Math.abs(b / prefactor) * EPSILON;
|
|
237
|
+
const cf = BetaContFrac(b, a, 1.0 - x, epsabs);
|
|
238
|
+
const term = prefactor * cf / b;
|
|
239
|
+
return (1 - term);
|
|
240
|
+
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
};
|
|
244
|
+
|