@cortex-js/compute-engine 0.9.0 → 0.10.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/compute-engine.esm.js +370 -220
- package/dist/compute-engine.min.esm.js +2 -2
- package/dist/compute-engine.min.js +2 -2
- package/dist/math-json.esm.js +2 -2
- package/dist/math-json.min.esm.js +2 -2
- package/dist/math-json.min.js +2 -2
- package/dist/types/common/grapheme-splitter.d.ts +1 -1
- package/dist/types/common/signals.d.ts +1 -1
- package/dist/types/common/utils.d.ts +1 -1
- package/dist/types/compute-engine/assume.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +1 -2
- package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-domain.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-function-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -2
- package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -2
- package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -2
- package/dist/types/compute-engine/boxed-expression/boxed-symbol-definition.d.ts +2 -3
- package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -2
- package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
- package/dist/types/compute-engine/compute-engine.d.ts +3 -2
- package/dist/types/compute-engine/cost-function.d.ts +1 -1
- package/dist/types/compute-engine/domain-utils.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-inequalities.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/public.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic-add.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic-divide.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic-multiply.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic-power.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/calculus.d.ts +1 -1
- package/dist/types/compute-engine/library/collections.d.ts +1 -1
- package/dist/types/compute-engine/library/core.d.ts +1 -1
- package/dist/types/compute-engine/library/domains.d.ts +1 -1
- package/dist/types/compute-engine/library/library.d.ts +1 -1
- package/dist/types/compute-engine/library/logic.d.ts +1 -1
- package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
- package/dist/types/compute-engine/library/sets.d.ts +1 -1
- package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
- package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
- package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
- package/dist/types/compute-engine/public.d.ts +12 -14
- package/dist/types/compute-engine/rules.d.ts +1 -1
- package/dist/types/compute-engine/simplify-rules.d.ts +1 -1
- package/dist/types/compute-engine/solve.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/expand.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/flatten.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/negate.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/product.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/sum.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/utils.d.ts +1 -1
- package/dist/types/compute-engine.d.ts +2 -2
- package/dist/types/math-json/math-json-format.d.ts +1 -1
- package/dist/types/math-json/utils.d.ts +1 -1
- package/dist/types/math-json.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** CortexJS Compute Engine 0.
|
|
1
|
+
/** CortexJS Compute Engine 0.10.0 */
|
|
2
2
|
/** @internal */
|
|
3
3
|
function isSymbolEntry(entry) {
|
|
4
4
|
return !('kind' in entry) || entry.kind === 'symbol';
|
|
@@ -13988,6 +13988,8 @@ function primeFactors$1(n) {
|
|
|
13988
13988
|
*
|
|
13989
13989
|
*/
|
|
13990
13990
|
function factorPower$1(n, exponent) {
|
|
13991
|
+
if (n >= Number.MAX_SAFE_INTEGER)
|
|
13992
|
+
return [1, n];
|
|
13991
13993
|
// @todo: handle negative n
|
|
13992
13994
|
console.assert(Number.isInteger(n) && n > 0 && n < Number.MAX_SAFE_INTEGER);
|
|
13993
13995
|
const factors = primeFactors$1(n);
|
|
@@ -14562,6 +14564,9 @@ function validateArgumentCount(ce, ops, count) {
|
|
|
14562
14564
|
* the number of expected arguments.
|
|
14563
14565
|
*/
|
|
14564
14566
|
function validateNumericArgs(ce, ops, count) {
|
|
14567
|
+
// @fastpath
|
|
14568
|
+
if (!ce.strict)
|
|
14569
|
+
return ops.map((x) => ce.box(x));
|
|
14565
14570
|
let xs = [];
|
|
14566
14571
|
if (count === undefined) {
|
|
14567
14572
|
xs = ops.map((x) => ce.box(x));
|
|
@@ -14585,6 +14590,9 @@ function validateNumericArgs(ce, ops, count) {
|
|
|
14585
14590
|
*/
|
|
14586
14591
|
function validateSignature(sig, ops, codomain) {
|
|
14587
14592
|
const ce = sig.engine;
|
|
14593
|
+
// @fastpath
|
|
14594
|
+
if (!ce.strict)
|
|
14595
|
+
return ops;
|
|
14588
14596
|
const opsDomain = ops.map((x) => x.domain);
|
|
14589
14597
|
const targetSig = ce.domain([
|
|
14590
14598
|
'Function',
|
|
@@ -14996,7 +15004,8 @@ function asMachineRational(r) {
|
|
|
14996
15004
|
* @returns
|
|
14997
15005
|
*/
|
|
14998
15006
|
function add(lhs, rhs) {
|
|
14999
|
-
console.assert(Array.isArray(rhs) ||
|
|
15007
|
+
console.assert(Array.isArray(rhs) ||
|
|
15008
|
+
(rhs.numericValue !== null && !(rhs instanceof Complex)));
|
|
15000
15009
|
if (Array.isArray(rhs)) {
|
|
15001
15010
|
if (isBigRational(rhs))
|
|
15002
15011
|
return [rhs[1].mul(lhs[0]).add(rhs[0].mul(lhs[1])), rhs[1].mul(lhs[1])];
|
|
@@ -15034,7 +15043,8 @@ function add(lhs, rhs) {
|
|
|
15034
15043
|
return lhs;
|
|
15035
15044
|
}
|
|
15036
15045
|
function mul(lhs, rhs) {
|
|
15037
|
-
console.assert(Array.isArray(rhs) ||
|
|
15046
|
+
console.assert(Array.isArray(rhs) ||
|
|
15047
|
+
(rhs.numericValue !== null && !(rhs instanceof Complex)));
|
|
15038
15048
|
if (Array.isArray(rhs)) {
|
|
15039
15049
|
if (isBigRational(lhs))
|
|
15040
15050
|
return [lhs[0].mul(rhs[0]), lhs[1].mul(rhs[1])];
|
|
@@ -15199,7 +15209,7 @@ function asCoefficient(expr) {
|
|
|
15199
15209
|
//
|
|
15200
15210
|
if (expr.head === 'Power') {
|
|
15201
15211
|
// We can only extract a coef if the exponent is a literal
|
|
15202
|
-
if (
|
|
15212
|
+
if (expr.op2.numericValue === null)
|
|
15203
15213
|
return [[1, 1], expr];
|
|
15204
15214
|
// eslint-disable-next-line prefer-const
|
|
15205
15215
|
let [coef, base] = asCoefficient(expr.op1);
|
|
@@ -15274,7 +15284,9 @@ function signDiff(lhs, rhs, tolerance) {
|
|
|
15274
15284
|
return 0;
|
|
15275
15285
|
const lhsN = lhs.N();
|
|
15276
15286
|
const rhsN = rhs.N();
|
|
15277
|
-
|
|
15287
|
+
const lhsNum = lhsN.numericValue;
|
|
15288
|
+
const rhsNum = rhsN.numericValue;
|
|
15289
|
+
if (lhsNum === null || rhsNum === null) {
|
|
15278
15290
|
// Couldn't calculate a numeric value, use the `sgn`
|
|
15279
15291
|
const lhsS = lhs.sgn;
|
|
15280
15292
|
const rhsS = rhs.sgn;
|
|
@@ -15289,8 +15301,6 @@ function signDiff(lhs, rhs, tolerance) {
|
|
|
15289
15301
|
return undefined;
|
|
15290
15302
|
}
|
|
15291
15303
|
tolerance ?? (tolerance = lhs.engine.tolerance);
|
|
15292
|
-
const lhsNum = lhsN.numericValue;
|
|
15293
|
-
const rhsNum = rhsN.numericValue;
|
|
15294
15304
|
if (lhsNum instanceof Complex && rhsNum instanceof Complex)
|
|
15295
15305
|
return chop(lhsNum.re - rhsNum.re, tolerance) === 0 &&
|
|
15296
15306
|
chop(lhsNum.im - rhsNum.im, tolerance) === 0
|
|
@@ -15322,11 +15332,11 @@ function negateLiteral(expr, metadata) {
|
|
|
15322
15332
|
return null;
|
|
15323
15333
|
if (typeof n === 'number')
|
|
15324
15334
|
n = -n;
|
|
15325
|
-
if (n instanceof Decimal)
|
|
15335
|
+
else if (n instanceof Decimal)
|
|
15326
15336
|
n = n.neg();
|
|
15327
|
-
if (n instanceof complex.exports.Complex)
|
|
15337
|
+
else if (n instanceof complex.exports.Complex)
|
|
15328
15338
|
n = n.neg();
|
|
15329
|
-
if (Array.isArray(n))
|
|
15339
|
+
else if (Array.isArray(n))
|
|
15330
15340
|
n = neg(n);
|
|
15331
15341
|
return expr.engine.number(n, { metadata });
|
|
15332
15342
|
}
|
|
@@ -15344,7 +15354,7 @@ function canonicalNegate(expr, metadata) {
|
|
|
15344
15354
|
if (expr.head === 'Negate')
|
|
15345
15355
|
return validateArgument(expr.engine, expr.op1?.canonical, 'Number');
|
|
15346
15356
|
expr = validateArgument(expr.engine, expr.canonical, 'Number');
|
|
15347
|
-
if (expr.
|
|
15357
|
+
if (expr.numericValue !== null)
|
|
15348
15358
|
return negateLiteral(expr, metadata);
|
|
15349
15359
|
// Distribute over addition
|
|
15350
15360
|
// Negate(Add(a, b)) -> Add(Negate(a), Negate(b))
|
|
@@ -15369,10 +15379,10 @@ function canonicalNegate(expr, metadata) {
|
|
|
15369
15379
|
* `canonical` chain.
|
|
15370
15380
|
*/
|
|
15371
15381
|
function distributeNegate(expr) {
|
|
15382
|
+
if (expr.numericValue !== null)
|
|
15383
|
+
return negateLiteral(expr);
|
|
15372
15384
|
if (expr.head === 'Negate')
|
|
15373
15385
|
return expr.op1;
|
|
15374
|
-
if (expr.isLiteral)
|
|
15375
|
-
return negateLiteral(expr);
|
|
15376
15386
|
const ce = expr.engine;
|
|
15377
15387
|
// Distribute over addition
|
|
15378
15388
|
// Negate(Add(a, b)) -> Add(Negate(a), Negate(b))
|
|
@@ -15414,7 +15424,7 @@ function negateProduct(ce, args) {
|
|
|
15414
15424
|
// else If there is a literal integer, negate it
|
|
15415
15425
|
result = [];
|
|
15416
15426
|
for (const arg of args) {
|
|
15417
|
-
if (done ||
|
|
15427
|
+
if (done || arg.numericValue === null || !arg.isInteger)
|
|
15418
15428
|
result.push(arg);
|
|
15419
15429
|
else {
|
|
15420
15430
|
done = true;
|
|
@@ -15426,7 +15436,7 @@ function negateProduct(ce, args) {
|
|
|
15426
15436
|
// else If there is a literal number, negate it
|
|
15427
15437
|
result = [];
|
|
15428
15438
|
for (const arg of args) {
|
|
15429
|
-
if (done ||
|
|
15439
|
+
if (done || arg.numericValue === null || !arg.isNumber)
|
|
15430
15440
|
result.push(arg);
|
|
15431
15441
|
else {
|
|
15432
15442
|
done = true;
|
|
@@ -16185,9 +16195,6 @@ class AbstractBoxedExpression {
|
|
|
16185
16195
|
get url() {
|
|
16186
16196
|
return undefined;
|
|
16187
16197
|
}
|
|
16188
|
-
get isLiteral() {
|
|
16189
|
-
return false;
|
|
16190
|
-
}
|
|
16191
16198
|
get wikidata() {
|
|
16192
16199
|
return this._wikidata;
|
|
16193
16200
|
}
|
|
@@ -16285,7 +16292,7 @@ class AbstractBoxedExpression {
|
|
|
16285
16292
|
* `3√2x^5y^3` -> 8 (5 + 3)
|
|
16286
16293
|
*/
|
|
16287
16294
|
function totalDegree(expr) {
|
|
16288
|
-
if (expr.head === 'Power' && expr.op2.
|
|
16295
|
+
if (expr.head === 'Power' && expr.op2.numericValue !== null) {
|
|
16289
16296
|
const deg = asSmallInteger(expr.op2);
|
|
16290
16297
|
if (deg !== null && deg > 0)
|
|
16291
16298
|
return deg;
|
|
@@ -16310,7 +16317,7 @@ function totalDegree(expr) {
|
|
|
16310
16317
|
*
|
|
16311
16318
|
*/
|
|
16312
16319
|
function maxDegree(expr) {
|
|
16313
|
-
if (expr.head === 'Power' && expr.op2.
|
|
16320
|
+
if (expr.head === 'Power' && expr.op2.numericValue !== null) {
|
|
16314
16321
|
const deg = asSmallInteger(expr.op2);
|
|
16315
16322
|
if (deg !== null && deg > 0)
|
|
16316
16323
|
return deg;
|
|
@@ -16404,17 +16411,17 @@ function order(a, b) {
|
|
|
16404
16411
|
// 1/ Literal numeric values
|
|
16405
16412
|
//
|
|
16406
16413
|
const af = asFloat(a);
|
|
16407
|
-
if (
|
|
16414
|
+
if (af !== null) {
|
|
16408
16415
|
const bf = asFloat(b);
|
|
16409
|
-
if (
|
|
16416
|
+
if (bf !== null)
|
|
16410
16417
|
return af - bf;
|
|
16411
16418
|
return -1;
|
|
16412
16419
|
}
|
|
16413
16420
|
//
|
|
16414
16421
|
// 2/ Complex numbers
|
|
16415
16422
|
//
|
|
16416
|
-
if (a.
|
|
16417
|
-
if (b.
|
|
16423
|
+
if (a.numericValue instanceof Complex) {
|
|
16424
|
+
if (b.numericValue instanceof Complex) {
|
|
16418
16425
|
if (a.numericValue.re === b.numericValue.re) {
|
|
16419
16426
|
if (Math.abs(a.numericValue.im) === Math.abs(b.numericValue.im)) {
|
|
16420
16427
|
return a.numericValue.im - b.numericValue.im;
|
|
@@ -16423,7 +16430,7 @@ function order(a, b) {
|
|
|
16423
16430
|
}
|
|
16424
16431
|
return a.numericValue.re - b.numericValue.re;
|
|
16425
16432
|
}
|
|
16426
|
-
if (b.
|
|
16433
|
+
if (b.numericValue !== null)
|
|
16427
16434
|
return +1;
|
|
16428
16435
|
return -1;
|
|
16429
16436
|
}
|
|
@@ -16436,7 +16443,7 @@ function order(a, b) {
|
|
|
16436
16443
|
return 0;
|
|
16437
16444
|
return a.symbol > b.symbol ? 1 : -1;
|
|
16438
16445
|
}
|
|
16439
|
-
if (b.
|
|
16446
|
+
if (b.numericValue !== null)
|
|
16440
16447
|
return +1;
|
|
16441
16448
|
return -1;
|
|
16442
16449
|
}
|
|
@@ -16466,7 +16473,7 @@ function order(a, b) {
|
|
|
16466
16473
|
}
|
|
16467
16474
|
return aComplexity - bComplexity;
|
|
16468
16475
|
}
|
|
16469
|
-
if (
|
|
16476
|
+
if (b.numericValue !== null || b.symbol)
|
|
16470
16477
|
return +1;
|
|
16471
16478
|
return -1;
|
|
16472
16479
|
}
|
|
@@ -16589,7 +16596,7 @@ class Product {
|
|
|
16589
16596
|
// }
|
|
16590
16597
|
// If we're calculation a canonical product, fold exact literals into
|
|
16591
16598
|
// running terms
|
|
16592
|
-
if (term.
|
|
16599
|
+
if (term.numericValue !== null) {
|
|
16593
16600
|
if (term.isOne)
|
|
16594
16601
|
return;
|
|
16595
16602
|
if (term.isZero) {
|
|
@@ -16608,9 +16615,10 @@ class Product {
|
|
|
16608
16615
|
}
|
|
16609
16616
|
let num = term.numericValue;
|
|
16610
16617
|
if (typeof num === 'number') {
|
|
16611
|
-
if (num < 0)
|
|
16618
|
+
if (num < 0) {
|
|
16612
16619
|
this._sign *= -1;
|
|
16613
|
-
|
|
16620
|
+
num = -num;
|
|
16621
|
+
}
|
|
16614
16622
|
if (Number.isInteger(num))
|
|
16615
16623
|
this._rational = mul(this._rational, [num, 1]);
|
|
16616
16624
|
else if (bignumPreferred(this.engine))
|
|
@@ -16661,11 +16669,11 @@ class Product {
|
|
|
16661
16669
|
}
|
|
16662
16670
|
}
|
|
16663
16671
|
// Note: rest should be positive, so no need to handle the -1 case
|
|
16664
|
-
if (rest.
|
|
16672
|
+
if (rest.numericValue !== null && rest.isOne)
|
|
16665
16673
|
return;
|
|
16666
16674
|
// If this is a power expression, extract the exponent
|
|
16667
16675
|
let exponent = [1, 1];
|
|
16668
|
-
if (rest.head === 'Power'
|
|
16676
|
+
if (rest.head === 'Power') {
|
|
16669
16677
|
// Term is `Power(op1, op2)`
|
|
16670
16678
|
const r = asRational(rest.op2);
|
|
16671
16679
|
if (r) {
|
|
@@ -16726,38 +16734,36 @@ class Product {
|
|
|
16726
16734
|
return [];
|
|
16727
16735
|
return [{ exponent: [1, 1], terms: [ce.number(b)] }];
|
|
16728
16736
|
}
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
if (
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
|
|
16752
|
-
if (z.equals(1))
|
|
16753
|
-
return [];
|
|
16754
|
-
return [{ exponent: [1, 1], terms: [ce.number(z)] }];
|
|
16755
|
-
}
|
|
16756
|
-
n *= this._complex.re;
|
|
16757
|
-
if (n === 1)
|
|
16737
|
+
// Machine preferred
|
|
16738
|
+
let n = 1;
|
|
16739
|
+
if (!isRationalOne(this._rational)) {
|
|
16740
|
+
if (isBigRational(this._rational))
|
|
16741
|
+
n = this._rational[0].toNumber() / this._rational[1].toNumber();
|
|
16742
|
+
else
|
|
16743
|
+
n = this._rational[0] / this._rational[1];
|
|
16744
|
+
}
|
|
16745
|
+
// if (!isRationalOne(this._squareRootRational)) {
|
|
16746
|
+
// if (isBigRational(this._squareRootRational))
|
|
16747
|
+
// n *= Math.sqrt(
|
|
16748
|
+
// this._squareRootRational[0].toNumber() /
|
|
16749
|
+
// this._squareRootRational[1].toNumber()
|
|
16750
|
+
// );
|
|
16751
|
+
// else
|
|
16752
|
+
// n *= Math.sqrt(
|
|
16753
|
+
// this._squareRootRational[0] / this._squareRootRational[1]
|
|
16754
|
+
// );
|
|
16755
|
+
// }
|
|
16756
|
+
n *= this._sign * this._number * this._bignum.toNumber();
|
|
16757
|
+
if (this._complex.im !== 0) {
|
|
16758
|
+
const z = this._complex.mul(n);
|
|
16759
|
+
if (z.equals(1))
|
|
16758
16760
|
return [];
|
|
16759
|
-
return [{ exponent: [1, 1], terms: [ce.number(
|
|
16761
|
+
return [{ exponent: [1, 1], terms: [ce.number(z)] }];
|
|
16760
16762
|
}
|
|
16763
|
+
n *= this._complex.re;
|
|
16764
|
+
if (n === 1)
|
|
16765
|
+
return [];
|
|
16766
|
+
return [{ exponent: [1, 1], terms: [ce.number(n)] }];
|
|
16761
16767
|
}
|
|
16762
16768
|
//
|
|
16763
16769
|
// Terms of degree 1 (exponent = [1,1])
|
|
@@ -16795,7 +16801,12 @@ class Product {
|
|
|
16795
16801
|
});
|
|
16796
16802
|
}
|
|
16797
16803
|
else {
|
|
16798
|
-
|
|
16804
|
+
if (n === -1) {
|
|
16805
|
+
unitTerms.push(ce.number(neg(this._rational)));
|
|
16806
|
+
n = 1;
|
|
16807
|
+
}
|
|
16808
|
+
else
|
|
16809
|
+
unitTerms.push(ce.number(this._rational));
|
|
16799
16810
|
}
|
|
16800
16811
|
}
|
|
16801
16812
|
// if (!isRationalOne(this._squareRootRational)) {
|
|
@@ -16926,7 +16937,7 @@ class Product {
|
|
|
16926
16937
|
}
|
|
16927
16938
|
asRationalExpression() {
|
|
16928
16939
|
const [numerator, denominator] = this.asNumeratorDenominator();
|
|
16929
|
-
if (denominator.
|
|
16940
|
+
if (denominator.numericValue !== null) {
|
|
16930
16941
|
if (denominator.isOne)
|
|
16931
16942
|
return numerator;
|
|
16932
16943
|
if (denominator.isNegativeOne)
|
|
@@ -16992,7 +17003,7 @@ function termsAsExpressions(ce, terms) {
|
|
|
16992
17003
|
}
|
|
16993
17004
|
|
|
16994
17005
|
function subtract(ce, a, b, metadata) {
|
|
16995
|
-
if (a.
|
|
17006
|
+
if (a.numericValue !== null) {
|
|
16996
17007
|
if (isRational(a.numericValue)) {
|
|
16997
17008
|
if (machineNumerator(a.numericValue) < 0) {
|
|
16998
17009
|
return serializeJsonFunction(ce, 'Subtract', [b, ce.number(neg(a.numericValue))], metadata);
|
|
@@ -17025,7 +17036,7 @@ function serializeJsonCanonicalFunction(ce, head, args, metadata) {
|
|
|
17025
17036
|
return serializeJsonFunction(ce, 'Multiply', [args[0], ce._fn('Power', [args[1], ce._NEGATIVE_ONE])], metadata);
|
|
17026
17037
|
}
|
|
17027
17038
|
if (head === 'Multiply' && !exclusions.includes('Negate')) {
|
|
17028
|
-
if (
|
|
17039
|
+
if (asFloat(args[0]) === -1)
|
|
17029
17040
|
return serializeJsonFunction(ce, 'Negate', [ce._fn('Multiply', args.slice(1))], metadata);
|
|
17030
17041
|
}
|
|
17031
17042
|
if (head === 'Multiply' && !exclusions.includes('Divide')) {
|
|
@@ -17040,7 +17051,7 @@ function serializeJsonCanonicalFunction(ce, head, args, metadata) {
|
|
|
17040
17051
|
if (head === 'Power') {
|
|
17041
17052
|
if (!exclusions.includes('Exp') && args[0]?.symbol === 'ExponentialE')
|
|
17042
17053
|
return serializeJsonFunction(ce, 'Exp', [args[1]], metadata);
|
|
17043
|
-
if (args[1]?.
|
|
17054
|
+
if (args[1]?.numericValue !== null) {
|
|
17044
17055
|
const exp = asSmallInteger(args[1]);
|
|
17045
17056
|
if (exp === 2 && !exclusions.includes('Square'))
|
|
17046
17057
|
return serializeJsonFunction(ce, 'Square', [args[0]], metadata);
|
|
@@ -17105,7 +17116,7 @@ function serializeJsonFunction(ce, head, args, metadata) {
|
|
|
17105
17116
|
return serializeJsonFunction(ce, 'Add', [args[0], ce._fn('Multiply', [args[1], ce.symbol('ImaginaryUnit')])], metadata);
|
|
17106
17117
|
if (head === 'Sqrt' && args.length === 1)
|
|
17107
17118
|
return serializeJsonFunction(ce, 'Power', [args[0], exclusions.includes('Half') ? ce.number([1, 2]) : ce._HALF], metadata);
|
|
17108
|
-
if (head === 'Root' && args.length === 2 && args[1].
|
|
17119
|
+
if (head === 'Root' && args.length === 2 && args[1].numericValue !== null) {
|
|
17109
17120
|
const n = asSmallInteger(args[1]);
|
|
17110
17121
|
if (n === 2)
|
|
17111
17122
|
return serializeJsonFunction(ce, 'Sqrt', [args[0]]);
|
|
@@ -17127,7 +17138,7 @@ function serializeJsonFunction(ce, head, args, metadata) {
|
|
|
17127
17138
|
return serializeJsonFunction(ce, 'Negate', args, metadata);
|
|
17128
17139
|
}
|
|
17129
17140
|
if (head === 'Add' && args.length === 2 && !exclusions.includes('Subtract')) {
|
|
17130
|
-
if (args[1].
|
|
17141
|
+
if (args[1].numericValue !== null) {
|
|
17131
17142
|
const t1 = asSmallInteger(args[1]);
|
|
17132
17143
|
if (t1 !== null && t1 < 0)
|
|
17133
17144
|
return serializeJsonFunction(ce, 'Subtract', [args[0], ce.number(-t1)], metadata);
|
|
@@ -17900,14 +17911,13 @@ class BoxedFunction extends AbstractBoxedExpression {
|
|
|
17900
17911
|
set isCanonical(val) {
|
|
17901
17912
|
this._canonical = val ? this : undefined;
|
|
17902
17913
|
}
|
|
17903
|
-
get isLiteral() {
|
|
17904
|
-
return false;
|
|
17905
|
-
}
|
|
17906
17914
|
get isPure() {
|
|
17907
|
-
if (!this.isCanonical)
|
|
17908
|
-
return false;
|
|
17909
17915
|
if (this._isPure !== undefined)
|
|
17910
17916
|
return this._isPure;
|
|
17917
|
+
if (!this.isCanonical) {
|
|
17918
|
+
this._isPure = false;
|
|
17919
|
+
return false;
|
|
17920
|
+
}
|
|
17911
17921
|
let result = undefined;
|
|
17912
17922
|
if (this.functionDefinition?.pure !== undefined)
|
|
17913
17923
|
result = this.functionDefinition.pure;
|
|
@@ -18113,9 +18123,7 @@ class BoxedFunction extends AbstractBoxedExpression {
|
|
|
18113
18123
|
debugger;
|
|
18114
18124
|
}
|
|
18115
18125
|
get value() {
|
|
18116
|
-
if (!this.isCanonical)
|
|
18117
|
-
return undefined;
|
|
18118
|
-
if (!this.isPure)
|
|
18126
|
+
if (!this.isCanonical || !this.isPure)
|
|
18119
18127
|
return undefined;
|
|
18120
18128
|
// Use cached value if the function is pure
|
|
18121
18129
|
if (!this._value)
|
|
@@ -18459,12 +18467,12 @@ class BoxedFunction extends AbstractBoxedExpression {
|
|
|
18459
18467
|
//
|
|
18460
18468
|
// 1/ Use canonical form
|
|
18461
18469
|
//
|
|
18462
|
-
if (
|
|
18470
|
+
if (this._numericValue)
|
|
18471
|
+
return this._numericValue;
|
|
18472
|
+
if (this.engine.strict && !this.isValid)
|
|
18463
18473
|
return this;
|
|
18464
18474
|
if (!this.isCanonical)
|
|
18465
18475
|
return this.canonical.N(options);
|
|
18466
|
-
if (this._numericValue)
|
|
18467
|
-
return this._numericValue;
|
|
18468
18476
|
//
|
|
18469
18477
|
// 2/ Evaluate the applicable operands
|
|
18470
18478
|
//
|
|
@@ -18541,7 +18549,7 @@ function makeNumericFunction(ce, head, semiOps, metadata) {
|
|
|
18541
18549
|
return ce.power(ops[0], ce.number(2), metadata);
|
|
18542
18550
|
if (head === 'Sqrt') {
|
|
18543
18551
|
const op = ops[0].canonical;
|
|
18544
|
-
if (op.
|
|
18552
|
+
if (isRational(op.numericValue))
|
|
18545
18553
|
return new BoxedFunction(ce, 'Sqrt', [op], { metadata, canonical: true });
|
|
18546
18554
|
return ce.power(op, ce.number([1, 2]), metadata);
|
|
18547
18555
|
}
|
|
@@ -18895,12 +18903,13 @@ class BoxedNumber extends AbstractBoxedExpression {
|
|
|
18895
18903
|
* range
|
|
18896
18904
|
*/
|
|
18897
18905
|
constructor(ce, value, options) {
|
|
18898
|
-
|
|
18899
|
-
|
|
18900
|
-
|
|
18906
|
+
super(ce, options?.metadata);
|
|
18907
|
+
if (typeof value === 'number') {
|
|
18908
|
+
this._value = value;
|
|
18909
|
+
this._isCanonical = true;
|
|
18910
|
+
return;
|
|
18911
|
+
}
|
|
18901
18912
|
if (isRational(value)) {
|
|
18902
|
-
if (!('canonical' in options))
|
|
18903
|
-
options.canonical = true;
|
|
18904
18913
|
//
|
|
18905
18914
|
// This is a rational (or big rational)
|
|
18906
18915
|
//
|
|
@@ -18909,7 +18918,7 @@ class BoxedNumber extends AbstractBoxedExpression {
|
|
|
18909
18918
|
(Number.isInteger(n) && Number.isInteger(d) && d !== n && d !== 1));
|
|
18910
18919
|
console.assert(!(n instanceof Decimal && d instanceof Decimal) ||
|
|
18911
18920
|
(n.isInteger() && d.isInteger() && !d.eq(n) && !d.eq(1)));
|
|
18912
|
-
if (options
|
|
18921
|
+
if (options?.canonical ?? true) {
|
|
18913
18922
|
this._value = canonicalNumber(ce, value);
|
|
18914
18923
|
this._isCanonical = true;
|
|
18915
18924
|
}
|
|
@@ -18931,7 +18940,6 @@ class BoxedNumber extends AbstractBoxedExpression {
|
|
|
18931
18940
|
this._value = canonicalNumber(ce, value);
|
|
18932
18941
|
this._isCanonical = true;
|
|
18933
18942
|
}
|
|
18934
|
-
ce._register(this);
|
|
18935
18943
|
}
|
|
18936
18944
|
get hash() {
|
|
18937
18945
|
if (this._hash !== undefined)
|
|
@@ -18954,9 +18962,6 @@ class BoxedNumber extends AbstractBoxedExpression {
|
|
|
18954
18962
|
get isPure() {
|
|
18955
18963
|
return true;
|
|
18956
18964
|
}
|
|
18957
|
-
get isLiteral() {
|
|
18958
|
-
return true;
|
|
18959
|
-
}
|
|
18960
18965
|
get isExact() {
|
|
18961
18966
|
if (typeof this._value === 'number')
|
|
18962
18967
|
return Number.isInteger(this._value);
|
|
@@ -19386,9 +19391,6 @@ class BoxedString extends AbstractBoxedExpression {
|
|
|
19386
19391
|
get isPure() {
|
|
19387
19392
|
return true;
|
|
19388
19393
|
}
|
|
19389
|
-
get isLiteral() {
|
|
19390
|
-
return true;
|
|
19391
|
-
}
|
|
19392
19394
|
get isCanonical() {
|
|
19393
19395
|
return true;
|
|
19394
19396
|
}
|
|
@@ -19722,7 +19724,7 @@ function boxFunction(ce, head, ops, options) {
|
|
|
19722
19724
|
if (key.isValid && !key.isNothing) {
|
|
19723
19725
|
const value = arg.op2;
|
|
19724
19726
|
let k = key.symbol ?? key.string;
|
|
19725
|
-
if (!k && key.
|
|
19727
|
+
if (!k && (key.numericValue !== null || key.string)) {
|
|
19726
19728
|
const n = typeof key.numericValue === 'number'
|
|
19727
19729
|
? key.numericValue
|
|
19728
19730
|
: asSmallInteger(key);
|
|
@@ -19923,7 +19925,7 @@ class Sum {
|
|
|
19923
19925
|
if (this._isCanonical) {
|
|
19924
19926
|
if (term.isNothing)
|
|
19925
19927
|
return;
|
|
19926
|
-
if (term.
|
|
19928
|
+
if (term.numericValue !== null) {
|
|
19927
19929
|
if (term.isInfinity) {
|
|
19928
19930
|
if (term.isPositive)
|
|
19929
19931
|
this._posInfinityCount += 1;
|
|
@@ -19995,13 +19997,13 @@ class Sum {
|
|
|
19995
19997
|
return;
|
|
19996
19998
|
}
|
|
19997
19999
|
let hasTerm = false;
|
|
19998
|
-
if (
|
|
20000
|
+
if (term.numericValue === null) {
|
|
19999
20001
|
// There's an overhead to calculate the hash.
|
|
20000
20002
|
// For best results, only use the hash if there are many terms
|
|
20001
20003
|
if (this._terms.length > 500) {
|
|
20002
20004
|
const h = term.hash;
|
|
20003
20005
|
for (let i = 0; i < this._terms.length; i++) {
|
|
20004
|
-
if (
|
|
20006
|
+
if (this._terms[i].term.numericValue === null &&
|
|
20005
20007
|
h === this._terms[i].term.hash &&
|
|
20006
20008
|
term.isSame(this._terms[i].term)) {
|
|
20007
20009
|
this._terms[i].coef = add(this._terms[i].coef, coef);
|
|
@@ -20012,7 +20014,7 @@ class Sum {
|
|
|
20012
20014
|
}
|
|
20013
20015
|
else {
|
|
20014
20016
|
for (let i = 0; i < this._terms.length; i++) {
|
|
20015
|
-
if (
|
|
20017
|
+
if (this._terms[i].term.numericValue === null &&
|
|
20016
20018
|
term.isSame(this._terms[i].term)) {
|
|
20017
20019
|
this._terms[i].coef = add(this._terms[i].coef, coef);
|
|
20018
20020
|
hasTerm = true;
|
|
@@ -21034,7 +21036,7 @@ function canonicalAdd(ce, ops) {
|
|
|
21034
21036
|
console.assert(ops.every((x) => x.isCanonical));
|
|
21035
21037
|
ops = flattenOps(flattenSequence(ops.map((x) => x.canonical)), 'Add') ?? ops;
|
|
21036
21038
|
// Remove literal 0
|
|
21037
|
-
ops = ops.filter((x) =>
|
|
21039
|
+
ops = ops.filter((x) => x.numericValue === null || !x.isZero);
|
|
21038
21040
|
if (ops.length === 0)
|
|
21039
21041
|
return ce.number(0);
|
|
21040
21042
|
if (ops.length === 1)
|
|
@@ -21045,8 +21047,7 @@ function canonicalAdd(ce, ops) {
|
|
|
21045
21047
|
if (ops.length === 2) {
|
|
21046
21048
|
let im = 0;
|
|
21047
21049
|
let re = 0;
|
|
21048
|
-
|
|
21049
|
-
re = asFloat(ops[0]);
|
|
21050
|
+
re = asFloat(ops[0]);
|
|
21050
21051
|
if (re !== null && re !== 0)
|
|
21051
21052
|
im = getImaginaryCoef(ops[1]);
|
|
21052
21053
|
else {
|
|
@@ -21077,7 +21078,8 @@ function domainAdd(_ce, args) {
|
|
|
21077
21078
|
function simplifyAdd(ce, args) {
|
|
21078
21079
|
console.assert(args.length > 1, `simplifyAdd: not enough args`);
|
|
21079
21080
|
const sum = new Sum(ce);
|
|
21080
|
-
for (
|
|
21081
|
+
for (let arg of args) {
|
|
21082
|
+
arg = arg.simplify();
|
|
21081
21083
|
if (arg.isImaginary && arg.isInfinity)
|
|
21082
21084
|
return ce.symbol('ComplexInfinity');
|
|
21083
21085
|
if (arg.isNaN || arg.symbol === 'Undefined')
|
|
@@ -21087,7 +21089,25 @@ function simplifyAdd(ce, args) {
|
|
|
21087
21089
|
}
|
|
21088
21090
|
return sum.asExpression('expression');
|
|
21089
21091
|
}
|
|
21092
|
+
function evalAddNum(ops) {
|
|
21093
|
+
let sum = 0;
|
|
21094
|
+
for (const op of ops) {
|
|
21095
|
+
const v = op.numericValue;
|
|
21096
|
+
if (typeof v === 'number')
|
|
21097
|
+
sum += v;
|
|
21098
|
+
else
|
|
21099
|
+
return null;
|
|
21100
|
+
}
|
|
21101
|
+
return sum;
|
|
21102
|
+
}
|
|
21090
21103
|
function evalAdd(ce, ops, mode = 'evaluate') {
|
|
21104
|
+
// @fastpath
|
|
21105
|
+
if (mode === 'N' && ce.numericMode === 'machine') {
|
|
21106
|
+
ops = ops.map((x) => x.N());
|
|
21107
|
+
const sum = evalAddNum(ops);
|
|
21108
|
+
if (sum !== null)
|
|
21109
|
+
return ce.number(sum);
|
|
21110
|
+
}
|
|
21091
21111
|
//
|
|
21092
21112
|
// First pass: looking for early exits
|
|
21093
21113
|
//
|
|
@@ -21102,6 +21122,8 @@ function evalAdd(ce, ops, mode = 'evaluate') {
|
|
|
21102
21122
|
console.assert(flattenOps(ops, 'Add') === null);
|
|
21103
21123
|
if (mode === 'N')
|
|
21104
21124
|
ops = ops.map((x) => x.N());
|
|
21125
|
+
else
|
|
21126
|
+
ops = ops.map((x) => x.evaluate());
|
|
21105
21127
|
return new Sum(ce, ops).asExpression(mode === 'N' ? 'numeric' : 'expression');
|
|
21106
21128
|
}
|
|
21107
21129
|
function canonicalSummation(ce, body, range) {
|
|
@@ -21198,7 +21220,7 @@ function evalSummation(ce, expr, range, mode) {
|
|
|
21198
21220
|
if (!fn.scope)
|
|
21199
21221
|
for (let i = lower; i <= upper; i++) {
|
|
21200
21222
|
const term = fn.N();
|
|
21201
|
-
if (
|
|
21223
|
+
if (term.numericValue === null)
|
|
21202
21224
|
return undefined;
|
|
21203
21225
|
sum = add(sum, term);
|
|
21204
21226
|
}
|
|
@@ -21206,7 +21228,7 @@ function evalSummation(ce, expr, range, mode) {
|
|
|
21206
21228
|
for (let i = lower; i <= upper; i++) {
|
|
21207
21229
|
ce.set({ [index]: i });
|
|
21208
21230
|
const term = fn.N();
|
|
21209
|
-
if (
|
|
21231
|
+
if (term.numericValue === null) {
|
|
21210
21232
|
ce.context = savedContext;
|
|
21211
21233
|
return undefined;
|
|
21212
21234
|
}
|
|
@@ -21241,8 +21263,8 @@ function makePositive(expr) {
|
|
|
21241
21263
|
return [1, expr];
|
|
21242
21264
|
}
|
|
21243
21265
|
function apply(expr, fn, bigFn, complexFn) {
|
|
21244
|
-
console.assert(expr.isLiteral);
|
|
21245
21266
|
const n = expr.numericValue;
|
|
21267
|
+
console.assert(n !== null);
|
|
21246
21268
|
if (typeof n === 'number') {
|
|
21247
21269
|
if (bignumPreferred(expr.engine) && bigFn)
|
|
21248
21270
|
return expr.engine.chop(bigFn(expr.engine.bignum(n)));
|
|
@@ -21269,12 +21291,12 @@ function apply(expr, fn, bigFn, complexFn) {
|
|
|
21269
21291
|
return NaN;
|
|
21270
21292
|
}
|
|
21271
21293
|
function applyN(expr, fn, bigFn, complexFn) {
|
|
21272
|
-
if (
|
|
21294
|
+
if (expr.numericValue === null)
|
|
21273
21295
|
return undefined;
|
|
21274
21296
|
return expr.engine.number(apply(expr, fn, bigFn, complexFn));
|
|
21275
21297
|
}
|
|
21276
21298
|
function apply2(expr1, expr2, fn, bigFn, complexFn) {
|
|
21277
|
-
console.assert(expr1.
|
|
21299
|
+
console.assert(expr1.numericValue !== null && expr2.numericValue !== null);
|
|
21278
21300
|
const ce = expr1.engine;
|
|
21279
21301
|
let m1 = expr1.numericValue;
|
|
21280
21302
|
if (isMachineRational(m1))
|
|
@@ -21309,7 +21331,7 @@ function apply2(expr1, expr2, fn, bigFn, complexFn) {
|
|
|
21309
21331
|
return NaN;
|
|
21310
21332
|
}
|
|
21311
21333
|
function apply2N(expr1, expr2, fn, bigFn, complexFn) {
|
|
21312
|
-
if (
|
|
21334
|
+
if (expr1.numericValue === null || expr2.numericValue === null)
|
|
21313
21335
|
return undefined;
|
|
21314
21336
|
return expr1.engine.number(apply2(expr1, expr2, fn, bigFn, complexFn));
|
|
21315
21337
|
}
|
|
@@ -21324,11 +21346,11 @@ function canonicalPower(ce, base, exponent, metadata) {
|
|
|
21324
21346
|
exponent = validateArgument(ce, exponent?.canonical, 'Number');
|
|
21325
21347
|
if (exponent.symbol === 'ComplexInfinity')
|
|
21326
21348
|
return ce._NAN;
|
|
21327
|
-
if (exponent.
|
|
21349
|
+
if (exponent.numericValue !== null) {
|
|
21328
21350
|
if (exponent.isZero)
|
|
21329
21351
|
return ce._ONE;
|
|
21330
|
-
if (base.
|
|
21331
|
-
const
|
|
21352
|
+
if (base.numericValue !== null) {
|
|
21353
|
+
const numBase = asFloat(base);
|
|
21332
21354
|
//
|
|
21333
21355
|
// Special cases
|
|
21334
21356
|
//
|
|
@@ -21336,10 +21358,10 @@ function canonicalPower(ce, base, exponent, metadata) {
|
|
|
21336
21358
|
// See https://docs.sympy.org/1.6/modules/core.html#pow
|
|
21337
21359
|
//
|
|
21338
21360
|
// if (base.isOne) return ce._ONE;
|
|
21339
|
-
if (
|
|
21361
|
+
if (numBase === 1)
|
|
21340
21362
|
return ce._ONE;
|
|
21341
21363
|
// if (base.isZero) {
|
|
21342
|
-
if (
|
|
21364
|
+
if (numBase === 0) {
|
|
21343
21365
|
if (exponent.isPositive)
|
|
21344
21366
|
return ce._ZERO;
|
|
21345
21367
|
if (exponent.isNegative)
|
|
@@ -21351,21 +21373,19 @@ function canonicalPower(ce, base, exponent, metadata) {
|
|
|
21351
21373
|
// x^(-1)
|
|
21352
21374
|
// if (base.isOne) return ce._ONE;
|
|
21353
21375
|
// if (base.isNegativeOne) return ce._NEGATIVE_ONE;
|
|
21354
|
-
if (
|
|
21376
|
+
if (numBase === 1)
|
|
21355
21377
|
return ce._ONE;
|
|
21356
|
-
if (
|
|
21378
|
+
if (numBase === -1)
|
|
21357
21379
|
return ce._NEGATIVE_ONE;
|
|
21358
21380
|
if (base.isInfinity)
|
|
21359
21381
|
return ce._ZERO;
|
|
21360
21382
|
const r = base.numericValue;
|
|
21361
|
-
if (r
|
|
21362
|
-
|
|
21363
|
-
|
|
21364
|
-
|
|
21365
|
-
|
|
21366
|
-
|
|
21367
|
-
return ce.number(inverse(r), { metadata });
|
|
21368
|
-
}
|
|
21383
|
+
if (typeof r === 'number' && Number.isInteger(r))
|
|
21384
|
+
return ce.number([1, r], { metadata });
|
|
21385
|
+
if (r instanceof Decimal && r.isInteger())
|
|
21386
|
+
return ce.number([ce._BIGNUM_ONE, r], { metadata });
|
|
21387
|
+
if (isRational(r))
|
|
21388
|
+
return ce.number(inverse(r), { metadata });
|
|
21369
21389
|
return ce._fn('Power', [base, ce._NEGATIVE_ONE], metadata);
|
|
21370
21390
|
}
|
|
21371
21391
|
// x^{0.5}, x^{1/2} -> Square Root
|
|
@@ -21597,7 +21617,7 @@ function processPower(ce, base, exponent, mode) {
|
|
|
21597
21617
|
// If square root or cube root, attempt to factor out the perfect
|
|
21598
21618
|
// factors: sqrt(75) -> 5^2 * 3
|
|
21599
21619
|
//
|
|
21600
|
-
if (mode !== 'N' && base.
|
|
21620
|
+
if (mode !== 'N' && base.numericValue !== null && base.isInteger) {
|
|
21601
21621
|
const smallExpr = asSmallInteger(exponent);
|
|
21602
21622
|
if (smallExpr)
|
|
21603
21623
|
return numEvalPower(ce, base, exponent);
|
|
@@ -21632,7 +21652,8 @@ function processPower(ce, base, exponent, mode) {
|
|
|
21632
21652
|
}
|
|
21633
21653
|
}
|
|
21634
21654
|
else if (typeof base.numericValue === 'number') {
|
|
21635
|
-
|
|
21655
|
+
// Square root of a negative number, and no complex allowed
|
|
21656
|
+
if (base.numericValue < 0 && d % 2 === 0 && !complexAllowed(ce))
|
|
21636
21657
|
return ce._NAN;
|
|
21637
21658
|
const [factor, root] = factorPower$1(Math.abs(base.numericValue), d);
|
|
21638
21659
|
const sign = base.numericValue < 0
|
|
@@ -21662,7 +21683,9 @@ function processPower(ce, base, exponent, mode) {
|
|
|
21662
21683
|
return undefined;
|
|
21663
21684
|
}
|
|
21664
21685
|
}
|
|
21665
|
-
if (mode !== 'simplify' &&
|
|
21686
|
+
if (mode !== 'simplify' &&
|
|
21687
|
+
base.numericValue !== null &&
|
|
21688
|
+
exponent.numericValue !== null)
|
|
21666
21689
|
return numEvalPower(ce, base, exponent);
|
|
21667
21690
|
return undefined;
|
|
21668
21691
|
}
|
|
@@ -21777,22 +21800,46 @@ function canonicalMultiply(ce, ops) {
|
|
|
21777
21800
|
return ops[0];
|
|
21778
21801
|
if (ops.length === 2)
|
|
21779
21802
|
return multiply2(ops[0], ops[1]);
|
|
21780
|
-
|
|
21781
|
-
|
|
21803
|
+
const product = new Product(ce);
|
|
21804
|
+
for (const op of ops) {
|
|
21805
|
+
if (op.isNaN || op.symbol === 'Undefined')
|
|
21806
|
+
return ce._NAN;
|
|
21807
|
+
product.addTerm(op);
|
|
21808
|
+
}
|
|
21809
|
+
return product.asExpression();
|
|
21782
21810
|
}
|
|
21783
21811
|
function simplifyMultiply(ce, ops) {
|
|
21784
21812
|
console.assert(flattenOps(ops, 'Multiply') === null);
|
|
21785
21813
|
const product = new Product(ce);
|
|
21786
|
-
for (
|
|
21814
|
+
for (let op of ops) {
|
|
21815
|
+
op = op.simplify();
|
|
21787
21816
|
if (op.isNaN || op.symbol === 'Undefined')
|
|
21788
21817
|
return ce._NAN;
|
|
21789
21818
|
product.addTerm(op);
|
|
21790
21819
|
}
|
|
21791
21820
|
return product.asExpression();
|
|
21792
21821
|
}
|
|
21822
|
+
function fastEvalMultiply(ops) {
|
|
21823
|
+
let prod = 1;
|
|
21824
|
+
for (const op of ops) {
|
|
21825
|
+
if (typeof op.numericValue !== 'number')
|
|
21826
|
+
return null;
|
|
21827
|
+
prod *= op.numericValue;
|
|
21828
|
+
}
|
|
21829
|
+
return prod;
|
|
21830
|
+
}
|
|
21793
21831
|
function evalMultiply(ce, ops, mode = 'evaluate') {
|
|
21794
21832
|
console.assert(ops.length > 1, 'evalMultiply(): no arguments');
|
|
21795
21833
|
//
|
|
21834
|
+
// @fastpath
|
|
21835
|
+
//
|
|
21836
|
+
if (mode === 'N' && ce.numericMode === 'machine') {
|
|
21837
|
+
ops = ops.map((x) => x.N());
|
|
21838
|
+
const result = fastEvalMultiply(ops);
|
|
21839
|
+
if (result !== null)
|
|
21840
|
+
return ce.number(result);
|
|
21841
|
+
}
|
|
21842
|
+
//
|
|
21796
21843
|
// First pass: looking for early exits
|
|
21797
21844
|
//
|
|
21798
21845
|
for (const op of ops) {
|
|
@@ -21804,6 +21851,8 @@ function evalMultiply(ce, ops, mode = 'evaluate') {
|
|
|
21804
21851
|
console.assert(flattenOps(ops, 'Multiply') === null);
|
|
21805
21852
|
if (mode === 'N')
|
|
21806
21853
|
ops = ops.map((x) => x.N());
|
|
21854
|
+
else
|
|
21855
|
+
ops = ops.map((x) => x.evaluate());
|
|
21807
21856
|
//
|
|
21808
21857
|
// Second pass
|
|
21809
21858
|
//
|
|
@@ -21822,34 +21871,41 @@ function multiply2(op1, op2, metadata) {
|
|
|
21822
21871
|
console.assert(op1.isCanonical);
|
|
21823
21872
|
console.assert(op2.isCanonical);
|
|
21824
21873
|
const ce = op1.engine;
|
|
21825
|
-
if (op1.
|
|
21874
|
+
if (op1.numericValue !== null &&
|
|
21875
|
+
op2.numericValue !== null &&
|
|
21876
|
+
op1.isInteger &&
|
|
21877
|
+
op2.isInteger) {
|
|
21826
21878
|
return (apply2N(op1, op2, (a, b) => a * b, (a, b) => a.mul(b)) ?? ce._NAN);
|
|
21827
21879
|
}
|
|
21880
|
+
if (op1.isNaN ||
|
|
21881
|
+
op2.isNaN ||
|
|
21882
|
+
op1.symbol === 'Undefined' ||
|
|
21883
|
+
op2.symbol === 'Undefined')
|
|
21884
|
+
return ce._NAN;
|
|
21828
21885
|
if (op1.isNothing)
|
|
21829
21886
|
return op2;
|
|
21830
21887
|
if (op2.isNothing)
|
|
21831
21888
|
return op1;
|
|
21832
|
-
if (op1.
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
if (op2.
|
|
21839
|
-
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
|
|
21843
|
-
if (!c.isLiteral) {
|
|
21844
|
-
t = op2;
|
|
21845
|
-
c = op1;
|
|
21889
|
+
if (op1.numericValue !== null) {
|
|
21890
|
+
if (op1.isOne)
|
|
21891
|
+
return op2;
|
|
21892
|
+
if (op1.isNegativeOne)
|
|
21893
|
+
return canonicalNegate(op2);
|
|
21894
|
+
}
|
|
21895
|
+
if (op2.numericValue !== null) {
|
|
21896
|
+
if (op2.isOne)
|
|
21897
|
+
return op1;
|
|
21898
|
+
if (op2.isNegativeOne)
|
|
21899
|
+
return canonicalNegate(op1);
|
|
21846
21900
|
}
|
|
21901
|
+
let sign = 1;
|
|
21902
|
+
let [t, c] = op1.numericValue !== null ? [op1, op2] : [op2, op1];
|
|
21847
21903
|
console.assert(t.head !== 'Subtract');
|
|
21848
21904
|
if (t.head === 'Negate') {
|
|
21849
21905
|
t = t.op1;
|
|
21850
21906
|
sign = -sign;
|
|
21851
21907
|
}
|
|
21852
|
-
if (c.
|
|
21908
|
+
if (c.numericValue !== null) {
|
|
21853
21909
|
const r = asRational(c);
|
|
21854
21910
|
if (r) {
|
|
21855
21911
|
if (isRationalOne(r))
|
|
@@ -21861,12 +21917,10 @@ function multiply2(op1, op2, metadata) {
|
|
|
21861
21917
|
c = canonicalNegate(c);
|
|
21862
21918
|
return ce.add(t.ops.map((x) => multiply2(c, x)), metadata);
|
|
21863
21919
|
}
|
|
21864
|
-
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
return ce.number(sign < 0 ? neg(p) : p, { metadata });
|
|
21869
|
-
}
|
|
21920
|
+
const tr = asRational(t);
|
|
21921
|
+
if (tr) {
|
|
21922
|
+
const p = mul(r, tr);
|
|
21923
|
+
return ce.number(sign < 0 ? neg(p) : p, { metadata });
|
|
21870
21924
|
}
|
|
21871
21925
|
if (sign < 0)
|
|
21872
21926
|
return ce._fn('Multiply', [canonicalNegate(c), t], metadata);
|
|
@@ -21958,7 +22012,7 @@ function evalMultiplication(ce, expr, range, mode) {
|
|
|
21958
22012
|
const n = ce.number(i);
|
|
21959
22013
|
const r = fn.subs({ _1: n, _: n });
|
|
21960
22014
|
const term = r.N();
|
|
21961
|
-
if (
|
|
22015
|
+
if (term.numericValue === null)
|
|
21962
22016
|
return undefined;
|
|
21963
22017
|
product = mul(product, term);
|
|
21964
22018
|
}
|
|
@@ -21981,7 +22035,7 @@ function canonicalDivide(ce, op1, op2) {
|
|
|
21981
22035
|
op2 = validateArgument(ce, op2, 'Number');
|
|
21982
22036
|
if (!op1.isValid || !op2.isValid)
|
|
21983
22037
|
return ce._fn('Divide', [op1, op2]);
|
|
21984
|
-
if (op1.
|
|
22038
|
+
if (op1.numericValue !== null && op2.numericValue !== null) {
|
|
21985
22039
|
if (op2.isOne)
|
|
21986
22040
|
return op1;
|
|
21987
22041
|
if (op2.isNegativeOne)
|
|
@@ -21999,25 +22053,25 @@ function canonicalDivide(ce, op1, op2) {
|
|
|
21999
22053
|
(op2.head === 'Divide' || op2.head === 'Rational')) {
|
|
22000
22054
|
return canonicalDivide(ce, ce.mul([op1.op1, op2.op2]), ce.mul([op1.op2, op2.op1]));
|
|
22001
22055
|
}
|
|
22002
|
-
|
|
22003
|
-
|
|
22004
|
-
if (isMachineRational(
|
|
22005
|
-
const [a, b] =
|
|
22056
|
+
const num1 = op1.numericValue;
|
|
22057
|
+
if (num1 !== null) {
|
|
22058
|
+
if (isMachineRational(num1)) {
|
|
22059
|
+
const [a, b] = num1;
|
|
22006
22060
|
return canonicalDivide(ce, ce.mul([ce.number(a), op2]), ce.number(b));
|
|
22007
22061
|
}
|
|
22008
|
-
if (isBigRational(
|
|
22009
|
-
const [a, b] =
|
|
22062
|
+
if (isBigRational(num1)) {
|
|
22063
|
+
const [a, b] = num1;
|
|
22010
22064
|
return canonicalDivide(ce, ce.mul([ce.number(a), op2]), ce.number(b));
|
|
22011
22065
|
}
|
|
22012
22066
|
}
|
|
22013
|
-
|
|
22014
|
-
|
|
22015
|
-
if (isMachineRational(
|
|
22016
|
-
const [a, b] =
|
|
22067
|
+
const num2 = op2.numericValue;
|
|
22068
|
+
if (num2 !== null) {
|
|
22069
|
+
if (isMachineRational(num2)) {
|
|
22070
|
+
const [a, b] = num2;
|
|
22017
22071
|
return canonicalDivide(ce, ce.mul([op1, ce.number(b)]), ce.number(a));
|
|
22018
22072
|
}
|
|
22019
|
-
if (isBigRational(
|
|
22020
|
-
const [a, b] =
|
|
22073
|
+
if (isBigRational(num2)) {
|
|
22074
|
+
const [a, b] = num2;
|
|
22021
22075
|
return canonicalDivide(ce, ce.mul([op1, ce.number(b)]), ce.number(a));
|
|
22022
22076
|
}
|
|
22023
22077
|
}
|
|
@@ -22031,11 +22085,11 @@ function canonicalDivide(ce, op1, op2) {
|
|
|
22031
22085
|
let [dSign, d] = makePositive(op2);
|
|
22032
22086
|
n = n.canonical;
|
|
22033
22087
|
d = d.canonical;
|
|
22034
|
-
if (d.
|
|
22088
|
+
if (d.numericValue !== null && d.isOne)
|
|
22035
22089
|
return nSign * dSign < 0 ? canonicalNegate(n) : n;
|
|
22036
22090
|
// Divide: transform into multiply/power
|
|
22037
22091
|
d = ce.inverse(d);
|
|
22038
|
-
if (n.
|
|
22092
|
+
if (n.numericValue !== null) {
|
|
22039
22093
|
if (n.isOne)
|
|
22040
22094
|
return d;
|
|
22041
22095
|
if (n.isNegativeOne)
|
|
@@ -22049,7 +22103,7 @@ function canonicalDivide(ce, op1, op2) {
|
|
|
22049
22103
|
* Simplify form of 'Divide' (and 'Rational')
|
|
22050
22104
|
*/
|
|
22051
22105
|
function simplifyDivide(ce, op1, op2) {
|
|
22052
|
-
if (op1.
|
|
22106
|
+
if (op1.numericValue !== null && op2.numericValue !== null) {
|
|
22053
22107
|
const r1 = asRational(op1);
|
|
22054
22108
|
const r2 = asRational(op2);
|
|
22055
22109
|
if (r1 && r2 && !isRationalZero(r2))
|
|
@@ -22112,6 +22166,7 @@ const ARITHMETIC_LIBRARY = [
|
|
|
22112
22166
|
threadable: true,
|
|
22113
22167
|
idempotent: true,
|
|
22114
22168
|
complexity: 1300,
|
|
22169
|
+
hold: 'all',
|
|
22115
22170
|
signature: {
|
|
22116
22171
|
domain: 'NumericFunction',
|
|
22117
22172
|
codomain: (ce, args) => domainAdd(ce, args.map((x) => x.domain)),
|
|
@@ -22366,6 +22421,7 @@ const ARITHMETIC_LIBRARY = [
|
|
|
22366
22421
|
commutative: true,
|
|
22367
22422
|
idempotent: true,
|
|
22368
22423
|
complexity: 2100,
|
|
22424
|
+
hold: 'all',
|
|
22369
22425
|
signature: {
|
|
22370
22426
|
domain: 'NumericFunction',
|
|
22371
22427
|
canonical: (ce, args) => canonicalMultiply(ce, args),
|
|
@@ -22427,7 +22483,14 @@ const ARITHMETIC_LIBRARY = [
|
|
|
22427
22483
|
canonical: (ce, args) => canonicalPower(ce, args[0], args[1]) ?? ce._fn('Power', args),
|
|
22428
22484
|
simplify: (ce, ops) => processPower(ce, ops[0], ops[1], 'simplify'),
|
|
22429
22485
|
evaluate: (ce, ops) => processPower(ce, ops[0], ops[1], 'evaluate'),
|
|
22430
|
-
N: (ce, ops) =>
|
|
22486
|
+
N: (ce, ops) => {
|
|
22487
|
+
// @fastpath
|
|
22488
|
+
if (ce.numericMode === 'machine' &&
|
|
22489
|
+
typeof ops[0].numericValue === 'number' &&
|
|
22490
|
+
typeof ops[1].numericValue === 'number')
|
|
22491
|
+
return ce.number(Math.pow(ops[0].numericValue, ops[1].numericValue));
|
|
22492
|
+
return processPower(ce, ops[0], ops[1], 'N');
|
|
22493
|
+
},
|
|
22431
22494
|
// Defined as RealNumber for all power in RealNumber when base > 0;
|
|
22432
22495
|
// when x < 0, only defined if n is an integer
|
|
22433
22496
|
// if x is a non-zero complex, defined as ComplexNumber
|
|
@@ -23262,8 +23325,8 @@ const CORE_LIBRARY = [
|
|
|
23262
23325
|
// Is it a string in a base form:
|
|
23263
23326
|
// `"deadbeef"_{16}` `"0101010"_2?
|
|
23264
23327
|
if (op1.string) {
|
|
23265
|
-
|
|
23266
|
-
|
|
23328
|
+
const base = asSmallInteger(op2);
|
|
23329
|
+
if (base !== null) {
|
|
23267
23330
|
if (base > 1 && base <= 36) {
|
|
23268
23331
|
const [value, rest] = fromDigits(op1.string, base);
|
|
23269
23332
|
if (rest) {
|
|
@@ -23280,9 +23343,7 @@ const CORE_LIBRARY = [
|
|
|
23280
23343
|
if (op1.symbolDefinition?.at)
|
|
23281
23344
|
return ce._fn('At', [op1, op2.canonical]);
|
|
23282
23345
|
// Maybe a compound symbol
|
|
23283
|
-
|
|
23284
|
-
if (!sub && op2.isLiteral && asSmallInteger(op2) !== null)
|
|
23285
|
-
sub = asSmallInteger(op2).toString();
|
|
23346
|
+
const sub = op2.string ?? op2.symbol ?? asSmallInteger(op2)?.toString();
|
|
23286
23347
|
if (sub)
|
|
23287
23348
|
return ce.symbol(op1.symbol + '_' + sub);
|
|
23288
23349
|
}
|
|
@@ -23304,10 +23365,7 @@ const CORE_LIBRARY = [
|
|
|
23304
23365
|
if (ops.length === 0)
|
|
23305
23366
|
return ce.symbol('Nothing');
|
|
23306
23367
|
const arg = ops
|
|
23307
|
-
.map((x) => x.symbol ??
|
|
23308
|
-
x.string ??
|
|
23309
|
-
(x.isLiteral ? asSmallInteger(x)?.toString() : null) ??
|
|
23310
|
-
'')
|
|
23368
|
+
.map((x) => x.symbol ?? x.string ?? asSmallInteger(x)?.toString() ?? '')
|
|
23311
23369
|
.join('');
|
|
23312
23370
|
if (arg.length > 0)
|
|
23313
23371
|
return ce.symbol(arg);
|
|
@@ -24445,7 +24503,7 @@ const TRIGONOMETRY_LIBRARY = [
|
|
|
24445
24503
|
if (ops.length !== 1)
|
|
24446
24504
|
return ce.box(['Degrees', ops]);
|
|
24447
24505
|
const arg = validateArgument(ce, ops[0].canonical, 'Number');
|
|
24448
|
-
if (
|
|
24506
|
+
if (arg.numericValue === null || !arg.isValid)
|
|
24449
24507
|
return ce.box(['Degrees', arg]);
|
|
24450
24508
|
return ce.mul([arg, ce.box(['Divide', 'Pi', 180])]);
|
|
24451
24509
|
},
|
|
@@ -25066,7 +25124,7 @@ function constructibleValues(ce, head, x) {
|
|
|
25066
25124
|
return cache;
|
|
25067
25125
|
});
|
|
25068
25126
|
x = x.N();
|
|
25069
|
-
if (
|
|
25127
|
+
if (x.numericValue === null)
|
|
25070
25128
|
return undefined;
|
|
25071
25129
|
let theta = asFloat(x) ?? null;
|
|
25072
25130
|
if (theta === null)
|
|
@@ -25163,7 +25221,10 @@ function evalTrig(ce, mode, head, op) {
|
|
|
25163
25221
|
case 'Artanh':
|
|
25164
25222
|
return applyN(op, Math.atanh, (x) => x.atanh(), (x) => x.atanh());
|
|
25165
25223
|
case 'Cos':
|
|
25166
|
-
return applyN(op, Math.cos, (x) => x
|
|
25224
|
+
return applyN(op, Math.cos, (x) => x
|
|
25225
|
+
.toSignificantDigits(ce.precision + 4)
|
|
25226
|
+
.cos()
|
|
25227
|
+
.toSignificantDigits(ce.precision), (x) => x.cos());
|
|
25167
25228
|
case 'Cosh':
|
|
25168
25229
|
return applyN(op, Math.cosh, (x) => x.cosh(), (x) => x.cosh());
|
|
25169
25230
|
case 'Cot':
|
|
@@ -25179,11 +25240,17 @@ function evalTrig(ce, mode, head, op) {
|
|
|
25179
25240
|
case 'Sech':
|
|
25180
25241
|
return applyN(op, (x) => 1 / Math.cosh(x), (x) => ce._BIGNUM_ONE.div(x.cosh()), (x) => x.cosh().inverse());
|
|
25181
25242
|
case 'Sin':
|
|
25182
|
-
return applyN(op, Math.sin, (x) => x
|
|
25243
|
+
return applyN(op, Math.sin, (x) => x
|
|
25244
|
+
.toSignificantDigits(ce.precision + 4)
|
|
25245
|
+
.sin()
|
|
25246
|
+
.toSignificantDigits(ce.precision), (x) => x.sin());
|
|
25183
25247
|
case 'Sinh':
|
|
25184
25248
|
return applyN(op, Math.sinh, (x) => x.sinh(), (x) => x.sinh());
|
|
25185
25249
|
case 'Tan':
|
|
25186
|
-
return applyN(op, Math.tan, (x) => x
|
|
25250
|
+
return applyN(op, Math.tan, (x) => x
|
|
25251
|
+
.toSignificantDigits(ce.precision + 4)
|
|
25252
|
+
.tan()
|
|
25253
|
+
.toSignificantDigits(ce.precision), (x) => x.tan());
|
|
25187
25254
|
case 'Tanh':
|
|
25188
25255
|
return applyN(op, Math.tanh, (x) => x.tanh(), (x) => x.tanh());
|
|
25189
25256
|
}
|
|
@@ -25429,8 +25496,6 @@ function valueToFlags(value) {
|
|
|
25429
25496
|
finite: value.isFinite,
|
|
25430
25497
|
even: value.isEven,
|
|
25431
25498
|
odd: value.isOdd,
|
|
25432
|
-
prime: value.isPrime,
|
|
25433
|
-
composite: value.isComposite,
|
|
25434
25499
|
});
|
|
25435
25500
|
}
|
|
25436
25501
|
class BoxedSymbolDefinitionImpl {
|
|
@@ -25549,11 +25614,47 @@ class BoxedSymbolDefinitionImpl {
|
|
|
25549
25614
|
this.bind();
|
|
25550
25615
|
if (this.constant)
|
|
25551
25616
|
throw new Error(`The value of the constant "${this.name}" cannot be changed`);
|
|
25552
|
-
if (typeof val === 'number')
|
|
25617
|
+
if (typeof val === 'number') {
|
|
25618
|
+
if (typeof this._value?.numericValue === 'number') {
|
|
25619
|
+
this._value['_value'] = val;
|
|
25620
|
+
}
|
|
25621
|
+
else {
|
|
25622
|
+
this._value = this._engine.number(val);
|
|
25623
|
+
}
|
|
25624
|
+
// this.setProps(valueToFlags(val));
|
|
25625
|
+
this._number = undefined;
|
|
25626
|
+
this._integer = undefined;
|
|
25627
|
+
this._rational = undefined;
|
|
25628
|
+
this._algebraic = undefined;
|
|
25629
|
+
this._real = undefined;
|
|
25630
|
+
this._extendedReal = undefined;
|
|
25631
|
+
this._complex = undefined;
|
|
25632
|
+
this._extendedComplex = undefined;
|
|
25633
|
+
this._imaginary = undefined;
|
|
25634
|
+
this._positive = undefined;
|
|
25635
|
+
this._nonPositive = undefined;
|
|
25636
|
+
this._negative = undefined;
|
|
25637
|
+
this._nonNegative = undefined;
|
|
25638
|
+
this._zero = undefined;
|
|
25639
|
+
this._notZero = undefined;
|
|
25640
|
+
this._one = undefined;
|
|
25641
|
+
this._negativeOne = undefined;
|
|
25642
|
+
this._infinity = undefined;
|
|
25643
|
+
this._finite = undefined;
|
|
25644
|
+
this._NaN = undefined;
|
|
25645
|
+
this._even = undefined;
|
|
25646
|
+
this._odd = undefined;
|
|
25647
|
+
this._prime = undefined;
|
|
25648
|
+
this._composite = undefined;
|
|
25649
|
+
}
|
|
25650
|
+
else if (val) {
|
|
25553
25651
|
val = this._engine.box(val);
|
|
25554
|
-
|
|
25555
|
-
|
|
25556
|
-
|
|
25652
|
+
this._value = val;
|
|
25653
|
+
if (val)
|
|
25654
|
+
this.setProps(valueToFlags(val));
|
|
25655
|
+
}
|
|
25656
|
+
else
|
|
25657
|
+
this._value = null;
|
|
25557
25658
|
}
|
|
25558
25659
|
get domain() {
|
|
25559
25660
|
if (this._domain === null)
|
|
@@ -26200,12 +26301,12 @@ function costFunction(expr) {
|
|
|
26200
26301
|
//
|
|
26201
26302
|
// 2/ Literal Numeric Values
|
|
26202
26303
|
//
|
|
26203
|
-
|
|
26304
|
+
const num = expr.numericValue;
|
|
26305
|
+
if (num !== null) {
|
|
26204
26306
|
if (expr.isZero)
|
|
26205
26307
|
return 1;
|
|
26206
|
-
if (expr.isInteger
|
|
26308
|
+
if (expr.isInteger)
|
|
26207
26309
|
return numericCostFunction(asFloat(expr));
|
|
26208
|
-
const num = expr.numericValue;
|
|
26209
26310
|
if (isRational(num)) {
|
|
26210
26311
|
if (isMachineRational(num))
|
|
26211
26312
|
return numericCostFunction(num[0]) + numericCostFunction(num[1]) + 1;
|
|
@@ -26725,9 +26826,6 @@ class BoxedSymbol extends AbstractBoxedExpression {
|
|
|
26725
26826
|
get isNothing() {
|
|
26726
26827
|
return this._name === 'Nothing';
|
|
26727
26828
|
}
|
|
26728
|
-
get isLiteral() {
|
|
26729
|
-
return false;
|
|
26730
|
-
}
|
|
26731
26829
|
// A base definition is the base class of both symbol and function definition
|
|
26732
26830
|
get baseDefinition() {
|
|
26733
26831
|
if (this._def === null)
|
|
@@ -27124,7 +27222,7 @@ function makeCanonicalSymbol(ce, name) {
|
|
|
27124
27222
|
const def = ce.lookupSymbol(name, undefined, ce.context);
|
|
27125
27223
|
if (def) {
|
|
27126
27224
|
if (def.hold === false && def.value)
|
|
27127
|
-
return
|
|
27225
|
+
return def.value;
|
|
27128
27226
|
}
|
|
27129
27227
|
return new BoxedSymbol(ce, name, { canonical: true });
|
|
27130
27228
|
}
|
|
@@ -27245,6 +27343,7 @@ class ComputeEngine {
|
|
|
27245
27343
|
};
|
|
27246
27344
|
if (options !== undefined && typeof options !== 'object')
|
|
27247
27345
|
throw Error('Unexpected argument');
|
|
27346
|
+
this.strict = true;
|
|
27248
27347
|
this._latexDictionary = options?.latexDictionary;
|
|
27249
27348
|
this._jsonSerializationOptions = {
|
|
27250
27349
|
exclude: [],
|
|
@@ -27627,6 +27726,16 @@ class ComputeEngine {
|
|
|
27627
27726
|
* wikidata, if provided.
|
|
27628
27727
|
*/
|
|
27629
27728
|
lookupSymbol(symbol, wikidata, scope) {
|
|
27729
|
+
// @fastpath
|
|
27730
|
+
if (!this.strict) {
|
|
27731
|
+
scope ?? (scope = this.context ?? undefined);
|
|
27732
|
+
let def = undefined;
|
|
27733
|
+
while (scope && !def) {
|
|
27734
|
+
def = scope.symbolTable?.symbols.get(symbol);
|
|
27735
|
+
scope = scope.parentScope;
|
|
27736
|
+
}
|
|
27737
|
+
return def;
|
|
27738
|
+
}
|
|
27630
27739
|
if (typeof symbol !== 'string')
|
|
27631
27740
|
throw Error('Expected a string');
|
|
27632
27741
|
// Wildcards never have definitions
|
|
@@ -27795,20 +27904,46 @@ class ComputeEngine {
|
|
|
27795
27904
|
console.assert(this.context !== null);
|
|
27796
27905
|
}
|
|
27797
27906
|
set(identifiers) {
|
|
27907
|
+
// @fastpath
|
|
27908
|
+
if (!this.strict) {
|
|
27909
|
+
for (const k of Object.keys(identifiers)) {
|
|
27910
|
+
if (k !== 'Nothing') {
|
|
27911
|
+
const def = this.lookupSymbol(k);
|
|
27912
|
+
const idk = identifiers[k];
|
|
27913
|
+
if (def)
|
|
27914
|
+
def.value = idk ?? undefined;
|
|
27915
|
+
else if (idk !== undefined && idk !== null) {
|
|
27916
|
+
const val = this.box(idk);
|
|
27917
|
+
if (val.domain.isNumeric)
|
|
27918
|
+
this.defineSymbol({ name: k, value: val, domain: 'Number' });
|
|
27919
|
+
else
|
|
27920
|
+
this.defineSymbol({ name: k, value: val });
|
|
27921
|
+
}
|
|
27922
|
+
}
|
|
27923
|
+
}
|
|
27924
|
+
return;
|
|
27925
|
+
}
|
|
27798
27926
|
for (const k of Object.keys(identifiers)) {
|
|
27799
27927
|
if (k !== 'Nothing') {
|
|
27800
27928
|
const def = this.lookupSymbol(k);
|
|
27801
|
-
const
|
|
27802
|
-
if (
|
|
27803
|
-
if (def
|
|
27804
|
-
|
|
27805
|
-
def.value = val;
|
|
27929
|
+
const idk = identifiers[k];
|
|
27930
|
+
if (idk === undefined || idk === null) {
|
|
27931
|
+
if (def)
|
|
27932
|
+
def.value = undefined;
|
|
27806
27933
|
}
|
|
27807
27934
|
else {
|
|
27808
|
-
|
|
27809
|
-
|
|
27810
|
-
|
|
27811
|
-
|
|
27935
|
+
const val = this.box(idk);
|
|
27936
|
+
if (def) {
|
|
27937
|
+
if (def.domain && !val.domain.isCompatible(def.domain))
|
|
27938
|
+
throw Error(`Expected value with domain ${def.domain.toString()} for "${k}"`);
|
|
27939
|
+
def.value = val;
|
|
27940
|
+
}
|
|
27941
|
+
else {
|
|
27942
|
+
if (val.domain.isNumeric)
|
|
27943
|
+
this.defineSymbol({ name: k, value: val, domain: 'Number' });
|
|
27944
|
+
else
|
|
27945
|
+
this.defineSymbol({ name: k, value: val });
|
|
27946
|
+
}
|
|
27812
27947
|
}
|
|
27813
27948
|
}
|
|
27814
27949
|
}
|
|
@@ -27938,7 +28073,7 @@ class ComputeEngine {
|
|
|
27938
28073
|
}
|
|
27939
28074
|
add(ops, metadata) {
|
|
27940
28075
|
// Short path. Note that are arguments are **not** validated.
|
|
27941
|
-
ops = flattenSequence(ops);
|
|
28076
|
+
// ops = flattenSequence(ops);
|
|
27942
28077
|
const result = canonicalAdd(this, ops);
|
|
27943
28078
|
if (metadata?.latex !== undefined)
|
|
27944
28079
|
result.latex = metadata.latex;
|
|
@@ -28062,7 +28197,7 @@ class ComputeEngine {
|
|
|
28062
28197
|
// `Half` is a synonym for the rational 1/2
|
|
28063
28198
|
if (name === 'Half')
|
|
28064
28199
|
return this._HALF;
|
|
28065
|
-
if (!isValidIdentifier(name)) {
|
|
28200
|
+
if (this.strict && !isValidIdentifier(name)) {
|
|
28066
28201
|
const where = options?.metadata?.latex;
|
|
28067
28202
|
const nameStr = `'${name}'`;
|
|
28068
28203
|
if (where)
|
|
@@ -28128,16 +28263,15 @@ class ComputeEngine {
|
|
|
28128
28263
|
return this._ZERO;
|
|
28129
28264
|
if (n === -1)
|
|
28130
28265
|
return this._NEGATIVE_ONE;
|
|
28131
|
-
if (
|
|
28132
|
-
return this._NAN;
|
|
28133
|
-
if (!Number.isFinite(n))
|
|
28134
|
-
return n < 0 ? this._NEGATIVE_INFINITY : this._POSITIVE_INFINITY;
|
|
28135
|
-
if (Number.isInteger(n) && this._commonNumbers[n] === null) {
|
|
28136
|
-
this._commonNumbers[n] = boxNumber(this, value);
|
|
28266
|
+
if (Number.isInteger(n) && this._commonNumbers[n] !== undefined) {
|
|
28137
28267
|
if (this._commonNumbers[n] === null)
|
|
28138
|
-
|
|
28268
|
+
this._commonNumbers[n] = boxNumber(this, value) ?? this._NAN;
|
|
28139
28269
|
return this._commonNumbers[n];
|
|
28140
28270
|
}
|
|
28271
|
+
if (Number.isNaN(n))
|
|
28272
|
+
return this._NAN;
|
|
28273
|
+
if (!Number.isFinite(n))
|
|
28274
|
+
return n < 0 ? this._NEGATIVE_INFINITY : this._POSITIVE_INFINITY;
|
|
28141
28275
|
}
|
|
28142
28276
|
return boxNumber(this, value, options) ?? this._NAN;
|
|
28143
28277
|
}
|
|
@@ -28271,8 +28405,20 @@ class ComputeEngine {
|
|
|
28271
28405
|
forget(symbol) {
|
|
28272
28406
|
if (!this.context)
|
|
28273
28407
|
throw Error('No scope available');
|
|
28408
|
+
//
|
|
28409
|
+
// Theory of Operations
|
|
28410
|
+
//
|
|
28411
|
+
// When forgeting we need to preserve existing definitions for symbols,
|
|
28412
|
+
// as some expressions may be pointing to them. Instead, we
|
|
28413
|
+
// reset the value/domain of those definitions.
|
|
28414
|
+
//
|
|
28274
28415
|
if (symbol === undefined) {
|
|
28275
|
-
this.context.symbolTable
|
|
28416
|
+
if (this.context.symbolTable?.symbols)
|
|
28417
|
+
for (const k of this.context.symbolTable.symbols.keys())
|
|
28418
|
+
this.forget(k);
|
|
28419
|
+
if (this.context.symbolTable?.functions)
|
|
28420
|
+
for (const k of this.context.symbolTable.functions.keys())
|
|
28421
|
+
this.forget(k);
|
|
28276
28422
|
this.assumptions.clear();
|
|
28277
28423
|
return;
|
|
28278
28424
|
}
|
|
@@ -28284,13 +28430,17 @@ class ComputeEngine {
|
|
|
28284
28430
|
if (typeof symbol === 'string') {
|
|
28285
28431
|
// Remove symbol definition in the current scope (if any)
|
|
28286
28432
|
if (this.context.symbolTable) {
|
|
28287
|
-
this.context.symbolTable.symbols.
|
|
28433
|
+
const sdef = this.context.symbolTable.symbols.get(symbol);
|
|
28434
|
+
if (sdef) {
|
|
28435
|
+
sdef.value = undefined;
|
|
28436
|
+
sdef.domain = undefined;
|
|
28437
|
+
}
|
|
28438
|
+
this.context.symbolTable.functions.get(symbol);
|
|
28288
28439
|
this.context.symbolTable.symbolWikidata.delete(symbol);
|
|
28289
|
-
this.context.symbolTable.functions.delete(symbol);
|
|
28290
28440
|
this.context.symbolTable.functionWikidata.delete(symbol);
|
|
28291
28441
|
}
|
|
28292
28442
|
// Remove any assumptions that make a reference to this symbol
|
|
28293
|
-
// (note that when a scope
|
|
28443
|
+
// (note that when a scope is created, any assumptions from the
|
|
28294
28444
|
// parent scope are copied over, so this effectively removes any
|
|
28295
28445
|
// reference to this symbol, even if there are assumptions about
|
|
28296
28446
|
// it in a parent scope. However, when the current scope exits,
|
|
@@ -28305,6 +28455,6 @@ class ComputeEngine {
|
|
|
28305
28455
|
}
|
|
28306
28456
|
|
|
28307
28457
|
// This file is the root of the `compute-engine` package
|
|
28308
|
-
const version = '0.
|
|
28458
|
+
const version = '0.10.0';
|
|
28309
28459
|
|
|
28310
28460
|
export { ComputeEngine, getVars, isEnvironmentEntry, isFunctionEntry, isInfixEntry, isMatchfixEntry, isPostfixEntry, isPrefixEntry, isSymbolEntry, version };
|