@khanacademy/kas 0.5.1 → 2.0.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/es/index.js +27 -2
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +157 -129
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5,13 +5,16 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var perseusUtils = require('@khanacademy/perseus-utils');
|
|
6
6
|
var _ = require('underscore');
|
|
7
7
|
|
|
8
|
-
function
|
|
8
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
9
|
|
|
10
|
-
var ___default = /*#__PURE__*/
|
|
10
|
+
var ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
11
11
|
|
|
12
12
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
13
|
+
// version number during the release build.
|
|
14
|
+
// In dev, you'll never see the version number.
|
|
15
|
+
|
|
13
16
|
const libName = "@khanacademy/kas";
|
|
14
|
-
const libVersion = "0.
|
|
17
|
+
const libVersion = "2.0.0";
|
|
15
18
|
perseusUtils.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
16
19
|
|
|
17
20
|
// this is a @generated file
|
|
@@ -2622,6 +2625,9 @@ var parser = function () {
|
|
|
2622
2625
|
}();
|
|
2623
2626
|
|
|
2624
2627
|
/* eslint-disable prettier/prettier */
|
|
2628
|
+
/* eslint-disable import/order */
|
|
2629
|
+
/* TODO: fix these lint errors (http://eslint.org/docs/rules): */
|
|
2630
|
+
/* eslint-disable indent, no-undef, no-var, no-dupe-keys, no-new-func, no-redeclare, comma-dangle, max-len, prefer-spread, space-infix-ops, space-unary-ops */
|
|
2625
2631
|
|
|
2626
2632
|
/* The node hierarcy is as follows:
|
|
2627
2633
|
|
|
@@ -2676,7 +2682,7 @@ var TOLERANCE = 9; // decimal places
|
|
|
2676
2682
|
function partition(list, iteratee) {
|
|
2677
2683
|
const a = [];
|
|
2678
2684
|
const b = [];
|
|
2679
|
-
___default
|
|
2685
|
+
___default.default.forEach(list, (elem, key, ctx) => {
|
|
2680
2686
|
if (iteratee(elem, key, ctx)) {
|
|
2681
2687
|
a.push(elem);
|
|
2682
2688
|
} else {
|
|
@@ -2735,7 +2741,7 @@ class Expr {
|
|
|
2735
2741
|
passed[_key - 1] = arguments[_key];
|
|
2736
2742
|
}
|
|
2737
2743
|
var args = this.args().map(function (arg) {
|
|
2738
|
-
return ___default
|
|
2744
|
+
return ___default.default.isString(arg) || ___default.default.isNumber(arg) ? arg : arg?.[method].apply(arg, passed);
|
|
2739
2745
|
});
|
|
2740
2746
|
return this.construct(args);
|
|
2741
2747
|
}
|
|
@@ -2778,7 +2784,7 @@ class Expr {
|
|
|
2778
2784
|
// returns a TeX string, modified by the given options
|
|
2779
2785
|
asTex(options) {
|
|
2780
2786
|
options = options || {};
|
|
2781
|
-
___default
|
|
2787
|
+
___default.default.defaults(options, {
|
|
2782
2788
|
display: true,
|
|
2783
2789
|
dynamic: true,
|
|
2784
2790
|
times: false
|
|
@@ -2806,7 +2812,7 @@ class Expr {
|
|
|
2806
2812
|
// returns a string representing current node structure
|
|
2807
2813
|
repr() {
|
|
2808
2814
|
return this.name() + "(" + this.args().map(function (arg) {
|
|
2809
|
-
return ___default
|
|
2815
|
+
return ___default.default.isString(arg) || ___default.default.isNumber(arg) ? arg : arg?.repr();
|
|
2810
2816
|
}).join(",") + ")";
|
|
2811
2817
|
}
|
|
2812
2818
|
|
|
@@ -2887,13 +2893,13 @@ class Expr {
|
|
|
2887
2893
|
|
|
2888
2894
|
// return the variables (function and non) within the expression
|
|
2889
2895
|
getVars(excludeFunc) {
|
|
2890
|
-
return ___default
|
|
2896
|
+
return ___default.default.uniq(___default.default.flatten(___default.default.invoke(this.exprArgs(), "getVars", excludeFunc))).sort();
|
|
2891
2897
|
}
|
|
2892
2898
|
getConsts() {
|
|
2893
|
-
return ___default
|
|
2899
|
+
return ___default.default.uniq(___default.default.flatten(___default.default.invoke(this.exprArgs(), "getConsts"))).sort();
|
|
2894
2900
|
}
|
|
2895
2901
|
getUnits() {
|
|
2896
|
-
return ___default
|
|
2902
|
+
return ___default.default.flatten(___default.default.invoke(this.exprArgs(), "getUnits"));
|
|
2897
2903
|
}
|
|
2898
2904
|
|
|
2899
2905
|
// check whether this expression node is of a particular type
|
|
@@ -2906,7 +2912,7 @@ class Expr {
|
|
|
2906
2912
|
if (this instanceof func) {
|
|
2907
2913
|
return true;
|
|
2908
2914
|
}
|
|
2909
|
-
return ___default
|
|
2915
|
+
return ___default.default.any(this.exprArgs(), function (arg) {
|
|
2910
2916
|
return arg.has(func);
|
|
2911
2917
|
});
|
|
2912
2918
|
}
|
|
@@ -2942,10 +2948,11 @@ class Expr {
|
|
|
2942
2948
|
// the other Expr can have more variables than this one
|
|
2943
2949
|
// this lets you multiply equations by other variables
|
|
2944
2950
|
var same = function (array1, array2) {
|
|
2945
|
-
|
|
2951
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
2952
|
+
return !___default.default.difference(array1, array2).length;
|
|
2946
2953
|
};
|
|
2947
2954
|
var lower = function (array) {
|
|
2948
|
-
return ___default
|
|
2955
|
+
return ___default.default.uniq(___default.default.invoke(array, "toLowerCase")).sort();
|
|
2949
2956
|
};
|
|
2950
2957
|
var equal = same(vars1, vars2);
|
|
2951
2958
|
var equalIgnoringCase = same(lower(vars1), lower(vars2));
|
|
@@ -2963,7 +2970,7 @@ class Expr {
|
|
|
2963
2970
|
if (other instanceof Eq) {
|
|
2964
2971
|
return false;
|
|
2965
2972
|
}
|
|
2966
|
-
var varList = ___default
|
|
2973
|
+
var varList = ___default.default.union(this.getVars(/* excludeFunc */true), other.getVars(/* excludeFunc */true));
|
|
2967
2974
|
|
|
2968
2975
|
// If the numbers are large we would like to do a relative comparison
|
|
2969
2976
|
// rather than an absolute one, but if they're small enough then an
|
|
@@ -2977,7 +2984,7 @@ class Expr {
|
|
|
2977
2984
|
};
|
|
2978
2985
|
var equalNumbers = function (num1, num2) {
|
|
2979
2986
|
var delta = getDelta(num1, num2);
|
|
2980
|
-
return num1 === num2 /* needed if either is +/- Infinity */ || isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -
|
|
2987
|
+
return num1 === num2 /* needed if either is +/- Infinity */ || isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -9);
|
|
2981
2988
|
};
|
|
2982
2989
|
|
|
2983
2990
|
// If no variables, only need to evaluate once.
|
|
@@ -2985,7 +2992,8 @@ class Expr {
|
|
|
2985
2992
|
// where there are no variables / functions.
|
|
2986
2993
|
// Ran into issues with it in LEMS-2777 and found that tests pass
|
|
2987
2994
|
// with this removed, but keeping a modified version out of caution.
|
|
2988
|
-
const varAndFuncList = ___default
|
|
2995
|
+
const varAndFuncList = ___default.default.union(this.getVars(/* excludeFunc */false), other.getVars(/* excludeFunc */false));
|
|
2996
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
2989
2997
|
if (!varAndFuncList.length && !this.has(Unit) && !other.has(Unit)) {
|
|
2990
2998
|
return equalNumbers(this.eval(), other.eval());
|
|
2991
2999
|
}
|
|
@@ -2997,7 +3005,7 @@ class Expr {
|
|
|
2997
3005
|
var expr2 = other.collect();
|
|
2998
3006
|
var unitList1 = this.getUnits();
|
|
2999
3007
|
var unitList2 = other.getUnits();
|
|
3000
|
-
if (!___default
|
|
3008
|
+
if (!___default.default.isEqual(unitList1, unitList2)) {
|
|
3001
3009
|
return false;
|
|
3002
3010
|
}
|
|
3003
3011
|
|
|
@@ -3031,8 +3039,8 @@ class Expr {
|
|
|
3031
3039
|
//
|
|
3032
3040
|
// TODO(alex): Add support for complex numbers, then remove this.
|
|
3033
3041
|
var useFloats = i % 2 === 0;
|
|
3034
|
-
___default
|
|
3035
|
-
vars[v] = useFloats ? randomFloat(-range, range) : ___default
|
|
3042
|
+
___default.default.each(varList, function (v) {
|
|
3043
|
+
vars[v] = useFloats ? randomFloat(-range, range) : ___default.default.random(-range, range);
|
|
3036
3044
|
});
|
|
3037
3045
|
let equal;
|
|
3038
3046
|
if (expr1.has(Func) || expr2.has(Func) || expr1.has(Unit) || expr2.has(Unit)) {
|
|
@@ -3112,7 +3120,7 @@ class Expr {
|
|
|
3112
3120
|
return this;
|
|
3113
3121
|
}
|
|
3114
3122
|
var expr = this.construct(this.args());
|
|
3115
|
-
expr.hints = ___default
|
|
3123
|
+
expr.hints = ___default.default.clone(this.hints);
|
|
3116
3124
|
expr.hints[hint] = true;
|
|
3117
3125
|
return expr;
|
|
3118
3126
|
}
|
|
@@ -3153,7 +3161,7 @@ class Seq extends Expr {
|
|
|
3153
3161
|
return this.terms;
|
|
3154
3162
|
}
|
|
3155
3163
|
normalize() {
|
|
3156
|
-
var terms = ___default
|
|
3164
|
+
var terms = ___default.default.sortBy(___default.default.invoke(this.terms, "normalize"), term => {
|
|
3157
3165
|
return term.print();
|
|
3158
3166
|
});
|
|
3159
3167
|
return new this.func(terms);
|
|
@@ -3175,7 +3183,7 @@ class Seq extends Expr {
|
|
|
3175
3183
|
// this is a shallow flattening and will return a non-Seq if terms.length <= 1
|
|
3176
3184
|
flatten() {
|
|
3177
3185
|
var type = this;
|
|
3178
|
-
var terms = ___default
|
|
3186
|
+
var terms = ___default.default.reject(this.terms, term => {
|
|
3179
3187
|
// @ts-expect-error: `identity` is defined on Add and Mul but doesn't
|
|
3180
3188
|
// exist on Seq itself.
|
|
3181
3189
|
return term.equals(type.identity);
|
|
@@ -3193,22 +3201,22 @@ class Seq extends Expr {
|
|
|
3193
3201
|
const [same, others] = partition(terms, term => {
|
|
3194
3202
|
return term instanceof type.func;
|
|
3195
3203
|
});
|
|
3196
|
-
var flattened = others.concat(___default
|
|
3204
|
+
var flattened = others.concat(___default.default.flatten(___default.default.pluck(same, "terms"), /* shallow: */true));
|
|
3197
3205
|
return new type.func(flattened);
|
|
3198
3206
|
}
|
|
3199
3207
|
|
|
3200
3208
|
// reduce a numeric sequence to a Num
|
|
3201
3209
|
|
|
3202
3210
|
isPositive() {
|
|
3203
|
-
var terms = ___default
|
|
3204
|
-
return ___default
|
|
3211
|
+
var terms = ___default.default.invoke(this.terms, "collect");
|
|
3212
|
+
return ___default.default.all(___default.default.invoke(terms, "isPositive"));
|
|
3205
3213
|
}
|
|
3206
3214
|
|
|
3207
3215
|
// return a new Seq with a given term replaced by a different term
|
|
3208
3216
|
// (or array of terms). given term can be passed directly, or by index
|
|
3209
3217
|
// if no new term is provided, the old one is simply removed
|
|
3210
3218
|
replace(oldTerm, newTerm) {
|
|
3211
|
-
const index = oldTerm instanceof Expr ? ___default
|
|
3219
|
+
const index = oldTerm instanceof Expr ? ___default.default.indexOf(this.terms, oldTerm) : oldTerm;
|
|
3212
3220
|
var newTerms = [];
|
|
3213
3221
|
if (Array.isArray(newTerm)) {
|
|
3214
3222
|
newTerms = newTerm;
|
|
@@ -3225,7 +3233,7 @@ class Seq extends Expr {
|
|
|
3225
3233
|
}
|
|
3226
3234
|
getDenominator() {
|
|
3227
3235
|
// TODO(alex): find and return LCM
|
|
3228
|
-
return new Mul(___default
|
|
3236
|
+
return new Mul(___default.default.invoke(this.terms, "getDenominator")).flatten();
|
|
3229
3237
|
}
|
|
3230
3238
|
}
|
|
3231
3239
|
|
|
@@ -3236,21 +3244,21 @@ class Add extends Seq {
|
|
|
3236
3244
|
eval() {
|
|
3237
3245
|
let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
3238
3246
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
3239
|
-
return ___default
|
|
3247
|
+
return ___default.default.reduce(this.terms, (memo, term) => {
|
|
3240
3248
|
return memo + term.eval(vars, options);
|
|
3241
3249
|
}, 0);
|
|
3242
3250
|
}
|
|
3243
3251
|
codegen() {
|
|
3244
|
-
return ___default
|
|
3252
|
+
return ___default.default.map(this.terms, term => {
|
|
3245
3253
|
return "(" + term.codegen() + ")";
|
|
3246
3254
|
}).join(" + ") || "0";
|
|
3247
3255
|
}
|
|
3248
3256
|
print() {
|
|
3249
|
-
return ___default
|
|
3257
|
+
return ___default.default.invoke(this.terms, "print").join("+");
|
|
3250
3258
|
}
|
|
3251
3259
|
tex() {
|
|
3252
3260
|
let tex = "";
|
|
3253
|
-
___default
|
|
3261
|
+
___default.default.each(this.terms, term => {
|
|
3254
3262
|
if (!tex || term.isSubtract()) {
|
|
3255
3263
|
tex += term.tex();
|
|
3256
3264
|
} else {
|
|
@@ -3260,9 +3268,9 @@ class Add extends Seq {
|
|
|
3260
3268
|
return tex;
|
|
3261
3269
|
}
|
|
3262
3270
|
collect(options) {
|
|
3263
|
-
var terms = ___default
|
|
3271
|
+
var terms = ___default.default.invoke(this.terms, "collect", options);
|
|
3264
3272
|
var pairs = [];
|
|
3265
|
-
___default
|
|
3273
|
+
___default.default.each(terms, term => {
|
|
3266
3274
|
if (term instanceof Mul) {
|
|
3267
3275
|
var muls = term.partition();
|
|
3268
3276
|
pairs.push([muls[1].flatten(), muls[0].reduce(options)]);
|
|
@@ -3274,12 +3282,12 @@ class Add extends Seq {
|
|
|
3274
3282
|
});
|
|
3275
3283
|
|
|
3276
3284
|
// { (Expr expr).print(): [[Expr expr, Num coefficient]] }
|
|
3277
|
-
var grouped = ___default
|
|
3285
|
+
var grouped = ___default.default.groupBy(pairs, pair => {
|
|
3278
3286
|
return pair[0].normalize().print();
|
|
3279
3287
|
});
|
|
3280
|
-
var collected = ___default
|
|
3288
|
+
var collected = ___default.default.compact(___default.default.map(grouped, pairs => {
|
|
3281
3289
|
var expr = pairs[0][0];
|
|
3282
|
-
var sum = new Add(___default
|
|
3290
|
+
var sum = new Add(___default.default.zip.apply(___default.default, pairs)[1]);
|
|
3283
3291
|
var coefficient = sum.reduce(options);
|
|
3284
3292
|
return new Mul(coefficient, expr).collect(options);
|
|
3285
3293
|
}));
|
|
@@ -3303,8 +3311,8 @@ class Add extends Seq {
|
|
|
3303
3311
|
} else {
|
|
3304
3312
|
factors = [terms[0]];
|
|
3305
3313
|
}
|
|
3306
|
-
___default
|
|
3307
|
-
factors = ___default
|
|
3314
|
+
___default.default.each(___default.default.rest(this.terms), term => {
|
|
3315
|
+
factors = ___default.default.map(factors, factor => {
|
|
3308
3316
|
return term.findGCD(factor);
|
|
3309
3317
|
});
|
|
3310
3318
|
});
|
|
@@ -3317,7 +3325,7 @@ class Add extends Seq {
|
|
|
3317
3325
|
return Mul.createOrAppend(left, right).flatten();
|
|
3318
3326
|
}
|
|
3319
3327
|
reduce(options) {
|
|
3320
|
-
return ___default
|
|
3328
|
+
return ___default.default.reduce(this.terms,
|
|
3321
3329
|
// @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
|
|
3322
3330
|
(memo, term) => {
|
|
3323
3331
|
return memo.add(term, options);
|
|
@@ -3327,11 +3335,11 @@ class Add extends Seq {
|
|
|
3327
3335
|
return false;
|
|
3328
3336
|
}
|
|
3329
3337
|
isNegative() {
|
|
3330
|
-
var terms = ___default
|
|
3331
|
-
return ___default
|
|
3338
|
+
var terms = ___default.default.invoke(this.terms, "collect");
|
|
3339
|
+
return ___default.default.all(___default.default.invoke(terms, "isNegative"));
|
|
3332
3340
|
}
|
|
3333
3341
|
negate() {
|
|
3334
|
-
return new Add(___default
|
|
3342
|
+
return new Add(___default.default.invoke(this.terms, "negate"));
|
|
3335
3343
|
}
|
|
3336
3344
|
|
|
3337
3345
|
// create a new sequence unless left is already one (returns a copy)
|
|
@@ -3351,22 +3359,22 @@ class Mul extends Seq {
|
|
|
3351
3359
|
eval() {
|
|
3352
3360
|
let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
3353
3361
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
3354
|
-
return ___default
|
|
3362
|
+
return ___default.default.reduce(this.terms, (memo, term) => {
|
|
3355
3363
|
return memo * term.eval(vars, options);
|
|
3356
3364
|
}, 1);
|
|
3357
3365
|
}
|
|
3358
3366
|
codegen() {
|
|
3359
|
-
return ___default
|
|
3367
|
+
return ___default.default.map(this.terms, term => {
|
|
3360
3368
|
return "(" + term.codegen() + ")";
|
|
3361
3369
|
}).join(" * ") || "0";
|
|
3362
3370
|
}
|
|
3363
3371
|
print() {
|
|
3364
|
-
return ___default
|
|
3372
|
+
return ___default.default.map(this.terms, term => {
|
|
3365
3373
|
return term instanceof Add ? "(" + term.print() + ")" : term.print();
|
|
3366
3374
|
}).join("*");
|
|
3367
3375
|
}
|
|
3368
3376
|
getUnits() {
|
|
3369
|
-
var tmUnits = ___default
|
|
3377
|
+
var tmUnits = ___default.default(this.terms).chain().map(term => {
|
|
3370
3378
|
return term.getUnits();
|
|
3371
3379
|
}).flatten().value();
|
|
3372
3380
|
tmUnits.sort((a, b) => a.unit.localeCompare(b.unit));
|
|
@@ -3377,7 +3385,7 @@ class Mul extends Seq {
|
|
|
3377
3385
|
// so we follow convention: first any negatives, then any numbers, then everything else
|
|
3378
3386
|
tex() {
|
|
3379
3387
|
var cdot = " \\cdot ";
|
|
3380
|
-
var terms = ___default
|
|
3388
|
+
var terms = ___default.default.groupBy(this.terms, term => {
|
|
3381
3389
|
if (term.isDivide()) {
|
|
3382
3390
|
return "inverse";
|
|
3383
3391
|
} else if (term instanceof Num) {
|
|
@@ -3386,8 +3394,12 @@ class Mul extends Seq {
|
|
|
3386
3394
|
return "other";
|
|
3387
3395
|
}
|
|
3388
3396
|
});
|
|
3397
|
+
|
|
3398
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3389
3399
|
var inverses = terms.inverse || [];
|
|
3400
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3390
3401
|
var numbers = terms.number || [];
|
|
3402
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3391
3403
|
var others = terms.other || [];
|
|
3392
3404
|
var negatives = "";
|
|
3393
3405
|
var numerator;
|
|
@@ -3404,14 +3416,14 @@ class Mul extends Seq {
|
|
|
3404
3416
|
return numbers[i].tex() + new Mul(newTerms).tex();
|
|
3405
3417
|
}
|
|
3406
3418
|
}
|
|
3407
|
-
numbers = ___default
|
|
3419
|
+
numbers = ___default.default.compact(___default.default.map(numbers, term => {
|
|
3408
3420
|
var shouldPushDown = !term.hints.fraction || inverses.length > 0;
|
|
3409
3421
|
if (term instanceof Rational && !(term instanceof Int) && shouldPushDown) {
|
|
3410
3422
|
// e.g. 3x/4 -> 3/4*x (internally) -> 3x/4 (rendered)
|
|
3411
3423
|
inverses.push(new Pow(new Int(term.d), NumDiv));
|
|
3412
3424
|
var number = new Int(term.n);
|
|
3413
3425
|
number.hints = term.hints;
|
|
3414
|
-
return ___default
|
|
3426
|
+
return ___default.default.any(term.hints) ? number : null;
|
|
3415
3427
|
} else {
|
|
3416
3428
|
return term;
|
|
3417
3429
|
}
|
|
@@ -3421,7 +3433,7 @@ class Mul extends Seq {
|
|
|
3421
3433
|
numerator = others[0].tex();
|
|
3422
3434
|
} else {
|
|
3423
3435
|
var tex = "";
|
|
3424
|
-
___default
|
|
3436
|
+
___default.default.each(numbers, term => {
|
|
3425
3437
|
if (term.hints.subtract && term.hints.entered) {
|
|
3426
3438
|
negatives += "-";
|
|
3427
3439
|
tex += (tex ? cdot : "") + term.abs().tex();
|
|
@@ -3434,7 +3446,7 @@ class Mul extends Seq {
|
|
|
3434
3446
|
tex += (tex ? cdot : "") + term.tex();
|
|
3435
3447
|
}
|
|
3436
3448
|
});
|
|
3437
|
-
___default
|
|
3449
|
+
___default.default.each(others, term => {
|
|
3438
3450
|
if (term.needsExplicitMul()) {
|
|
3439
3451
|
// e.g. 2*2^3 -> 2(dot)2^3
|
|
3440
3452
|
tex += (tex ? cdot : "") + term.tex();
|
|
@@ -3448,15 +3460,17 @@ class Mul extends Seq {
|
|
|
3448
3460
|
});
|
|
3449
3461
|
numerator = tex ? tex : "1";
|
|
3450
3462
|
}
|
|
3463
|
+
|
|
3464
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3451
3465
|
if (!inverses.length) {
|
|
3452
3466
|
return negatives + numerator;
|
|
3453
3467
|
} else {
|
|
3454
|
-
var denominator = new Mul(___default
|
|
3468
|
+
var denominator = new Mul(___default.default.invoke(inverses, "asDivide")).flatten().tex();
|
|
3455
3469
|
return negatives + "\\frac{" + numerator + "}{" + denominator + "}";
|
|
3456
3470
|
}
|
|
3457
3471
|
}
|
|
3458
3472
|
strip() {
|
|
3459
|
-
var terms = ___default
|
|
3473
|
+
var terms = ___default.default.map(this.terms, term => {
|
|
3460
3474
|
return term instanceof Num ? term.abs() : term.strip();
|
|
3461
3475
|
});
|
|
3462
3476
|
return new Mul(terms).flatten();
|
|
@@ -3472,8 +3486,8 @@ class Mul extends Seq {
|
|
|
3472
3486
|
};
|
|
3473
3487
|
const mul = this.recurse("expand").flatten();
|
|
3474
3488
|
const factors = getFactors(mul);
|
|
3475
|
-
const hasAdd = ___default
|
|
3476
|
-
const hasInverseAdd = ___default
|
|
3489
|
+
const hasAdd = ___default.default.any(factors, isAdd);
|
|
3490
|
+
const hasInverseAdd = ___default.default.any(factors, isInverseAdd);
|
|
3477
3491
|
if (!(hasAdd || hasInverseAdd)) {
|
|
3478
3492
|
return mul;
|
|
3479
3493
|
}
|
|
@@ -3482,22 +3496,22 @@ class Mul extends Seq {
|
|
|
3482
3496
|
const [adds, others] = partition(normals, isAdd);
|
|
3483
3497
|
|
|
3484
3498
|
// loop over each additive sequence
|
|
3485
|
-
const expanded = ___default
|
|
3499
|
+
const expanded = ___default.default.reduce(adds, function (expanded, add) {
|
|
3486
3500
|
// loop over each expanded array of terms
|
|
3487
|
-
return ___default
|
|
3501
|
+
return ___default.default.reduce(expanded, function (temp, array) {
|
|
3488
3502
|
// loop over each additive sequence's terms
|
|
3489
|
-
return temp.concat(___default
|
|
3503
|
+
return temp.concat(___default.default.map(add.terms, term => array.concat(term)));
|
|
3490
3504
|
}, []);
|
|
3491
3505
|
}, [[]]);
|
|
3492
3506
|
|
|
3493
3507
|
// join each fully expanded array of factors with remaining multiplicative factors
|
|
3494
|
-
const muls = ___default
|
|
3508
|
+
const muls = ___default.default.map(expanded, function (array) {
|
|
3495
3509
|
return new Mul(others.concat(array)).flatten();
|
|
3496
3510
|
});
|
|
3497
3511
|
normals = [new Add(muls)];
|
|
3498
3512
|
}
|
|
3499
3513
|
if (hasInverseAdd) {
|
|
3500
|
-
const denominator = new Mul(___default
|
|
3514
|
+
const denominator = new Mul(___default.default.invoke(inverses, "getDenominator")).flatten();
|
|
3501
3515
|
inverses = [new Pow(denominator.expand(), NumDiv)];
|
|
3502
3516
|
}
|
|
3503
3517
|
return new Mul(normals.concat(inverses)).flatten();
|
|
@@ -3516,7 +3530,7 @@ class Mul extends Seq {
|
|
|
3516
3530
|
// Could also accomplish this by passing a new option
|
|
3517
3531
|
// e.g. return memo.mul(term, {autocollect: false});
|
|
3518
3532
|
// TODO(alex): Decide whether this is a good use of options or not
|
|
3519
|
-
const ratObj = ___default
|
|
3533
|
+
const ratObj = ___default.default.reduce(rationals, (memo, term) => {
|
|
3520
3534
|
return {
|
|
3521
3535
|
n: memo.n * term.n,
|
|
3522
3536
|
d: memo.d * term.d
|
|
@@ -3545,7 +3559,7 @@ class Mul extends Seq {
|
|
|
3545
3559
|
}
|
|
3546
3560
|
const others = other.terms;
|
|
3547
3561
|
var pairs = [];
|
|
3548
|
-
___default
|
|
3562
|
+
___default.default.each(others, term => {
|
|
3549
3563
|
if (term instanceof Pow) {
|
|
3550
3564
|
pairs.push([term.base, term.exp]);
|
|
3551
3565
|
} else {
|
|
@@ -3554,12 +3568,12 @@ class Mul extends Seq {
|
|
|
3554
3568
|
});
|
|
3555
3569
|
|
|
3556
3570
|
// {(Expr base).print(): [[Expr base, Expr exp]]}
|
|
3557
|
-
var grouped = ___default
|
|
3571
|
+
var grouped = ___default.default.groupBy(pairs, pair => {
|
|
3558
3572
|
return pair[0].normalize().print();
|
|
3559
3573
|
});
|
|
3560
|
-
var summed = ___default
|
|
3574
|
+
var summed = ___default.default.compact(___default.default.map(grouped, pairs => {
|
|
3561
3575
|
var base = pairs[0][0];
|
|
3562
|
-
var sum = new Add(___default
|
|
3576
|
+
var sum = new Add(___default.default.zip.apply(___default.default, pairs)[1]);
|
|
3563
3577
|
var exp = sum.collect(options);
|
|
3564
3578
|
if (exp instanceof Num && exp.eval() === 0) {
|
|
3565
3579
|
return null;
|
|
@@ -3569,7 +3583,7 @@ class Mul extends Seq {
|
|
|
3569
3583
|
}));
|
|
3570
3584
|
|
|
3571
3585
|
// XXX `pairs` is shadowed four or five times in this function
|
|
3572
|
-
const groupedPairs = ___default
|
|
3586
|
+
const groupedPairs = ___default.default.groupBy(summed, pair => {
|
|
3573
3587
|
if (pair[0] instanceof Trig && pair[0].isBasic()) {
|
|
3574
3588
|
return "trig";
|
|
3575
3589
|
} else if (pair[0] instanceof Log) {
|
|
@@ -3578,18 +3592,21 @@ class Mul extends Seq {
|
|
|
3578
3592
|
return "expr";
|
|
3579
3593
|
}
|
|
3580
3594
|
});
|
|
3595
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3581
3596
|
let trigs = groupedPairs.trig || [];
|
|
3597
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3582
3598
|
let logs = groupedPairs.log || [];
|
|
3599
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3583
3600
|
const exprs = groupedPairs.expr || [];
|
|
3584
3601
|
if (trigs.length > 1) {
|
|
3585
3602
|
// combine sines and cosines into other trig functions
|
|
3586
3603
|
|
|
3587
3604
|
// {Trig.arg.print(): [[Trig base, Expr exp]]}
|
|
3588
|
-
var byArg = ___default
|
|
3605
|
+
var byArg = ___default.default.groupBy(trigs, pair => {
|
|
3589
3606
|
return pair[0].arg.normalize().print();
|
|
3590
3607
|
});
|
|
3591
3608
|
trigs = [];
|
|
3592
|
-
___default
|
|
3609
|
+
___default.default.each(byArg, pairs => {
|
|
3593
3610
|
const arg = pairs[0][0].arg;
|
|
3594
3611
|
|
|
3595
3612
|
// {Trig.type: Expr exp}
|
|
@@ -3597,7 +3614,7 @@ class Mul extends Seq {
|
|
|
3597
3614
|
sin: NumZero,
|
|
3598
3615
|
cos: NumZero
|
|
3599
3616
|
};
|
|
3600
|
-
___default
|
|
3617
|
+
___default.default.each(pairs, pair => {
|
|
3601
3618
|
funcs[pair[0].type] = pair[1];
|
|
3602
3619
|
});
|
|
3603
3620
|
if (Mul.handleNegative(funcs.sin).collect(options).equals(funcs.cos)) {
|
|
@@ -3616,7 +3633,7 @@ class Mul extends Seq {
|
|
|
3616
3633
|
// TODO(alex): combine even if exponents not a perfect match
|
|
3617
3634
|
// TODO(alex): transform 1/sin and 1/cos into csc and sec
|
|
3618
3635
|
|
|
3619
|
-
___default
|
|
3636
|
+
___default.default.each(funcs, (exp, type) => {
|
|
3620
3637
|
trigs.push([new Trig(type, arg), exp]);
|
|
3621
3638
|
});
|
|
3622
3639
|
});
|
|
@@ -3625,11 +3642,11 @@ class Mul extends Seq {
|
|
|
3625
3642
|
// combine logs with the same base
|
|
3626
3643
|
|
|
3627
3644
|
// {Log.base.print(): [[Log base, Expr exp]]}
|
|
3628
|
-
var byBase = ___default
|
|
3645
|
+
var byBase = ___default.default.groupBy(logs, pair => {
|
|
3629
3646
|
return pair[0].base.normalize().print();
|
|
3630
3647
|
});
|
|
3631
3648
|
logs = [];
|
|
3632
|
-
___default
|
|
3649
|
+
___default.default.each(byBase, pairs => {
|
|
3633
3650
|
// only combine two logs of the same base, otherwise commutative
|
|
3634
3651
|
// differences result in different equally valid output
|
|
3635
3652
|
// e.g. ln(x)/ln(z)*ln(y) -> log_z(x)*ln(y)
|
|
@@ -3648,13 +3665,13 @@ class Mul extends Seq {
|
|
|
3648
3665
|
|
|
3649
3666
|
// TODO(alex): combine if all inverses are the same e.g. ln(y)*ln(z)/ln(x)/ln(x)
|
|
3650
3667
|
}
|
|
3651
|
-
var collected = ___default
|
|
3668
|
+
var collected = ___default.default.map([...trigs, ...logs, ...exprs], pair => {
|
|
3652
3669
|
return new Pow(pair[0], pair[1]).collect(options);
|
|
3653
3670
|
});
|
|
3654
3671
|
return new Mul([number].concat(collected)).flatten();
|
|
3655
3672
|
}
|
|
3656
3673
|
isSubtract() {
|
|
3657
|
-
return ___default
|
|
3674
|
+
return ___default.default.any(this.terms, term => {
|
|
3658
3675
|
return term instanceof Num && Boolean(term.hints.subtract);
|
|
3659
3676
|
});
|
|
3660
3677
|
}
|
|
@@ -3666,7 +3683,10 @@ class Mul extends Seq {
|
|
|
3666
3683
|
// `partition` splits the terms into two Seqs - one containing
|
|
3667
3684
|
// only Nums and the all non-Num nodes.
|
|
3668
3685
|
var numbers = partitioned[0].terms;
|
|
3669
|
-
|
|
3686
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3687
|
+
var fold = numbers.length && ___default.default.all(numbers, num => num.n > 0);
|
|
3688
|
+
|
|
3689
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
3670
3690
|
if (fold) {
|
|
3671
3691
|
// e.g. - x*2*3 -> x*-2*3
|
|
3672
3692
|
var num = numbers[0].negate();
|
|
@@ -3683,7 +3703,7 @@ class Mul extends Seq {
|
|
|
3683
3703
|
// TODO(alex): make more general or rename to be more specific
|
|
3684
3704
|
factorOut() {
|
|
3685
3705
|
var factored = false;
|
|
3686
|
-
var terms = ___default
|
|
3706
|
+
var terms = ___default.default.compact(___default.default.map(this.terms, term => {
|
|
3687
3707
|
if (!factored && term instanceof Num && term.hints.divide) {
|
|
3688
3708
|
factored = true;
|
|
3689
3709
|
return term.n !== -1 ? term.negate() : null;
|
|
@@ -3698,14 +3718,14 @@ class Mul extends Seq {
|
|
|
3698
3718
|
}
|
|
3699
3719
|
}
|
|
3700
3720
|
reduce(options) {
|
|
3701
|
-
return ___default
|
|
3721
|
+
return ___default.default.reduce(this.terms,
|
|
3702
3722
|
// @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
|
|
3703
3723
|
(memo, term) => {
|
|
3704
3724
|
return memo.mul(term, options);
|
|
3705
3725
|
}, this.identity);
|
|
3706
3726
|
}
|
|
3707
3727
|
findGCD(factor) {
|
|
3708
|
-
return new Mul(___default
|
|
3728
|
+
return new Mul(___default.default.invoke(this.terms, "findGCD", factor)).flatten();
|
|
3709
3729
|
}
|
|
3710
3730
|
asMul() {
|
|
3711
3731
|
return this;
|
|
@@ -3720,7 +3740,7 @@ class Mul extends Seq {
|
|
|
3720
3740
|
}
|
|
3721
3741
|
isNegative() {
|
|
3722
3742
|
const terms = getFactors(this.collect()).map(factor => factor.isNegative());
|
|
3723
|
-
return ___default
|
|
3743
|
+
return ___default.default.any(terms);
|
|
3724
3744
|
}
|
|
3725
3745
|
fold() {
|
|
3726
3746
|
return Mul.fold(this);
|
|
@@ -3729,7 +3749,7 @@ class Mul extends Seq {
|
|
|
3729
3749
|
var isNum = expr => {
|
|
3730
3750
|
return expr instanceof Num;
|
|
3731
3751
|
};
|
|
3732
|
-
const num = ___default
|
|
3752
|
+
const num = ___default.default.find(this.terms, isNum);
|
|
3733
3753
|
if (num) {
|
|
3734
3754
|
return this.replace(num, num.negate());
|
|
3735
3755
|
} else {
|
|
@@ -3764,7 +3784,7 @@ class Mul extends Seq {
|
|
|
3764
3784
|
// dividing by a Mul is the same as repeated division by its terms
|
|
3765
3785
|
if (right instanceof Mul) {
|
|
3766
3786
|
var first = Mul.handleDivide(left, right.terms[0]);
|
|
3767
|
-
var rest = new Mul(___default
|
|
3787
|
+
var rest = new Mul(___default.default.rest(right.terms)).flatten();
|
|
3768
3788
|
return Mul.handleDivide(first, rest);
|
|
3769
3789
|
}
|
|
3770
3790
|
var isInt = expr => {
|
|
@@ -3776,7 +3796,7 @@ class Mul extends Seq {
|
|
|
3776
3796
|
|
|
3777
3797
|
// for simplification purposes, fold Ints into Rationals if possible
|
|
3778
3798
|
// e.g. 3x / 4 -> 3/4 * x (will still render as 3x/4)
|
|
3779
|
-
if (isInt(right) && left instanceof Mul && ___default
|
|
3799
|
+
if (isInt(right) && left instanceof Mul && ___default.default.any(left.terms, isInt)) {
|
|
3780
3800
|
// search from the right
|
|
3781
3801
|
var reversed = left.terms.slice().reverse();
|
|
3782
3802
|
var num = reversed.find(isRational);
|
|
@@ -3849,8 +3869,8 @@ class Mul extends Seq {
|
|
|
3849
3869
|
if (left instanceof Mul) {
|
|
3850
3870
|
// NOTE(kevinb): `terms` should always have at least two
|
|
3851
3871
|
// elements so getting the last element is safe to do.
|
|
3852
|
-
var divided = divide(___default
|
|
3853
|
-
return new Mul(___default
|
|
3872
|
+
var divided = divide(___default.default.last(left.terms), right);
|
|
3873
|
+
return new Mul(___default.default.initial(left.terms).concat(divided));
|
|
3854
3874
|
} else {
|
|
3855
3875
|
var divided = divide(left, right);
|
|
3856
3876
|
return new Mul(divided).flatten();
|
|
@@ -3872,17 +3892,17 @@ class Mul extends Seq {
|
|
|
3872
3892
|
static fold(expr) {
|
|
3873
3893
|
if (expr instanceof Mul) {
|
|
3874
3894
|
// assuming that this will be second to last
|
|
3875
|
-
var trigLog = ___default
|
|
3895
|
+
var trigLog = ___default.default.find(___default.default.initial(expr.terms), term => {
|
|
3876
3896
|
return (term instanceof Trig || term instanceof Log) && Boolean(term.hints.open);
|
|
3877
3897
|
});
|
|
3878
3898
|
if (trigLog) {
|
|
3879
3899
|
// expr.terms should always have at least two terms
|
|
3880
|
-
const last = ___default
|
|
3900
|
+
const last = ___default.default.last(expr.terms);
|
|
3881
3901
|
if (trigLog.hints.parens || last.hints.parens || last.has(Trig) || last.has(Log)) {
|
|
3882
3902
|
trigLog.hints.open = false;
|
|
3883
3903
|
} else {
|
|
3884
3904
|
const newTrigLog = trigLog instanceof Trig ? Trig.create([trigLog.type, trigLog.exp], Mul.createOrAppend(trigLog.arg, last).fold()) : Log.create(trigLog.base, Mul.createOrAppend(trigLog.power, last).fold());
|
|
3885
|
-
const index = ___default
|
|
3905
|
+
const index = ___default.default.indexOf(expr.terms, trigLog);
|
|
3886
3906
|
if (index === 0) {
|
|
3887
3907
|
return newTrigLog;
|
|
3888
3908
|
} else {
|
|
@@ -3908,9 +3928,9 @@ class Mul extends Seq {
|
|
|
3908
3928
|
const negNum = numbers.find(neg);
|
|
3909
3929
|
if (numbers.length > 1 && negNum && posNum &&
|
|
3910
3930
|
// @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
|
|
3911
|
-
___default
|
|
3912
|
-
var firstNeg = ___default
|
|
3913
|
-
var firstNum = ___default
|
|
3931
|
+
___default.default.every(numbers, posOrNeg)) {
|
|
3932
|
+
var firstNeg = ___default.default.indexOf(expr.terms, negNum);
|
|
3933
|
+
var firstNum = ___default.default.indexOf(expr.terms, posNum);
|
|
3914
3934
|
|
|
3915
3935
|
// e.g. -x*2 -> x*-2
|
|
3916
3936
|
if (firstNeg < firstNum) {
|
|
@@ -4042,7 +4062,7 @@ class Pow extends Expr {
|
|
|
4042
4062
|
if (pow.base instanceof Mul) {
|
|
4043
4063
|
// e.g. (ab)^c -> a^c*b^c
|
|
4044
4064
|
|
|
4045
|
-
var terms = ___default
|
|
4065
|
+
var terms = ___default.default.map(pow.base.terms, term => {
|
|
4046
4066
|
return new Pow(term, pow.exp);
|
|
4047
4067
|
});
|
|
4048
4068
|
return new Mul(terms).expand();
|
|
@@ -4071,10 +4091,10 @@ class Pow extends Expr {
|
|
|
4071
4091
|
}
|
|
4072
4092
|
|
|
4073
4093
|
// otherwise decompose n into powers of 2 ...
|
|
4074
|
-
let indices = ___default
|
|
4094
|
+
let indices = ___default.default.map(n.toString(2).split(""), function (str, i, list) {
|
|
4075
4095
|
return Number(str) * Math.pow(2, list.length - i - 1);
|
|
4076
4096
|
});
|
|
4077
|
-
indices = ___default
|
|
4097
|
+
indices = ___default.default.without(indices, 0);
|
|
4078
4098
|
|
|
4079
4099
|
// ... then combine
|
|
4080
4100
|
const factors = [];
|
|
@@ -4089,7 +4109,7 @@ class Pow extends Expr {
|
|
|
4089
4109
|
// DEFINITELY want behind super-simplify() flag
|
|
4090
4110
|
// e.g. x^(a+b) -> x^a*x^b
|
|
4091
4111
|
|
|
4092
|
-
const terms = ___default
|
|
4112
|
+
const terms = ___default.default.map(pow.exp.terms, term => {
|
|
4093
4113
|
return new Pow(pow.base, term).expand();
|
|
4094
4114
|
});
|
|
4095
4115
|
return new Mul(terms).expand();
|
|
@@ -4100,7 +4120,7 @@ class Pow extends Expr {
|
|
|
4100
4120
|
factor() {
|
|
4101
4121
|
var pow = this.recurse("factor");
|
|
4102
4122
|
if (pow.base instanceof Mul) {
|
|
4103
|
-
var terms = ___default
|
|
4123
|
+
var terms = ___default.default.map(pow.base.terms, term => {
|
|
4104
4124
|
if (term instanceof Int && pow.exp.equals(NumDiv)) {
|
|
4105
4125
|
// Anything that can be a Rational should be a Rational
|
|
4106
4126
|
// e.g. 2^(-1) -> 1/2
|
|
@@ -4136,7 +4156,7 @@ class Pow extends Expr {
|
|
|
4136
4156
|
} else if (isSimilarLog(pow.exp)) {
|
|
4137
4157
|
// e.g. b^(log_b(x)) -> x
|
|
4138
4158
|
return pow.exp.power;
|
|
4139
|
-
} else if (pow.exp instanceof Mul && ___default
|
|
4159
|
+
} else if (pow.exp instanceof Mul && ___default.default.any(pow.exp.terms, isSimilarLog)) {
|
|
4140
4160
|
// e.g. b^(2*y*log_b(x)) -> x^(2*y)
|
|
4141
4161
|
// `log` will always be defined here because of the
|
|
4142
4162
|
// `_.any(pow.exp.terms, isSimilarLog)` check above.
|
|
@@ -4185,7 +4205,7 @@ class Pow extends Expr {
|
|
|
4185
4205
|
var isDiv = function (arg) {
|
|
4186
4206
|
return arg instanceof Num && Boolean(arg.hints.divide);
|
|
4187
4207
|
};
|
|
4188
|
-
return isDiv(this.exp) || this.exp instanceof Mul && ___default
|
|
4208
|
+
return isDiv(this.exp) || this.exp instanceof Mul && ___default.default.any(this.exp.terms, isDiv);
|
|
4189
4209
|
}
|
|
4190
4210
|
|
|
4191
4211
|
// assuming this Pow represents user-entered division, returns the denominator
|
|
@@ -4195,7 +4215,7 @@ class Pow extends Expr {
|
|
|
4195
4215
|
return this.base;
|
|
4196
4216
|
} else {
|
|
4197
4217
|
var negated = this.exp.negate();
|
|
4198
|
-
negated.hints = ___default
|
|
4218
|
+
negated.hints = ___default.default.clone(this.exp.hints);
|
|
4199
4219
|
negated.hints.divide = false;
|
|
4200
4220
|
return new Pow(this.base, negated);
|
|
4201
4221
|
}
|
|
@@ -4360,7 +4380,7 @@ class Log extends Expr {
|
|
|
4360
4380
|
// might want behind super-simplify() flag
|
|
4361
4381
|
// e.g. ln(xy) -> ln(x) + ln(y)
|
|
4362
4382
|
|
|
4363
|
-
var terms = ___default
|
|
4383
|
+
var terms = ___default.default.map(log.power.terms, term => {
|
|
4364
4384
|
// need to expand again in case new log powers are Pows
|
|
4365
4385
|
return new Log(log.base, term).expand();
|
|
4366
4386
|
});
|
|
@@ -4566,13 +4586,13 @@ class Trig extends Expr {
|
|
|
4566
4586
|
}
|
|
4567
4587
|
};
|
|
4568
4588
|
isEven() {
|
|
4569
|
-
return ___default
|
|
4589
|
+
return ___default.default.contains(["cos", "sec"], this.type);
|
|
4570
4590
|
}
|
|
4571
4591
|
isInverse() {
|
|
4572
4592
|
return this.type.indexOf("arc") === 0;
|
|
4573
4593
|
}
|
|
4574
4594
|
isBasic() {
|
|
4575
|
-
return ___default
|
|
4595
|
+
return ___default.default.contains(["sin", "cos"], this.type);
|
|
4576
4596
|
}
|
|
4577
4597
|
eval() {
|
|
4578
4598
|
let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -4632,7 +4652,7 @@ class Trig extends Expr {
|
|
|
4632
4652
|
// e.g. tan(x) -> sin(x)/cos(x)
|
|
4633
4653
|
// NOTE(kevinb): All non-inverse trig functions have an expand property.
|
|
4634
4654
|
var expand = trig.functions[trig.type].expand;
|
|
4635
|
-
return ___default
|
|
4655
|
+
return ___default.default.bind(expand, trig)();
|
|
4636
4656
|
} else {
|
|
4637
4657
|
return trig;
|
|
4638
4658
|
}
|
|
@@ -4716,7 +4736,7 @@ class Abs extends Expr {
|
|
|
4716
4736
|
return abs.arg.abs();
|
|
4717
4737
|
} else if (abs.arg instanceof Mul) {
|
|
4718
4738
|
// e.g. |-2*pi*x| -> 2*pi*|x|
|
|
4719
|
-
var terms = ___default
|
|
4739
|
+
var terms = ___default.default.groupBy(abs.arg.terms, term => {
|
|
4720
4740
|
if (term.isPositive()) {
|
|
4721
4741
|
return "positive";
|
|
4722
4742
|
} else if (term instanceof Num) {
|
|
@@ -4725,7 +4745,9 @@ class Abs extends Expr {
|
|
|
4725
4745
|
return "other";
|
|
4726
4746
|
}
|
|
4727
4747
|
});
|
|
4728
|
-
var positives = terms.positive.concat(___default
|
|
4748
|
+
var positives = terms.positive.concat(___default.default.invoke(terms.number, "abs"));
|
|
4749
|
+
|
|
4750
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
4729
4751
|
if (terms.other.length) {
|
|
4730
4752
|
positives.push(new Abs(new Mul(terms.other).flatten()));
|
|
4731
4753
|
}
|
|
@@ -4740,7 +4762,7 @@ class Abs extends Expr {
|
|
|
4740
4762
|
var abs = this.recurse("expand");
|
|
4741
4763
|
if (abs.arg instanceof Mul) {
|
|
4742
4764
|
// e.g. |xyz| -> |x|*|y|*|z|
|
|
4743
|
-
var terms = ___default
|
|
4765
|
+
var terms = ___default.default.map(abs.arg.terms, term => {
|
|
4744
4766
|
return new Abs(term);
|
|
4745
4767
|
});
|
|
4746
4768
|
return new Mul(terms);
|
|
@@ -4787,7 +4809,7 @@ class Eq extends Expr {
|
|
|
4787
4809
|
}
|
|
4788
4810
|
normalize() {
|
|
4789
4811
|
var eq = this.recurse("normalize");
|
|
4790
|
-
if (___default
|
|
4812
|
+
if (___default.default.contains([">", ">="], eq.type)) {
|
|
4791
4813
|
// inequalities should have the smaller side on the left
|
|
4792
4814
|
return new Eq(eq.right, eq.type.replace(">", "<"), eq.left);
|
|
4793
4815
|
} else {
|
|
@@ -4808,7 +4830,7 @@ class Eq extends Expr {
|
|
|
4808
4830
|
// first convert to a sequence of additive terms
|
|
4809
4831
|
let terms = [];
|
|
4810
4832
|
if (this.left instanceof Add) {
|
|
4811
|
-
terms = ___default
|
|
4833
|
+
terms = ___default.default.clone(this.left.terms);
|
|
4812
4834
|
} else if (!isZero(this.left)) {
|
|
4813
4835
|
terms = [this.left];
|
|
4814
4836
|
}
|
|
@@ -4824,7 +4846,7 @@ class Eq extends Expr {
|
|
|
4824
4846
|
// float precision. We have to be very careful to not introduce any
|
|
4825
4847
|
// irrational floats before asExpr() returns, because by definition
|
|
4826
4848
|
// they do not have exact denominators...
|
|
4827
|
-
terms = ___default
|
|
4849
|
+
terms = ___default.default.invoke(terms, "collect", {
|
|
4828
4850
|
preciseFloats: true
|
|
4829
4851
|
});
|
|
4830
4852
|
|
|
@@ -4837,7 +4859,7 @@ class Eq extends Expr {
|
|
|
4837
4859
|
denominator = denominator.asPositiveFactor();
|
|
4838
4860
|
}
|
|
4839
4861
|
if (!denominator.equals(NumOne)) {
|
|
4840
|
-
terms = ___default
|
|
4862
|
+
terms = ___default.default.map(terms, term => {
|
|
4841
4863
|
return Mul.createOrAppend(term, denominator).simplify({
|
|
4842
4864
|
once: true,
|
|
4843
4865
|
preciseFloats: true
|
|
@@ -4865,29 +4887,35 @@ class Eq extends Expr {
|
|
|
4865
4887
|
return expr;
|
|
4866
4888
|
}
|
|
4867
4889
|
const terms = factored.terms;
|
|
4890
|
+
|
|
4891
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
4868
4892
|
const hasVar = term => !!term.getVars().length;
|
|
4869
4893
|
const isOne = term => term.equals(NumOne);
|
|
4870
4894
|
const [adds, others] = partition(terms, isAdd);
|
|
4895
|
+
|
|
4896
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
4871
4897
|
if (adds.length && this.isEquality()) {
|
|
4872
4898
|
// keep only Adds
|
|
4873
4899
|
// e.g. 2xy(z+1)(=0) -> z+1(=0)
|
|
4874
4900
|
return new Mul(adds).flatten();
|
|
4875
4901
|
}
|
|
4876
4902
|
let denominator = others;
|
|
4903
|
+
|
|
4904
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
4877
4905
|
if (!adds.length) {
|
|
4878
4906
|
// if no Adds, keep all variable terms to preserve meaning
|
|
4879
4907
|
// e.g. 42xyz(=0) -> xyz(=0)
|
|
4880
|
-
denominator = ___default
|
|
4908
|
+
denominator = ___default.default.reject(denominator, hasVar);
|
|
4881
4909
|
}
|
|
4882
4910
|
if (isInequality) {
|
|
4883
4911
|
// can't divide inequalities by non 100% positive factors
|
|
4884
4912
|
// e.g. 42x^2y(z+1)(=0) -> y(z+1)(=0)
|
|
4885
|
-
denominator = ___default
|
|
4913
|
+
denominator = ___default.default.invoke(denominator, "asPositiveFactor");
|
|
4886
4914
|
}
|
|
4887
4915
|
|
|
4888
4916
|
// don't need to divide by one
|
|
4889
|
-
denominator = ___default
|
|
4890
|
-
denominator = ___default
|
|
4917
|
+
denominator = ___default.default.reject(denominator, isOne);
|
|
4918
|
+
denominator = ___default.default.map(denominator, term => {
|
|
4891
4919
|
return new Pow(term, NumDiv);
|
|
4892
4920
|
});
|
|
4893
4921
|
const dividedResult = new Mul(terms.concat(denominator)).collect();
|
|
@@ -4901,7 +4929,7 @@ class Eq extends Expr {
|
|
|
4901
4929
|
}
|
|
4902
4930
|
}
|
|
4903
4931
|
isEquality() {
|
|
4904
|
-
return ___default
|
|
4932
|
+
return ___default.default.contains(["=", "<>"], this.type);
|
|
4905
4933
|
}
|
|
4906
4934
|
compare(other) {
|
|
4907
4935
|
// expression comparisons are handled by Expr.compare()
|
|
@@ -4954,7 +4982,7 @@ class Eq extends Expr {
|
|
|
4954
4982
|
throw new Error("Can only handle linear equations of the form " + "a + bx (= 0)");
|
|
4955
4983
|
}
|
|
4956
4984
|
var hasVar = term => {
|
|
4957
|
-
return term.has(Var) && ___default
|
|
4985
|
+
return term.has(Var) && ___default.default.contains(term.getVars(), variable.symbol);
|
|
4958
4986
|
};
|
|
4959
4987
|
const termHasVar = hasVar(expr.terms[0]);
|
|
4960
4988
|
const a = termHasVar ? Mul.handleNegative(expr.terms[1]) : Mul.handleNegative(expr.terms[0]);
|
|
@@ -5001,7 +5029,7 @@ class Func extends Sym {
|
|
|
5001
5029
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
5002
5030
|
var arg = this.arg;
|
|
5003
5031
|
var func = vars[this.symbol];
|
|
5004
|
-
var newVars = ___default
|
|
5032
|
+
var newVars = ___default.default.extend(___default.default.clone(vars), {
|
|
5005
5033
|
x: arg.eval(vars, options)
|
|
5006
5034
|
});
|
|
5007
5035
|
var parsedFunc = parse(func, options);
|
|
@@ -5021,7 +5049,7 @@ class Func extends Sym {
|
|
|
5021
5049
|
if (excludeFunc) {
|
|
5022
5050
|
return this.arg.getVars();
|
|
5023
5051
|
} else {
|
|
5024
|
-
return ___default
|
|
5052
|
+
return ___default.default.union(this.arg.getVars(), [this.symbol]).sort();
|
|
5025
5053
|
}
|
|
5026
5054
|
}
|
|
5027
5055
|
getConsts() {
|
|
@@ -5261,13 +5289,13 @@ class Num extends Expr {
|
|
|
5261
5289
|
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
|
5262
5290
|
args[_key3] = arguments[_key3];
|
|
5263
5291
|
}
|
|
5264
|
-
return ___default
|
|
5292
|
+
return ___default.default.min(args, num => num.eval());
|
|
5265
5293
|
}
|
|
5266
5294
|
static max() {
|
|
5267
5295
|
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
|
5268
5296
|
args[_key4] = arguments[_key4];
|
|
5269
5297
|
}
|
|
5270
|
-
return ___default
|
|
5298
|
+
return ___default.default.max(args, num => num.eval());
|
|
5271
5299
|
}
|
|
5272
5300
|
}
|
|
5273
5301
|
|
|
@@ -5532,9 +5560,9 @@ parser.yy = {
|
|
|
5532
5560
|
parseError: parseError,
|
|
5533
5561
|
constants: ["e"],
|
|
5534
5562
|
symbolLexer: function (symbol) {
|
|
5535
|
-
if (___default
|
|
5563
|
+
if (___default.default.contains(parser.yy.constants, symbol)) {
|
|
5536
5564
|
return "CONST";
|
|
5537
|
-
} else if (___default
|
|
5565
|
+
} else if (___default.default.contains(parser.yy.functions, symbol)) {
|
|
5538
5566
|
return "FUNC";
|
|
5539
5567
|
} else {
|
|
5540
5568
|
return "VAR";
|
|
@@ -5545,7 +5573,7 @@ const parse = function (input, options) {
|
|
|
5545
5573
|
try {
|
|
5546
5574
|
if (options && options.functions) {
|
|
5547
5575
|
// reserve the symbol "i" for complex numbers
|
|
5548
|
-
parser.yy.functions = ___default
|
|
5576
|
+
parser.yy.functions = ___default.default.without(options.functions, "i");
|
|
5549
5577
|
} else {
|
|
5550
5578
|
parser.yy.functions = [];
|
|
5551
5579
|
}
|
|
@@ -5612,9 +5640,9 @@ class Unit extends Sym {
|
|
|
5612
5640
|
|
|
5613
5641
|
// Simplify units by replacing prefixes with multiplication
|
|
5614
5642
|
collect(options) {
|
|
5615
|
-
if (___default
|
|
5643
|
+
if (___default.default(baseUnits).has(this.symbol)) {
|
|
5616
5644
|
return this;
|
|
5617
|
-
} else if (___default
|
|
5645
|
+
} else if (___default.default(derivedUnits).has(this.symbol)) {
|
|
5618
5646
|
return derivedUnits[this.symbol].conversion;
|
|
5619
5647
|
} else {
|
|
5620
5648
|
throw new Error("could not understand unit: " + this.symbol);
|
|
@@ -5627,12 +5655,12 @@ class Unit extends Sym {
|
|
|
5627
5655
|
// "g" -> Unit("g")
|
|
5628
5656
|
// "kg" -> 1000 * Unit("g")
|
|
5629
5657
|
var unprefixify = function (symbol) {
|
|
5630
|
-
if (___default
|
|
5658
|
+
if (___default.default(baseUnits).has(symbol) || ___default.default(derivedUnits).has(symbol)) {
|
|
5631
5659
|
return new Unit(symbol);
|
|
5632
5660
|
}
|
|
5633
5661
|
|
|
5634
5662
|
// check for prefix
|
|
5635
|
-
var prefix = ___default
|
|
5663
|
+
var prefix = ___default.default(___default.default(siPrefixes).keys()).find(testPrefix => {
|
|
5636
5664
|
return new RegExp("^" + testPrefix).test(symbol);
|
|
5637
5665
|
});
|
|
5638
5666
|
if (prefix) {
|
|
@@ -5644,7 +5672,7 @@ var unprefixify = function (symbol) {
|
|
|
5644
5672
|
//
|
|
5645
5673
|
// Otherwise, we're trying to parse a unit label which is not
|
|
5646
5674
|
// allowed (mwk, mBTU, etc).
|
|
5647
|
-
if (___default
|
|
5675
|
+
if (___default.default(baseUnits).has(base) || derivedUnits[base] && derivedUnits[base].prefixes === hasPrefixes) {
|
|
5648
5676
|
return new Mul(siPrefixes[prefix], new Unit(base));
|
|
5649
5677
|
} else {
|
|
5650
5678
|
throw new Error(base + " does not allow prefixes");
|
|
@@ -5673,10 +5701,10 @@ const unitParse = function (input) {
|
|
|
5673
5701
|
// denom is optionally null
|
|
5674
5702
|
|
|
5675
5703
|
const unitArray = [];
|
|
5676
|
-
___default
|
|
5704
|
+
___default.default(parseResult.unit.num).each(unitSpec => {
|
|
5677
5705
|
unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(unitSpec.pow)));
|
|
5678
5706
|
});
|
|
5679
|
-
___default
|
|
5707
|
+
___default.default(parseResult.unit.denom).each(unitSpec => {
|
|
5680
5708
|
unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(-1 * unitSpec.pow)));
|
|
5681
5709
|
});
|
|
5682
5710
|
var unit = new Mul(unitArray).flatten();
|