@trebco/treb 31.1.3 → 31.3.2
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 +2 -2
- package/dist/treb-spreadsheet.mjs +13 -13
- package/dist/treb.d.ts +2 -2
- package/package.json +1 -1
- package/test/parser.ts +13 -0
- package/treb-calculator/src/complex-math.ts +104 -0
- package/treb-calculator/src/descriptors.ts +6 -0
- package/treb-calculator/src/functions/base-functions.ts +177 -96
- package/treb-calculator/src/functions/statistics-functions.ts +1 -0
- package/treb-calculator/tsconfig.json +0 -4
- package/treb-embed/src/embedded-spreadsheet.ts +6 -3
- package/treb-format/src/format.ts +8 -0
- package/treb-grid/src/editors/editor.ts +2 -2
- package/treb-grid/src/editors/formula_bar.ts +83 -10
- package/treb-grid/src/editors/overlay_editor.ts +11 -0
- package/treb-grid/src/types/grid.ts +56 -5
- package/treb-parser/src/parser-types.ts +4 -0
- package/treb-parser/src/parser.ts +44 -2
package/dist/treb.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! API v31.
|
|
1
|
+
/*! API v31.3. 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
|
|
@@ -908,7 +908,7 @@ export declare class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
908
908
|
*
|
|
909
909
|
* @public
|
|
910
910
|
*/
|
|
911
|
-
FormatNumber(value: number, format?: string): string;
|
|
911
|
+
FormatNumber(value: number | Complex, format?: string): string;
|
|
912
912
|
|
|
913
913
|
/**
|
|
914
914
|
* convert a javascript date (or timestamp) to a spreadsheet date
|
package/package.json
CHANGED
package/test/parser.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
import { Parser } from '../treb-parser/src/parser.js';
|
|
3
|
+
|
|
4
|
+
const parser = new Parser();
|
|
5
|
+
|
|
6
|
+
let text = "=NORMDIST((LN(S/K)+(r+s^2/2)*T)/(s*SQRT(T)), 0, 1, TRUE)*S - NORMDIST((LN(S/K)+(r-s^2/2)*T)/(s*SQRT(T)), 0, 1, TRUE)*K*EXP(-r*T)";
|
|
7
|
+
let result = parser.Parse(text);
|
|
8
|
+
// console.info('valid?', result.valid, result.expression);
|
|
9
|
+
|
|
10
|
+
text = "=s*SQRT(T)";
|
|
11
|
+
result = parser.Parse(text);
|
|
12
|
+
console.info('valid?', result.valid, result.expression);
|
|
13
|
+
|
|
@@ -175,6 +175,110 @@ export const Sin = (z: Complex) => {
|
|
|
175
175
|
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
+
export const ASin = (cpx: Complex) => {
|
|
179
|
+
|
|
180
|
+
if (cpx.imaginary === 0) {
|
|
181
|
+
return {
|
|
182
|
+
real: Math.asin(cpx.real),
|
|
183
|
+
imaginary: 0,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const x = Math.hypot(cpx.real + 1, cpx.imaginary) / 2;
|
|
188
|
+
const y = Math.hypot(cpx.real - 1, cpx.imaginary) / 2;
|
|
189
|
+
|
|
190
|
+
const sum = x + y;
|
|
191
|
+
const difference = x - y;
|
|
192
|
+
|
|
193
|
+
const result: Complex = {
|
|
194
|
+
real: Math.asin(difference),
|
|
195
|
+
imaginary: Math.log(sum + Math.sqrt(sum * sum - 1)),
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
if(cpx.imaginary < 0 || (cpx.imaginary === 0 && cpx.real > 1)) {
|
|
199
|
+
result.imaginary = -result.imaginary;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return result;
|
|
203
|
+
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export const ACos = (cpx: Complex) => {
|
|
207
|
+
|
|
208
|
+
if (cpx.imaginary === 0) {
|
|
209
|
+
return {
|
|
210
|
+
real: Math.acos(cpx.real),
|
|
211
|
+
imaginary: 0,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const asin = ASin(cpx);
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
real: Math.PI / 2 - asin.real,
|
|
219
|
+
imaginary: asin.imaginary,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const ATan = (cpx: Complex): Complex => {
|
|
225
|
+
|
|
226
|
+
const { real: x, imaginary: y } = cpx;
|
|
227
|
+
|
|
228
|
+
// Handle special case where z is purely imaginary
|
|
229
|
+
if (x === 0) {
|
|
230
|
+
if (y > 1) {
|
|
231
|
+
return { real: Math.PI / 2, imaginary: 0.5 * Math.log((y - 1) / (y + 1)) };
|
|
232
|
+
} else if (y < -1) {
|
|
233
|
+
return { real: -Math.PI / 2, imaginary: 0.5 * Math.log((1 - y) / (-1 - y)) };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const x2 = x * x;
|
|
238
|
+
const y2 = y * y;
|
|
239
|
+
|
|
240
|
+
// Calculate real and imaginary parts
|
|
241
|
+
const realPart = 0.5 * Math.atan2(2 * x, 1 - x2 - y2);
|
|
242
|
+
const imagPart = 0.25 * Math.log((x2 + (y + 1) * (y + 1)) / (x2 + (y - 1) * (y - 1)));
|
|
243
|
+
|
|
244
|
+
return { real: realPart, imaginary: imagPart };
|
|
245
|
+
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export const ATan2 = (y: Complex, x: Complex): Complex|false => {
|
|
249
|
+
|
|
250
|
+
// Special case: both arguments are zero
|
|
251
|
+
if (x.real === 0 && x.imaginary === 0 && y.real === 0 && y.imaginary === 0) {
|
|
252
|
+
// throw new Error("Both arguments of arctan2 are zero");
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Calculate z = y / x
|
|
257
|
+
const denominator = x.real * x.real + x.imaginary * x.imaginary;
|
|
258
|
+
const z: Complex = {
|
|
259
|
+
real: (y.real * x.real + y.imaginary * x.imaginary) / denominator,
|
|
260
|
+
imaginary: (y.imaginary * x.real - y.real * x.imaginary) / denominator
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Now calculate arctan(z)
|
|
264
|
+
const x2 = z.real * z.real;
|
|
265
|
+
const y2 = z.imaginary * z.imaginary;
|
|
266
|
+
|
|
267
|
+
const result = {
|
|
268
|
+
real: 0.5 * Math.atan2(2 * z.real, 1 - x2 - y2),
|
|
269
|
+
imaginary: 0.25 * Math.log((x2 + (z.imaginary + 1) * (z.imaginary + 1)) / (x2 + (z.imaginary - 1) * (z.imaginary - 1))),
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Adjust the real part based on the quadrant of x
|
|
273
|
+
if (x.real < 0) {
|
|
274
|
+
result.real += (y.real >= 0 || y.imaginary >= 0) ? Math.PI : -Math.PI;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return result;
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
};
|
|
281
|
+
|
|
178
282
|
export const Product = (...args: Complex[]): Complex => {
|
|
179
283
|
let base = args.shift();
|
|
180
284
|
if (!base) {
|
|
@@ -71,6 +71,12 @@ export interface ArgumentDescriptor {
|
|
|
71
71
|
*/
|
|
72
72
|
boxed?: boolean;
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* this argument repeasts. this has no impact on the function descriptor
|
|
76
|
+
* but it's useful to know for clients.
|
|
77
|
+
*/
|
|
78
|
+
repeat?: boolean;
|
|
79
|
+
|
|
74
80
|
/**
|
|
75
81
|
* similar to collector, this flag will return metadata about the cell
|
|
76
82
|
*
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { FunctionMap, IntrinsicValue } from '../descriptors';
|
|
22
|
+
import type { CompositeFunctionDescriptor, FunctionMap, IntrinsicValue } from '../descriptors';
|
|
23
23
|
import * as Utils from '../utilities';
|
|
24
24
|
// import { StringUnion, NumberUnion } from '../utilities';
|
|
25
25
|
import { ReferenceError, NAError, ArgumentError, DivideByZeroError, ValueError } from '../function-error';
|
|
@@ -213,6 +213,27 @@ const NumberArgument = (argument?: UnionValue, default_value: number|false = fal
|
|
|
213
213
|
|
|
214
214
|
};
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* helper for trig functions, curious what this does to size
|
|
218
|
+
*/
|
|
219
|
+
const TrigFunction = (real: (value: number) => number, complex: (value: Complex) => Complex, description?: string): CompositeFunctionDescriptor => {
|
|
220
|
+
return {
|
|
221
|
+
description,
|
|
222
|
+
arguments: [
|
|
223
|
+
{ name: 'number', boxed: true, unroll: true },
|
|
224
|
+
],
|
|
225
|
+
fn: (a: UnionValue) => {
|
|
226
|
+
if (a.type === ValueType.number) {
|
|
227
|
+
return { type: ValueType.number, value: real(a.value) };
|
|
228
|
+
}
|
|
229
|
+
if (a.type === ValueType.complex) {
|
|
230
|
+
return { type: ValueType.complex, value: complex(a.value) };
|
|
231
|
+
}
|
|
232
|
+
return ArgumentError();
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
216
237
|
/**
|
|
217
238
|
* alternate functions. these are used (atm) only for changing complex
|
|
218
239
|
* behavior.
|
|
@@ -345,7 +366,11 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
345
366
|
|
|
346
367
|
Sum: {
|
|
347
368
|
description: 'Adds arguments and ranges',
|
|
348
|
-
arguments: [{
|
|
369
|
+
arguments: [{
|
|
370
|
+
boxed: true,
|
|
371
|
+
name: 'values or ranges' ,
|
|
372
|
+
repeat: true,
|
|
373
|
+
}],
|
|
349
374
|
fn: (...args: UnionValue[]) => {
|
|
350
375
|
|
|
351
376
|
const sum = { real: 0, imaginary: 0 };
|
|
@@ -374,7 +399,7 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
374
399
|
|
|
375
400
|
SumSQ: {
|
|
376
401
|
description: 'Returns the sum of the squares of all arguments',
|
|
377
|
-
arguments: [{ boxed: true, name: 'values or ranges' }],
|
|
402
|
+
arguments: [{ boxed: true, name: 'values or ranges', repeat: true, }],
|
|
378
403
|
fn: (...args: UnionValue[]) => {
|
|
379
404
|
|
|
380
405
|
const sum = { real: 0, imaginary: 0 };
|
|
@@ -1982,7 +2007,13 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
1982
2007
|
},
|
|
1983
2008
|
|
|
1984
2009
|
Log: {
|
|
1985
|
-
arguments: [ {
|
|
2010
|
+
arguments: [ {
|
|
2011
|
+
name: 'number',
|
|
2012
|
+
unroll: true
|
|
2013
|
+
}, {
|
|
2014
|
+
name: 'base',
|
|
2015
|
+
unroll: true
|
|
2016
|
+
} ],
|
|
1986
2017
|
|
|
1987
2018
|
/** default is base 10; allow specific base */
|
|
1988
2019
|
fn: (a: number, base = 10): UnionValue => {
|
|
@@ -1991,26 +2022,115 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
1991
2022
|
},
|
|
1992
2023
|
|
|
1993
2024
|
Log10: {
|
|
1994
|
-
arguments: [{
|
|
2025
|
+
arguments: [{
|
|
2026
|
+
name: 'number',
|
|
2027
|
+
unroll: true,
|
|
2028
|
+
}],
|
|
1995
2029
|
fn: (a: number): UnionValue => {
|
|
1996
2030
|
return { type: ValueType.number, value: Math.log(a) / Math.log(10) };
|
|
1997
2031
|
},
|
|
1998
2032
|
},
|
|
1999
2033
|
|
|
2000
2034
|
Ln: {
|
|
2001
|
-
arguments: [{
|
|
2035
|
+
arguments: [{
|
|
2036
|
+
name: 'number',
|
|
2037
|
+
unroll: true,
|
|
2038
|
+
}],
|
|
2002
2039
|
fn: (a: number): UnionValue => {
|
|
2003
2040
|
return { type: ValueType.number, value: Math.log(a) };
|
|
2004
2041
|
},
|
|
2005
2042
|
},
|
|
2006
2043
|
|
|
2007
|
-
Ceiling: {
|
|
2008
|
-
arguments: [ {
|
|
2044
|
+
'Ceiling.Math': {
|
|
2045
|
+
arguments: [ {
|
|
2046
|
+
name: 'number',
|
|
2047
|
+
unroll: true
|
|
2048
|
+
}, {
|
|
2049
|
+
name: 'significance',
|
|
2050
|
+
unroll: true
|
|
2051
|
+
}, {
|
|
2052
|
+
name: 'away from zero',
|
|
2053
|
+
unroll: true,
|
|
2054
|
+
} ],
|
|
2055
|
+
|
|
2056
|
+
fn: (a: number, significance = 1, mode?: number) => {
|
|
2057
|
+
|
|
2058
|
+
let value = 0;
|
|
2059
|
+
|
|
2060
|
+
if (mode && a < 0) {
|
|
2061
|
+
value = -Math.ceil(-a / significance) * significance;
|
|
2062
|
+
}
|
|
2063
|
+
else {
|
|
2064
|
+
value = Math.ceil(a / significance) * significance;
|
|
2065
|
+
}
|
|
2009
2066
|
|
|
2010
|
-
fn: (a: number) => {
|
|
2011
2067
|
return {
|
|
2012
2068
|
type: ValueType.number,
|
|
2013
|
-
value
|
|
2069
|
+
value,
|
|
2070
|
+
};
|
|
2071
|
+
},
|
|
2072
|
+
},
|
|
2073
|
+
|
|
2074
|
+
'Floor.Math': {
|
|
2075
|
+
arguments: [ {
|
|
2076
|
+
name: 'number',
|
|
2077
|
+
unroll: true
|
|
2078
|
+
}, {
|
|
2079
|
+
name: 'significance',
|
|
2080
|
+
unroll: true
|
|
2081
|
+
}, {
|
|
2082
|
+
name: 'away from zero',
|
|
2083
|
+
unroll: true,
|
|
2084
|
+
} ],
|
|
2085
|
+
|
|
2086
|
+
fn: (a: number, significance = 1, mode?: number) => {
|
|
2087
|
+
|
|
2088
|
+
let value = 0;
|
|
2089
|
+
|
|
2090
|
+
if (mode && a < 0) {
|
|
2091
|
+
value = -Math.floor(-a / significance) * significance;
|
|
2092
|
+
}
|
|
2093
|
+
else {
|
|
2094
|
+
value = Math.floor(a / significance) * significance;
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
return {
|
|
2098
|
+
type: ValueType.number,
|
|
2099
|
+
value,
|
|
2100
|
+
};
|
|
2101
|
+
},
|
|
2102
|
+
},
|
|
2103
|
+
|
|
2104
|
+
Floor: {
|
|
2105
|
+
arguments: [ {
|
|
2106
|
+
name: 'number',
|
|
2107
|
+
unroll: true
|
|
2108
|
+
}, {
|
|
2109
|
+
name: 'significance',
|
|
2110
|
+
unroll: true
|
|
2111
|
+
} ],
|
|
2112
|
+
|
|
2113
|
+
fn: (a: number, significance = 1) => {
|
|
2114
|
+
return {
|
|
2115
|
+
type: ValueType.number,
|
|
2116
|
+
value: Math.floor(a / significance) * significance,
|
|
2117
|
+
};
|
|
2118
|
+
},
|
|
2119
|
+
},
|
|
2120
|
+
|
|
2121
|
+
Ceiling: {
|
|
2122
|
+
arguments: [ {
|
|
2123
|
+
name: 'number',
|
|
2124
|
+
unroll: true
|
|
2125
|
+
}, {
|
|
2126
|
+
name: 'significance',
|
|
2127
|
+
unroll: true
|
|
2128
|
+
} ],
|
|
2129
|
+
|
|
2130
|
+
fn: (a: number, significance = 1) => {
|
|
2131
|
+
return {
|
|
2132
|
+
type: ValueType.number,
|
|
2133
|
+
value: Math.ceil(a / significance) * significance,
|
|
2014
2134
|
};
|
|
2015
2135
|
},
|
|
2016
2136
|
},
|
|
@@ -2476,113 +2596,62 @@ export const BaseFunctionLibrary: FunctionMap = {
|
|
|
2476
2596
|
},
|
|
2477
2597
|
},
|
|
2478
2598
|
|
|
2479
|
-
|
|
2480
|
-
arguments: [
|
|
2481
|
-
{ name: 'number', boxed: true, unroll: true },
|
|
2482
|
-
],
|
|
2483
|
-
fn: (a: UnionValue) => {
|
|
2484
|
-
|
|
2485
|
-
if (a.type === ValueType.number) {
|
|
2486
|
-
return { type: ValueType.number, value: Math.sinh(a.value) };
|
|
2487
|
-
}
|
|
2488
|
-
if (a.type === ValueType.complex) {
|
|
2489
|
-
return { type: ValueType.complex, value: ComplexMath.SinH(a.value) };
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
return ArgumentError();
|
|
2493
|
-
|
|
2494
|
-
},
|
|
2495
|
-
},
|
|
2496
|
-
|
|
2497
|
-
Sin: {
|
|
2599
|
+
ATan2: {
|
|
2498
2600
|
arguments: [
|
|
2499
|
-
{ name: '
|
|
2601
|
+
{ name: 'y', boxed: true, unroll: true },
|
|
2602
|
+
{ name: 'x', boxed: true, unroll: true },
|
|
2500
2603
|
],
|
|
2501
|
-
fn: (
|
|
2604
|
+
fn: (y: UnionValue, x: UnionValue) => {
|
|
2502
2605
|
|
|
2503
|
-
if (
|
|
2504
|
-
return { type: ValueType.number, value: Math.
|
|
2505
|
-
}
|
|
2506
|
-
if (a.type === ValueType.complex) {
|
|
2507
|
-
return { type: ValueType.complex, value: ComplexMath.Sin(a.value) };
|
|
2606
|
+
if (y.type === ValueType.number && x.type === ValueType.number) {
|
|
2607
|
+
return { type: ValueType.number, value: Math.atan2(y.value, x.value) };
|
|
2508
2608
|
}
|
|
2509
2609
|
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
},
|
|
2513
|
-
},
|
|
2514
|
-
|
|
2515
|
-
CosH: {
|
|
2516
|
-
arguments: [
|
|
2517
|
-
{ name: 'number', boxed: true, unroll: true },
|
|
2518
|
-
],
|
|
2519
|
-
fn: (a: UnionValue) => {
|
|
2520
|
-
|
|
2521
|
-
if (a.type === ValueType.number) {
|
|
2522
|
-
return { type: ValueType.number, value: Math.cosh(a.value) };
|
|
2523
|
-
}
|
|
2524
|
-
if (a.type === ValueType.complex) {
|
|
2525
|
-
return { type: ValueType.complex, value: ComplexMath.CosH(a.value) };
|
|
2610
|
+
if (y.type === ValueType.number) {
|
|
2611
|
+
y = { type: ValueType.complex, value: { real: y.value, imaginary: 0 }};
|
|
2526
2612
|
}
|
|
2527
2613
|
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
},
|
|
2531
|
-
},
|
|
2532
|
-
|
|
2533
|
-
Cos: {
|
|
2534
|
-
arguments: [
|
|
2535
|
-
{ name: 'angle in radians', boxed: true, unroll: true, }
|
|
2536
|
-
],
|
|
2537
|
-
fn: (a: UnionValue) => {
|
|
2538
|
-
|
|
2539
|
-
if (a.type === ValueType.number) {
|
|
2540
|
-
return { type: ValueType.number, value: Math.cos(a.value) };
|
|
2541
|
-
}
|
|
2542
|
-
if (a.type === ValueType.complex) {
|
|
2543
|
-
return { type: ValueType.complex, value: ComplexMath.Cos(a.value) };
|
|
2614
|
+
if (x.type === ValueType.number) {
|
|
2615
|
+
x = { type: ValueType.complex, value: { real: x.value, imaginary: 0 }};
|
|
2544
2616
|
}
|
|
2545
2617
|
|
|
2546
|
-
|
|
2618
|
+
if (y.type === ValueType.complex && x.type === ValueType.complex) {
|
|
2619
|
+
|
|
2620
|
+
const value = ComplexMath.ATan2(y.value, x.value);
|
|
2547
2621
|
|
|
2548
|
-
|
|
2549
|
-
|
|
2622
|
+
// should we have an error for infinities? not sure. not sure
|
|
2623
|
+
// why this hasn't come up before...
|
|
2550
2624
|
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
],
|
|
2555
|
-
fn: (a: UnionValue) => {
|
|
2625
|
+
if (value === false) {
|
|
2626
|
+
return ArgumentError();
|
|
2627
|
+
}
|
|
2556
2628
|
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
if (a.type === ValueType.complex) {
|
|
2561
|
-
return { type: ValueType.complex, value: ComplexMath.TanH(a.value) };
|
|
2629
|
+
return {
|
|
2630
|
+
type: ValueType.complex, value,
|
|
2631
|
+
}
|
|
2562
2632
|
}
|
|
2563
|
-
|
|
2633
|
+
|
|
2564
2634
|
return ArgumentError();
|
|
2565
2635
|
|
|
2566
2636
|
},
|
|
2567
2637
|
},
|
|
2568
2638
|
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
],
|
|
2573
|
-
fn: (a: UnionValue) => {
|
|
2639
|
+
Sin: TrigFunction(Math.sin, ComplexMath.Sin),
|
|
2640
|
+
SinH: TrigFunction(Math.sinh, ComplexMath.SinH),
|
|
2641
|
+
ASin: TrigFunction(Math.asin, ComplexMath.ASin),
|
|
2574
2642
|
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
if (a.type === ValueType.complex) {
|
|
2579
|
-
return { type: ValueType.complex, value: ComplexMath.Tan(a.value) };
|
|
2580
|
-
}
|
|
2643
|
+
Cos: TrigFunction(Math.cos, ComplexMath.Cos),
|
|
2644
|
+
CosH: TrigFunction(Math.cosh, ComplexMath.CosH),
|
|
2645
|
+
ACos: TrigFunction(Math.acos, ComplexMath.ACos),
|
|
2581
2646
|
|
|
2582
|
-
|
|
2647
|
+
Tan: TrigFunction(Math.tan, ComplexMath.Tan),
|
|
2648
|
+
TanH: TrigFunction(Math.tanh, ComplexMath.TanH),
|
|
2649
|
+
ATan: TrigFunction(Math.atan, ComplexMath.ATan),
|
|
2583
2650
|
|
|
2584
|
-
|
|
2585
|
-
},
|
|
2651
|
+
E: { fn: () => { return { type: ValueType.number, value: Math.E } } },
|
|
2652
|
+
PI: { fn: () => { return { type: ValueType.number, value: Math.PI } } },
|
|
2653
|
+
SQRT2: { fn: () => { return { type: ValueType.number, value: Math.SQRT2 } } },
|
|
2654
|
+
SQRT1_2: { fn: () => { return { type: ValueType.number, value: Math.SQRT1_2 } } },
|
|
2586
2655
|
|
|
2587
2656
|
Sequence: {
|
|
2588
2657
|
arguments:[
|
|
@@ -2637,7 +2706,19 @@ for (const key of Object.keys(BaseFunctionLibrary)) {
|
|
|
2637
2706
|
// block these names from auto-import from Math
|
|
2638
2707
|
|
|
2639
2708
|
const block_list = [
|
|
2709
|
+
'ceil',
|
|
2640
2710
|
'pow',
|
|
2711
|
+
'ln10',
|
|
2712
|
+
'ln2',
|
|
2713
|
+
'log10',
|
|
2714
|
+
'log10e',
|
|
2715
|
+
'log1p',
|
|
2716
|
+
'log2',
|
|
2717
|
+
'log2e',
|
|
2718
|
+
'random',
|
|
2719
|
+
'imul',
|
|
2720
|
+
'clz32',
|
|
2721
|
+
'fround',
|
|
2641
2722
|
];
|
|
2642
2723
|
|
|
2643
2724
|
const block_map: Record<string, string> = {};
|
|
@@ -4217,11 +4217,14 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4217
4217
|
*
|
|
4218
4218
|
* @public
|
|
4219
4219
|
*/
|
|
4220
|
-
public FormatNumber(value: number, format = 'General'): string {
|
|
4221
|
-
|
|
4222
|
-
// API v1 OK
|
|
4220
|
+
public FormatNumber(value: number|Complex, format = 'General'): string {
|
|
4223
4221
|
|
|
4222
|
+
if (IsComplex(value)) {
|
|
4223
|
+
return NumberFormat.FormatPartsAsText(NumberFormatCache.Get(format).FormatComplex(value));
|
|
4224
|
+
}
|
|
4225
|
+
|
|
4224
4226
|
return NumberFormatCache.Get(format).Format(value);
|
|
4227
|
+
|
|
4225
4228
|
}
|
|
4226
4229
|
|
|
4227
4230
|
/**
|
|
@@ -489,6 +489,14 @@ export class NumberFormat {
|
|
|
489
489
|
// all zeros
|
|
490
490
|
// (5) change default fraction to #/## (actually we should do that always)
|
|
491
491
|
|
|
492
|
+
if (value.imaginary === Infinity || value.imaginary === -Infinity ||
|
|
493
|
+
value.real === Infinity || value.real === -Infinity) {
|
|
494
|
+
return [
|
|
495
|
+
{
|
|
496
|
+
text: 'Infinity',
|
|
497
|
+
}
|
|
498
|
+
]
|
|
499
|
+
}
|
|
492
500
|
|
|
493
501
|
// check if the imaginary format will render as 0.00i -- we want to
|
|
494
502
|
// handle this differently.
|
|
@@ -1133,11 +1133,11 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
1133
1133
|
* @param node
|
|
1134
1134
|
* @returns [substring to start of selection, substring to end of selection]
|
|
1135
1135
|
*/
|
|
1136
|
-
protected SubstringToCaret2(node: HTMLElement): [string, string] {
|
|
1136
|
+
protected SubstringToCaret2(node: HTMLElement, force = false): [string, string] {
|
|
1137
1137
|
|
|
1138
1138
|
const result: [string, string] = ['', ''];
|
|
1139
1139
|
|
|
1140
|
-
if (node !== node.ownerDocument.activeElement || node !== this.active_editor?.node) {
|
|
1140
|
+
if (!force && node !== node.ownerDocument.activeElement || node !== this.active_editor?.node) {
|
|
1141
1141
|
return result;
|
|
1142
1142
|
}
|
|
1143
1143
|
|