@stemcmicro/core
Version:
Computer Algebra System in TypeScript
1,141 lines (1,129 loc) • 1.34 MB
JavaScript
/**
* @stemcmicro/core 0.9.79
* (c) David Geo Holmes david.geo.holmes@gmail.com
* Released under the MIT License.
*/
System.register(['@stemcmicro/native', '@stemcmicro/atoms', '@stemcmicro/diagnostics', '@stemcmicro/helpers', '@stemcmicro/tree', '@stemcmicro/context', '@stemcmicro/directive', '@stemcmicro/stack', '@stemcmicro/em-parse', '@stemcmicro/eigenmath'], (function (exports) {
'use strict';
var native_sym, Native, is_native, log$1, multiply$1, real$1, exp$1, create_sym, is_boo$1, Flt, negOne, is_num$1, is_rat, imu, is_flt$1, Rat, bigInt, is_tensor, zero, one, Tensor, create_int, BigInteger, is_sym$1, is_str$2, is_err, is_uom, is_blade, is_hyp$1, is_keyword, is_imu, Err, Cell, Map$1, create_flt$1, create_str$1, create_tensor, et, booT, epsilon, Str, piAsFlt$1, eAsFlt, two, four, half, negFour, three, nine, third, eight, Sym, Boo, assert_tensor, Hyp, create_tensor_elements_diagonal, is_map, is_tag, is_jsobject, create_boo, JsObject, assert_jsobject, assert_sym$1, booU, Uom, QQ, create_rat, zeroAsFlt$1, is_cell, assert_str, assert_map, assert_cell, assert_flt, create_hyp, booF, assert_rat, Keyword, create_tensor_elements, oneAsFlt$1, diagnostic, Diagnostics, is_localizable, Localizable, str_to_string, isone$1, is_add$1, is_multiply$1, is_power$1, guess, is_num_and_negative, is_rat_and_integer, is_num_and_eq_rational, is_cons_opr_eq_power, is_num_and_eq_number, is_num_and_eq_one_half, multiply_items, negate, subst, add$1, divide$1, is_mul_2_any_any, num_to_number, multiply, power, inverse, subtract$1, iszero, is_negative, is_cons_opr_eq_multiply, compare_num_num, is_cons_opr_eq_add, is_cons_opr_eq_sym, is_outer, is_inner_or_dot, lt_num_num, is_cons_opr_eq_inv, is_base_of_natural_logarithm, is_pi, is_num_and_eq_two, count_factors, contains_single_blade, abs$1, is_factorial$1, is_rat_and_fraction$1, convertMetricToNative, convert_tensor_to_strings, create_algebra_as_tensor, predicate_return_value, prolog_eval_varargs, float, is_safe_integer_range, is_opr_2_any_any, is_atom, nil, is_nil, is_cons, cadr$1, caddr$1, cadnr, items_to_cons, cdr, car, cons, assert_cons$1, assert_U$1, assert_cons_or_nil$1, cddr$1, cdddr, caadr$1, cadadr, is_cons2, cadddr$1, is_singleton, Lambda, SIGN_GT$1, SIGN_LT$1, SIGN_EQ$1, is_lambda, Directive, StackU, Stack, scan_meta, complexity, conjfunc, inner$1, push_rational, power$1, make_stack_draw, value_of, stopf, pop_integer, multiply$2, expfunc, add$2, sqrtfunc, subtract$2, negate$1, push_integer, multiply_factors$1, power_e_expo, stack_infix, stack_kronecker, stack_log, stack_mag, stack_mod, stack_noexpand, stack_outer, stack_rank, stack_arccosh, stack_arcsin, stack_arcsinh, stack_arctan, stack_arctanh, stack_arg, stack_binding, stack_circexp, stack_clock, stack_cos, stack_cosh, stack_exp, stack_expcos, stack_expcosh, stack_expsin, stack_expsinh, stack_exptan, stack_exptanh, stack_floor, stack_hadamard, stack_imag, stack_index, stack_inv, stack_minor, stack_minormatrix, stack_nroots, stack_polar, stack_rationalize, stack_real, stack_rect, stack_sin, stack_sinh, stack_sqrt, stack_testlt, stack_testge, stack_testgt, stack_transpose, stack_unit;
return {
setters: [function (module) {
native_sym = module.native_sym;
Native = module.Native;
is_native = module.is_native;
log$1 = module.log;
multiply$1 = module.multiply;
real$1 = module.real;
exp$1 = module.exp;
exports({ NATIVE_MAX: module.NATIVE_MAX, NATIVE_MIN: module.NATIVE_MIN, Native: module.Native, code_from_native_sym: module.code_from_native_sym, is_native_sym: module.is_native_sym, native_sym: module.native_sym });
}, function (module) {
create_sym = module.create_sym;
is_boo$1 = module.is_boo;
Flt = module.Flt;
negOne = module.negOne;
is_num$1 = module.is_num;
is_rat = module.is_rat;
imu = module.imu;
is_flt$1 = module.is_flt;
Rat = module.Rat;
bigInt = module.bigInt;
is_tensor = module.is_tensor;
zero = module.zero;
one = module.one;
Tensor = module.Tensor;
create_int = module.create_int;
BigInteger = module.BigInteger;
is_sym$1 = module.is_sym;
is_str$2 = module.is_str;
is_err = module.is_err;
is_uom = module.is_uom;
is_blade = module.is_blade;
is_hyp$1 = module.is_hyp;
is_keyword = module.is_keyword;
is_imu = module.is_imu;
Err = module.Err;
Cell = module.Cell;
Map$1 = module.Map;
create_flt$1 = module.create_flt;
create_str$1 = module.create_str;
create_tensor = module.create_tensor;
et = module.et;
booT = module.booT;
epsilon = module.epsilon;
Str = module.Str;
piAsFlt$1 = module.piAsFlt;
eAsFlt = module.eAsFlt;
two = module.two;
four = module.four;
half = module.half;
negFour = module.negFour;
three = module.three;
nine = module.nine;
third = module.third;
eight = module.eight;
Sym = module.Sym;
Boo = module.Boo;
assert_tensor = module.assert_tensor;
Hyp = module.Hyp;
create_tensor_elements_diagonal = module.create_tensor_elements_diagonal;
is_map = module.is_map;
is_tag = module.is_tag;
is_jsobject = module.is_jsobject;
create_boo = module.create_boo;
JsObject = module.JsObject;
assert_jsobject = module.assert_jsobject;
assert_sym$1 = module.assert_sym;
booU = module.booU;
Uom = module.Uom;
QQ = module.QQ;
create_rat = module.create_rat;
zeroAsFlt$1 = module.zeroAsFlt;
is_cell = module.is_cell;
assert_str = module.assert_str;
assert_map = module.assert_map;
assert_cell = module.assert_cell;
assert_flt = module.assert_flt;
create_hyp = module.create_hyp;
booF = module.booF;
assert_rat = module.assert_rat;
Keyword = module.Keyword;
create_tensor_elements = module.create_tensor_elements;
oneAsFlt$1 = module.oneAsFlt;
}, function (module) {
diagnostic = module.diagnostic;
Diagnostics = module.Diagnostics;
is_localizable = module.is_localizable;
Localizable = module.Localizable;
}, function (module) {
str_to_string = module.str_to_string;
isone$1 = module.isone;
is_add$1 = module.is_add;
is_multiply$1 = module.is_multiply;
is_power$1 = module.is_power;
guess = module.guess;
is_num_and_negative = module.is_num_and_negative;
is_rat_and_integer = module.is_rat_and_integer;
is_num_and_eq_rational = module.is_num_and_eq_rational;
is_cons_opr_eq_power = module.is_cons_opr_eq_power;
is_num_and_eq_number = module.is_num_and_eq_number;
is_num_and_eq_one_half = module.is_num_and_eq_one_half;
multiply_items = module.multiply_items;
negate = module.negate;
subst = module.subst;
add$1 = module.add;
divide$1 = module.divide;
is_mul_2_any_any = module.is_mul_2_any_any;
num_to_number = module.num_to_number;
multiply = module.multiply;
power = module.power;
inverse = module.inverse;
subtract$1 = module.subtract;
iszero = module.iszero;
is_negative = module.is_negative;
is_cons_opr_eq_multiply = module.is_cons_opr_eq_multiply;
compare_num_num = module.compare_num_num;
is_cons_opr_eq_add = module.is_cons_opr_eq_add;
is_cons_opr_eq_sym = module.is_cons_opr_eq_sym;
is_outer = module.is_outer;
is_inner_or_dot = module.is_inner_or_dot;
lt_num_num = module.lt_num_num;
is_cons_opr_eq_inv = module.is_cons_opr_eq_inv;
is_base_of_natural_logarithm = module.is_base_of_natural_logarithm;
is_pi = module.is_pi;
is_num_and_eq_two = module.is_num_and_eq_two;
count_factors = module.count_factors;
contains_single_blade = module.contains_single_blade;
abs$1 = module.abs;
is_factorial$1 = module.is_factorial;
is_rat_and_fraction$1 = module.is_rat_and_fraction;
convertMetricToNative = module.convertMetricToNative;
convert_tensor_to_strings = module.convert_tensor_to_strings;
create_algebra_as_tensor = module.create_algebra_as_tensor;
predicate_return_value = module.predicate_return_value;
prolog_eval_varargs = module.prolog_eval_varargs;
float = module.float;
is_safe_integer_range = module.is_safe_integer_range;
is_opr_2_any_any = module.is_opr_2_any_any;
exports("create_algebra_as_blades", module.create_algebra_as_blades);
}, function (module) {
is_atom = module.is_atom;
nil = module.nil;
is_nil = module.is_nil;
is_cons = module.is_cons;
cadr$1 = module.cadr;
caddr$1 = module.caddr;
cadnr = module.cadnr;
items_to_cons = module.items_to_cons;
cdr = module.cdr;
car = module.car;
cons = module.cons;
assert_cons$1 = module.assert_cons;
assert_U$1 = module.assert_U;
assert_cons_or_nil$1 = module.assert_cons_or_nil;
cddr$1 = module.cddr;
cdddr = module.cdddr;
caadr$1 = module.caadr;
cadadr = module.cadadr;
is_cons2 = module.is_cons2;
cadddr$1 = module.cadddr;
is_singleton = module.is_singleton;
}, function (module) {
Lambda = module.Lambda;
SIGN_GT$1 = module.SIGN_GT;
SIGN_LT$1 = module.SIGN_LT;
SIGN_EQ$1 = module.SIGN_EQ;
is_lambda = module.is_lambda;
}, function (module) {
Directive = module.Directive;
}, function (module) {
StackU = module.StackU;
Stack = module.Stack;
}, function (module) {
scan_meta = module.scan_meta;
}, function (module) {
complexity = module.complexity;
conjfunc = module.conjfunc;
inner$1 = module.inner;
push_rational = module.push_rational;
power$1 = module.power;
make_stack_draw = module.make_stack_draw;
value_of = module.value_of;
stopf = module.stopf;
pop_integer = module.pop_integer;
multiply$2 = module.multiply;
expfunc = module.expfunc;
add$2 = module.add;
sqrtfunc = module.sqrtfunc;
subtract$2 = module.subtract;
negate$1 = module.negate;
push_integer = module.push_integer;
multiply_factors$1 = module.multiply_factors;
power_e_expo = module.power_e_expo;
stack_infix = module.stack_infix;
stack_kronecker = module.stack_kronecker;
stack_log = module.stack_log;
stack_mag = module.stack_mag;
stack_mod = module.stack_mod;
stack_noexpand = module.stack_noexpand;
stack_outer = module.stack_outer;
stack_rank = module.stack_rank;
stack_arccosh = module.stack_arccosh;
stack_arcsin = module.stack_arcsin;
stack_arcsinh = module.stack_arcsinh;
stack_arctan = module.stack_arctan;
stack_arctanh = module.stack_arctanh;
stack_arg = module.stack_arg;
stack_binding = module.stack_binding;
stack_circexp = module.stack_circexp;
stack_clock = module.stack_clock;
stack_cos = module.stack_cos;
stack_cosh = module.stack_cosh;
stack_exp = module.stack_exp;
stack_expcos = module.stack_expcos;
stack_expcosh = module.stack_expcosh;
stack_expsin = module.stack_expsin;
stack_expsinh = module.stack_expsinh;
stack_exptan = module.stack_exptan;
stack_exptanh = module.stack_exptanh;
stack_floor = module.stack_floor;
stack_hadamard = module.stack_hadamard;
stack_imag = module.stack_imag;
stack_index = module.stack_index;
stack_inv = module.stack_inv;
stack_minor = module.stack_minor;
stack_minormatrix = module.stack_minormatrix;
stack_nroots = module.stack_nroots;
stack_polar = module.stack_polar;
stack_rationalize = module.stack_rationalize;
stack_real = module.stack_real;
stack_rect = module.stack_rect;
stack_sin = module.stack_sin;
stack_sinh = module.stack_sinh;
stack_sqrt = module.stack_sqrt;
stack_testlt = module.stack_testlt;
stack_testge = module.stack_testge;
stack_testgt = module.stack_testgt;
stack_transpose = module.stack_transpose;
stack_unit = module.stack_unit;
}],
execute: (function () {
exports({
assert_sym: assert_sym,
create_env: create_env,
create_uom: create_uom,
directive_from_flag: directive_from_flag,
env_term: env_term,
init_env: init_env,
render_as_ascii: render_as_ascii,
render_as_human: render_as_human,
render_as_infix: render_as_infix,
render_as_latex: render_as_latex,
render_as_sexpr: render_as_sexpr,
roots: roots,
simplify: simplify$1,
transform_tree: transform_tree
});
const SIGN_LT = -1;
const SIGN_EQ = 0;
const SIGN_GT = 1;
/**
* The expression was ignored by the transformer, usually because it did not match the transformer.
*/
const TFLAG_NONE = 0;
/**
* The expression changed as a result of the transformation.
*/
const TFLAG_DIFF = 1 << 0;
/**
* The expression did not change as a result of the transformation because it is stable.
*/
const TFLAG_HALT = 1 << 1;
/**
* Returns true if flags has the "diff" bit set.
*/
function diffFlag(flags) {
return (flags & TFLAG_DIFF) === TFLAG_DIFF;
}
const ALL_FEATURES = exports("ALL_FEATURES", ["Blade", "Boo", "Cell", "Flt", "Imu", "Map", "Rat", "Sym", "Tensor", "Uom"]);
function directive_from_flag(value) {
if (typeof value === "boolean") {
return value ? 1 : 0;
}
else {
return 0;
}
}
const MODE_EXPANDING = 1;
const MODE_FACTORING = 2;
const MODE_SEQUENCE = [MODE_EXPANDING, MODE_FACTORING];
const MODE_FLAGS_ALL = MODE_EXPANDING | MODE_FACTORING;
const PHASE_FLAGS_EXPANDING_UNION_FACTORING = MODE_EXPANDING | MODE_FACTORING;
let Builder$k = class Builder {
extension;
constructor(extension) {
this.extension = extension;
}
create(config) {
return new this.extension(config);
}
};
function mkbuilder(extension) {
return new Builder$k(extension);
}
/**
* A convenience function for constructing transform results and peforming correct reference counting.
* If the expressions are the same then we return the oldExpr (it may have better positional metadata), and TFLAG_NONE.
* If the expressions differ, we return newExpr and TFLAG_DIFF.
*
*/
function wrap_as_transform(newExpr, oldExpr) {
if (newExpr.equals(oldExpr)) {
// If the expressions have the same value, we return the oldExpr because it may have better meta information
// such as pos and end properties.
oldExpr.addRef();
return [TFLAG_NONE, oldExpr];
}
else {
newExpr.addRef();
return [TFLAG_DIFF, newExpr];
}
}
class ProgrammingError extends Error {
constructor(message) {
super();
this.name = "ProgrammingError";
if (typeof message === "string") {
this.message = message;
}
}
}
/* eslint-disable @typescript-eslint/no-unused-vars */
class AtomExtensionFromExprHandler {
handler;
#type;
#guard;
constructor(handler, type, guard) {
this.handler = handler;
this.#type = type;
this.#guard = guard;
}
get hash() {
return this.#type;
}
get name() {
return this.#type;
}
iscons() {
return false;
}
operator() {
throw new ProgrammingError();
}
isKind(expr) {
if (is_atom(expr)) {
return this.#guard(expr);
}
else {
return false;
}
}
toHumanString(expr, $) {
return str_to_string(this.handler.dispatch(expr, native_sym(Native.human), nil, $));
}
toInfixString(expr, $) {
return str_to_string(this.handler.dispatch(expr, native_sym(Native.infix), nil, $));
}
toLatexString(expr, $) {
return str_to_string(this.handler.dispatch(expr, native_sym(Native.latex), nil, $));
}
toListString(expr, $) {
return str_to_string(this.handler.dispatch(expr, native_sym(Native.sexpr), nil, $));
}
evaluate(opr, argList, $) {
throw new Error("evaluate method not implemented.");
}
transform(expr, env) {
const newExpr = this.valueOf(expr, env);
try {
return wrap_as_transform(newExpr, expr);
}
finally {
newExpr.release();
}
}
valueOf(expr, env) {
return this.dispatch(expr, create_sym("valueof"), nil, env);
}
binL(lhs, opr, rhs, env) {
return this.handler.binL(lhs, opr, rhs, env);
}
binR(rhs, opr, lhs, env) {
return this.handler.binR(rhs, opr, lhs, env);
}
dispatch(target, opr, argList, env) {
const response = this.handler.dispatch(target, opr, argList, env);
if (is_nil(response)) {
return diagnostic(Diagnostics.Property_0_does_not_exist_on_type_1, opr, create_sym(target.type));
}
else {
return response;
}
}
subst(expr, oldExpr, newExpr, env) {
throw new Error("subst method not implemented.");
}
test(expr, opr, env) {
const response = this.handler.dispatch(expr, opr, nil, env);
if (is_boo$1(response)) {
return response.isTrue();
}
else {
throw diagnostic(Diagnostics.Property_0_does_not_exist_on_type_1, opr, create_sym(expr.type));
}
}
}
class AtomExtensionBuilderFromExprHandlerBuilder {
builder;
type;
guard;
constructor(builder, type, guard) {
this.builder = builder;
this.type = type;
this.guard = guard;
}
create(config) {
return new AtomExtensionFromExprHandler(this.builder.create(), this.type, this.guard);
}
} exports("AtomExtensionBuilderFromExprHandlerBuilder", AtomExtensionBuilderFromExprHandlerBuilder);
/**
*
*/
class ExtensionFromExprHandler {
handler;
constructor(handler) {
this.handler = handler;
}
get hash() {
throw new Error("Method not implemented.");
}
get name() {
throw new Error("Method not implemented.");
}
phases;
dependencies;
iscons() {
throw new Error("Method not implemented.");
}
operator() {
throw new Error("Method not implemented.");
}
isKind(expr, $) {
throw new Error("Method not implemented.");
}
subst(expr, oldExpr, newExpr, $) {
throw new Error("Method not implemented.");
}
toHumanString(expr, $) {
throw new Error("Method not implemented.");
}
toInfixString(expr, $) {
throw new Error("Method not implemented.");
}
toLatexString(expr, $) {
throw new Error("Method not implemented.");
}
toListString(expr, $) {
throw new Error("Method not implemented.");
}
evaluate(opr, argList, $) {
throw new Error("Method not implemented.");
}
transform(expr, $) {
throw new Error("Method not implemented.");
}
valueOf(expr, $) {
throw new Error("Method not implemented.");
}
test(atom, opr, env) {
return this.handler.test(atom, opr, env);
}
binL(lhs, opr, rhs, env) {
return this.handler.binL(lhs, opr, rhs, env);
}
binR(rhs, opr, lhs, env) {
return this.handler.binR(rhs, opr, lhs, env);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
dispatch(target, opr, argList, env) {
return this.handler.dispatch(target, opr, argList, env);
}
}
/**
* Constructs a floating point number object from a number primitive.
* @param value The floating point number value.
* @param pos The start position of the number in the source text.
* @param end The end position of the number in the source text.
*/
function create_flt(value, pos, end) {
if (value === zeroAsFlt.d) {
return zeroAsFlt;
}
if (value === oneAsFlt.d) {
return oneAsFlt;
}
if (value === negOneAsFlt.d) {
return negOneAsFlt;
}
if (value === twoAsFlt.d) {
return twoAsFlt;
}
if (value === negTwoAsFlt.d) {
return negTwoAsFlt;
}
// console.lg("wrap_as_flt", value);
return new Flt(value, pos, end);
}
const zeroAsFlt = new Flt(0.0);
const oneAsFlt = new Flt(1.0);
const twoAsFlt = new Flt(2.0);
const piAsFlt = new Flt(Math.PI);
new Flt(1e-6);
new Flt(Math.E);
const negOneAsFlt = new Flt(-1.0);
const negTwoAsFlt = new Flt(-2.0);
// The canonical keys for various mathematical symbols.
// These MUST be unique.
// These MUST be stable over time.
// Think of these as a universal standard identifying mathematical standards.
// Implementations do not need to couple to this file, but they should use it as a standard.
// TODO: Don't need to define functions; these are pluggable and should not be centrally defined.
const MATH_ADD$1 = native_sym(Native.add);
const MATH_COS = native_sym(Native.cos);
const MATH_TAN = native_sym(Native.tan);
native_sym(Native.subtract);
const MATH_MUL$2 = native_sym(Native.multiply);
native_sym(Native.divide);
const MATH_POW$1 = native_sym(Native.pow);
const MATH_OUTER = native_sym(Native.outer);
const MATH_INNER = native_sym(Native.inner);
const MATH_INV = native_sym(Native.inv);
const MATH_LCO = native_sym(Native.lco);
const MATH_RCO = native_sym(Native.rco);
const MATH_SIN$1 = native_sym(Native.sin);
native_sym(Native.succ);
native_sym(Native.pred);
native_sym(Native.E);
const MATH_PI$1 = native_sym(Native.PI);
const MATH_FACTORIAL = native_sym(Native.factorial);
native_sym(Native.iszero);
native_sym(Native.testlt);
native_sym(Native.testgt);
native_sym(Native.testle);
/**
* ':'
*/
create_sym(":");
/**
* tau(x) = 2 * pi * x
*/
native_sym(Native.tau);
const MATH_IMU$1 = native_sym(Native.IMU);
//
// WARNING This module should not depend on anything.
// The imports below are for types only and will not create a dependency.
//
var PrintMode;
(function (PrintMode) {
/**
* Two-dimensional rendering.
*/
PrintMode[PrintMode["Ascii"] = 0] = "Ascii";
/**
* Like infix but with extra whitespace and may have multiplication operators removed.
*/
PrintMode[PrintMode["Human"] = 1] = "Human";
/**
* Infix is how we normally write math but whitespace is removed and may be parsed by a computer.
*/
PrintMode[PrintMode["Infix"] = 2] = "Infix";
/**
* MathJax compatible.
*/
PrintMode[PrintMode["LaTeX"] = 3] = "LaTeX";
/**
* Symbolic Expression is LISP-like.
*/
PrintMode[PrintMode["SExpr"] = 4] = "SExpr";
PrintMode[PrintMode["EcmaScript"] = 5] = "EcmaScript";
})(PrintMode || (PrintMode = {}));
class Defs {
constructor() {
// Nothing to see here yet.
}
/**
* top of stack
*/
tos = 0;
/**
* The program execution stack.
* TODO: This should be moved to the $ to achieve isolation of executions.
* It should also not allow undefined and null values as this requires casting elsewhere.
* Encapsulation with assertion may help.
*/
stack = [];
}
/**
* Global (singleton) instance of Defs.
*/
const defs = new Defs();
/**
* This should only be used for scripting when the stack is being used.
* Otherwise, there should be a convenient way to throw structured Error(s).
*/
function halt(s) {
move_top_of_stack(0);
throw new Error(`Stop: ${s}`);
}
function move_top_of_stack(stackPos) {
if (defs.tos <= stackPos) {
// we are moving the stack pointer
// "up" the stack (as if we were doing a push)
defs.tos = stackPos;
return;
}
// we are moving the stack pointer
// "down" the stack i.e. as if we were
// doing a pop, we can zero-
// out all the elements that we pass
// so we can reclaim the memory
while (defs.tos > stackPos) {
defs.stack[defs.tos] = null;
defs.tos--;
}
}
function noexpand_unary(func, arg, $) {
$.pushDirective(Directive.expanding, 0);
try {
return func(arg, $);
}
finally {
$.popDirective();
}
}
function noexpand_binary(func, lhs, rhs, $) {
$.pushDirective(Directive.expanding, 0);
try {
return func(lhs, rhs, $);
}
finally {
$.popDirective();
}
}
function doexpand_unary(func, arg, $) {
$.pushDirective(Directive.expanding, 1);
try {
return func(arg, $);
}
finally {
$.popDirective();
}
}
function doexpand_binary(func, lhs, rhs, $) {
$.pushDirective(Directive.expanding, 1);
try {
return func(lhs, rhs, $);
}
finally {
$.popDirective();
}
}
/**
*
*/
class DynamicConstants {
static NegOne($) {
return $.getDirective(Directive.evaluatingAsFloat) ? negOneAsFlt : negOne;
}
static PI($) {
return $.getDirective(Directive.evaluatingAsFloat) ? piAsFlt : MATH_PI$1;
}
}
function length_of_cons_otherwise_zero(expr) {
return is_cons(expr) ? [...expr].length : 0;
}
const do_simplify_nested_radicals = true;
// TODO: Migrate to a situation of only creating these on demand by extensions.
const ADD$9 = native_sym(Native.add);
create_sym("adj");
create_sym("algebra");
const AND = create_sym("and");
const APPROXRATIO = create_sym("approxratio");
const ARCCOS$1 = create_sym("arccos");
const ARCCOSH = create_sym("arccosh");
const ARCSIN = create_sym("arcsin");
const ARCSINH = create_sym("arcsinh");
const ARCTAN = create_sym("arctan");
const ARCTANH = create_sym("arctanh");
create_sym("atomize");
const BESSELJ = create_sym("besselj");
const BESSELY = create_sym("bessely");
create_sym("binding");
const BINOMIAL = create_sym("binomial");
const CEILING = create_sym("ceiling");
const CHECK = create_sym("check");
const CHOOSE = create_sym("choose");
native_sym(Native.circexp);
const CLEAR = create_sym("clear");
create_sym("clearall");
create_sym("clearpatterns");
const COEFF = create_sym("coeff");
create_sym("cofactor");
create_sym("compare");
create_sym("compare-factors");
create_sym("compare-terms");
const COMPONENT$2 = native_sym(Native.component);
const CONDENSE = native_sym(Native.condense);
const CONTRACT = create_sym("contract");
const COS$2 = MATH_COS;
const COSH = create_sym("cosh");
create_sym("decomp");
const DEFINT = create_sym("defint");
create_sym("denominator");
const DET$1 = create_sym("det");
const DIM = create_sym("dim");
const DIRAC = create_sym("dirac");
create_sym("divide");
create_sym("divisors");
const DO = create_sym("do");
const DOT = create_sym("dot");
create_sym("draw");
create_sym("dsolve");
const EIGEN = create_sym("eigen");
const EIGENVAL = create_sym("eigenval");
const EIGENVEC = create_sym("eigenvec");
create_sym("equal");
const ERF = create_sym("erf");
const ERFC = create_sym("erfc");
/**
* 'eval'
*/
const EVAL = create_sym("eval");
const EXP$3 = native_sym(Native.exp);
const EXPAND$1 = native_sym(Native.expand);
create_sym("expcos");
native_sym(Native.factor);
const FACTORIAL = MATH_FACTORIAL;
create_sym("factorpoly");
const FLOAT = native_sym(Native.float);
const FLOOR = create_sym("floor");
/**
* (fn [params*] expr*)
*/
const FN = native_sym(Native.fn);
const FOR = create_sym("for");
/**
* (Sym("function") body paramList)
*
* Notice that the syntax is different from ClojureScript, which is (fn params body), and params is a Tensor of symbols.
*/
const FUNCTION = native_sym(Native.function);
const GAMMA = create_sym("gamma");
const GCD = native_sym(Native.gcd);
const HERMITE = native_sym(Native.hermite);
native_sym(Native.hilbert);
create_sym("if");
const IMAG$1 = native_sym(Native.imag);
native_sym(Native.inner);
const INTEGRAL = native_sym(Native.integral);
const INV$1 = MATH_INV;
create_sym("invg");
create_sym("isinteger");
const ISPRIME = native_sym(Native.isprime);
const LAGUERRE = create_sym("laguerre");
create_sym("laplace");
const LCM = create_sym("lcm");
native_sym(Native.lco);
const LEGENDRE = create_sym("legendre");
const LET$1 = create_sym("let");
const LOG$1 = native_sym(Native.log);
const MULTIPLY$2 = MATH_MUL$2;
native_sym(Native.not);
create_sym("nroots");
create_sym("number");
create_sym("numerator");
const OPERATOR = create_sym("operator");
const OR = create_sym("or");
native_sym(Native.outer);
const PATTERN = create_sym("pattern");
native_sym(Native.polar);
const POWER$2 = MATH_POW$1;
const PRINT_LEAVE_E_ALONE = create_sym("printLeaveEAlone");
const PRINT_LEAVE_X_ALONE = create_sym("printLeaveXAlone");
create_sym("print");
const PRODUCT = create_sym("product");
const QUOTE = create_sym("quote");
create_sym("quotient");
const RANK = create_sym("rank");
native_sym(Native.rco);
const REAL$1 = native_sym(Native.real);
const ISREAL$3 = native_sym(Native.isreal);
const ROUND$1 = create_sym("round");
native_sym(Native.rect);
create_sym("roots");
const ASSIGN = native_sym(Native.assign);
const SGN = create_sym("sgn");
const SIN = MATH_SIN$1;
const SINH = create_sym("sinh");
create_sym("shape");
const SQRT$1 = create_sym("sqrt");
create_sym("stop");
native_sym(Native.subst);
create_sym("-");
const SUM = create_sym("sum");
const TAN = MATH_TAN;
const TANH = create_sym("tanh");
const TAYLOR = native_sym(Native.taylor);
const TEST = native_sym(Native.test);
const TESTGE = native_sym(Native.testge);
const TESTGT = native_sym(Native.testgt);
const TESTLE = native_sym(Native.testle);
const TESTLT = native_sym(Native.testlt);
const TRANSPOSE = create_sym("transpose");
const UNIT = create_sym("unit");
const UOM = create_sym("uom");
native_sym(Native.zero);
create_sym("lastPrint");
create_sym("lastAsciiPrint");
create_sym("lastInfixPrint");
create_sym("lastLatexPrint");
create_sym("lastSexprPrint");
create_sym("lastHumanPrint");
create_sym("autoexpand");
create_sym("autofactor");
const BAKE = create_sym("bake");
create_sym("trace");
const METAA = create_sym("$METAA");
const METAB = create_sym("$METAB");
const METAX = create_sym("$METAX");
const SECRETX = create_sym("$SECRETX");
create_sym("version");
/**
* 'a'
*/
create_sym("a");
create_sym("b");
create_sym("c");
/**
* 'd' is commonly used for the derivative.
*/
const SYMBOL_D = create_sym("d");
const SYMBOL_I = create_sym("i");
const SYMBOL_J = create_sym("j");
create_sym("n");
create_sym("r");
const SYMBOL_S = create_sym("s");
const SYMBOL_T = create_sym("t");
/**
* x
*/
const SYMBOL_X = create_sym("x");
const SYMBOL_Y = create_sym("y");
const SYMBOL_Z = create_sym("z");
const SYMBOL_IDENTITY_MATRIX = create_sym("I");
const SYMBOL_A_UNDERSCORE = create_sym("a_");
const SYMBOL_B_UNDERSCORE = create_sym("b_");
const SYMBOL_X_UNDERSCORE = create_sym("x_");
create_sym("$C1");
create_sym("$C2");
create_sym("$C3");
create_sym("$C4");
create_sym("$C5");
create_sym("$C6");
const MAXPRIMETAB = 10000;
//define _USE_MATH_DEFINES // for MS C++
const MAXDIM = 24;
const primetab = (function () {
const primes = [2];
let i = 3;
while (primes.length < MAXPRIMETAB) {
let j = 0;
const ceil = Math.sqrt(i);
while (j < primes.length && primes[j] <= ceil) {
if (i % primes[j] === 0) {
j = -1;
break;
}
j++;
}
if (j !== -1) {
primes.push(i);
}
i += 2;
}
primes[MAXPRIMETAB] = 0;
return primes;
})();
function MSIGN(p) {
if (p.isZero()) {
return 0;
}
if (p.isPositive()) {
return 1;
}
return -1;
}
/**
* p.equals(n)
*/
function MEQUAL(p, n) {
return p.equals(n);
}
//
// TODO: In order not to torture our future selves, these should be documented and have coverage unit testing.
// Maybe document the matching patterns?
// Using block comments makes it possible to compose these with logical operators.
//
/**
* The expression must be a Rat or Flt, otherwise the return value is false.
* TODO: Interesting that this required expr > 0, when positive usually includes zero.
* @param expr The expression being tested.
*/
function is_num_and_gt_zero(expr) {
if (is_rat(expr)) {
return MSIGN(expr.a) === 1;
}
else if (is_flt$1(expr)) {
return expr.d > 0.0;
}
else {
return false;
}
}
/**
*
*/
function is_num_and_eq_minus_one(p) {
if (is_num$1(p)) {
return p.isMinusOne();
}
else {
return false;
}
}
/**
*
*/
function is_plus_or_minus_one(x, $) {
return isone$1(x, $) || is_num_and_eq_minus_one(x);
}
// --------------------------------------
function isunivarpolyfactoredorexpandedform(p, x) {
// console.lg("isunivarpolyfactoredorexpandedform", `${p}`, `${x}`);
if (x == null) {
x = guess(p);
}
if (is_poly_factored_or_expanded_form(p, x) && countTrue(p.contains(SYMBOL_X), p.contains(SYMBOL_Y), p.contains(SYMBOL_Z)) === 1) {
return x;
}
else {
return false;
}
}
function countTrue(...a) {
// Number(true) = 1
return a.reduce((count, x) => count + Number(x), 0);
}
// --------------------------------------
// sometimes we want to check if we have a poly in our
// hands, however it's in factored form and we don't
// want to expand it.
function is_poly_factored_or_expanded_form(p, x) {
return is_poly_factored_or_expanded_form_factor(p, x);
}
function is_poly_factored_or_expanded_form_factor(p, x) {
if (is_multiply$1(p)) {
return p.tail().every((el) => {
const bool = is_poly_factored_or_expanded_form_power(el, x);
return bool;
});
}
else {
return is_poly_factored_or_expanded_form_power(p, x);
}
}
function is_poly_factored_or_expanded_form_power(p, x) {
if (is_power$1(p)) {
const base = p.base;
const expo = p.expo;
return is_rat(expo) && expo.isPositiveInteger() && is_poly_expanded_form_expr(base, x);
}
else {
return is_poly_expanded_form_expr(p, x);
}
}
// --------------------------------------
/**
* Determines whether the expression, p, is a polynomial in the variable, x.
*/
function is_poly_expanded_form(p, x) {
// console.lg(`is_poly_expanded_form ${print_expr(p, $)} ${x}`);
if (p.contains(x)) {
return is_poly_expanded_form_expr(p, x);
}
else {
// If the expression does not contain the variable then it's a non-starter.
return false;
}
}
function is_poly_expanded_form_expr(p, x) {
// console.lg(`is_poly_expanded_form_expr ${print_expr(p, $)} ${x}`);
if (is_add$1(p)) {
return p.tail().every((term) => is_poly_expanded_form_term(term, x));
}
else {
return is_poly_expanded_form_term(p, x);
}
}
function is_poly_expanded_form_term(p, x) {
// console.lg(`is_poly_expanded_form_term ${print_expr(p, $)} ${x}`);
if (is_multiply$1(p)) {
return p.tail().every((factor) => is_poly_expanded_form_factor(factor, x));
}
else {
return is_poly_expanded_form_factor(p, x);
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function is_poly_expanded_form_factor(p, x) {
// console.lg(`is_poly_expanded_form_factor ${print_expr(p, $)} ${x}`);
if (p.equals(x)) {
return true;
}
if (is_power$1(p) && p.base.equals(x)) {
const expo = p.expo;
return is_rat(expo) && expo.isPositiveInteger();
}
if (p.contains(x)) {
return false;
}
else {
return true;
}
}
function is_power_and_has_rational_exponent_and_negative_base(expr) {
if (is_power$1(expr)) {
const expo = expr.expo;
if (is_rat(expo)) {
if (is_num_and_negative(expr.base)) {
return true;
}
}
}
return false;
}
function isimaginarynumberdouble(p, $) {
return (is_multiply$1(p) && length_of_cons_otherwise_zero(p) === 3 && is_flt$1(cadnr(p, 1)) && is_power_and_has_rational_exponent_and_negative_base(cadnr(p, 2))) || $.equals(p, imu);
}
/**
* (multiply Num i)
*/
function is_imaginary_number(expr) {
if (is_multiply$1(expr)) {
// (multiply a1 a2 a3 ...)
if (length_of_cons_otherwise_zero(expr) === 3) {
// (multiply x y)
if (is_num$1(cadr$1(expr)) && caddr$1(expr).equals(imu)) {
// (multiply Num i)
return true;
}
if (expr.equals(imu)) {
// Probbaly dead code because i => (pow -1 1/2), which isn't a (multiply )
return true;
}
if (is_power_and_has_rational_exponent_and_negative_base(caddr$1(expr))) {
return true;
}
}
}
return false;
}
function iscomplexnumberdouble(p, $) {
return (is_add$1(p) && length_of_cons_otherwise_zero(p) === 3 && is_flt$1(cadr$1(p)) && isimaginarynumberdouble(caddr$1(p), $)) || isimaginarynumberdouble(p, $);
}
/**
* Determines whether expr is of the form (+ Num (something times i))
* For this to work it is crucial that the complex number terms be arranged with
* the real part on the left hand side. e.g. 1.0 + 2.0*i.
*/
function is_complex_number(expr) {
// console.lg(`is_complex_number ${render_as_sexpr(expr, $)}`);
if (is_add$1(expr)) {
// console.lg(`${$.toInfixString(expr)} is an add expression`);
const n = length_of_cons_otherwise_zero(expr);
// console.lg(`${$.toInfixString(expr)} n = ${n}`);
if (n === 3) {
const x = cadr$1(expr);
// console.lg(`${$.toInfixString(expr)} X = ${$.toInfixString(X)}`);
if (is_num$1(x)) {
if (is_imaginary_number(caddr$1(expr)) || is_imaginary_number(expr)) {
return true;
}
}
}
}
return false;
}
function is_rat_and_even_integer(expr) {
return is_rat_and_integer(expr) && expr.a.isEven();
}
function isNumberOneOverSomething(p) {
return is_rat(p) && p.isFraction() && MEQUAL(p.a.abs(), 1);
}
/**
*
*/
function is_rat_and_fraction(p) {
return is_rat(p) && p.isFraction();
}
// p == -1/2 ?
funct