@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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /*! API v30.12. Copyright 2018-2024 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "30.12.0",
3
+ "version": "30.16.0",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "homepage": "https://treb.app",
6
6
  "repository": {
@@ -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
+